MySQL中WHERE后跟着N多个OR条件会怎样...

SQL自学:组合WHERE子句以建立功能更强、更高级的搜索条件 在 SQL 查询的WHERE子句中,AND,表示时,才会选中相应的记录。假设有一个员工表,包含字段员工姓名(employee_name)、工资(salary)和职位(position)。 阅读详情
  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
  • 作者:叶金荣
  • 文章来源:社区原创

可能会执行非常慢,线上生产环境千万别写出这种SQL ...

背景交代

用 tpcc-mysql 工具生成 50个仓库 的测试数据,表 order_line 共有 37970973 条记录。

某工具在运行过程中,会产生下面的SQL进行查询,WHERE后跟了N多个条件:

mysql> select * from order_line where 
   (ol_w_id = '1' and ol_d_id = '1' and ol_o_id = '2221' and ol_number = '5') 
or (ol_w_id = '1' and ol_d_id = '1' and ol_o_id = '2225' and ol_number = '1')
or (ol_w_id = '1' and ol_d_id = '1' and ol_o_id = '2155' and ol_number = '2')
...

这里说的N多个,是指总共有10000个OR条件,这条SQL的长度大概将近800KB。

这条SQL在我的测试服务器上,运行了约56秒(另一个性能略差的机器上跑了1800秒左右才完成),共扫描75563行记录,返回8192行结果:

# Query_time: 56.031955  Lock_time: 0.047795 Rows_sent: 8129  Rows_examined: 75563 ... Read_first: 0 Read_last: 0 Read_key: 1 Read_next: 75563 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 ...
...
#   InnoDB_pages_distinct: 501
...
select * from order_line where ...

相当于只做了1次索引范围查询,但总共要扫描7.5万条数据。

问题分析

只需要扫描 7.5万行记录,501个page,返回8192行结果,正常情况下不应该需要这么久才对,肯定是哪里有问题。

再次手动执行这条SQL,发现的确是这么慢,并且在最后还有个 warnings 提醒,查看下是啥内容:

mysql> show warnings\G
...
  Level: Warning
   Code: 3170
Message: Memory capacity of 8388608 bytes for 'range_optimizer_max_mem_size' exceeded. Range optimization was not done for this query.

第一次见到这种告警,先检查MySQL手册,看看 range_optimizer_max_mem_size 这个选项是干嘛用的:

文档出处:https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_range_optimizer_max_mem_size

The limit on memory consumption for the range optimizer. A value of 0 means “no limit.” 
If an execution plan considered by the optimizer uses the range access method but 
the optimizer estimates that the amount of memory needed for this method would 
exceed the limit, it abandons the plan and considers other plans. For more 
information, see Limiting Memory Use for Range Optimization.

这个选项是从MySQL 5.7.9开始引入的,用于控制当优化器采用范围(RANGE)查询优化方案时使用的内存消耗限制。

其默认值为8MB(5.7.12及以上版本),当设置为0时,表示不做任何限制。当WHERE查询条件里有很多OR、AND组成时,优化器判断超过内存消耗限制,则会调整SQL执行计划,变成其他执行方案,甚至可能是全表扫描。

这也就是为什么执行上面的大SQL后,MySQL会有这样的告警提示了。

经过几次简单尝试,把 range_optimizer_max_mem_size 选项值调大到 24MB 后,这个SQL就可以正常执行,并且运行速度很快:

# Query_time: 6.721209  Lock_time: 0.044637 Rows_sent: 8129  Rows_examined: 8129 Read_first: 0 Read_last: 0 Read_key: 10000 Read_next: 0 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0 ...
...
#   InnoDB_pages_distinct: 81

注意到几个变化:

  • 耗时从56秒降到6.7秒;
  • 扫描行数从7.5万行降到8192行(返回结果数不变);
  • Read_key从1增加到10000;
  • Read_next从75563降到0;
  • 扫描的page数从501降到81。

相当于做了1万次索引列等值条件查询。

查询效率提升非常显著。

进一步优化

线上生产环境中,各式各样的SQL层出不穷,这次可能是一万条OR条件,下次可能是其他的,是不能无限度增加数据库内存消耗的。

针对本案中的SQL,更好的优化办法是找出这些OR条件的范围规律,并改写成一条更简单的SQL,类似下面这样:

mysql> select * from order_line where
ol_w_id = 1 and ol_d_id = 1 and (ol_o_id between 2007 and 2997) 
and (ol_number between 1 and 15 );

新的SQL执行代价:

