记一次 DISTINCT 导致的 SQL 效率问题
来源 | blog.csdn.net/ol950919/article/details/108052642
问题描述 :distinct的使用可能导致SQL的性能下降,也可能是distinct和group by一起使用的原因
场景 :查询有多个组织的人员数据,人员在a表有多个组织,所以查询出来是多行记录
数据量: a表65W+数据,b表54W+数据,c表54W+数据,d表4W+数据,e表8000+数据
下图SQL会显示多行数据,然后再用distinct去重
select distinct a.ORG_CODE,d.DEPT_NAME,b.PROVINCE_LOGIN_NAME,c.STAFF_CODE,c.STAFF_NAME,e.DICT_DISPLAY POSITION_LEVEL
from ua_staff_in_position a,ua_account b,ua_organization d,ua_staff c
left join ua_dict_data e on e.dict_type='POSITION_LEVEL' and e.DICT_VALUE=c.POSITION_LEVEL
where a.STAFF_CODE=b.STAFF_CODE
and a.STAFF_CODE=c.STAFF_CODE
and d.ORG_CODE=a.ORG_CODE
and a.SET_ID_DEPT='Cm013'
可以看到索引的级别都是ref的,还不错,查询速度很快(execution: 253 ms, fetching: 88 ms)
后来需求需要多个组织在一行显示,于是对SQL做了修改,想到可以用 group_concat 函数来实现之
select distinct a.ORG_CODE,group_concat(d.DEPT_NAME) as DEPT_NAME,b.PROVINCE_LOGIN_NAME,c.STAFF_CODE,c.STAFF_NAME,e.DICT_DISPLAY POSITION_LEVEL
from ua_staff_in_position a,ua_account b,ua_organization d,ua_staff c
left join ua_dict_data e on e.dict_type='POSITION_LEVEL' and e.DICT_VALUE=c.POSITION_LEVEL
where a.STAFF_CODE=b.STAFF_CODE
and a.STAFF_CODE=c.STAFF_CODE
and d.ORG_CODE=a.ORG_CODE
and a.SET_ID_DEPT='Cm013'
group by a.STAFF_CODE
加了个函数并没有影响到索引级别,还是ref的
执行之,发现dataGrip一直在转圈圈,结果一直都出不来
执行了大概十分钟还没有出来结果,我取消了,那肯定不能忍受
于是把distinct去掉试试,可能distinct和group by的功能重合了,去掉之后
500 rows retrieved starting from 1 in 657 ms (execution: 552 ms, fetching: 105 ms)
select a.ORG_CODE,group_concat(d.DEPT_NAME) as DEPT_NAME,b.PROVINCE_LOGIN_NAME,c.STAFF_CODE,c.STAFF_NAME,e.DICT_DISPLAY POSITION_LEVEL
from ua_staff_in_position a,ua_account b,ua_organization d,ua_staff c
left join ua_dict_data e on e.dict_type='POSITION_LEVEL' and e.DICT_VALUE=c.POSITION_LEVEL
where a.STAFF_CODE=b.STAFF_CODE
and a.STAFF_CODE=c.STAFF_CODE
and d.ORG_CODE=a.ORG_CODE
and a.SET_ID_DEPT='Cm013'
group by a.STAFF_CODE;
果然,sql执行立马恢复正常
问题是解决了,但是并没有找到相关的资料,解释问题产生的原因,大部分文章是比较distinct和group by的性能,也有说distinct是一个 双重循环 ,然后比较去重的过程,所以导致性能比较差,所以能用group by就尽量用group by吧
说到这里,先给大家放上一个链接:
1、(Mysql5.7官方手册中提及到的关于优化distinct的方法)
https://dev.mysql.com/doc/refman/5.7/en/distinct-optimization.html2、还有一个优化group by的:
https://dev.mysql.com/doc/refman/5.7/en/group-by-optimization.html
推荐大家阅读。
Mysql5.7官方手册中提及到的关于优化distinct的方法,原文如下:
MySQL 5.7 Reference Manual / … / DISTINCT Optimization
8.2.1.16 DISTINCT Optimization
DISTINCT combined with ORDER BY needs a temporary table in many cases.】
推荐阅读:
不是你需要中台,而是一名合格的架构师(附各大厂中台建设PPT)