文章目录
- 1、count效率比较
- 2、作者遇到的慢sql问题
-
- 2.1、使用排序导致变慢问题
- [2.2、使用LEFT JOIN 导致索引失效的问题](#2.2、使用LEFT JOIN 导致索引失效的问题)
- 2.3、子查询导致索引失效
- 3、explain命令介绍
- 4、阿里云rds数据库(mysql的一种)主键索引查询很慢问题
- 参考文档
1、count效率比较
- 所以结论是:按照效率排序的话,count(字段)<count(主键 id)<count(1)=count(*)
- 所以我建议你,尽量使用 count(*)或count(1)。
2、作者遇到的慢sql问题
2.1、使用排序导致变慢问题
-
表的数据大概为100万条
-
问题原因:使用create_time字段排序,但是create_time字段没有增加索引导致速度变慢
-
原执行速度 2.6秒
sql#导致原因 order by create_time
-
解决方式给字段create_time 增加一个索引,执行速度从2秒变成0.031
sqlalter table 'system_log' add index 'idx_create_time'
2.2、使用LEFT JOIN 导致索引失效的问题
-
小表sys_user(用户表)
-
大表system_log (系统日志表),默认system_log.create_time 已经创建了普通索引
-
问题原因:索引在大表上,使用left join导致大表的索引失效
-
原执行速度2.6秒
sql#导致原因 from sys_user left join system_log on sys_user.id=system_log.user_id order by system_log.create_time
-
解决办法一:使用 inner join,执行速度0.031秒
sqlfrom sys_user inner join system_log on sys_user.id=system_log.user_id order by system_log.create_time
-
解决办法二:使用大表驱动小表,执行速度0.033秒
sqlfrom system_log left join sys_user on sys_user.id=system_log.user_id order by system_log.create_time
2.3、子查询导致索引失效
-
rds数据库(mysql的一种),recode_table表记录数5亿,org_table表记录数4万
-
原执行速度超时(60秒以上)
sqlSELECT cu.org_no as orgNo, org.org_short_name as orgName, round(sum(qty) /10000, 2) as aValue, cast(round((sum(qty) -sum(qty_corrprd)) / sum(qty_corrprd) *100, 2) as decimal(22, 2)) as cValue FROM `org_table` org left join recode_table cu on cu.org_no= org.org_no and cu.time_period= '01' and cu.ind_cls in ('0101', '0202', '0303') and cu.stat_date between '20240801' and '20240810' where org.prnt_org_no= '11101' group by org.org_no, org.org_name, org.org_short_name
sql#等价于 SELECT cu.org_no as orgNo, org.org_short_name as orgName, round(sum(qty) /10000, 2) as aValue, cast(round((sum(qty) -sum(qty_corrprd)) / sum(qty_corrprd) *100, 2) as decimal(22, 2)) as cValue from org_table org left join( select cu.org_no, qty, qty_corrprd from recode_table cu where cu.time_period= '01' and cu.ind_cls in('0101', '0202', '0303') and cu.stat_date between '20240801' and '20240810' ) cu on cu.org_no= org.org_no where org.prnt_org_no= '11101' group by org.org_no, org.org_name, org.org_short_name
-
解决方式一:把条件都放到where中,执行速度2.5s
sql#搜索的结果会有略微差异,org_table关联不上的结果会消失 SELECT cu.org_no as orgNo, org.org_short_name as orgName, round(sum(qty) /10000, 2) as aValue, cast(round((sum(qty) -sum(qty_corrprd)) / sum(qty_corrprd) *100, 2) as decimal(22, 2)) as cValue FROM `org_table` org join recode_table cu on cu.org_no= org.org_no where cu.time_period= '01' and cu.ind_cls in('0101', '0202', '0303') and cu.stat_date between '20240801' and '20240810' and org.prnt_org_no= '11101' group by org.org_no, org.org_name, org.org_short_name
-
解决方式二:把条件都放到where中,同时外层再重复关联org_table表执行速度2.5s
sql#多嵌套了一层非常难看,但是可以解决org_table关联结果不丢失的问题 select org.org_no as orgNo, org.org_short_name as orgName, a.aValue as aValue, a.cValue as cValue FROM org_table org left join ( SELECT cu.org_no as orgNo, org.org_short_name as orgName, round(sum(qty) /10000, 2) as aValue, cast(round((sum(qty) -sum(qty_corrprd)) / sum(qty_corrprd) *100, 2) as decimal(22, 2)) as cValue FROM `org_table` org inner join recode_table cu on cu.org_no= org.org_no where cu.time_period= '01' and cu.ind_cls in ('0101', '0202', '0303') and cu.stat_date between '20240801' and '20240810' and org.prnt_org_no= '11101' group by org.org_no, org.org_name, org.org_short_name ) as a on a.orgNo= org.org_no where org.prnt_org_no= '11101'
-
解决方法三:使用union 强制让子查询走索引,执行速度0.2s
sqlSELECT cu.org_no as orgNo, org.org_short_name as orgName, round(sum(qty) /10000, 2) as aValue, cast(round((sum(qty) -sum(qty_corrprd)) / sum(qty_corrprd) *100, 2) as decimal(22, 2)) as cValue from org_table org left join( select cu.org_no, qty, qty_corrprd from recode_table cu where cu.time_period= '01' and cu.ind_cls in('0101', '0202', '0303') and cu.stat_date between '20240801' and '20240810' union select null,null,null ) cu on cu.org_no= org.org_no where org.prnt_org_no= '11101' group by org.org_no, org.org_name, org.org_short_name
3、explain命令介绍
-
explain命令可以查看执行计划,在你需要执行的sql语句前面加explain即可
-
filtered越小代表索引的优化效果越好,定位到需要的记录速度越快
-
例如
sqlexplain select * from `order` where code='002';
-
执行计划包含列的含义
4、阿里云rds数据库(mysql的一种)主键索引查询很慢问题
- where的查询条件也在索引上,但是单表查询的速度非常慢
- 解决方式:添加多个单字段索引,原本主键字段为date、org_code、type,建3个索引,每个索引对应一个字段
- 原速度10s,加完之后0.05s
- 为什么添加单字段索引会变快,这个问题作者也没想通