2009-10-13 3 views
6

Я работал с переходом из файлов доступа MS в файлы SQLite для моих простых потребностей в базе данных; по обычным причинам: меньший размер файла, меньше накладных расходов, с открытым исходным кодом и т. д.Как ускорить запрос с несколькими INNER JOINs

Одна вещь, которая мешает мне сделать коммутатор, - это то, что кажется недостатком скорости в SQLite. Для простых запросов SELECT SQLite, похоже, работает так же хорошо, как и MS-Access. Проблема возникает с довольно сложной запрос на выборку с несколькими операторами внутреннего соединения:

SELECT DISTINCT 
     DESCRIPTIONS.[oCode] AS OptionCode, 
     DESCRIPTIONS.[descShort] AS OptionDescription 
FROM DESCRIPTIONS 
INNER JOIN tbl_D_E ON DESCRIPTIONS.[oCode] = tbl_D_E.[D] 
INNER JOIN tbl_D_F ON DESCRIPTIONS.[oCode] = tbl_D_F.[D] 
INNER JOIN tbl_D_H ON DESCRIPTIONS.[oCode] = tbl_D_H.[D] 
INNER JOIN tbl_D_J ON DESCRIPTIONS.[oCode] = tbl_D_J.[D] 
INNER JOIN tbl_D_T ON DESCRIPTIONS.[oCode] = tbl_D_T.[D] 
INNER JOIN tbl_Y_D ON DESCRIPTIONS.[oCode] = tbl_Y_D.[D] 
WHERE ((tbl_D_E.[E] LIKE '%') 
     AND (tbl_D_H.[oType] ='STANDARD') 
     AND (tbl_D_J.[oType] ='STANDARD') 
     AND (tbl_Y_D.[Y] = '41') 
     AND (tbl_Y_D.[oType] ='STANDARD') 
     AND (DESCRIPTIONS.[oMod]='D')) 

В MS-Access, этот запрос выполняется в течение примерно 2,5 секунд. В SQLite требуется немного больше 8 минут. Требуется столько же времени, сколько я запускаю запрос из кода VB или из командной строки с помощью sqlite3.exe.

Так мои вопросы следующие:

  1. ли SQLite просто не оптимизированы для обработки нескольких инструкций INNER JOIN?
  2. Я сделал что-то явно глупо в моем запросе (потому что я новичок в SQLite), что делает его настолько медленным?

И прежде чем кто-либо предложит совершенно другую технологию, нет, я не могу переключить. Мои варианты - MS-Access или SQLite. :)

ОБНОВЛЕНИЕ: Назначение индекса для каждого из столбцов в базе данных SQLite уменьшается время запроса из более чем 8 минут до около 6 секунд. Благодаря Larry Lustig для объяснения причин необходимости применения INDEXing.

+3

Вы используете ИНДЕКСЫ? –

+0

@Phill Pafford: Я не использую индексы на MS-Access или SQLite-данных. Я пытаюсь сравнить доступ к sqlite, поэтому я оставил структуру данных одинаковой в обоих. – Stewbob

+9

Невозможно отправить ответ, поэтому попробуйте комментарий: MS Access очень агрессивно относится к индексированию столбцов от вашего имени, тогда как SQLite потребует от вас явно создавать нужные вам индексы. Таким образом, возможно, что Access проиндексировал либо [Description], либо [D] для вас, но эти индексы отсутствуют в SQLite. У меня нет опыта с этим количеством активности JOIN в SQLite. Я использовал его в одном проекте Django с относительно небольшим объемом данных и не обнаружил никаких проблем с производительностью. –

ответ

11

В соответствии с просьбой, я перепроведении мой предыдущий комментарий как фактический ответ (когда я первый отправил комментарий Мне почему-то не удалось опубликовать его в качестве ответа):

MS Access очень агрессивно относится к индексированию столбцов от вашего имени, тогда как SQLite потребует от вас явно создавать нужные вам индексы. Таким образом, возможно, что Access проиндексировал либо [Description], либо [D] для вас, но эти индексы отсутствуют в SQLite. У меня нет опыта работы с этим количеством активности JOIN в SQLite. Я использовал его в одном проекте Django с относительно небольшим объемом данных и не обнаружил никаких проблем с производительностью.

6

У вас есть проблемы с референциальной целостностью? Я спрашиваю, потому что такое впечатление, что вы получили ненужные соединения, так что я переписал запрос как:

SELECT DISTINCT 
     t.[oCode] AS OptionCode, 
     t.[descShort] AS OptionDescription 
    FROM DESCRIPTIONS t 
    JOIN tbl_D_H h ON h.[D] = t.[oCode] 
       AND h.[oType] = 'STANDARD' 
    JOIN tbl_D_J j ON j.[D] = t.[oCode] 
       AND j.[oType] = 'STANDARD' 
    JOIN tbl_Y_D d ON d.[D] = t.[oCode] 
       AND d.[Y] = '41' 
       AND d.[oType] ='STANDARD' 
WHERE t.[oMod] = 'D' 
+0

@rexem: Спасибо за вашу очищенную версию запроса. Я вернулся и посмотрел на мой запрос, и оказалось, что я не рассмотрел несколько инструкций WHERE, так что да, мне нужны все JOIN. Я все еще узнал несколько полезных вещей из вашего ответа. БЛАГОДАРЯ! – Stewbob

+0

Stewbob - если это действительно ответ, вы должны отметить его как таковой, чтобы rexem получал очки. Он поставил хорошую работу для решения этого вопроса! –

+0

@Mark: Согласно комментариям, Ларри Лустиг предоставил ответ, но не вернулся, чтобы опубликовать его как ответ, чтобы получить кредит. –

0

Если ОПИСАНИЕ и tbl_D_E имеют несколько сканирований строк, тогда oCode и D следует проиндексировать. Посмотрите пример здесь, чтобы посмотреть, как индексировать и рассказать, сколько сканирований строк есть (http://www.siteconsortium.com/h/p1.php?id=mysql002).

Это может исправить хотя ..

CREATE INDEX ocode_index ON ОПИСАНИЯ (oCode) С ИСПОЛЬЗОВАНИЕМ ВТКЕЕ; CREATE INDEX d_index ON tbl_D_E (D) ИСПОЛЬЗОВАНИЕ BTREE;

и т.д ....

индексирование правильно это одна часть головоломки, которая может легко удвоить, утроить или более скорость запроса.

Смежные вопросы