暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【知识拓展】数据库检核规则系列(一)-高并发调用的SQL语句不得走索引跳跃扫描(INDEX SKIP SCAN)

非功能之路 2021-06-10
3335



请输入标题     bcdef

在数据库开发设计规范中常能见到这条规则“高并发调用的SQL语句不得走INDEX SKIP SCAN”,在笔者的测试工作中,也将这条规则列入了数据库检核范围,那么什么是索引跳跃扫描呢?这种索引扫描方式是在什么情况下发生的呢?数据库检核时是如何检测到INDEX SKIP SCAN,如果发现了INDEX SKIP SCAN,该关注些什么呢?笔者带着这些疑问学习了索引跳跃扫描的相关知识,并在此分享给大家!

请输入标题     abcdefg

请入标题     abcd

索引扫描类型



Oracle提供了五种索引扫描类型,根据具体索引类型、数据分布、约束条件以及where限制的不同进行选择

1.索引唯一扫描(INDEX UNIQUE SCAN)
2.索引范围扫描(INDEX RANGE SCAN)

3.索引全扫描(INDEX FULL SCAN)
4.索引跳跃扫描(INDEX SKIP SCAN)
5.索引快速全扫描(INDEX FAST FULL SCAN)

本文将重点学习索引跳跃扫描(INDEX SKIP SCAN)的相关知识。

索引跳跃扫描


Index Skip Scan是Oracle 9i之后提供的新功能,适用于所有类型的复合B树索引,包括唯一性索引和非唯一性索引。“跳跃”一词的含义是,即使在where语句的查询条件中不存在索引的前导列,也可以使用该索引。例如,假设表employee上存在一个B树索引为IDX1(gender,id),其中gender为前导列,执行SQL语句select * from employee where id = 1时,虽然查询条件中没有gender,但这条语句仍可能通过访问索引IDX1来访问数据

那么在什么情况下会发生Index Skip Scan呢?主要前提条件如下:

1)优化器模式为CBO,即对每个SQL语句,计算分析表和索引的统计信息,选取成本最小的执行计划;

2)复合索引,且索引的前导列distinct值较少,前导列的值的选择性较低;

3)where语句查询条件中不存在索引前导列。


当where语句查询条件中不包含索引前导列时,Oracle会遍历获取索引前导列的所有distinct值,每一个distinct值都会作为查询入口之一,再合并所有入口的查询结果,得到不含前导列的查询结果。即跳跃扫描本质上是根据前导列的distinct值数目将复合索引分成多个较小的逻辑子索引,引导列的distinct值数目越小,分割的子索引数目也就越少,就越可能达到较高的运算效率,如果distinct值数目较多,则可能直接执行全表扫描。


例如上文中的SQL语句select * from employee where id = 1,假设gender包含m和f两个取值,则这条语句在进行Skip Scan时,实际使用的语句相当于:

Select * from employee where  gender = ‘f’ and id = 1

Union all

Select * from employee where  gender = ‘m’ and id = 1

如图1所示,可以理解为访问的是(m,id)和(f,id)这两个逻辑子索引,直接定位到数据块1和数据块3中。


图1 数据访问示例

若查看执行计划,如图2所示,可以看到执行计划中包含“INDEX SKIP SCAN”字样。

图2 执行计划示例


如果Oracle没有使用索引跳跃式扫描的话,可以通过提示INDEX_SS来强制使用,语句如下:

select XX  /*+ INDEX_SS(表名 索引名) */  from XX where XX


在定期对数据库进行检核时,可通过读取DBA_HIST_SQL_PLAN表,获取其中options字段为“%SKIP%”的记录,并且通过表DBA_USERS排除系统用户的记录,如 “SYS”、“SYSMAN” 、“SYSTEM”、“PATROL”、“MDSYS”、“OLAPSYS”、“EXFSYS”等,得到应用用户的问题SQL记录。


Index Skip Scan没有直接索引查询快,但相比于全表扫描,索引跳跃扫描的速度还是相对较快的。并且,若一个索引可以满足两个查询条件的使用,比单独建立两个索引节约了空间和维护成本。

Index Skip Scan是Oracle的新特性,对于使用复合索引数据库的应用程序意义重大。但在测试过程中,若遇到索引跳跃扫描,尤其当响应时间较长时,需要仔细分析,使用索引跳跃扫描是否真的更好。根据索引特性,索引列的选择性越高则索引的效果越好,因此一般在建多列索引的时候,也都把选择性高的列放到前面,这样可以极大的提高索引访问的效率,如性别这种区分度很低的列,经常要放在后面,因此如果使用了跳跃扫描,若无其他因素考虑,则可能是索引建立不够合理。并且,Oracle在判断是否进行跳跃扫描时,并没有考虑第二索引列,如果第二个索引列的区分度很高,建立直接查询索引往往是一种更高效的访问方式。在高并发情况下,更要慎用索引跳跃扫描,并发越多,逻辑子索引越多,效率将会大大下降,此时建立多个直接查询索引是很必要的。因此,需要结合业务特性、数据特点及语句执行情况分析索引跳跃扫描方式的合理性和正确性


结束语


本文介绍了INDEX SKIP SCAN的含义、原理以及如何检测,并分析使用INDEX SKIP SCAN时可能存在的问题,建议在测试时遇到索引跳跃扫描的SQL语句,结合业务特性、数据特点及语句执行情况分析索引扫描方式的合理性和正确性。


-----------------------------------------------------

非功能之路

公众号ID:nfttest_mp

长按二维码关注我们

一起来涨姿势吧~













文章转载自非功能之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论