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

 更新时间:2025年10月09日 09:45:34   作者:程序新视界  
今天这篇文章我们来简单介绍一下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: 1
  select_type: SIMPLE
        table: example_table
   partitions: NULL
         type: ALL
possible_keys: PRIMARY
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4
     filtered: 43.75
        Extra: 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: 1
  select_type: PRIMARY
        table: example_table
   partitions: NULL
         type: const
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 2
  select_type: UNION
        table: example_table
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 4
     filtered: 25.00
        Extra: 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: 1
  select_type: SIMPLE
        table: example_table
   partitions: NULL
         type: index_merge
possible_keys: PRIMARY,index_name
          key: PRIMARY,index_name
      key_len: 4,403
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using union(PRIMARY,index_name); Using where

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

总结规则

第一、一般规则:

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

第二、优化建议:

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

第三、特别注意:

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

到此这篇关于MySQL的OR条件查询不走索引及解决方案的文章就介绍到这了,更多相关MySQL OR条件查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Mysql中文数据变成问号的解决办法

    Mysql中文数据变成问号的解决办法

    mysql存进去的数据,有中文的字段变成了???的样式,所以本文给大家详细介绍了Mysql中文数据变成问号的解决办法,文中通过图文结合的方式讲解的非常详细,需要的朋友可以参考下
    2023-12-12
  • MySQL系列之十一 日志记录

    MySQL系列之十一 日志记录

    这篇文章主要介绍了MySQL日志文件详解,本文分别讲解了错误日志、二进制日志、通用查询日志、慢查询日志、Innodb的在线redo日志、更新日志等日志类型和作用介绍,需要的朋友可以参考下
    2021-07-07
  • MySQL文件权限存在的安全问题和解决方案

    MySQL文件权限存在的安全问题和解决方案

    MySQL文件权限是用来控制用户对数据库文件以及目录的操作权限,在MySQL中,这些权限通常由系统管理员分配,通过GRANT和REVOKE语句进行管理,本文给大家介绍了MySQL文件权限存在的安全问题和解决方案,需要的朋友可以参考下
    2024-07-07
  • MySQL分表自增ID问题的解决方法

    MySQL分表自增ID问题的解决方法

    这篇文章主要为大家详细介绍了MySQL分表自增ID问题的解决方法,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • mysql性能优化之索引优化

    mysql性能优化之索引优化

    我们首先讨论索引,因为它是加快查询的最重要的工具。当然还有其他加快查询的技术,但是最有效的莫过于恰当地使用索引了。下面我们就来介绍索引是什么、它怎样改善查询性能、索引在什么情况下可能会降低性能,以及怎样为表选择索引。
    2015-12-12
  • MySQL数据库的多表操作

    MySQL数据库的多表操作

    这篇文章主要介绍了MySQL数据库的多表操作,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-08-08
  • MySQL外键约束常见操作方法示例【查看、添加、修改、删除】

    MySQL外键约束常见操作方法示例【查看、添加、修改、删除】

    这篇文章主要介绍了MySQL外键约束常见操作方法,结合实例形式分析了mysql针对外键约束的查看、添加、修改、删除等相关操作实现方法,需要的朋友可以参考下
    2018-05-05
  • MySQL SELECT数据查看WHERE(AND OR IN NOT)语句

    MySQL SELECT数据查看WHERE(AND OR IN NOT)语句

    这篇文章主要介绍了MySQL SELECT数据查看WHERE(AND OR IN NOT)de 语句学习,非常适合新手小白朋友,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 全面详解MySQL单行函数分析

    全面详解MySQL单行函数分析

    MySQL常见的函数分为单行函数和分组函数,单行函数包含字符函数、数学函数、日期函数、流程控制函数等,下面就详细的来介绍一下MySQL单行函数
    2023-10-10
  • Ubuntu上mysql的安装及使用(通用版)

    Ubuntu上mysql的安装及使用(通用版)

    今天小编就为大家分享一篇关于Ubuntu上mysql的安装及使用(通用版),小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论