Mysql优化(三):优化order by
MySQL中的兩種排序方式
因為索引的結構是B+樹,索引中的數據是按照一定順序進行排列的,所以在排序查詢中如果能利用索引,就能避免額外的排序操作。EXPLAIN分析查詢時,Extra顯示為Using index。MySQL會結合SQL中的where、order by中的字段去選擇索引。
所有不是通過索引直接返回排序結果的操作都是Filesort排序,也就是說進行了額外的排序操作。EXPLAIN分析查詢時,Extra顯示為Using filesort。
無法使用索引排序的情況
首先要注意:
MySQL一次查詢只能使用一個索引,如果要對多個字段使用索引,建立復合索引。
注:下列key指代索引,key_part1、key_part2…指代索引中的順序字段
通過B+Tree結構判斷索引是否能用于排序
索引是B+Tree的結構,能否使用某個索引來避免排序可以通過數據在B+Tree中的是否有序判斷,下文有具體例子。
InnoDB的聚簇索引結構如下:
由此可知道,聚簇索引可以用于主鍵的排序,即order by 主鍵。
InnoDB的二級索引結構如下:
(1)二級索引的葉節點并不包含行記錄的全部數據,僅包含索引中的所有鍵和一個用于查找對應行記錄的主鍵值。(非葉子節點不包含主鍵)
(2)Innodb二級索引,索引列值全相同的情況下,節點按主鍵值排序。
(3)二級索引鍵值的順序和聚簇索引鍵值順序通常不同,所以二級索引做范圍查詢讀取記錄的性能通常不如聚簇索引高效(查詢的列不存在二級索引時需要回表,回表操作會有大量的隨機IO)。
是否使用索引排序取決于使用索引的成本
在滿足了使用索引排序的條件(上文提及不可用索引排序的情況)的前提下,是否使用索引、使用哪個索引取決于使用索引的成本。
設有表 t(id, create_at),主鍵為id,同時有索引 index(create_at)。不同查詢索引 index(create_at) 的使用情況:
(1)SELECT id FROM t WHERE create_at='2019年10月15日' ORDER BY id 和 SELECT create_at FROM t WHERE create_at='2019年10月15日' ORDER BY id
等值查詢,create_at='2019年10月15日'的節點在 索引 index(create_at)結構中按主鍵(id)的順序存儲,因此使用index(create_at)可以避免排序,同時因為覆蓋了所有列,無需回表(Extra 出現 Using index)
(2)SELECT * FROM t WHERE create_at='2019年10月15日' ORDER BY id
等值查詢,create_at='2019年10月15日'的節點在 索引 index(create_at)結構中按主鍵(id)的順序存儲,因此使用index(create_at)可以避免排序,雖然需要回表但是通過索引可以過濾大部分的數據,成本低于使用聚簇索引
(3)SELECT * FROM t WHERE create_at>'2019年10月15日' ORDER BY id
索引 index(create_at) 不包含所有數據,因此使用 index(create_at)做范圍查詢,每讀取每條記錄都需要回表查詢,會有大量的隨機IO,同時,此時在index(create_at)上id是無序的,所以性能不如直接使用聚簇索引。所以該查詢使用主鍵,通過對主鍵的聚簇索引進行掃描,只需要過濾掉不滿足條件的值而不需要排序
范圍查詢,需要回表,回表操作會有大量的隨機IO
(4)SELECT create_at FROM t WHERE create_at>'2019年10月15日' ORDER BY id
SELECT id FROM t WHERE create_at>'2019年10月15日' ORDER BY id
此查詢因為索引 index(create_at) 包含所需列,不需要回表查詢,因此使用index(create_at) 可以掃描更少的行,成本低于使用主鍵索引。
參考
- 推薦閱讀:淺談InnoDB中的聚簇索引和二級索引[譯]
- order by 原理以及優化
- MySQL——優化ORDER BY語句
- MySQL官網
總結
以上是生活随笔為你收集整理的Mysql优化(三):优化order by的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么申请qq企业邮箱(qq企业邮箱怎么注
- 下一篇: 安卓罪恶都市存档合集zip下载(安卓罪恶