MySQL性能优化(六)优化or条件

俊达3年前技术文章1660

优化器是数据库中非常核心,又非常复杂的一个组件。有的SQL,优化器选择的执行计划并不是最优的,通过改写SQL,可以帮助优化器找到最优的执行计划。

where条件中的or子句,是比较容易出问题的一个场景。

一个例子

SELECT count(1)
FROM car
WHERE is_deleted = 0 AND car_id NOT IN (  
    SELECT car_id FROM product WHERE product_type = 2 AND source = 2)
AND (seller_id = 100 
     OR (creator = 200 AND seller_id = -1))


执行计划

6-1.jpg


上面的SQL中,过滤性好的2个条件seller_id=100和creator = 200使用OR,

分别使用seller_id=100和creator=200过滤数据,再把数据和并起来,比单走seller_id的索引效果好。

mysql支持index_merge的执行计划。但是上面这个例子只用到了seller_id的索引。而seller_id=-1的过滤性差,从执行计划中也可以看到,car表的rows是16万,比较高。


这种情况下,默认的执行计划不够好,我们可以对SQL做一个小小的改造,改成这种形式:

 SELECT sum(a) FROM (
    SELECT count(1) as a FROM car WHERE is_deleted = 0 AND car_id NOT IN ( SELECT car_id  FROM product WHERE product_type = 2 AND source = 2)  
AND (seller_id = 100)    
    union all     
    SELECT count(1) as a FROM car WHERE is_deleted = 0 AND car_id NOT IN (SELECT car_id  FROM product WHERE product_type = 2 AND source = 2)
AND creator = 1000  AND seller_id = -1
) t


查看执行计划:

6-2.png


改写之后,union的2个SQL片段分别使用了2个不同的索引,扫描的行数分别是1238和7130,比改写之前的扫描16万行记录提升了一个数量级。


总结

虽然数据库的优化器非常强大,但是在有的场景下,改写SQL能帮助优化器更好地优化查询语句。也能让执行计划更稳定。



相关文章

PG初识

PG数据库是一种典型的C/S模型应用,不同的客户端通过TCP/IP进行连接、每个连接启动一个fork进程(多进程数据库)。一、pg逻辑架构1.1 pg与MySQL异同对比逻辑架构postgresMyS...

gin框架连接mysql数据库连接池泄露

gin框架连接mysql数据库连接池泄露

1、故障爆发12月1号上午10点出头,我们收到阿里云监控告警:客户官网探测异常,如图所示:然后我们DBA查看了后端数据库实例,发现数据库连接已经被用尽了,导致服务出现异常,如图所示:当时我们和客户协商...

Redis 命令行 redis-cli 介绍

前言redis-cli 是 Redis 自带的命令行工具,是运维和开发人员常用的工具,本篇文章将介绍它的使用技巧和一些有趣的功能。1. 连接 Redis 服务redis-cli 默认连接的是 127....

Ambari集群Spark3.x动态资源分配

Ambari集群Spark3.x动态资源分配

环境节点hdp01HDP3.1.5hdp02Spark3.2.4hdp03首先Spark配置History服务配置spark-defaults.confspark.master            ...

nginx分发算法

nginx分发算法

一、分发算法介绍如何将用户请求按照一定的规律分发给业务服务器。主要分为Nginx集群默认算法和基于请求头分发算法。二、nginx集群默认算法nginx的upstream 目前支持4种方式的分配轮询(默...

Kubernetes网络模型与CNI网络插件

Kubernetes网络模型与CNI网络插件

在 Flannel 的网络插件中,容器跨主机网络的两种实现方法:UDP 和 VXLAN。它们有一个共性,就是用户的容器都连接在 docker0 网桥上。而网络插件则在宿主机上创建了一个特殊的设备(UD...

发表评论    

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