当前位置: 首页 > news >正文

MySQL的OR条件查询不走索引及解决方案

今天这篇文章我们来简单介绍一下MySQL的OR条件查询,以及它可能会引发的索引失效(即不走索引)的场景以及解决方案。方便大家在实践中,留意是否正确使用了OR条件查询。

MySQL的OR条件查询简介

在 MySQL 中,OR 条件查询是一种利用 OR 逻辑操作符在 WHERE 子句中连接多个条件的查询方式。当查询中使用 OR 操作符时,只要其中任何一个条件满足就会返回对应的数据行。它是一种常见的逻辑运算,用于实现灵活的数据筛选。

OR条件查询经常用于:多字段查询、联合范围查询、动态筛选等场景。

多字段查询示例:

SELECT * FROM users 
WHERE name = 'Alice' OR city = 'Chicago';

联合范围查询示例:

SELECT * FROM users
WHERE age < 30 OR age > 35;

动态筛选示例:

SELECT * FROM orders
WHERE status = 'pending' OR status = 'processing';

其中,在多字段查询的场景下,需要特别留意是否会出现不走索引的情况,下面我们来详细介绍一下这种情况及解决方案。

不走索引案例分析

如果查询条件中包含 OR 操作符,通常情况下,即使其中一个条件是基于索引的,MySQL 也可能不会使用该索引,转而执行全表扫描(Table Scan)。

原因:MySQL 查询优化器无法高效地利用索引来处理 OR 条件,尤其是在多个条件中一个或多个字段没有索引的情况下。

推荐操作:尽量避免使用 OR,可以通过 UNION ALLUNION 来重构查询逻辑,从而强制使用索引。

案例分析

假设有一个表 example_table,结构如下:

CREATE TABLE example_table (id INT NOT NULL,                  -- 有索引字段name VARCHAR(100),                -- 没有索引字段age INT,                          -- 有索引字段PRIMARY KEY (id),                 -- 主键索引INDEX index_age (age)             -- 辅助索引
);

插入一些测试数据:

INSERT INTO example_table (id, name, age) VALUES 
(1, 'Alice', 30),
(2, 'Bob', 25),
(3, 'Charlie', 35),
(4, 'Dave', 40);
使用 OR 条件的查询:
mysql> EXPLAIN SELECT * FROM example_table  WHERE id = 1 OR name = 'Alice' \G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: example_tablepartitions: NULLtype: ALL
possible_keys: PRIMARYkey: NULLkey_len: NULLref: NULLrows: 4filtered: 43.75Extra: Using where
分析:
  • id = 1 是主键查询,本应该使用索引 PRIMARY
  • 但是,由于包含 OR 条件 name = 'Alice',而 name 列没有索引,MySQL 的优化器选择了不使用索引而执行全表扫描。
  • 最终结果:查询执行了全表扫描 (type: ALL)。

解决方案

方法 1:使用 UNION 替代 OR

将原查询拆分,并通过 UNION 分别处理有索引和无索引的条件,从而强制使用索引:

mysql> EXPLAIN SELECT * FROM example_table WHERE id = 1-> UNION ALL-> SELECT * FROM example_table WHERE name = 'Alice' \G
*************************** 1. row ***************************id: 1select_type: PRIMARYtable: example_tablepartitions: NULLtype: const
possible_keys: PRIMARYkey: PRIMARYkey_len: 4ref: constrows: 1filtered: 100.00Extra: NULL
*************************** 2. row ***************************id: 2select_type: UNIONtable: example_tablepartitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 4filtered: 25.00Extra: Using where

通过执行计划可以看出,对于第一部分查询使用了索引,对于第二部分查询使用全表扫描,因为name字段无索引。虽然仍有一部分未使用索引,但数据量较大的情况下,这种分拆方式对性能更优。

方法 2:添加索引优化

如果查询中经常根据 name 条件筛选数据,可以考虑为 name 列添加索引:

mysql> ALTER TABLE example_table ADD INDEX index_name (name);mysql> explain SELECT * FROM example_table WHERE id = 1 OR name = 'Alice' \G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: example_tablepartitions: NULLtype: index_merge
possible_keys: PRIMARY,index_namekey: PRIMARY,index_namekey_len: 4,403ref: NULLrows: 2filtered: 100.00Extra: Using union(PRIMARY,index_name); Using where

针对name列添加索引之后,MySQL 使用了 index_merge 查询优化策略,结合主键索引和辅助索引 index_name。数据量较大的时候,这种方式可以显著加速查询,避免全表扫描。

总结规则

第一、一般规则:

  • 查询条件使用 OR 且部分字段没有索引时,MySQL 很可能会选择执行全表扫描,而不是使用索引。
  • MySQL 的查询优化器在处理 OR 时效率较差。

第二、优化建议:

  • 尽量避免使用 OR,使用 UNION ALLUNION 替代。
  • 根据查询条件频率,合理为字段创建索引。
  • 如果数据复杂,可以通过改写查询逻辑,分拆条件使得索引能被充分使用。

第三、特别注意:

  • OR 可能导致索引失效的情况对于大数据量的表尤为关键,因为全表扫描的性能代价在数据量增加时会严重影响查询速度。
http://www.dtcms.com/a/456673.html

相关文章:

  • 1688 店铺商品全量采集与智能分析:从接口调用到供应链数据挖掘
  • 淘宝商品详情采集方式,json数据返回
  • 【论文精度-1】 组合优化中的机器学习:方法论之旅(Yoshua Bengio, 2021)
  • 南京维露斯网站建设微信营销软件app
  • 从帧边界识别到数据编码:嵌入式通信协议与数据序列化方案深度对比
  • Quick SwiftObjective-C测试框架入门教程
  • GRM tools三大插件使用教程
  • C62-结构体的指针
  • 腾讯云 建网站企业网站seo公司
  • Java-143 深入浅出 MongoDB NoSQL:MongoDB、Redis、HBase、Neo4j应用场景与对比
  • 线程1——javaEE 附面题
  • 吴恩达机器学习课程(PyTorch适配)学习笔记:1.4 模型评估与问题解决
  • 后端_基于注解实现的请求限流
  • 从 0 到 1 搭建 Python 语言 Web UI自动化测试学习系列 10--基础知识 6--元素等待方式和内联框架
  • 织梦网站如何做seo重庆市城市建设档案馆官方网站
  • 一文详解Go语言字符串
  • 通用:MySQL-LBCC并发锁机制
  • Elasticsearch:使用推理端点及语义搜索演示
  • 基于websocket的多用户网页五子棋(九)
  • Async++ 源码分析13--parallel_reduce.h
  • 分布式api调用时间优化和问题排查
  • LeetCode每日一题,20251008
  • h5网站建设的具体内容电子商务平台网站模板
  • hive sql优化基础
  • Linux小课堂: Linux 系统的多面性与 CentOS 下载指南
  • 详解redis,MySQL,mongodb以及各自使用场景
  • 开发网站设计公司建设通网站会员共享密码
  • Linux相关工具vim/gcc/g++/gdb/cgdb的使用详解
  • Verilog和FPGA的自学笔记2——点亮LED
  • uniapp创建ts项目tsconfig.json报错的问题