[英]MySQL Query optimization with ORDER BY and multiple joins
我有以下表格(所有InnoDb):
CREATE TABLE `user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`num` INT(11) NOT NULL,
`date` DATETIME NOT NULL DEFAULT '2014-01-01 00:00:00',
`year` VARCHAR(4) NOT NULL DEFAULT '1999',
PRIMARY KEY (`id`),
INDEX `yearIDX` (`year`, `num`),
INDEX `date` (`year`, `date`),
INDEX `dateonly` (`date`),
)
CREATE TABLE `log` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`unit_id` BIGINT(20) NULL DEFAULT NULL
PRIMARY KEY (`id`),
INDEX `logunitIDX` (`unit_id`),
CONSTRAINT `logunitIDX` FOREIGN KEY (`unit_id`) REFERENCES `unit` (`id`)
)
CREATE TABLE `user_log` (
`user_id` BIGINT(20) NOT NULL,
`log_id` BIGINT(20) NOT NULL,
`user_log_idx` INT(11) NOT NULL,
PRIMARY KEY (`user_id`, `user_log_idx`),
INDEX `user_log_key` (`user_id`),
INDEX `user_log` (`log_id`),
INDEX `Index 4` (`user_id`, `log_id`, `user_log_idx`),
CONSTRAINT `user_log` FOREIGN KEY (`log_id`) REFERENCES `log` (`id`),
CONSTRAINT `user_log_key` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
)
CREATE TABLE `unit` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`code` SMALLINT(6) NOT NULL
PRIMARY KEY (`id`),
UNIQUE INDEX `codeIDX_U` (`code`)
)
和以下查詢
SELECT
user0_.id AS e1_26_,
user0_.`num` AS registry4_26_,
user0_.`date` AS date5_26_
FROM `user` user0_
INNER JOIN `user_log` userlog1
ON user0_.id=userlog1.`user_id`
INNER JOIN `log` userlo2
ON userlog1.`log_id`=userlo2.id
INNER JOIN `unit` unit3_
ON userlo2.`unit_id`=unit3_.id
WHERE
user0_.`year`='2014'
AND
(unit3_.`code` in ('41','42','43','45'))
ORDER BY user0_.`date` DESC
LIMIT 400
查詢分析器將顯示此內容(為簡便起見,我省略了select_type和key_len。select_type為SIMPLE)
id table type possible_keys key ref rows Extra
1 unit3_ range PRIMARY,
codeIDX_U codeIDX_U Null 10 Using where;
Using index;
Using temporary;
Using filesort
1 userlo2 ref PRIMARY,
logunitIDX,
Index 6 logunitIDX unit3_.id 1194 Using where;
Using index
1 userlog1 ref PRIMARY,
user_log_key,
user_log,
Index 4 user_log userlo2.id 1 Using index
1 user0_ eq_ref PRIMARY,
yearIDX,
date PRIMARY userlog1.user_id 1 Using where
我相信第一行中出現“使用臨時;使用文件排序”的原因是因為“我正在聯接許多表,而ORDER BY中的列不是從第一個非常數表中檢索行”
是否有人可以優化此查詢以不使用temp / filesort?
您選擇的所有內容都來自user0_
,因此您似乎正在使用join
進行過濾。 假設您不關心多行,則可以使用exists
重寫查詢。 這可能使優化器擺脫文件排序:
SELECT u0.id AS e1_26_, u0.`num` AS registry4_26_, u0.`date` AS date5_26_
FROM `user` u0
WHERE EXISTS (SELECT 1
FROM `user_log` userlog1 INNER JOIN
`log` userlo2
ON userlog1.`log_id`= userlo2.id INNER JOIN
`unit` unit3_
ON userlo2.`unit_id`= unit3_.id
WHERE u0.id = userlog1.`user_id` AND
unit3_.`code` in ('41', '42', '43', '45')
) AND
u0.`year` = '2014'
ORDER BY u0.`date` DESC
LIMIT 400;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.