# Query_time: 0.006338  Lock_time: 0.000084 Rows_sent: 9883  Rows_examined: 9883...Read_first: 0 Read_last: 0 Read_key: 1 Read_next: 9883 Read_prev: 0 Read_rnd: 0 Read_rnd_next: 0...
...
#   InnoDB_pages_distinct: 81

相当于只做了1次索引范围查询,且只需扫描9883条记录。

相比上面调高内存上限的优化方案,本次的做法则更为彻底,耗时从6.7秒直接降为6.3毫秒,提升了1000倍;扫描行数、次数和page数也下降了很多。

不过要注意的是,改写后的SQL查询结果和原来并不是完全一致的,实际应用中,可能还要再做进一步筛选或者增加 LIMIT N 来控制。

最后再次提醒,WHERE条件后跟着N多个OR/AND条件的写法非常不可取,尤其是在用一些开发框架构造查询SQL时,尤其要注意规避这个问题,否则可能造成严重性能问题。

延伸阅读


Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

捉虫活动详情:https://greatsql.cn/thread-97-1-1.html

社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

6440

MySQL - NOT/AND/OR执行顺序 一:SQL语句测试_1 # 创建GBK编码的数据库,然后删除,创建UTF8编码的数据库 CREATE DATABASE mydb_test CHARSET gbk; DROP DATABASE mydb_test; CREATE DATABASE mydb_test CHARSET utf8; # 在mydb_test数据库中创建一张学生表 USE MYDB_TEST; CREATE TABLE student( stu_id INT, stu_name VARCHAR(255) )· CHARSET 阅读详情

相关推荐

数据中心——Vxlan基本概念1

东西流量指的就是横向流量-------例如:服务器与服务器之间交换流量南北流量指的就是纵向流量-------例如:客户端和服务器之间的流量以下主要是讲解业务平面的网络架构(一般业务平面就需要用到专用的数据中心交换机)

m0_49864110的博客 1万+

mysql sql where or_SQL -------- WHERE子句与AND,OR和NOT运算符结合使用。

AND, OR and NOT 与运算符中的且或非的意思相同WHERE子句可以与AND,OR和NOT运算符结合使用。and 表示 查询的语句必须全部包含and连接的两个或多个条件or 表示 查询的语句包含or连接条件中的其中一个not 表示 查询的语句中不包含not连接的条件表中数据:使用AND进行查询语法:select * from 表名 where 表中字段...

weixin_29056101的博客 5899

从12摄像头到纯视觉:小鹏AI鹰眼方案如何用LOFIC技术省掉激光雷达?

本文深入解析小鹏汽车AI鹰眼方案如何通过LOFIC技术实现纯视觉自动驾驶,替代传统激光雷达。LOFIC摄像头在动态范围、噪声控制和HDR优化方面表现卓越,结合800万像素双目广角摄像头,达到激光雷达级测距精度。该方案不仅降低成本,还提升系统可靠性和用户体验,展示了纯视觉路线的技术潜力与边界。

t8u9v0w1x的博客 934

MySQL基础---SQL语句2(WHERE、AND、OR、ORDER BY、COUNT)

WHERE、AND、OR、ORDER BY、COUNT

Anorry的博客 1969

DAZ STUDIO 快速渲染技巧

DAZ STUDIO 快速渲染技巧: 本文将向您展示几个快速渲染技巧。您将学习如何使您的Daz Iray渲染和照明在Daz工作室内更快。 当你有一个大场景,这可能需要很多小时进行渲染。 但是如果你想大幅度降低渲染时间呢?这篇文章的提示应该能让你达到这个目标。 首先,我们需要弄清楚一件事——没有“完美的环境或设置”这样的东西。是因为渲染设置是高度个性化和主观性的东西,这主要取决于场景和硬件。如果你有一个功能强大的计算机,你可以允许更多的低渲染时间,反之亦然。因此,一切都取决于您尝试渲染的对象和机器。

DAZSTUDIO的博客 9647

软解调详解

在这个示例中,生成了一个随机的比特序列,将其调制为QPSK信号,添加了高斯白噪声,然后计算了每个比特的LLR,并根据LLR的符号进行了解调判决。软解调是一种基于接收信号的概率估计进行解调的方法。与传统的硬解调相比,软解调不仅考虑了接收信号的幅度和相位信息,还利用统计特性计算每个比特为0或1的概率,从而提高了解调性能。软解调过程中涉及的主要公式包括对数似然比(LLR)的计算公式、信号的概率分布函数以及解调判决公式等。软解调的计算处理流程包括信号接收、预处理、相位估计、LLR计算、解调判决和输出等步骤。

ahah12345678的博客 1226

MySQL语句之or/and

1 在where中可以包含任意数目的and和or操作副

