2014-09-18 2 views
0

У меня есть этот запрос, который занимает слишком много времени (с момента последнего посещения 1 час до сих пор работает), чтобы выполнить:SQLite запросов Производительность Время

select RL.[LINK_ID] as LINK_ID, RPA.[POSTAL_AREA_ID] as POSTAL_AREA_ID, RRN.[STREET_NAME] as STREET_NAME 
from RDF_LINK as RL, RDF_POSTAL_AREA as RPA, RDF_ROAD_LINK as RRL, RDF_ROAD_NAME as RRN 
where RRL.[ROAD_NAME_ID] = RRN.[ROAD_NAME_ID] 
AND RPA.[POSTAL_AREA_ID] IN (RL.[LEFT_POSTAL_AREA_ID], RL.[RIGHT_POSTAL_AREA_ID]) 
AND RL.[LINK_ID] = RRL.[LINK_ID] 

Все столбцы, которые являются частью запроса индексируются.
Команда ANALYZE уже была. выполняется в базе данных.
База данных имеет ок. 73 миллиона записей в таблице RDF_ROAD_LINK и столько же записей в других таблицах.

Есть ли другой способ написать этот запрос?

EXPLAIN QUERY PLAN 
select RL.[LINK_ID] as LINK_ID, RPA.[POSTAL_AREA_ID] as POSTAL_AREA_ID, RRN.[STREET_NAME] as STREET_NAME 
from RDF_LINK as RL, RDF_POSTAL_AREA as RPA, RDF_ROAD_LINK as RRL, RDF_ROAD_NAME as RRN 
where RRL.[ROAD_NAME_ID] = RRN.[ROAD_NAME_ID] 
AND RPA.[POSTAL_AREA_ID] IN (RL.[LEFT_POSTAL_AREA_ID], RL.[RIGHT_POSTAL_AREA_ID]) 
AND RL.[LINK_ID] = RRL.[LINK_ID] 

Выход ::

0 0 3 SCAN TABLE RDF_ROAD_NAME AS RRN 
0 1 2 SEARCH TABLE RDF_ROAD_LINK AS RRL USING INDEX IND_ROAD_NAME_ID (ROAD_NAME_ID=?) 
0 2 0 SEARCH TABLE RDF_LINK AS RL USING INDEX sqlite_autoindex_RDF_LINK_1 (LINK_ID=?) 
0 3 1 SEARCH TABLE RDF_POSTAL_AREA AS RPA USING COVERING INDEX sqlite_autoindex_RDF_POSTAL_AREA_1 (POSTAL_AREA_ID=?) 
0 0 0 EXECUTE LIST SUBQUERY 1 
+1

* Sigh *. РАЗРАБОТАТЬ ПЛАН ЗАПРОСА –

+0

@CL. .. Объяснить результаты плана запроса добавлены ... он сканирует таблицу RDF_ROAD_NAME .. Я не знаю, почему хотя ROAD_NAME_ID является первичным ключом в этой таблице, а также я создал индексирование в том же столбце. – Hardik

ответ

1

Этот запрос возвращает все 73 миллионов записей, и должен искать соответствующие записи из других таблиц. Это не так быстро, потому что слишком много данных для кэширования (и с таким размером, скорее всего, даже индексы не вписываются в кеш).

В соединении между двумя таблицами база данных проходит через все строки первой таблицы и просматривает соответствующие строки (строки) второй таблицы. Это означает, что первая таблица всегда заканчивается SCAN, потому что не имеет смысла использовать индекс (прохождение индекса не будет более быстрым, если вам нужно будет загружать все строки в любом случае).

В этом случае, используя индекс для RDF_ROAD_NAME был бы возможен лишь при наличии дополнительного фильтра на индексированной колонке (WHERE STREET_NAME = 'My Street'), или если результат должен быть отсортирован по индексированному колонку (ORDER BY ROAD_NAME_ID).

Если в таблицах имеется много столбцов, которые не используются в этом запросе, возможно, вы сможете немного ускорить его с помощью covering indexes (если все данные, которые вам нужны, уже находятся в индексе, база данных не требуется найдите соответствующую таблицу в таблице):

CREATE INDEX ... ON RDF_ROAD_LINK(ROAD_NAME_ID, LINK_ID); 
CREATE INDEX ... ON RDF_LINK(LINK_ID, LEFT_POSTAL_AREA_ID, RIGHT_POSTAL_AREA_ID); 
Смежные вопросы