У меня есть таблица со следующими деталями:
CREATE TABLE 'test' (
'seenDate' datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
'corrected_test' varchar(45) DEFAULT NULL,
'corrected_timestamp' timestamp NULL DEFAULT NULL,
'unable_to_correct' tinyint(1) DEFAULT '0',
'fk_zone_for_correction' int(11) DEFAULT NULL,
PRIMARY KEY ('sightinguid'),
KEY 'corrected_test' ('corrected_test'),
KEY 'idx_seenDate' ('seenDate'),
KEY 'idx_corrected_test_seenDate' ('corrected_test','seenDate'),
KEY 'zone_for_correction_fk_idx' ('fk_zone_for_correction'),
KEY 'idx_corrected_test_zone' ('fk_zone_for_correction','corrected_test','seenDate'),
CONSTRAINT 'zone_for_correction_fk' FOREIGN KEY ('fk_zone_for_correction') REFERENCES 'zone_test' ('id') ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Затем я использую следующий запрос:
SELECT
*
FROM
test
WHERE
fk_zone_for_correction = 1
AND (unable_to_correct = 0
OR unable_to_correct IS NULL)
AND (corrected_test = ''
OR corrected_test IS NULL)
AND (last_accessed_timestamp IS NULL
OR last_accessed_timestamp < (NOW() - INTERVAL 30 MINUTE))
ORDER BY seenDate ASC
LIMIT 1
Вот скриншот оптимизатора - ORDER BY
замедляет работу, и, на мой взгляд, кажется, что он правильно проиндексирован и выбран правильный индекс (idx_corrected_test_zone
). Что можно сделать для его улучшения?
Нет INDEX, который очень поможет.
Это может помочь:
INDEX(fk_zone_for_correction, seenDate)
Возможно, обе колонки могут использоваться - первая для фильтрации, вторая - для исключения сортировки. Но он может иметь неприятные последствия, если он не может быстро найти 1
строку.
Убийца - это OR
. Если бы вы не смогли заполнить ни один из этих 3 столбцов NULL
, это может быть лучше:
INDEX(fk_zone_for_correction, unable_to_correct, corrected_test, last_accessed_timestamp)
-- the range thing needs to be last
-- this index would do the filtering, but fail to help with 'ORDER' and 'LIMIT'.
Несмотря на то, что он использует idx_corrected_test_zone
, он, вероятно, не использует больше, чем первые два столбца - из-за OR
.
У вас есть два случая избыточных индексов. Например, первая из них - левая часть второй; поэтому первый является избыточным и может быть DROPped
:
KEY 'corrected_test' ('corrected_test'),
KEY 'idx_corrected_test_seenDate' ('corrected_test','seenDate'),