开发者

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

目录
  • mysql的OR条件查询简介
  • 不走索引案例分析
    • 案例分析
      • 使用OR条件的查询:
      • 分析:
    • 解决方案
      • 方法 1:使用UNION替代OR
      • 方法 2:添加索www.devze.com引优化
    • 总结规则

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

    MySQL的OR条件查询简介

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

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

    多字段查询示例:

    SELEwww.devze.comChttp://www.devze.comT * 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 查询优化器无法高效地python利用索引来处理 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
    p编程ossible_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条件查询内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)! 

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新数据库

    数据库排行榜