当前位置: 首页 > 科技观察

Oracle中索引位图转换的优点

时间:2023-03-23 11:02:16 科技观察

第一章Oracle索引位图转换介绍1.1索引位图转换首先介绍一下索引位图转换的概念:索引位图转换是对一个或多个目标索引进行布尔运算的优化。Oracle数据库中有一个映射函数(MappingFunction),可以在B树索引中的ROWID和对应位图索引中的位图之间进行转换。目的是对同一个ROWID进行AND、OR等连接操作。当执行计划中出现“BITMAPCONVERSIONFROM/TOROWIDS”和“BITMAPAND”时,表示Oracle对应的索引已经将ROWID转换为位图,然后在转换后的位图上执行BITMAPAND(位图逐位和)布尔运算。最后再次使用映射函数将布尔运算结果转化为ROWID返回表中,得到最终结果。1.2性能分析根据我们以往的经验,映射函数是用来将ROWID转换成位图的。这期间可能会访问多个索引,甚至一个索引可能会被访问??N次。然后执行位图布尔运算。最后将运算结果转换为ROWID返回表。这个过程在实际生产环境中的执行效率往往是有问题的。我们可以通过隐藏参数_b_tree_bitmap_plans来禁止这个过程中ROWID到位图的转换。但实际上,当我们看到“BITMAPCONVERSIONFROM/TOROWIDS”的执行计划时,是否就一定意味着存在性能问题呢?我用一个案例来说明:创建一个测试表结构如下:DROPTABLET1PURGE;创建TABLET1ASSELECT*FROMDBA_OBJECTS;CREATEINDEXIDX_T1_IDONT1(OBJECT_ID);EXECdbms_stats.gather_table_stats(ownname=>'SZT',tabname=>'T1');第二章实验环境测试的实验脚本如下:select*from(select*fromt1WHEREobject_id>88500orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;目的是通过单个索引比较优化器是否进行索引位图转换的执行效率。2.1比较执行效率首先测试默认的执行计划:select*from(select*fromt1WHEREobject_id>88500orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;可以看到,优化器并没有对索引进行Bitmap转换,而是使用了OR扩展的方法。分别访问这两部分查询条件,对IN条件使用IN-LIST迭代的方式获取数据。分析优点:IN条件中的多个值会单独访问并与索引中的数据进行比较,条件中的多个值不会多次访问索引,执行效率高。也可以通过逻辑读部分来判断。通过HINT,尝试让优化器脱离索引位图转换方法:select/*+OUTLINE_LEAF(@"SEL$2")OUTLINE_LEAF(@"SEL$1")BITMAP_TREE(@"SEL$2""T1"@"SEL$2“或(11("T1"."OBJECT_ID")2("T1"."OBJECT_ID")3("T1"."OBJECT_ID")4("T1"."OBJECT_ID")5("T1"。"OBJECT_ID")6("T1"."OBJECT_ID")7("T1"."OBJECT_ID")8("T1"."OBJECT_ID")))*/*from(select*fromt1WHEREobject_id>88500orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;可以看出每次位图访问只得到一个对应的IN条件值,同一个索引访问每次消耗固定的逻辑读,据此分析当前场景下位图索引转换执行效率低下。原因来自索引的多次访问。我们查看对应表的索引信息:可以看出,建立索引的原则是唯一值与表数据1:1的情况。同时,由于使用了OBJECT_ID及其自增长特性,索引的聚簇因子比较小,是一种比较高效的索引。得出聚类因子较小时,OR扩展和IN-LIST迭代的执行效率高于索引位图转换。并且优化器还可以准确评估COST成本。但是在实际生产环境中,大部分索引的聚簇因子并不是那么高效。接下来,我们降低聚类因子的值并进行测试。2.2降低索引的聚簇因子:我们重新创建新表。实验脚本如下:CREATETABLET2ASSELECT*FROMDBA_OBJECTSWHERE1=2;insertintot2select*fromdba_objectsorderbydbms_random.value;--随机插入CREATEINDEXIDX_T2_IDONT1(OBJECT_ID);EXECdbms_stats.gather_table_stats(ownname=>'SZT',tabname=>'T2顺序,降簇factor值。可以看出聚簇因子几乎接近表中的数据行数,索引叶子块也增加了。2.2.1比较执行效率select*from(select*fromt2WHEREobject_id>88500orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;可以看到默认情况下执行计划变成了索引位图转换的形式,分析它的优点:只进行一次回表。优化器通过HINT回到原来的执行计划:select*from(select/*+USE_CONCAT(@"SEL$2"8OR_PREDICATES(1))*/*fromt2WHEREobject_id>88500orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;可见自t表两次返回,聚簇因子大,消耗的逻辑读逐渐接近索引位图转换的方式。并分析表返回的逻辑读:Bitmap格式:返回表134行,消耗147-16=131。OR扩展:返回表128行,消耗130-2=128。对表的逻辑读回非常接近。总结:索引位图转换的好处是减少表返回次数。OR扩展的好处是它的IN-LIST迭代部分消耗的逻辑读更少。分析到这里,我们已经基本理清了不同方式的优缺点,但是对于实际的逻辑读消耗对比,我们还不够确定。让我们增加查询条件的范围。2.2.2增加查询条件范围select*from(select*fromt2WHEREobject_id>88450orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;测试或扩展:select/*+USE_CONCAT(@"SEL$2"8OR_PREDICATES(1))*/*from(select*fromt2WHEREobject_id>88450orobject_idin(1,2,3,4,5,6,7)orderbyobject_id)whererownum<100;可以看出,当查询范围值增大时,两种不同执行计划的实际消耗越来越接近,最终通过索引位图转换的执行效率甚至比原来的OR扩展形式还要高。所以我们在判断执行效率的时候,还是要具体情况具体分析。分析表返回的逻辑读开销:Bitmap格式:返回表172行,消耗180-16=164OR扩展:返回表166行,消耗168-2=166据此,我们可以确定传统的表返回方式是实际资源开销高于索引位图转换后的返回方式。这又是索引位图转换的一大好处。得出聚簇因子越大的索引在索引位图转换方式中获益越大的结论。因为它只需要回表一次。经过索引位图转换后,回表消耗的资源开销会低于传统的回表方式。这也是索引位图转换的优点之一。Chapter3综上所述,我们使用三个测试实例来验证不同场景下的执行计划性能。关于我们一开始的问题,我们可以很清楚的回答。1、索引位图转换与传统OR展开、IN-LIST迭代等形式的执行效率要详细分析。主要受相关索引上聚类因子值的影响。2、索引位图转换的好处是可以一次性回表,通过ROWID回表的成本会比传统形式略低。3.IN-LIST迭代的好处是访问IN后面条件的多个值的实际资源开销比较低。莫天伦原文链接:https://www.modb.pro/db/25952(复制链接到浏览器或点击文末阅读原文)保险业。现负责:公司Oracle、SQLServer、MySQL数据库优化的技术工作;公司SQL审计软件SQM的审计相关工作。热衷于学习和分享性能优化。