Pab*_*icz 1 mysql sql performance filesort
假设我有下表(让我们称之为my_table):
CREATE TABLE `my_table` (
`table_id` int(10) unsigned NOT NULL auto_increment,
`my_field` int(10) unsigned NOT NULL default '0'
PRIMARY KEY (`table_id`),
KEY `my_field` (`my_field`,`table_id`)
) ENGINE=MyISAM
Run Code Online (Sandbox Code Playgroud)
主键my_table是table_id(auto_increment),我也有一个带my_field和的键table_id.
如果我测试这个查询...
EXPLAIN SELECT * FROM my_table
WHERE my_field = 28
ORDER BY table_id DESC;
Run Code Online (Sandbox Code Playgroud)
......我明白了:
id select_type table type possible_keys key key_len ref rows Extra --- ----------- -------- ---- ------------- -------- ------- ----- ---- ----- 1 SIMPLE my_table ref my_field my_field 8 const 36
您可以看到它正在使用正确的密钥(my_field).
但如果我试试这个......
EXPLAIN SELECT * FROM my_table
WHERE my_field IN (1, 28, 20)
ORDER BY table_id DESC;
Run Code Online (Sandbox Code Playgroud)
......我明白了:
id select_type table type possible_keys key key_len ref rows Extra --- ----------- -------- ---- ------------- ------ ------- ------ ---- --------------------------- 1 SIMPLE my_table ALL my_field (NULL) (NULL) (NULL) 406 Using where; Using filesort
您可以看到它根本没有使用任何密钥,更糟糕的是,使用filesort.
即使我做" FORCE INDEX (my_field)",它仍然执行文件.
有没有办法避免filesort?
Jos*_*vis 14
据我所知,MySQL无法使用索引对此查询进行排序.
MySQL只能使用索引,如果恰好按照与查询相同的方式进行排序.让我们说你的记录(table_id,my_field)是
(1,1), (2,28), (3,14), (4,20)
Run Code Online (Sandbox Code Playgroud)
索引(my_field,table_id)将像这样存储
(1,1), (14,3), (20,4), (28,2)
Run Code Online (Sandbox Code Playgroud)
从IN示例执行查询时(为简单起见,我们会说你的ORDER BY是ASCending),MySQL会找到
(1,1), (20,4), (28,2)
Run Code Online (Sandbox Code Playgroud)
......按此顺序 无论如何,它都必须将它们分类(1,1),(28,2),(20,4).那是文件档案.这就是为什么MySQL只能在查询时使用该索引,ORDER BY my_field或者ORDER BY my_field, table_id因为索引已经按此顺序使用.这也是为什么它不能[目前,某些未来版本可能允许您按混合顺序对复合索引进行排序]如果混合使用ASC和DESC,则使用索引.索引在ASC,ASC中排序,无论您以何种方式阅读它,它的顺序都不正确.
请注意,"filesort"没有任何问题,它是正常执行查询的一部分.它实际上并不使用文件,应该非常快.
如果你必须排序成千上万的行,你可以通过使用一个小的派生表来获得更好的结果,特别是如果每一行真的很大(很多字段,BLOB等......)
SELECT t.*
FROM (
SELECT table_id FROM my_table WHERE my_field IN (1, 28, 20)
) tmp
JOIN my_table t USING (table_id)
ORDER BY t.table_id DESC
Run Code Online (Sandbox Code Playgroud)
您将为派生表交换文件排序.在某些情况下,它可以更高性能,而在其他情况下,稍微更少.因人而异
| 归档时间: |
|
| 查看次数: |
6488 次 |
| 最近记录: |