Mysql与Ooracle 索引失效场景对比

MySQL 和 Oracle 作为主流关系型数据库,其索引失效的场景既有共性,也因底层优化器、索引类型支持等差异存在不同。以下从常见索引失效场景对比两者的表现及原因:

一、索引列上使用函数 / 表达式

  • 共性 :若直接在索引列上使用函数或表达式(如SUBSTR(name, 1, 3)age + 1),优化器通常无法利用索引,导致失效。

    • 例:WHERE SUBSTR(name, 1, 3) = 'abc'name为索引列),两者均可能失效。
  • 差异

    • MySQL :在 8.0 版本前不支持 "函数索引",此类场景必然失效;8.0 后支持函数索引(需显式创建,如CREATE INDEX idx_func ON t (SUBSTR(name, 1, 3))),创建后可避免失效。
    • Oracle :原生支持 "函数索引"(如CREATE INDEX idx_func ON t (SUBSTR(name, 1, 3))),若查询中的函数与索引定义一致,可正常使用索引,否则失效。

二、OR 连接的条件中存在无索引列

  • 共性 :若OR连接的多个条件中,存在某列未建索引,优化器可能放弃使用索引(因需同时扫描索引和非索引列,效率可能低于全表扫描)。

  • 差异

    • MySQL :对OR的处理较严格。即使OR两边的列都有索引,也可能因优化器判断成本较高而失效(尤其当索引选择性低时)。例如:WHERE age = 20 OR name = 'abc'(两列均有索引),可能仍走全表扫描。
    • Oracle :优化器对OR的兼容性更好。若OR两边的列均有索引,通常会使用索引合并(Index Merge)策略,避免全表扫描。

三、否定操作符(!=、<>、NOT IN、IS NOT NULL)

  • 共性:此类操作符可能导致索引失效,因优化器认为扫描范围较大,全表扫描更高效。

  • 差异

    • MySQL!=NOT INIS NOT NULL几乎必然导致索引失效(仅当索引列值分布极不均匀时可能例外)。例如:WHERE age != 20age有索引),通常走全表扫描。
    • Oracle :处理更灵活。若索引列值稀疏(如大部分为NULL,查询IS NOT NULL),或NOT IN的范围极小,可能仍使用索引(但效率较低)。

四、隐式类型转换

  • 共性 :当索引列类型与查询条件值类型不匹配时,数据库会自动进行类型转换(如字符串列name用数字123查询),导致索引失效。
    • 例:WHERE name = 123nameVARCHAR类型),两者均会失效(因转换为WHERE CAST(name AS UNSIGNED) = 123,等价于函数操作)。

五、模糊查询(LIKE)

  • 共性 :以%开头的模糊查询(如LIKE '%abc'),索引通常失效(因无法通过索引前缀定位);以常量开头的查询(如LIKE 'abc%'),可能使用索引。

  • 差异

    • MySQLLIKE 'abc%'仅当索引列是字符串类型且无其他复杂条件时,才会使用索引;若结合其他条件(如AND age > 20),可能失效。
    • OracleLIKE 'abc%'对 B 树索引的支持更稳定,即使结合其他简单条件,也更可能使用索引(优化器对范围扫描的判断更灵活)。

六、联合索引违反 "最左前缀原则"

  • 共性 :联合索引(如(a, b, c))需满足 "最左前缀"(查询条件包含a,或a + b,或a + b + c),否则失效。

    • 例:联合索引(a, b),查询WHERE b = 10,两者均失效。
  • 差异

    • MySQL :若联合索引中左侧列有 "范围查询"(如a > 10),则右侧列的索引失效(如WHERE a > 10 AND b = 20,仅a的索引有效,b失效)。
    • Oracle :优化器可能对范围查询后的列进行 "跳跃扫描"(Index Skip Scan),尤其当左侧列的基数(不同值数量)较小时(如a只有 2 个值),即使a用范围查询,b仍可能使用索引。

七、数据量极小或索引选择性低

  • 共性:当表数据量极小(如 <1000 行),或索引列选择性极低(如性别列,只有 "男 / 女"),优化器会认为全表扫描比索引扫描更快,主动忽略索引。

  • 差异

    • MySQL:对 "小表" 的判断更激进,即使表有几万行,若索引选择性低(如重复值占比 > 50%),也可能放弃索引。
    • Oracle:优化器对索引选择性的判断更精细,会结合统计信息(如直方图)评估成本,选择性略低时仍可能使用索引。

总结:核心差异点

场景 MySQL 特点 Oracle 特点
函数索引支持 8.0 后支持,需显式创建 原生支持,可直接适配查询中的函数
OR 条件处理 严格,易失效,索引合并较少 灵活,索引合并较常见
否定操作符 几乎必然失效 部分场景(如稀疏数据)可能使用索引
联合索引范围查询 范围后列索引失效 可能支持跳跃扫描,范围后列仍可用索引

实际开发中,需结合数据库类型、版本及执行计划(EXPLAIN/EXPLAIN PLAN)判断索引是否生效,避免依赖经验主义。

相关推荐
Jasonakeke3 分钟前
【重学 MySQL】九十三、MySQL的字符集的修改与底层原理详解
数据库·mysql·adb
麦兜*16 分钟前
MongoDB 聚合管道(Aggregation)高级用法:数据统计与分析
java·数据库·后端·mongodb·springboot·springcloud
老友@1 小时前
MySQL 索引失效全解析与优化指南
数据库·mysql·索引失效·索引
共享家95272 小时前
MySQL-事务(下)-MySQL事务隔离级别与MVCC
数据库·mysql
秋难降3 小时前
零基础学习SQL(十)——性能分析
数据库·sql·mysql
cooldream20093 小时前
centos7中MySQL 5.7.32 到 5.7.44 升级指南:基于官方二进制包的原地替换式升级
数据库·mysql
风清再凯4 小时前
【一】Django框架版本介绍
数据库·django·sqlite
Aczone284 小时前
Linux 软件编程(十四)网络编程:数据存储与 SQLite 数据库
linux·数据库·sqlite
百锦再5 小时前
SQLSugar 封装原理详解:从架构到核心模块的底层实现
sql·mysql·sqlserver·架构·core·sqlsugar·net
亲爱的非洲野猪5 小时前
时序数据库的 LSM 树介绍
数据库·时序数据库