Mysql
GROUP BY 需要 ORDER BY NULL 以避免文件排序
我一次又一次地註意到,當我
EXPLAIN
用一個GROUP BY
子句查詢時,我得到filesort
了一個額外的條件。很久以前,我讀過一個建議GROUP BY NULL
在這些情況下使用以避免文件排序,它確實消除了這種令人討厭的filesort
情況。我認為,如果不存在
ORDER BY
子句,則 dbms 只會呈現任意順序或任何最有效的順序,而不是按需要文件排序的某些神秘列進行排序。對我來說似乎很奇怪,我需要包含一個額外的方向,基本上相當於說*“不要做任何愚蠢的事情”*。我的問題是為什麼這甚至是必要的並且
ORDER BY NULL
實際上增加了性能?
MySQL 5.7 參考手冊 / … / SELECT 語法
如果您使用 GROUP BY,則輸出行將根據 GROUP BY 列進行排序,就好像您對相同的列有一個 ORDER BY。為了避免 GROUP BY 產生的排序成本,添加 ORDER BY NULL
Using filesort
當用於分組的列沒有適當的索引時出現。如上所述,返回的結果GROUP BY
按相同的列排序。如果您filesort
進行排序,則還可以使用文件排序進行分組。以同樣的方式侮辱表現。因此,您必須創建索引,而不是抑制排序。EXPLAIN SELECT w.t_id , count(1) AS counter FROM points AS w GROUP BY w.t_id ; +----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+ | 1 | SIMPLE | w | index | t_id | t_id | 2 | NULL | 27228500 | Using index | +----+-------------+-------+-------+---------------+-------+---------+------+----------+-------------+
沒有。
filesort
_ORDER BY NULL
SELECT w.t_id, count(1) AS counter FROM points AS w GROUP BY w.t_id; /* Affected rows: 0 Found rows: 606 Warnings: 0 Duration for 1 query: 6,922 sec. */ SELECT w.t_id, count(1) AS counter FROM points AS w GROUP BY w.t_id ORDER BY NULL; /* Affected rows: 0 Found rows: 606 Warnings: 0 Duration for 1 query: 6,781 sec. */
附言
至於小提琴失敗這裡是
mysql
輸出:沒有多列索引:
+----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+ | 1 | SIMPLE | animals | ALL | PRIMARY | NULL | NULL | NULL | 3 | Using temporary; Using filesort | | 1 | SIMPLE | animal_colors | ALL | animal_id,color | NULL | NULL | NULL | 6 | Using where; Using join buffer (Block Nested Loop) | +----+-------------+---------------+------+-----------------+------+---------+------+------+----------------------------------------------------+ 2 rows in set (0.00 sec)
添加了多列索引:
+----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+ | 1 | SIMPLE | animals | index | PRIMARY | PRIMARY | 4 | NULL | 3 | NULL | | 1 | SIMPLE | animal_colors | ref | animal_id,color,animal_id_color | animal_id | 4 | test.animals.animal_id | 1 | Using where | +----+-------------+---------------+-------+---------------------------------+-----------+---------+------------------------+------+-------------+ 2 rows in set (0.00 sec)