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)判断索引是否生效,避免依赖经验主义。

相关推荐
Hx__26 分钟前
Redis对象编码
数据库·redis·缓存
运维帮手大橙子2 小时前
完整的登陆学生管理系统(配置数据库)
java·前端·数据库·eclipse·intellij-idea
0wioiw02 小时前
Redis(④-消息队列削峰)
数据库·redis·缓存
beijingliushao3 小时前
32-Hive SQL DML语法之查询数据
数据库·hive·sql
JIngJaneIL3 小时前
专利服务系统平台|个人专利服务系统|基于java和小程序的专利服务系统设计与实现(源码+数据库+文档)
java·数据库·小程序·论文·毕设·专利服务系统平台
__风__3 小时前
windows 上编译PostgreSQL
数据库·postgresql
木木子99994 小时前
数据库范式
数据库
涛思数据(TDengine)4 小时前
通过最严时序标准,再登产业图谱榜首,TDengine 时序数据库在可信数据库大会荣获双荣誉
大数据·数据库·时序数据库·tdengine·涛思数据
涛思数据(TDengine)4 小时前
新客户 | TDengine 时序数据库是怎么在钢厂“撬动”PI 的?
大数据·运维·数据库·时序数据库·tdengine