当使用索引时,查找数据流程
–索引查找流程: 索引提供 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 结构索引,位图索引结构特殊,情况有些特别
–对于非常小的表(比如只有几个数据块),全表扫描几乎总是最优的,即使查询只返回一行(所以对于数据量很少的表(小几百行的数据),完全没有必要建索引)。
815

被折叠的 条评论
为什么被折叠?



