为什么索引查询返回的结果过多时,索引会失效

当使用索引时,查找数据流程
–索引查找流程: 索引提供 ROWID -> 根据 ROWID 定位数据块 -> 访问数据块(一次随机的I/O读取)。
–数据块:最常见且默认的大小是 8KB (8192 bytes),会读取整个数据块到内存
–I/O指数据库从磁盘中读取数据到内存

全表扫描
–按顺序依次I/O读取所有数据块

读取相同的数据块时,随机I/O耗时要高于顺序I/O
select * from emp where salary = 5000
假设数据有100万条
–假如使用索引的话
对于扫描到的每一个索引条目,数据库都要检查其 salary 值是否 = 5000
如果值等于 5000,就收集该条目指向的数据行指针 (ROWID)
收集完所有 “等于5000” 的指针(指向99万行)后,数据库再根据这 99万个指针 去表中随机读取对应的 99万行 数据。
随机I/O:因为每次根据ROWID跳转到不同数据块
成本: 扫描几乎整个索引(访问约99万个索引条目) + 99万次随机I/O(回表读取数据行)。成本极高!

全表扫描
数据库按顺序读取表中的所有数据块(物理上连续的或接近连续的)。
顺序读取存储整个表的所有数据块。虽然数据量大(100万行),但因为是顺序I/O,效率远高于99万次随机I/O。

当覆盖索引时,返回数据量大的时候也会使用索引,因为索引会存储相关列的内容,不用再通过rowid回表去取数据,仅在索引中通过顺序I/O筛查数据即可

优化器的“经验法则”
经验值:当条件匹配 > 表总行数的 5%-30% 时,优化器就会更倾向全表扫描。
低集群因子 (好): 索引键值相邻的行在物理磁盘上也大致相邻存储。回表操作需要访问的数据块数量少(I/O 效率高)。临界点高,可能达到 50%, 70% 甚至更高 比例时,索引扫描成本仍低于 全表扫描。
高集群因子 (差): 索引键值相邻的行在物理磁盘上极度分散存储。回表操作几乎需要访问表中每一个包含目标行的数据块(大量单块 I/O)。临界点极低,可能低至 1%-5% 时,索引扫描的成本就已远超 全表扫描。这是最常见导致“少量数据返回也走全表扫”的原因。

Oracle优化器的工作原理-它不需要实际扫描索引就能预判成本,根据预先收集的相关信息

  • 表的总行数(num_rows)
  • 索引的选择性(distinct_keys)
  • 聚簇因子(clustering_factor)
  • 数据块数量(blocks)
  • 系统I/O特性
    优化器不需要扫描索引就能判断跟背后的 Oracle 统计信息(Statistics) 和 直方图(Histogram) 有关

–上面仅适用于 B-Tree 结构索引,位图索引结构特殊,情况有些特别
–对于非常小的表(比如只有几个数据块),全表扫描几乎总是最优的,即使查询只返回一行(所以对于数据量很少的表(小几百行的数据),完全没有必要建索引)。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值