lpa*_*lpa 5 mysql performance query-performance
简单查询但无法摆脱“using filesort”:
CREATE TABLE IF NOT EXISTS `online` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL,
`expiration` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
KEY `expiration` (`expiration`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1925234 ;
mysql> explain SELECT i.id, i.uid, i.expiration, u.nick, u.mainpicture
-> FROM online i join usertable u on i.uid = u.id
-> order by i.expiration DESC limit 0,12;
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+----------------+
| 1 | SIMPLE | i | ALL | uid | NULL | NULL | NULL | 1020 | Using filesort |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | dbasen01.i.uid | 1 | |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+----------------+
2 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
"usertable"列上有索引"id"。尝试按"i.id"(主键)排序,但相同 - 查询仍然使用文件排序。
RolandoMySQLDBA 回答后更新:
+----+-------------+-----------------+--------+---------------+---------+---------+-------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+--------+---------------+---------+---------+-------+------+----------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 12 | |
| 1 | PRIMARY | u | eq_ref | PRIMARY | PRIMARY | 4 | i.uid | 1 | |
| 2 | DERIVED | online | ALL | NULL | NULL | NULL | NULL | 1009 | Using filesort |
+----+-------------+-----------------+--------+---------------+---------+---------+-------+------+----------------+
Run Code Online (Sandbox Code Playgroud)
解决方案:
我删除了“id”列,因为它没有被使用。然后修改索引:
ALTER TABLE online ADD INDEX expiration (expiration,uid);
Run Code Online (Sandbox Code Playgroud)
结果:
+----+-------------+-------+--------+---------------+------------+---------+----------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+------------+---------+----------------+------+-------------+
| 1 | SIMPLE | i | index | uid | expiration | 8 | NULL | 12 | Using index |
| 1 | SIMPLE | u | eq_ref | PRIMARY | PRIMARY | 4 | dbasen01.i.uid | 1 | |
+----+-------------+-------+--------+---------------+------------+---------+----------------+------+-------------+
Run Code Online (Sandbox Code Playgroud)
谢谢大家。
小智 2
我没有时间去检查;但是,只要查看查询,我预计文件排序是由 ORDER BY/LIMIT 触发的。当仍然需要执行 O(n) 数据文件查找,然后进行外部排序以在执行 12 之前提取前 12 个数据时,对 uid 索引执行顺序 O(n) 传递并没有多大用处) eq_ref 连接到 usertable 的 id 索引,然后探测 usertable 的数据文件以提取 select 所需的字段。
我希望 Mysql 认为(正确地)最好对数据文件执行一次顺序 O(n) 传递,然后进行外部排序、eq_ref 连接和探测。
您需要的是预先为 mysql 执行外部排序,因此它不必自己执行。这意味着您需要一个覆盖连接/where 条件的索引。
IE。
ALTER TABLE online ADD INDEX expiration (expiration,uid,id);
Run Code Online (Sandbox Code Playgroud)
话又说回来,鉴于在线只有 1020 行,你为什么现在担心这个呢?
| 归档时间: |
|
| 查看次数: |
11323 次 |
| 最近记录: |