MySQL性能优化(八)exists子查询优化一例

俊达2年前技术文章585


一个例子

SELECT u.id userId,       u.mobile,       u.created_date createdDate 
FROM `user` u
    LEFT JOIN user_cash_detail ucd ON u.id= ucd.user_id
WHERE 1= 1
AND EXISTS( SELECT 1 FROM borrow b WHERE b.user_id= u.id AND b.borrow_no LIKE '202001011212XXX%') 
ORDER BY u.id limit 13

这个查询需要执行120秒,


执行计划:

8-1.png


从执行计划中来看都有这良好的索引,而且需要扫描的rows 也很少,此条SQL性能应该比较好,为什么会执行需要120s 的时间呢?

此时需要了解下exists查询的执行过程:先执行主查询,然后用主查询的结果,检查exists子句中的子查询是否能匹配。

如果主表返回的纪录数比较大,exists 运行的次数就会大,导致整个查询的运行时间长。


在上面这个例子中,exists子查询中有一个b.borrow_no的条件,看起来过滤性比较高,可以尝试对SQL进行改写:

SELECT distinct u.id userId,       u.mobile,       u.created_date createdDate  
FROM borrow b 
join `user` u on b.user_id= u.id 
where b.borrow_no LIKE '202001011212XXX%' order by u.id limit 13


执行计划:

8-2.png


将exists子查询改写为常规的表关联,有几个地方需要注意:

1、原始SQL中并没有使用到user_cash_detail表,可以将left join去掉。

2、Exists 改成join后,由于borrow表user_id不唯一,SQL改写后可能会有重复数据出现,需要添加distinct,


SQL改写后,执行时间从120秒提升到3毫秒。


总结

SQL优化的一个基本思想是尽早过滤尽可能多的数据。这本例中,先执行exists中的子查询可以提前过滤掉大量数据。当然有时候需要对SQL进行一些改写。

相关文章

Hadoop集群小文件合并优化建议指导

Hadoop集群小文件合并优化建议指导

1 综述1.1 综述本指导书旨在指导大数据集群使用者在大数据集群小文件较多的情况下,针对小文件进行优化处理,有效减小集群文件对象数目,减缓namenode所承载的压力,减少mapreduce任务扫描文...

K8s cni0网卡异常

K8s cni0网卡异常

一、问题现象pod启动时,调度到其中某个节点上的pod都无法正常启动,查看启动报错:network: failed to set bridge addr: "cni0" alrea...

阿里云ES跨账号数据迁移(reindex)

阿里云ES跨账号数据迁移(reindex)

1、背景与前置条件总的来说,阿里云es集群间数据迁移,有三中方式,logstash、reindex、镜像备份恢复,分别使用不同的场景,本文档主要讨论reindex方式进行账号下,ES跨集群迁移时,使用...

sparksql集成ranger权限测试

sparksql集成ranger权限测试

##启动thriftserver cd /opt/dtstack/spark/spark_pkg/sbin ./start-thriftserver.sh \ --master yarn \...

Linux_ACL权限、mask值

acl权限在什么情况下使用:当要给一个用户与文件的属主、属组、其他人权限都不同的时候使用。也就是说,这个用户对应于这个文件不属于三个身份中的任何一种,是属于第四种身份,那么我们就需要使用acl权限去给...

kafka节点数规划

按磁盘容量规划节点数Kafka的数据存放在本地磁盘,建议使用SAS盘,提供较高磁盘IO,以提高Kafka吞吐量。在本规划基于的硬件规格下,单节点平均吞吐量参考值为读300MB/s,写150MB/s。数...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。