Оптимизация SELECT через индексы - PullRequest
2 голосов
/ 20 мая 2011

У меня есть большая таблица около 7M строк (и считая). Я пытаюсь оптимизировать SELECT, чтобы быть как можно быстрее. SELECT из одной таблицы, без соединений. База данных IBM Informix. Скорость SELECT является приоритетной, однако в таблицу добавляется довольно постоянное количество вставок.

В WHERE есть 23 параметра, но я определил даты и язык как те, которые стоит индексировать:

...
WHERE (? >= valid_from OR valid_from IS NULL)
AND (? <= valid_to OR valid_to IS NULL)
AND ((? >= date_from AND ? <= date_to) OR (? >= date_from AND ? <= date_to)) 
AND language = ?
...

Теперь, как лучше всего создать индексы для этого?

  1. Создавать ли отдельные индексы из valid_from, valid_to, date_from, date_to и language? Или мне создать три составных индекса (valid_from, valid_to), (date_from, date_to) и язык? Или мне создать один большой составной индекс со всеми пятью? Все поля обязательны для заполнения.

  2. Являются ли индексы сравниваемых дат хорошей идеей, или я должен ограничиться только теми полями, которые используют = (точное совпадение)?

  3. Если составные индексы таковы, я думаю, порядок полей в составном индексе важен - как мне упорядочить столбцы в индексе? Столбцы date_from и date_to дадут мне самое большое первое сокращение, но язык может дать мне более быстрое сокращение (хотя это предположение, которое я вынул из воздуха - см. Вопрос 2).

  4. Если существует несколько индексов, Informix использует их все или только один (и какой)?

  5. Мои тесты показывают, что порядок условий в ГДЕ не важен, однако я могу ошибаться - не так ли?

  6. Некоторые условия в WHERE относятся к столбцам, которые являются наборами. Informix не позволяет мне индексировать эти столбцы. Означает ли это, что эти условия соответствуют последовательному сканированию? Имеет ли смысл по быстродействию перемещать их в отдельный стол и присоединяться к ним?

Что я сделал до сих пор:

  • Очевидно, что нет никаких объединений, и это денормализованная таблица. Я плачу за это с помощью добавления большего количества строк, что меня устраивает, поскольку обновления не зависят от времени.
  • Я использую довольно большие экстенты Informix, чтобы избежать фрагментации, и размер страницы, который дает наилучшие результаты для моей таблицы.

Ответы [ 3 ]

1 голос
/ 20 мая 2011

Ваша логика и / или логика могут очень расстроить любого оптимизатора попытками создать полезный индекс.

Однако вы можете создавать функциональные индексы в Informix, см. http://www.ibm.com/developerworks/data/library/techarticle/dm-0712wilcox/index.html. Так что для этого подхода вы создадите пользовательские функции, такие, что вы можете написать:

...
WHERE ? >= null_small_date(valid_from)
  AND ? <= null_large_date(valid_to)
  AND language = ?
  // hack, hack.  These 4 values should be the same as, but in a different order from
  // the next line .  This sanity check will let the index skip many possible records.
  AND max_date(?, ?) >= date_from AND min_date(?, ?) <= date_to
  AND ((? >= date_from AND ? <= date_to) OR (? >= date_from AND ? <= date_to)) 
  ...

Имея это в виду, вы можете затем создать единый каскадный индекс для (null_small_date(valid_from), null_large_date(valid_to), language, date_from, date_to), который позволит вам пропустить большинство ваших результатов, чтобы сосредоточиться только на небольшой части вашей таблицы.

1 голос
/ 20 мая 2011

Я еще один человек, который не знает Informix, так что это что-то вроде удара в темноте. В зависимости от того, насколько избирательны различные столбцы, вы можете индексировать только один или два из них для достижения желаемой производительности.

Обновление статистики стоит проверить. Похоже, что Informix поддерживает подсказки запросов:

http://www.ibm.com/developerworks/data/zones/informix/library/techarticle/0502fan/0502fan.html

, который позволит вам точно указать, какой индекс вы хотите использовать.

1 голос
/ 20 мая 2011

Я тоже не знаю Informix;вам придется проверить.Postgres достаточно умен, чтобы объединить отдельные просмотры индекса по переменным по отдельности очевидным способом, если он этого хочет, и он оценивает (не всегда так хорошо), лучше ли этот подход, чем сканирование таблицы.Тем не менее, я подозреваю, что составной индекс из 5 столбцов будет хорошо работать здесь.

У меня есть другое предложение: используйте значение по умолчанию, чтобы установить значения NULL для дат в бесконечные крайности;тогда вам не нужно в специальном случае NULL.Кроме того, это, вероятно, правильно отражает бизнес-логику.

Если два?представляют тот же параметр, который вы можете немного упростить (? >= date_from AND ? <= date_to) с помощью ? IS BETWEEN date_from and date_to.Только синтаксический сахар не повлияет на планы запросов.

...