Оптимизация соединения SQLite - PullRequest
6 голосов
/ 15 ноября 2010

Если у вас есть запрос, например:

select a.Name, a.Description from a
inner join b on a.id1 = b.id1
inner join c on b.id2 = c.id2
group by a.Name, a.Description

Каковы наиболее оптимальные столбцы для индексации этого запроса в SQLite, если учесть, что в каждой из таблиц содержится более 100 000 строк?

Причина, по которой я спрашиваю, состоит в том, что я не получаю производительность с запросом группы, которую я ожидаю от другой СУБД (SQL Server), когда применяю ту же оптимизацию.

Буду ли я прав, полагая, что все столбцы, на которые ссылается одна таблица в запросе в SQLite, должны быть включены в один составной индекс для лучшей производительности?

Ответы [ 5 ]

5 голосов
/ 15 ноября 2010

Проблема в том, что вы ожидаете, что SQLite будет иметь те же характеристики производительности, что и полноценная СУБД.Не будетSQLLite не может позволить себе так много кэширования в памяти, ему приходится перестраивать кэш каждый раз, когда вы запускаете приложение, возможно, он ограничен набором ядер, и т. Д., И т. Д. И т. Д.более полного.

Что касается оптимизации, попробуйте проиндексировать столбцы поиска и проверить.Затем попробуйте создать индекс покрытия.Обязательно протестируйте и selects, и пути кода, которые обновляют базу данных, вы ускоряете один за счет другого.Найдите индексирование, которое дает наилучший баланс между двумя для ваших нужд и продолжайте его.

3 голосов
/ 15 ноября 2010

Из обзора оптимизации запросов SQLite 1002 *:

При выполнении индексированного поиска строки обычной процедурой является выполнение двоичного поиска по индексу для поиска индексаentry, затем извлеките rowid из индекса и используйте этот rowid для выполнения двоичного поиска в исходной таблице.Таким образом, типичный индексированный поиск включает два бинарных поиска.Однако, если все столбцы, которые должны были быть извлечены из таблицы, уже доступны в самом индексе, SQLite будет использовать значения, содержащиеся в индексе, и никогда не будет искать исходную строку таблицы.Это сохраняет один двоичный поиск для каждой строки и позволяет выполнять много запросов в два раза быстрее.

Для любой другой СУБД, я бы сказал, поместить кластерный индекс в b.id1 и c.id2.Для SQLite может быть лучше включить любые столбцы из b и c, которые вы также хотите найти в этих индексах.

1 голос
/ 15 ноября 2010

Поскольку вы не используете другие таблицы для своих возвращаемых столбцов, возможно, это будет быстрее:

SELECT DISTINCT a.Name, a.Description
FROM a, b, c
WHERE a.id1 = b.id1
AND b.id2 = c.id2

Глядя на возвращаемые столбцы, поскольку критерии, по-видимому, состоят только в том, что они должны быть связаныот a до b до c вы можете искать все уникальные пары a.Name и a.Description.

SELECT DISTINCT a.Name, a.Description
FROM a
WHERE a.id1 IN (
 SELECT b.id1
 FROM b
 WHERE b.id2 IN (
  SELECT c.id2
  FROM c
  )
 )

Или, в зависимости от того, есть ли каждая пара a.Name и a.Description уже уникален, должен быть некоторый выигрыш в поиске сначала уникального идентификатора, а затем извлечения других столбцов.

SELECT a.Name, a.Description
FROM a 
WHERE a.id1 IN (
 SELECT DISTINCT a.id1
 FROM a
 WHERE a.id1 IN (
  SELECT b.id1
  FROM b
  WHERE b.id2 IN (
   SELECT c.id2
   FROM c
   )
  )
 )
1 голос
/ 15 ноября 2010

Осторожно: я ничего не знаю о возможных тонкостях SQLite и его планах выполнения.

Вам определенно нужны индексы для a.id1, b.id1, b.id2 и c.id2.Я думаю, что составной индекс (b.id1, b.id2) может дать небольшое увеличение производительности.То же самое касается (a.id1, a.Name, a.Description).

0 голосов
/ 15 ноября 2010

Я думаю, что индексы для a.id1 и b.id2 дадут вам столько же преимуществ, сколько вы можете получить с точки зрения JOIN. Но SQLite предлагает EXPLAIN, и он может помочь вам определить, можно ли избежать эффективности в текущем плане выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...