项目数据库 MySQL → Oracle,记录一下 Oracle 的常见索引
INDEX RANGE SCAN
一种很常见的表访问方式,适用于所有类型的 B 树索引,结果可能会返回多条记录
使用 Index Range Scan 的情况:
-
在唯一索引列上使用了 Range 操作符(>、<、<>、>=、<=、BETWEEN)
-
在组合索引上,只使用部分列进行查询,导致查询出多行
-
对非唯一索引列上进行的任何查询
INDEX UNIQUE SCAN
Index Unique Scan 和 Index Range Scan 在 B 树上的搜索路径是一样的,只是 Index Unique Scan 在找到应该含有要找的 Index Key 后停止搜索,因为该键唯一,效率最高
INDEX SKIP SCAN
当表中建立有复合索引的时候,除复合索引第一列外别的列作为条件且优化器模式为CBO(Cost-Based Optimization 基于代价的优化器)时,可能会用到 Index Skip Scan
Index Skip Scan 会检测出前导列的唯一值个数,每个唯一值都会作为常规扫描的入口,再次基础上做一次查找,最后将这些查询的结果做 UNION 后返回
举个🌰,PERSON 表如下:
ID | GENDER | NAME |
---|---|---|
1 | 男 | 张三 |
2 | 女 | 李四 |
3 | 男 | 王五 |
创建一个复合索引(SEX, NAME)
SELECT ID, GENDER, NAME FROM PERSON WHERE NAME = '张三'
查询条件 NAME 在复合索引中,但不是第一列,那么会将第一列 GENDER 作为入口,GENDER 在数据库中的值只有两种 ‘男’ OR ‘女’,那么上面的查询会被转换为
SELECT ID, GENDER, NAME FROM PERSON WHERE GENDER = '男' AND NAME = '张三'
UNION
SELECT ID, GENDER, NAME FROM PERSON WHERE GENDER = '女' AND NAME = '张三'
如果入口字段有 N 个值,就会做 N 次查询,UNION 后返回,不同值越少的列,越要放在前面
如果入口的数据集较大,则这个查询效率不高,一般来说:直接索引 > 索引跳跃 > 全表扫描
INDEX FULL SCAN
Index Full Scan 是指要扫描目标索引所有叶子块的所有索引行
- 查询的列有唯一索引,使用 Index Full Scan,
- 查询的列为非唯一索引时,不使用 Index Full Scan,而是使用 Table Access Full
INDEX FAST FULL SCAN
扫描索引中的所有的数据块,与 Index Full Scan 很类似,但是一个显著的区别就是它不对查询出的数据进行排序,即数据不是以排序顺序被返回。在这种存取方法中,可以使用多块读功能,也可以使用并行读入,以便获得最大吞吐量与缩短执行时间。
注意
-
索引需要额外的存储空间和处理,减少不必要索引,定期重构索引
- WHERE 子句中,如果索引列是函数的一部分,启用全表扫描
- 避免在索引列上使用 IS NULL 和 IS NOT NULL
- 对索引列使用 OR 将造成全表扫描,考虑用 UNION 替换 WHERE 子句中的 OR
- <> 将不使用索引,索引只能搜索什么“存在”于表中
- 相同的索引列不能互相比较,否则启用全表扫描