Создание индекса по временной метке для оптимизации запроса - PullRequest
49 голосов
/ 01 февраля 2012

У меня есть запрос следующей формы:

SELECT * FROM MyTable WHERE Timestamp > [SomeTime] AND Timestamp < [SomeOtherTime]

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

  • MyTable имеет 4 миллиона + строк.
  • Timestampна самом деле имеет тип INT.
  • После вставки строки она никогда не изменяется.
  • Количество строк с любым данным Timestamp в среднем составляет около 20, но можетбыть выше 200.
  • Вновь вставленные строки имеют Timestamp, который больше, чем большинство существующих строк, но может быть меньше, чем некоторые из более свежих строк.

Поможет ли мне индекс Timestamp оптимизировать этот запрос?

Ответы [ 4 ]

49 голосов
/ 01 февраля 2012

Нет вопросов по этому поводу.Без индекса ваш запрос должен просматривать каждую строку в таблице.С индексом запрос будет в значительной степени мгновенным, поскольку поиск правильных строк идет.Цена, которую вы заплатите, - это незначительное снижение производительности во вставках;но это действительно будет незначительным.

7 голосов
/ 01 февраля 2012

Вы обязательно должны использовать индекс.MySQL не имеет ни малейшего представления, в каком порядке находятся эти временные метки, и чтобы найти запись для данной временной метки (или диапазона временных меток), ему необходимо просмотреть каждую отдельную запись.И с 4 миллионами из них это совсем немного времени!Индексы - это ваш способ рассказать MySQL о ваших данных: «Я собираюсь довольно часто просматривать это поле, поэтому держите список, где я могу найти записи для каждого значения».

Индексы в целомхорошая идея для регулярно запрашиваемых полей.Единственным недостатком при определении индексов является то, что они используют дополнительное пространство для хранения, поэтому, если вы не очень ограничены в пространстве, вы должны попытаться использовать их.Если они не применяются, MySQL все равно их просто проигнорирует.

5 голосов
/ 01 февраля 2012

Если ваши запросы в основном используют эту временную метку, вы можете протестировать этот дизайн (увеличив Первичный ключ с временной меткой в ​​качестве первой части):

CREATE TABLE perf (
  , ts INT NOT NULL
  , oldPK 
  , ... other columns 
, PRIMARY KEY(ts, oldPK)
, UNIQUE (oldPK)
) ENGINE=InnoDB ;

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

Недостатком является то, что ваши вставки будут немного медленнее.Кроме того, если у вас есть другие индексы в таблице, они будут использовать немного больше места (поскольку они будут включать более широкий на 4 байта первичный ключ).

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

Старый PK все еще можно использовать для идентификации строк, сохраняя на нем ограничение UNIQUE.


Возможно, вы захотите взглянуть на TokuDB , вариант MySQL (и с открытым исходным кодом), который позволяет несколько кластеризованных индексов .

4 голосов
/ 10 марта 2014

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

Например, если у вас есть таблица с timestamp, category и userId, может быть лучше создать индекс для userId.В таблице с большим количеством разных пользователей это значительно сократит оставшийся набор для поиска временной отметки.

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

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

Сценарий для лучшего объяснения:

  1. отметка времени 99% уникальна
  2. userId 80% уникальна
  3. категория 25% уникальная

    • Индексирование по метке времени быстро сократит результаты запроса до 1% размера таблицы
    • Индексирование по userId быстро сократит результаты запроса до 20%.размер таблицы
    • Индексирование по категории быстро сократит результаты запроса до 75%. Размер таблицы
    • Вставка с индексами по метке времени будет иметь большие издержки **
    • Несмотря на то, что нашивставки будут учитывать факт увеличения меток времени, я не вижу обсуждения оптимизации MySQL на основе инкрементных ключей.
    • Вставка с индексами по userId будет иметь достаточно высокие накладные расходы.
    • Вставка с индексамидля категории будет иметь достаточно низкие накладные расходы.

** Извините, я не знаю рассчитанные накладные расходы или вставку с индексированием.

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