Составные индексы MySQL и оператор МЕЖДУ - PullRequest
6 голосов
/ 03 декабря 2010

У меня есть вопрос по этому запросу:

SELECT * 
  FROM runs 
 WHERE (NOW() BETWEEN began_at 
                  AND finished_at)

Как вы думаете, имеет ли смысл создавать составной индекс для столбцов begin_at и finish_at?Или имеет смысл создавать индекс только для begin_at?

Ответы [ 6 ]

7 голосов
/ 03 декабря 2010

Ваш стиль очень необычен.

Большинство людей, вероятно, написали бы WHERE began_at < NOW() AND finished_at > NOW()

Однако.Я бы порекомендовал поставить индекс для обоих полей.

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

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

Вы можете немного погуглить для "поиска в многомерном диапазоне".

Причина в том, что все совпадающие поля в одном поле в основном можно найти в журнале (о) время в деревьях.Таким образом, ваше общее время выполнения будет O (k * log (n)), что равно O (log (n)).

Для запросов многомерного диапазона время выполнения O (sqrt (n)) выше.Однако есть и лучшие реализации, которые также достигают логарифмического времени выполнения.Однако они не полностью реализованы в mysql, поэтому в зависимости от версии будет хуже или ужаснее.

Итак, позвольте мне подвести итог:

  • Сравнения равенства на отдельных полях: индекс хеша (время выполнения O (1))

  • Поиск диапазона по отдельным полям: индекс btree по отдельным полям (O (log (n))) *

  • Поиск равенства по нескольким полям: комбинированный хеш-ключ (время выполнения O (1))

эти случаи очевидны ...

  • Поиск диапазона по нескольким полям: отдельные индексы дерева (O (log (n)))

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

однако, когда mysql реализует свободные индексы, комбинированные ключи в полях, где вы выполняете запросы диапазона или сортируете в разных направлениях, становятся все более и более актуальными.

1 голос
/ 04 декабря 2010

Стратегия «Слияние индексов» может вступить в действие начиная с MySQL 5: http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html - что также предполагает, что отдельные индексы могут быть лучше.

Однако я так и не смог получитьэто у меня работает :)

1 голос
/ 03 декабря 2010

Из-за использования неравенств , а не равенств , составной индекс не будет намного лучше (если не хуже), чем два отдельных индекса.

Я бы выступил за то, чтобы склоняться к двум отдельным индексам как began_at, так и finished_at.

Справочные сведения для сканирования свободного индекса:

http://www.mysqlperformanceblog.com/2006/05/09/descending-indexing-and-loose-index-scan/

http://dev.mysql.com/doc/refman/5.5/en/loose-index-scan.html

0 голосов
/ 03 декабря 2010

Я никогда не заставлял MySQL использовать два отдельных индекса для begin_at или finished_at при попытке оптимизировать запрос такого типа.Очевидно, другие люди говорят, что составной индекс также не будет работать, поэтому MySQL может просто не оптимизировать этот запрос с помощью индекса.

0 голосов
/ 03 декабря 2010

Хороший вопрос, но я бы фактически начал с индексов и began_at и finished_at, потому что один разумный способ переписать этот запрос похож на

SELECT *
  FROM runs
 WHERE began_at < NOW()
   AND finished_at > NOW()

Что делает для меня более ясным (для меня), что каждый столбец нуждается в своем собственном индексе.

0 голосов
/ 03 декабря 2010

Правильный ответ на этот вопрос всегда: «это зависит». Попробуйте оба способа и сравните и сравните планы выполнения. Обратите внимание, что ответ также изменяется по мере изменения объема данных в ваших таблицах и рабочей нагрузки запроса. Индексы в развивающейся системе почти никогда не срабатывают и забывают.

...