Создание индекса в метке времени для оптимизации запроса

У меня есть запрос следующего вида:

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

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

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

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

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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

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

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

  • timestamp 99% уникальная
  • userId 80% уникальный
  • категория 25% уникальная

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

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