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

俊达3年前技术文章1596

优化器是数据库中非常核心,又非常复杂的一个组件。有的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能帮助优化器更好地优化查询语句。也能让执行计划更稳定。



相关文章

Helm 控制函数

Helm 控制结构(在模板语言中称为 "actions")提供给你和模板作者控制模板迭代流的能力。 Helm 的模板语言提供了以下控制结构:if/else,用来创建条件语句with,用来指定范围ran...

Redis 源码安装

Redis 源码安装

1. 下载安装包Linux 中常用两种安装方法,第一种是通过操作系统软件管理软件来安装,例如 CentOS 中的 yum Ubuntu 中的 apt。由于 Redis 更新比较快,而这些软件也不一定更...

CDH实操--hive表及分区检查

CDH实操--hive表及分区检查

1)DB数量select count(1) from DBS;2)各DB中的TABLE数量select TBLS.db_id, name, count(1) tab_num from TBLS jo...

PromQL查询解析

一. 概述Prometheus除了存储数据外,还提供了一种强大的功能表达式语言 PromQL,允许用户实时选择和汇聚时间序列数据。表达式的结果可以在浏览器中显示为图形,也可以显示为表格数据,或者由外部...

mysql部署

安装前准备创建用户和目录创建用户:groupadd mysqluseradd -g mysql mysql 创建目录mkdir /data/mysqlmkdir /log/mysql添加环境变量vim...

Mysql删除binlog

binlog 是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。一、手动删除直接在 /var/lib/m...

发表评论    

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