为什么这个查询使用文件排序?

问题描述 投票:0回答:1

我正在查看慢速查询日志并尝试修复一些慢速查询,我确定了一个要修复的查询并对其运行了 EXPLAIN 并使用文件排序注意到了它

为什么以下查询会显示“using filesort”

这是解释 enter image description here

这里是所有索引 enter image description here

这是我要使用的索引:

enter image description here

mysql indexing filesort
1个回答
0
投票

当 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 或更高版本。

© www.soinside.com 2019 - 2024. All rights reserved.