SQL优化 - Group By 导致的慢sql
优化前的慢SQL:3.8s
EXPLAIN SELECTproduct.id AS product_id,product.CODE AS product_code,product.NAME AS product_name,product.remarks AS product_remarks,warnLabel.storage_num_code AS "productStorageWarningLabel.storageNumCode",warnLabel.storage_duration_code AS "productStorageWarningLabel.storageDurationCode",warnLabel.product_retail_price_code AS "productStorageWarningLabel.productRetailPriceCode",sum(STORAGE.total_num ) AS "allStorageTotalNum",sum(STORAGE.total_num ) - sum(entityInfo.canNotUseEntityNum) AS "allStorageCanUseNum",sum(STORAGE.total_price ) AS "allStorageTotalPrice"
FROMtkl_product productLEFT JOIN tkl_product_type productType ON productType.id = product.product_type_idLEFT JOIN tkl_product_brand_series dictBrand ON dictBrand.id = product.dict_brand_idLEFT JOIN tkl_product_brand_series dictSeries ON dictSeries.id = product.dict_series_idLEFT JOIN tkl_product_supplier dictSupplier ON dictSupplier.id = product.dict_supplier_idLEFT JOIN tkl_dict_item dictProperty ON dictProperty.id = product.dict_property_idLEFT JOIN tkl_product_storage STORAGE ON STORAGE.product_id = product.id AND STORAGE.del_flag = 0LEFT JOIN (SELECTe.product_id AS product_id,e.dept_id AS dept_id,count(1 ) AS canNotUseEntityNum FROMtkl_product_entity e WHEREe.team_id = 16 AND e.STATUS = '待出库' AND e.del_flag = 0 GROUP BYproduct_id,dept_id ) entityInfo ON entityInfo.product_id = STORAGE.product_id AND entityInfo.dept_id = STORAGE.dept_idLEFT JOIN tkl_product_storage_warning_label warnLabel ON STORAGE.id = warnLabel.product_storage_id
WHEREproduct.del_flag = 0 AND product.team_id = 16 AND STORAGE.dept_id IN (2131)
GROUP BYproduct.id,product_code,product_remarks
HAVINGsum(STORAGE.total_num ) > 0
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | product | ref | PRIMARY,idx_teamid_delflag,index_team_id | idx_teamid_delflag | 4 | const | 2594 | 10 | Using index condition; Using temporary; Using filesort | |
1 | PRIMARY | productType | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.product_type_id | 1 | 100 | Using index | |
1 | PRIMARY | dictBrand | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_brand_id | 1 | 100 | Using index | |
1 | PRIMARY | dictSeries | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_series_id | 1 | 100 | Using index | |
1 | PRIMARY | dictSupplier | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_supplier_id | 1 | 100 | Using index | |
1 | PRIMARY | dictProperty | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_property_id | 1 | 100 | Using index | |
1 | PRIMARY | STORAGE | ref | index_tkl_product_storage_product_id | index_tkl_product_storage_product_id | 4 | tingkelai.product.id | 134 | 5 | Using where | |
1 | PRIMARY | ref | <auto_key0> | <auto_key0> | 8 | tingkelai.product.id,tingkelai.STORAGE.dept_id | 2 | 100 | |||
1 | PRIMARY | warnLabel | eq_ref | u_product_storage_warning_label | u_product_storage_warning_label | 8 | tingkelai.STORAGE.id | 1 | 100 | Using where | |
2 | DERIVED | e | ref | u_tkl_product_entity,index_tkl_product_entity_status_code,index_tkl_product_entity_teamId_deptId,idx_productid_deptid_status_delflag,idx_code_productid_deptid_teamid_status | index_tkl_product_entity_status_code | 767 | const | 93 | 7.84 | Using index condition; Using where; Using temporary; Using filesort |
优化后的SQL:1.9s
EXPLAIN SELECTproduct.id AS product_id,product.CODE AS product_code,product.NAME AS product_name,product.remarks AS product_remarks,warnLabel.storage_num_code AS "productStorageWarningLabel.storageNumCode",warnLabel.storage_duration_code AS "productStorageWarningLabel.storageDurationCode",warnLabel.product_retail_price_code AS "productStorageWarningLabel.productRetailPriceCode",sum(STORAGE.total_num ) AS "allStorageTotalNum",sum(STORAGE.total_num ) - sum(entityInfo.canNotUseEntityNum) AS "allStorageCanUseNum",sum(STORAGE.total_price ) AS "allStorageTotalPrice"
FROMtkl_product productLEFT JOIN tkl_product_type productType ON productType.id = product.product_type_idLEFT JOIN tkl_product_brand_series dictBrand ON dictBrand.id = product.dict_brand_idLEFT JOIN tkl_product_brand_series dictSeries ON dictSeries.id = product.dict_series_idLEFT JOIN tkl_product_supplier dictSupplier ON dictSupplier.id = product.dict_supplier_idLEFT JOIN tkl_dict_item dictProperty ON dictProperty.id = product.dict_property_idLEFT JOIN tkl_product_storage STORAGE ON STORAGE.product_id = product.id AND STORAGE.del_flag = 0LEFT JOIN (SELECTe.product_id AS product_id,e.dept_id AS dept_id,count(1 ) AS canNotUseEntityNum FROMtkl_product_entity e WHEREe.team_id = 16 AND e.STATUS = '待出库' AND e.del_flag = 0 GROUP BYproduct_id,dept_id ) entityInfo ON entityInfo.product_id = STORAGE.product_id AND entityInfo.dept_id = STORAGE.dept_idLEFT JOIN tkl_product_storage_warning_label warnLabel ON STORAGE.id = warnLabel.product_storage_id
WHEREproduct.del_flag = 0 AND product.team_id = 16 AND STORAGE.dept_id IN (2131)
GROUP BYproduct.id
HAVINGsum(STORAGE.total_num ) > 0
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | PRIMARY | product | index | PRIMARY,idx_teamid_delflag,index_team_id | index_team_id | 4 | 4732 | 5.48 | Using where | ||
1 | PRIMARY | productType | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.product_type_id | 1 | 100 | Using index | |
1 | PRIMARY | dictBrand | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_brand_id | 1 | 100 | Using index | |
1 | PRIMARY | dictSeries | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_series_id | 1 | 100 | Using index | |
1 | PRIMARY | dictSupplier | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_supplier_id | 1 | 100 | Using index | |
1 | PRIMARY | dictProperty | eq_ref | PRIMARY | PRIMARY | 4 | tingkelai.product.dict_property_id | 1 | 100 | Using index | |
1 | PRIMARY | STORAGE | ref | index_tkl_product_storage_product_id | index_tkl_product_storage_product_id | 4 | tingkelai.product.id | 134 | 5 | Using where | |
1 | PRIMARY | ref | <auto_key0> | <auto_key0> | 8 | tingkelai.product.id,tingkelai.STORAGE.dept_id | 2 | 100 | |||
1 | PRIMARY | warnLabel | eq_ref | u_product_storage_warning_label | u_product_storage_warning_label | 8 | tingkelai.STORAGE.id | 1 | 100 | Using where | |
2 | DERIVED | e | ref | u_tkl_product_entity,index_tkl_product_entity_status_code,index_tkl_product_entity_teamId_deptId,idx_productid_deptid_status_delflag,idx_code_productid_deptid_teamid_status | index_tkl_product_entity_status_code | 767 | const | 93 | 7.84 | Using index condition; Using where; Using temporary; Using filesort |
重点区别
优化前
语句
GROUP BY product.id,product_code,product_remarks
EXPLIAN
row | extra |
---|---|
2594 | Using index condition; Using temporary; Using filesort |
优化后
语句
GROUP BY product.id
EXPLIAN
row | extra |
---|---|
4732 | Using where |
之前我写SQL的逻辑是:
SELECT需要用到聚合函数时,非聚合函数的列必须出现在Group By后面!这是个错误的概念!
Group By多个字段逻辑:
例子:group by a,b,c
解释:先按照A字段分组,然后在分组的基础上在按照B字段分一次组,这里避免不了使用临时表和排序,即Using temporary; Using filesort
总结
- rows: 这个数表示mysql要遍历多少数据才能找到,在innodb上是不准确的。(如上述优化例子中明显优化后的row:4732更多,但是查询速度却明显比之前的row:2594更快!)
- extra:执行状态说明,这里如果出现Using temporary,Using filesor就说明sql亟需优化
番外篇
type从最好到最差的连接类型为system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
因此上述sql还可以继续优化,将type:index优化成ref,extra:Using where优化成Using index condition; Using where,1.9s提升到1.8s,有时还是会飙到1.9s,因此效果不是很明显,总而言之,优化主要根据type+row+extra三列的信息综合判断来优化,最终还是以查询效果为主。
参考资料
菜鸟教程-MySql索引优化攻略 (组合索引与前缀索引)
美团-MySQL索引原理及慢查询优化 (最左前缀匹配原则)
SQL优化 - Group By 导致的慢sql相关推荐
- MySQL高级 - SQL优化 - group by 优化
优化group by 语句 由于GROUP BY 实际上也同样会进行排序操作,而且与ORDER BY 相比,GROUP BY 主要只是多了排序之后的分组操作.当然,如果在分组的时候还使用了其他的一些聚 ...
- mysql sql优化_浅谈mysql中sql优化
说到sql优化,一般有几个步骤呢,在网上看到了一篇很不错的帖子.在这分享一下吧,也是自己学习的一个过程. 一.查找慢查询 1.1.查看SQL执行频率 SHOW STATUS LIKE 'Com_%'; ...
- 数据库sql优化总结之5--数据库SQL优化大总结
数据库SQL优化大总结 小编最近几天一直未出新技术点,是因为小编在忙着总结整理数据库的一些优化方案,特此奉上,优化总结较多,建议分段去消化,一口吃不成pang(胖)纸 一.百万级数据库优化方案 1.对 ...
- mysql优化和sql优化一样吗_mysql数据库的sql优化原则和常见误区
gistfile1.txt 优化目标 1.减少 IO 次数 IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作 所占用的,减少 IO 次数 ...
- SQL优化:紧急情况下提高SQL性能竟是这样实现的!(文中有惊喜)
关注我们获得更多精彩 作者 | 黄堋 ,多年一线 Oracle DBA 经验,长期服务电信.电网.医院.政府等行业客户.擅长数据库优化.数据库迁移升级.数据库故障处理. 在某运营商的优化经历中曾经遇到 ...
- mysql sql 优化 博客园_Mysql的SQL优化指北
概述 在一次和技术大佬的聊天中被问到,平时我是怎么做Mysql的优化的?在这个问题上我只回答出了几点,感觉回答的不够完美,所以我打算整理一次SQL的优化问题. 要知道怎么优化首先要知道一条SQL是怎么 ...
- 实战演练:通过伪列、虚拟列实现SQL优化
关注"数据和云",精彩不容错过 本文是技术同仁 蔡亮 在日常工作中通过试验,总结出的一些技巧方案,供大家参考学习.在此,感谢蔡亮的供稿分享,希望大家也可以后续将学习工作中遇到的问题 ...
- 这一篇说明大多数SQL优化的面试问题
一:创建的索引有没有被使用到 MySQL提供了explain命令来查看语句的执行计划. 二:SQL的生命周期 应用服务器与数据库服务器建立一个连接 数据库进程拿到请求sql 解析并生成执行计划,执行 ...
- SQL优化核心思想:或许你不知道的5条优化技巧
点击关注 异步图书,置顶公众号 每天与你分享 IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书. --异步小编 随着系统的数据量逐年增加,并发量也成倍增长,SQL性能越来越成为IT系统 ...
最新文章
- python教程:%s、%d、%f的使用
- Android 用户信息管理程序【SQLite数据库、多选框、单选按钮】
- boost::hana::make_optional用法的测试程序
- MySQL单列索引与复合索引选择
- 定义简单类-接收对象的变量同样是对对象的引用
- gprs连接中断记录_请收好!脉搏波血压计连接天天血压APP使用指南
- 平面设计 前端_我如何在5个月内从平面设计师过渡到前端开发人员
- php oauth 扩展,PHP扩展之Web服务(一)——OAuth
- panzer 电力项目十一--hibernate操作大文本字段Blob和Clob
- oracle建表语句string,编程式Mybatis获取oracle表创建表语句
- BZOJ2957楼房重建
- quartus仿真22:优先编码器74148的级联(详细)
- 普元BPS:唯一零错误的流程平台
- HelloWorld入门程序
- jQuery事件命名空间多事件绑定自定义事件js 命名空间 javascript命名空间
- win7计算机自动关机设置在哪里设置方法,win7怎么设置自动关机【详细步骤】
- 计算机组装与维护过程与方法,计算机组装与维护的实训报告
- 修心三不:不生气不计较不抱怨
- 结巴分词有前空格_jieba英文空格分词问题
- ROS2_Foxy学习1——前言与安装
热门文章
- 安工大2020计算机调剂,2020考研最新调剂信息,安大、安工大、东北林大211等高校调剂信息...
- 先学python还是ros_ROS学习入门(抛砖引玉篇)
- java list 子集_一个List的全部子集
- win7 php7 redis扩展,win7 php5.6 redis扩展
- JNI:本地代码调用Java代码
- USACO Farmer_John收苹果 (dp)
- 《网站分析实战--如何以数据驱动决策,提升网站价值》学习笔记
- 教你如何快速突破TikTok限流--TK领航社tiktok苹果版安卓版下载教程
- windows下SourceTree的安装位置,用于创建快捷方式到桌面
- 云队友丨真正限制你的,是你对潜力的一无所知