Оптимизация индекса в большой таблице MySQL - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть большая таблица (около 3 миллионов записей), которая включает в себя главным образом эти поля: rowID (int), deviceID (varchar (20)), UnixTimestamp в формате, подобном 1536169459 (int (10)), powerLevel, который имеет целые числа от 30 до 90 (smallint (6)).

Я хочу вытащить записи в определенном временном диапазоне (используя UnixTimestamp) для определенного идентификатора устройства и с уровнем мощности выше определенного числа. С более чем 3 миллионами записей это занимает некоторое время. Есть ли способ создать индекс, который будет оптимизировать для этого?

Ответы [ 3 ]

0 голосов
/ 05 сентября 2018

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

SELECT something
  FROM tbl
 WHERE deviceID = constant
   AND start <= UnixTimestamp
   AND UnixTimestamp < end
   AND Power >= constant

У вас есть один постоянный критерий (deviceID) и два критерия диапазона (UnixTimestamp и Power). Индексами MySQL являются BTREE (думаю, отсортированные по порядку), и MySQL может выполнять только одно сканирование диапазона индексов за SELECT.

Итак, вам, вероятно, следует выбрать индекс на (deviceID, UnixTimestamp, Power). Чтобы удовлетворить запрос, MySQL будет произвольно обращаться к индексу к записям для deviceID, а затем к произвольному доступу к первой строке, соответствующей критерию запуска UnixTimestamp.

Затем он будет сканировать индекс последовательно и использовать информацию Power из каждой записи индекса, чтобы решить, следует ли выбирать каждую строку.

Вы также можете использовать (deviceID, Power, UnixTimestamp). Но в этом случае MySQL найдет первую запись, соответствующую критерию устройства и мощности, а затем отсканирует индекс, чтобы просмотреть записи, которые будут иметь все временные метки, чтобы увидеть, какие строки следует выбрать.

Ваша цель производительности - заставить MySQL сканировать как можно меньше записей индекса, так что весьма вероятно, что выбор (deviceID, UnixTimestamp, Power) лучше. Столбец индекса на UnixTimestamp, вероятно, более селективный , чем столбец на Power. (Это мое предположение.)

ALTER TABLE tbl CREATE INDEX tbl_dev_ts_pwr (deviceID, UnixTimestamp, Power);

Посмотрите на учебники Билла Карвина. Также посмотрите на https://use -the-index-luke.com * Маркуса Винанда

0 голосов
/ 20 сентября 2018

Предлагаемые 3-колоночные индексы полезны лишь частично. Оптимизатор будет использовать первые 2 столбца, но игнорировать третий.

Лучше:

INDEX(DeviceId, PowerLevel),
INDEX(DeviceId, UnixTimestamp)

Почему?

Оптимизатор будет выбирать между этими двумя, на основе которых, кажется, более избирательным. Если временной диапазон «узкий», то будет использоваться второй индекс; если с нужным уровнем PowerLevel не так много строк, будет использован первый индекс.

Еще лучше ...

PRIMARY KEY ... Возможно, у вас Id в качестве ПК? Возможно (DeviceId, UnixTimestamp) уникален? (Или вы можете получить два показания для одного устройства за одну секунду?) Если пара уникальна, полностью избавьтесь от Id и получите

PRIMARY KEY(DeviceId, UnixTimestamp),
INDEX(DeviceId, PowerLevel)

Примечания:

  • Избавление от Id экономит место, обеспечивая тем самым небольшую скорость.
  • При использовании вторичного индекса выполнение тратит время на перераспределение между BTree индекса и данными BTree (по заказу PK). Имея PRIMARY KEY(Id), вы гарантированно будете прыгать. Изменяя PK на это, можно избежать подпрыгивания. Это может удвоить скорость запроса.
  • (я не уверен, что каждый вторичный индекс будет использоваться.)

Другое (незначительное) предложение: нормализовать DeviceId так, чтобы он (возможно) был 2-байтовым SMALLINT UNSIGNED (диапазон 0,64 КБ) вместо VARCHAR(20). Даже если это влечет за собой JOIN, запрос будет выполняться немного быстрее. И куча места сэкономлено.

0 голосов
/ 05 сентября 2018

Создать индекс более:

DeviceId,
PowerLevel,
UnixTimestamp

При выборе вы сначала сузите набор записей для данного устройства, а затем сузите его только до тех записей, которые находятся в правильном диапазоне PowerLevel. И, наконец, для каждого PowerLevel он сузится до правильных записей UnixTimestamp.

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