我正在查看慢速查询日志并尝试修复一些慢速查询,我确定了一个要修复的查询并对其运行了 EXPLAIN 并使用文件排序注意到了它
为什么以下查询会显示“using filesort”
这是我要使用的索引:
当 MySQL 无法假设它按照您请求的顺序读取行时,它会使用“文件排序”。
MySQL 总是以某种索引顺序读取行——该索引以 EXPLAIN 中第一个连接表命名。
如果我测试您的查询,但将其更改为
...ORDER BY power
,我们会发现它消除了文件排序,并且 key
列显示它正在使用 (titan, power)
上的索引。
CREATE TABLE titan_json (
id SERIAL,
titan VARCHAR(20),
power INT,
json JSON,
userID INT,
guildID INT,
guild VARCHAR(20),
INDEX (titan, power)
);
EXPLAIN
SELECT json FROM titan_json WHERE titan='Cronos' ORDER BY power;
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+-------+
| 1 | SIMPLE | titan_json | NULL | ref | titan | titan | 83 | const | 1 | 100.00 | NULL |
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+-------+
但是,如果我按照查询中的表达式(或者任何表达式)进行排序,MySQL 不会假设它获取行的顺序与索引顺序相同。所以它必须进行文件排序。
EXPLAIN
SELECT json FROM titan_json WHERE titan='Cronos' ORDER BY ABS(power-500000);
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+----------------+
| 1 | SIMPLE | titan_json | NULL | ref | titan | titan | 83 | const | 1 | 100.00 | Using filesort |
+----+-------------+------------+------------+------+---------------+-------+---------+-------+------+----------+----------------+
如果我为
ORDER BY
子句中的表达式创建一个带有功能部分的新索引,并重新测试查询,我们会发现它可以依赖索引顺序并消除文件排序。
ALTER TABLE titan_json
ADD KEY (titan, (ABS(power-500000)));
EXPLAIN
SELECT json FROM titan_json WHERE titan='Cronos' ORDER BY ABS(power-500000);
+----+-------------+------------+------------+------+------------------------+------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+------------------------+------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | titan_json | NULL | ref | titan,functional_index | functional_index | 83 | const | 1 | 100.00 | NULL |
+----+-------------+------------+------------+------+------------------------+------------------+---------+-------+------+----------+-------+
注意,功能关键部分的特性必须使用 MySQL 8.0 或更高版本。