從哪些方向去優化呢?
- 方向1: 既然它默認會排序,我們不給它排是不是就行啦。
- 方向2:既然臨時表是影響group by性能的X因素,我們是不是可以不用臨時表?
我們一起來想下,執行group by
語句為什么需要臨時表呢?group by
的語義邏輯,就是統計不同的值出現的個數。如果這個這些值一開始就是有序的,我們是不是直接往下掃描統計就好了,就不用臨時表來記錄並統計結果啦?
- group by 后面的字段加索引
- order by null 不用排序
- 盡量只使用內存臨時表
- 使用SQL_BIG_RESULT
5.1 group by 后面的字段加索引
如何保證group by
后面的字段數值一開始就是有序的呢?當然就是加索引啦。
我們回到一下這個SQL
select city ,count(*) as num from staff where age= 19 group by city;
復制代碼
它的執行計划
如果我們給它加個聯合索引idx_age_city(age,city)
alter table staff add index idx_age_city(age,city);
復制代碼
再去看執行計划,發現既不用排序,也不需要臨時表啦。
加合適的索引是優化group by
最簡單有效的優化方式。
5.2 order by null 不用排序
並不是所有場景都適合加索引的,如果碰上不適合創建索引的場景,我們如何優化呢?
如果你的需求並不需要對結果集進行排序,可以使用
order by null
。
select city ,count(*) as num from staff group by city order by null
復制代碼
執行計划如下,已經沒有filesort
啦
5.3 盡量只使用內存臨時表
如果group by
需要統計的數據不多,我們可以盡量只使用內存臨時表;因為如果group by 的過程因為數據放不下,導致用到磁盤臨時表的話,是比較耗時的。因此可以適當調大tmp_table_size
參數,來避免用到磁盤臨時表。
5.4 使用SQL_BIG_RESULT優化
如果數據量實在太大怎么辦呢?總不能無限調大tmp_table_size
吧?但也不能眼睜睜看着數據先放到內存臨時表,隨着數據插入發現到達上限,再轉成磁盤臨時表吧?這樣就有點不智能啦。
因此,如果預估數據量比較大,我們使用SQL_BIG_RESULT
這個提示直接用磁盤臨時表。MySQl優化器發現,磁盤臨時表是B+樹存儲,存儲效率不如數組來得高。因此會直接用數組來存
示例SQl如下:
select SQL_BIG_RESULT city ,count(*) as num from staff group by city;
復制代碼
執行計划的Extra
字段可以看到,執行沒有再使用臨時表,而是只有排序
執行流程如下:
- 初始化 sort_buffer,放入city字段;
- 掃描表staff,依次取出city的值,存入 sort_buffer 中;
- 掃描完成后,對 sort_buffer的city字段做排序
- 排序完成后,就得到了一個有序數組。
- 根據有序數組,統計每個值出現的次數。
6. 一個生產慢SQL如何優化
最近遇到個生產慢SQL,跟group by相關的,給大家看下怎么優化哈。
表結構如下:
CREATE TABLE `staff` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
`id_card` varchar(20) NOT NULL COMMENT '身份證號碼',
`name` varchar(64) NOT NULL COMMENT '姓名',
`status` varchar(64) NOT NULL COMMENT 'Y-已激活 I-初始化 D-已刪除 R-審核中',
`age` int(4) NOT NULL COMMENT '年齡',
`city` varchar(64) NOT NULL COMMENT '城市',
`enterprise_no` varchar(64) NOT NULL COMMENT '企業號',
`legal_cert_no` varchar(64) NOT NULL COMMENT '法人號碼',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='員工表';
復制代碼
查詢的SQL是這樣的:
select * from t1 where status = #{status} group by #{legal_cert_no}
作者:撿田螺的小男孩
鏈接:https://juejin.cn/post/7053966777088213005
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。