我有一个包含以下详细信息的表格:
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(fk_zone_for_correction, seenDate)
两列也许都可以使用——第一列用于过滤,第二列用于避免排序。但是,如果无法快速找到 1
行,可能会适得其反。
killer 是OR
。如果您可以避免使用 NULL
填充这 3 列中的任何一列,那么这可能会更好:
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
。
您有两种冗余索引的情况。例如,第一个是第二个的左侧部分;所以第一个是多余的,可以被删除:
KEY `corrected_test` (`corrected_test`),
KEY `idx_corrected_test_seenDate` (`corrected_test`,`seenDate`),
关于mysql - 索引需要加快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47749408/