group by 优化临时表
2015-11-11 16:39
363 查看
GROUP BY 优化之临时表
MySQL 在进行 GROUP BY 操作时要想利用索引,必须满足 GROUP BY 的字段同时存放于同一个索引中,且该索引是一个有序索引(如 Hash 索引就不能满足要求)。不仅如此,是否能够利用索引来实现 GROUP BY 还与使用的聚合函数有关系。前面两种 GROUP BY 的实现方式都是在有可以利用的索引时使用的,当 MySQL Query Optimizer无法找到可以利用的合适索引时,就不得不先读取需要的数据,然后通过临时表来完成 GROUP BY 操作,如示例代码8-27所示:
代码8-27
sky@localhost : example 09:02:40> EXPLAIN -> SELECT max(gmt_create) -> FROM group_message -> WHERE group_id > 1 and group_id < 10 -> GROUP BY user_id\G
*************************** 1. row ***************************
id: 1 select_type: SIMPLE table: group_message type: range possible_keys: idx_group_message_gid_uid,idx_gid_uid_gc key: idx_gid_uid_gc key_len: 4 ref: NULL rows: 32 Extra: Using where; Using index; Using temporary; Using filesort
这次的执行计划非常明显地告诉了我们 MySQL 通过索引找到了所需的数据,然后创建了临时表,又进行了排序操作,才得到所需的 GROUP BY 结果。整个执行过程大概如图8-9所示:
![]() |
(点击查看大图)图8-9 |
本示例是这样的情况。group_id 并不是一个常量条件,而是一个范围,而且 GROUP BY 字段为 user_id。所以 MySQL 无法根据索引的顺序来帮助 GROUP BY 的实现,只能先通过索引范围扫描得到需要的数据,将数据存入临时表,然后再进行排序和分组操作来完成 GROUP BY。
对于上面三种 MySQL 处理 GROUP BY 的方式,可以针对性地得出如下两种优化思路:
(1)尽可能让 MySQL利用索引来完成 GROUP BY 操作,当然最好是松散索引扫描的方式。在系统允许的情况下,可以通过调整索引或调整 Query 这两种方式来达到目的;
(2)当无法使用索引完成 GROUP BY时,由于要使用到临时表且需要 filesort,所以必须要有足够的 sort_buffer_size供 MySQL排序时使用,而且尽量不要进行大结果集的 GROUP BY 操作,因为如果超出系统设置的临时表大小就会出现将临时表数据复制(copy)到磁盘上面再进行操作的情况,这时的排序分组操作性能将成数量级的下降。
至于如何利用好这两种思路,还须要大家在实际应用场景中不断地尝试并测试效果,才能最终得到较佳方案。此外,在优化 GROUP BY时还有一个小技巧可以让我们在有些无法利用到索引的情况下避免 filesort 操作,即在整个语句最后添加一个以 null 排序(ORDER BY null)的子句,大家可以尝试一下看会有什么效果。
相关文章推荐
- jboss完全可以独立运行 servlet jsp ssh mybits spring mvc
- 又是一年光棍节,程序员的痛你懂得!
- HTTP Content-type 对照表
- Android 自定义字体
- Android开源项目(类库+控件)
- ubuntu15.10下搭建cordova+ionic开发环境
- sql导出导入大全
- APP设计师拿到APP产品原型开始,七步搞定APP设计(转)
- 限制文本框只能输入正数,负数,小数
- HDU 5527 Too Rich
- Verilog的信号强度学习
- 公司项目用到Dubbo框架 分享一下自己的测试结果
- c#中MD5的加密解密
- 第四章 Controller接口控制器详解 (4)——跟着开涛学SpringMVC
- 字符编码附属乱码篇
- mysql存储过程入门
- PLSQL循序渐进全面学习教程(全)
- verilog驱动强度解析
- git命令行
- SQL 基本语言使用