一 簡介:聊聊group by的分組
二 explain體現
extra下
1 using tempoary
2 using tempoary && using filesort
3 using filesort
4 none
三 實現方式
1 定義
GROUP BY 實際上也同樣會進行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作,所以group by同樣可以利用到索引
2 實現方式
使用松散(Loose)索引掃描實現 GROUP BY
1 單一表查詢
2 Group by中只有最左前綴列,沒有其他列
3 只支持max和min聚合,而且,要聚合的列必須是group by中列所在的索引(未測試)
4 未被group by引用的索引其他部分必須是常量(不理解)
5 不支持前綴索引。
eg
-- 因為聚合函數不是max或者min
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
-- 因為不符合最左前綴原則
SELECT c1, c2 FROM t1 GROUP BY c2, c3;
-- 查詢涉及到了索引的一部分,緊跟group by中的列,但是沒有常量等值語句,加上 WHERE c3 = const就好了
SELECT c1, c3 FROM t1 GROUP BY c1, c2;
2 使用臨時表實現 GROUP BY
處理過程 通過where索引過濾 然后放置在臨時表中再進行分組+排序
四 優化
1 盡量使用group by 的分組利用到聯合索引
2 盡量添加order by null避免filesort
五 order by 使用場景解析
select * from table order by a1 當a1有索引的時候是可以利用到索引的
select * from table where a1=1 order by b1 當a 和 b為聯合索引且a為最左的時候 是可以利用到索引的
select * from table order by a1 desc, b1 利用8.0的特性創建制定順序的聯合索引是可以的,其他情況下是不能利用到索引,因為聯合索引只能按照一個順序進行查找
select * from table order by a1,b1 當a和b為聯合索引時是可以利用到索引的
select * from table where a1 > n order by a1 這種情況下根據數據量的分布可能會利用到icp特性或者應用不到索引
select * from table where a1 = n and b1 > n order by b1 這種情況下可能會遇到ICP特性
select * from table group a1 order by b1 這種情況下不能利用索引
相關排序參數 sort_buffer_size 先利用這個參數內存,只有內存不夠了才會在磁盤形成臨時文件
六 order by 與分頁操作
select * from table where a = b = order by id limit 10
現象 通過explain 走的是ID主鍵 奇怪現象 asc 與 desc 相差速度很大,但是explain確是相同
分析 通過explain分析可知,執行順序為 先根據order by進行排序 然后再進行條件過濾 最后分頁取操作. asc與desc執行速度的不同其實也可以推測. 那么就是結果集的數據都集中在正向而不是反向.那么這樣desc 和asc的速度不一樣就可以得知了.而limit 小結果集的加入讓sql優化器更傾向於order by 索引
解決方法: 1 order by 的排序項最好能參與到 where條件過濾中,即是聯合索引的一部分 2 調大 limit 結果集(根據業務決定) 3 采用延遲join