[英]Using indexes with OR / GROUP BY / ORDER BY: How can I avoid filesort?
我正在尝试对以下查询使用 index ,但结果是filesort
。
我应该如何更改查询和/或索引以提高性能(避免文件排序)?
我尝试使用UNION
但文件filesort
仍然存在。
CREATE TABLE message (
Ms_ID INT(16) UNSIGNED NOT NULL AUTO_INCREMENT,
conversation INT(16) UNSIGNED NOT NULL,
subject ENUM('E', 'F', 'S-C', 'S-A', 'R-RS', 'R-ILP', 'Re-M', 'Re-I', 'Re-R', 'O', 'SP', 'T', 'I', 'C', 'Of', 'R') DEFAULT NULL,
subject_ID INT(16) UNSIGNED DEFAULT NULL,
sender INT(11) UNSIGNED, -- NULL=guest
recipient INT(11) UNSIGNED NOT NULL,
message VARCHAR(256),
status ENUM('U','R','SD', 'RD', 'SRD'), -- (unread, read, sender deleted, recipient deleted)
dateTime DATETIME NOT NULL,
PRIMARY KEY (Ms_ID),
FOREIGN KEY (sender) REFERENCES member (M_ID),
FOREIGN KEY (recipient) REFERENCES member (M_ID)
CREATE INDEX xMs_C ON message (conversation, sender, recipient, status, subject, dateTime)
CREATE INDEX xMs_D ON message (dateTime, conversation, recipient, sender, status, message)
CREATE INDEX xMs_R ON message (recipient, sender, status, dateTime, message)
CREATE INDEX xMs_S ON message (sender, recipient, status, dateTime, message)
EXPLAIN
SELECT Ms.*, M.userName
FROM message Ms -- FORCE INDEX (xMs_S)
INNER JOIN member M ON M_ID=IF (sender='3', recipient, sender)
WHERE Ms.status!='SRD' AND ((sender='3' AND Ms.status!='SD') OR (recipient='3' AND Ms.status!='RD'))
GROUP BY conversation
ORDER BY dateTime DESC
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Ms ALL xMs_S NULL NULL NULL 77 Using where; Using temporary; Using filesort
1 SIMPLE M eq_ref PRIMARY PRIMARY 4 func 1 Using where
你可以尝试这样的事情:
SELECT *
FROM
(
SELECT Ms.*, M.userName
FROM message Ms -- FORCE INDEX (xMs_S)
INNER JOIN member M ON M_ID = recipient
WHERE Ms.status!='SRD' AND sender='3' AND Ms.status!='SD'
UNION ALL
SELECT Ms.*, M.userName
FROM message Ms -- FORCE INDEX (xMs_S)
INNER JOIN member M ON M_ID = sender
WHERE Ms.status!='SRD' recipient='3' AND Ms.status!='RD'
) a
GROUP BY conversation
ORDER BY dateTime DESC;
GROUP BY
和ORDER BY
需要排序; 如果不对数据进行排序,MySQL 根本无法产生您要求的结果。 使用文件排序意味着 MySQL 正在对您的数据表进行排序。 继续对机器大发雷霆,但它正在做你要求它做的事情。
它可能会使用索引排序而不是文件排序,但您正在按conversation
分组。 该列不会作为您在问题中显示的任何索引的第一个组成部分出现。
发生的事情是服务器必须将您加入的数据收集到一个临时表中以对其进行排序。 查看 MySQL / MariaDB 开发人员 Sergey Petrunia 的博客,了解其工作原理。
http://s.petrunia.net/blog/?p=24
您还在GROUP BY
语句中包含了许多隐藏的列。 GROUP BY
隐藏列的能力是 MySQL 特有的(错误)功能。 这些隐藏的列可能是服务器收集您加入的数据然后在不同的步骤中对其进行排序的原因之一。 阅读 MySQL 手册的这一页以了解更多信息。
http://dev.mysql.com/doc/refman/5.6/en/group-by-hidden-columns.html
除了在EXPLAIN
输出中看到Using filesort 之外,您怎么知道您遇到了性能问题? 你处理了多少数据? 需要多长时间?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.