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

俊达3年前技术文章900


一个例子

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进行一些改写。

相关文章

谈谈K8S Pod Eviction 机制

Pod Eviction 简介Pod Eviction 是k8s一个特色功能,它在某些场景下应用,如节点NotReady、Node节点资源不足,把pod驱逐至其它Node节点。从发起模块的角度,pod...

keycloak部署和使用

keycloak部署和使用

简介Keycloak是一个开源软件产品,旨在为现代的应用程序和服务,提供包含身份管理和访问管理功能的单点登录工具。截至2018年3月,红帽公司负责管理这一JBoss社区项目,并将其作为他们RH-SSO...

CDH实操--修改集群主机名

CDH实操--修改集群主机名

1、停止集群2、停止cmsystemctl stop cloudera-scm-serversystemctl stop cloudera-scm-agnet3、修改服务器主机名修改下列配置文件下的主...

Linux命令traceroute—追踪网络路由利器

说明:通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径。当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能...

变更 Rancher Server IP 或域名

变更 Rancher Server IP 或域名

一.背景由于各种原因导致的需要对rancher的Server IP或者域名进行变更(更改访问地址,更改公网IP地址等)二.流程图三.操作前了解相关配置和要求相关官方文档rancher:日常使用的ran...

MySQL运维实战(4.4) SQL_MODE之STRICT_TRANS_TABLES和STRICT_ALL_TABLES

如果设置STRICT模式,则如果数据写入时,如果数据不符合字段定义(字符串超出长度、数值类型数据超出范围、违反not null约束等),SQL会报错。如果不设置STRICT模式,会对异常数据进行截断处...

发表评论    

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