stypace的专栏 4万+

注册GitHub时出现Unable to verify your captcha response.Please visit https://docs.github.com/解决方案(持续更新)

本文主要介绍了注册GitHub时出现Unable to verify your captcha response. Please visit https://docs.github.com/articles/troubleshooting-connectivity-problems/#troubleshooting-the-captcha for troubleshooting information.解决方案,希望能对学习使用GitHub的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 8万+

MySQL中WHERE后跟着N多个OR条件会怎样。。。

可能会执行非常慢,线上生产环境千万别写出这种SQL ...背景交代用 tpcc-mysql 工具生成50个仓库 的测试数据,表order_line 共有 37970973 条记录。某工具在运行过程中,会产生下面的SQL进行查询,WHERE后跟了N多个条件:mysql>select*fromorder_linewhere (ol_w_id='1'andol_d_i...

老叶茶馆 1211

Codex 100个真实案例 - 用AI绘制CAD机械图纸(工程师看了直呼内行)

本案例将展示如何用 Codex 生成 Python 脚本,通过 `ezdxf` 库绘制标准 DXF 格式的 CAD 机械图纸。我们会从零开始,逐步实现直线、圆、圆弧、标注等基本图形元素,最终绘制出一张包含主视图、俯视图、尺寸标注、标题栏和技术要求的完整法兰盘零件图。还会演示参数化批量生成不同规格零件图和自动 BOM 物料清单,生成的 DXF 文件可直接在 AutoCAD、FreeCAD 中打开。全程用自然语言驱动 Codex,工程师看完直接上手!

yueyeguzhuo的专栏 2075

如何正确的计算两个角度的角度差?

这一步是必要的,因为它确保了无论a相对于b是在逆时针方向还是顺时针方向,d2总是正确地反映出绕圆相反方向的角度差。这样,当函数进行最后的比较时,它能够准确地比较两个方向的旋转路径并选择最短的一个。

小秋 AI SLAM 入门实战教程 4137

MySQL中WHERE后跟着N多个OR条件会是你期望的结果吗?

当WHERE查询条件里有很多OR、AND组成时,优化器判断超过内存消耗限制,则会调整SQL执行计划,变成其他执行方案,甚至可能是全表扫描。最后再次提醒,WHERE条件后跟着N多个OR/AND条件的写法非常不可取,尤其是在用一些开发框架构造查询SQL时,尤其要注意规避这个问题,否则可能造成严重性能问题。线上生产环境中,各式各样的SQL层出不穷,这次可能是一万条OR条件,下次可能是其他的,是不能无限度增加数据库内存消耗的。这里说的N多个,是指总共有10000个OR条件,这条SQL的长度大概将近800KB。

Free雅轩的博客 681

精通 Android NDK/JNI:从入门到精通实战与面试精粹

在Android开发中,

郑伟强dev的专栏 144

mysql where 子句_MySql——使用where子句过滤数据

参考资料:《Mysql必知必会》1.使用where子句示例如下:查询价格等于10.5的行select * from commodity where price=10.5输出:1 1001 牙刷 10.52.where的操作符上个示例中,我们使用到了‘=’这个操作符,下面列出所有条件操作符where操作符=等于<>不等于!=不等于<小于>大于<=小于等于>=大于等...

weixin_39843151的博客 258

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

MySQL数据库——where

一、 select一般格式 SELECT [DISTINCT] * | {字段名1,字段名2,...} FROM 表名 [WHERE 条件表达式1] [GROUP BY 字段名1[HAVING 条件表达式2 ]] [ORDER BY 字段名 [ASC| DESC ]] 说明: 通配符*代表所有字段 WHERE之后为查询约束条件 GROUP BY 一般和合计函数一同使用,先根据字段名进行分组,...

Zzze0101的博客 809

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

mysql where子句 参数_MySql——使用where子句过滤数据

参考资料:《Mysql必知必会》1.使用where子句示例如下:查询价格等于10.5的行select * from commodity where price=10.5输出:1 1001 牙刷 10.52.where的操作符上个示例中,我们使用到了‘=’这个操作符,下面列出所有条件操作符where操作符=等于<>不等于!=不等于<小于>大于<=小于等于>=大于等...

weixin_30673759的博客 528

MySql——使用where子句过滤数据

示例使用的数据表在上一个博客中创建的https://www.cnblogs.com/lbhym/p/11895968.html 参考资料:《Mysql必知必会》 1.使用where子句 示例如下:查询价格等于10.5的行 select * from commodity where price=10.5 输出: 1 1001 牙刷 10.5 2.where的操作符 上个示例中,我们使用...

耶low的博客 469

【MYSQL】表的综合查询

limit有两个参数,分别是limit 偏移量,取出条目,可以使用在分页上。主要用途:两张不同的表中有相同的列时,把结果集合并,或者简化两个复杂的where条件, 使用条件:两个表的列必须相同,但是例外的是列名称可以不相同。having是针对where条件结果进行筛选,是对内存数据操作,所以having必须用在where之后。使用group时首先会对该列重新排序,再做统计,所以比较耗资源,尽量避免使用。内层select查询的结果充当外层select的where条件的查询。

Robin的博客 1403

mysql查询网址_Mysql查询

Mysql查询语句小结:where(条件查询)、having(筛选)、orderby(排序)、groupby(分组)、limit(限制结果数)一、子句1、where中常用运算符>,,>=,<=in(d1,d2,d3….,dn)betweend1andd2notorandlike%任意字符_单个字符2、groupby正常情况下groupby都是与聚合...

weixin_36150355的博客 321

mysql---select的五种子句学习(where、group by、having、order by、limit)

提示:在写sql语句的时候要注意 RE:这样的子句都是用来筛选行的,而列的筛选则在跟着select的后面。我也可以对列进行运算 field 提示:我们可以使用count(*)和sum(score 1.where  where后跟条件用来筛选我们所需的行。它后面可以跟的操作符有=、!=、、=、 in、 like(可以和通配符%结合一起用,效果将会更好) 、between....and....

continue my dream 1万+

MySQL快速入门指南:从零基础到基本操作

本文为初学者提供MySQL数据库的快速入门指导,涵盖安装配置、基础命令、数据操作等核心内容。通过简明步骤介绍如何创建数据库、表结构,执行增删改查(CRUD)操作,以及常用数据类型和约束的使用。适合希望快速掌握MySQL基础操作的开发人员或数据分析师,无需前置数据库经验。SQL是关系型数据库的标准语言,主要分为:DQL(数据查询,如SELECT)、DML(数据操作,如INSERT/UPDATE/DELETE)、DDL(数据定义,如CREATE/ALTER)、DCL(权限控制,如GRANT)和TCL(事务控制)

m0_53206841的博客 242

mysql range优化_MySQL - RANGE优化篇

RangeAccess使用单个索引的方式来检索包含在一个或多个索引值区间内的表行的子集。它也适用于单列或复合(组合)索引...单列索引对于单列索引,索引值区间可以方便地用WHERE语句中的相应范围条件表示。优化器在常量传播阶段,会将一些非常量值转换为常量。定义对于BTREE索引和HASH索引来说,索引的范围优化基本上只适用于等值查询。譬如=, <=>, IN(), IS NULL, I...

weixin_39805119的博客 322

第二高的薪水 & 第N高的薪水

问题一: 编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。 Employee 表 Id Salary 1 100 2 200 3 300 例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。 查询结果: SecondHighestSalary 200 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/proble

Millionmile的博客 1561

mysql 取所有字段值不为空的个数_MySQL语句大全,每天跟着操作一遍,不信你不懂!...

MySQL服务的配置和使用修改MySQL管理员的口令:mysqladmin –u root password 密码字符串 如:mysqldmin –u root password 111111连接MySQL服务器,使用命令: mysql [-h 主机名或IP地址] [-u 用户名] [-p] 如:mysql –u root –p如已有密码需修改root密码用命令: mysqladmin –u ro...

weixin_31848413的博客 680

别再让你的索引失效了!最常见的MySQL索引失效的场景全概括

列在索引里无序、你加工了索引列、优化器觉得全扫更划算。面试被问到的时候,先讲这三类大框架,再每类举一两个场景。对方就知道你是真的理解了,不是在背题。。

BCSJ666000的博客 379

【MySQL数据库学习】MySQL基本查询(下)

本文深入讲解MySQL中的Update和Delete操作,重点介绍了语法规范与实用技巧。在Update部分,通过修改学生成绩的四个经典案例(单字段更新、多字段更新、条件更新、全表更新),详细演示了SET子句与WHERE条件的配合使用。Delete部分则强调数据安全删除方法,包括单条记录删除、条件删除和全表清空,特别指出执行前先用SELECT验证的重要性。文中配有清晰的SQL示例和操作结果截图,帮助读者掌握数据修改与删除的核心技能,同时培养谨慎操作数据库的习惯。

承于所学,探技术之渊;以代码求政,寻成长之道。 5649
上一篇: 搭建基于lvs+nginx的负载均衡服务集群
下一篇: 图文结合带你搞懂MySQL日志之Error Log(错误日志)
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值