2015-09-23 4 views
1

У меня есть очень медленный запрос MySQL следующим образом:Очень медленный простой MySQL запрос

SELECT function, CONVERT_TZ(`time`, '+01:00','+01:00') 
FROM `function_logger` 
WHERE unit_id=3067785 
    and part_id=3 and channel=0 
    and `time` > NOW()-INTERVAL 1 DAY 
order by time; 

для следующей структуры таблицы

CREATE TABLE IF NOT EXISTS `function_logger` (
    `id` int(11) NOT NULL, 
    `unit_id` int(11) NOT NULL, 
    `part_id` tinyint(4) NOT NULL DEFAULT '0', 
    `channel` tinyint(4) NOT NULL DEFAULT '0', 
    `function` tinyint(11) NOT NULL, 
    `time` datetime NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

ALTER TABLE `function_logger` 
    ADD PRIMARY KEY (`id`), 
    ADD KEY `unit_id` (`unit_id`); 

Таблица содержит около 80 миллионов записей, но занимает около минуты до запустить. После кэширования это нормально.

unit_id содержит около 3000 различных случайных чисел, part_id ДО 10 и канала ДО 3.

Есть в любом случае, чтобы ускорить этот процесс?

Помогла ли разметка?

+2

Добавить индекс покрытия 'изменить таблицу function_logger добавить индекс search_idx (unit_id, part_id, канал, время)' –

+2

Какой смысл в преобразовании 'time' из одного часового пояса в той же временной зоне? – eggyal

+0

@AbhikChakraborty: Это не индекс покрытия ... – eggyal

ответ

2

Предполагая равномерное распределение unit_id, тогда выбор определенного (из 3000) среди 80-миллиметровых записей дает вам более 25 тыс. Записей для проверки.

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

Добавление индекса composite (т. Е. Того, которое определено для нескольких столбцов) поможет вам здесь: MySQL может тем самым уменьшить количество записей, которые необходимо изучить. Однако при такой малой мощности part_id и channel могут не сильно помочь. Пока не ясно, какой мощности может существовать от time, но это, вероятно, является хорошей отправной точкой:

CREATE INDEX unit_time ON function_logger (unit_id, time) 

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

Самой быстрая скорость чтения будет получен из covering индекса:

CREATE INDEX covering ON function_logger (
    unit_id, part_id, channel, time, function 
) 
+0

Большое вам спасибо. С индексом покрытия он теперь выбирает записи практически мгновенно. –

0

При попытке/tesing разных индексов выполните объяснить и сравнить результаты. USE INDEX поможет вам протестировать разные индексы, добавив в подсказку подсказку (не забудьте использовать qc).

set profiling = on; 

select * from function_logger; 
show profiles; 
show profile for query N;