oracle临时表经常被锁_实验验证:Oracle聚簇因子对索引使用的影响

【引言】
本文基于如下文章进行的实验,讲述聚簇因子对SQL索引的影响。

链接如下:
https://www.modb.pro/db/40283

一张表上有索引,sql在执行的时候却不走索引的原因有很多,一张表上的聚簇因子是影响CBO判断索引是否能被使用的一个重要判断依据。

索引范围扫描的成本计算公式如下:
cost = {(blevel+leaf_blocks * effective index selectivity)*(1-optimizer_index_caching/100)+(cluster_factor * effective table selectivity)*(optimizer_index_cost_adj/100)

这两个参数在oracle 10gR2之后建议保持默认值,从上面成本计算公式可看出这两个参数是如何影响成本计算的;还有一个参数在一定程度上也能决定索引的优先程度:db_file_multiblock_read_count。

先来了解下什么是聚簇因子。

聚簇因子(clustering factor)和索引高度(blevel)、叶块数(leaf_blocks)等统计信息值一样用于计算cost的值,以决定当前sql语句是走索引还是走全表扫描。

堆表中数据的存储方式为无序存储,
也就是任意的DML操作都可能使得当前数据块存在可用的空闲空间,出于节省空间的考虑,块上的可用空闲空间会被新插入的行填充,而不是按顺序填充到最后被使用的块上。

以上的操作也就导致了数据块中数据的无序性,而创建索引的时候,会将指定的列按顺序插入索引块中。正是因为表上的数据是无序的,索引上的数据是有序的,这种差异性就可以用聚簇因子来表示。

接下来看看索引聚簇因子(clustering factor)对于索引的使用是如何影响的,通过实验演示一下clustering factor对索引选择的影响。

测试数据准备

create tablespace tbs0831 datafile '/u01/app/oracle/oradata/ces/tbs0831.dbf' size 10M autoextend off;

create user test0831 identified by test0831 default tablespace tbs0831;

grant dba to test0831;

conn test0831/test0831

create table tb0831 (id1 number ,id2 number);

begin
for i in 1..100
loop
for j in 1..100
loop
insert into tb0831 values(i,j);
end loop;
end loop;
end;
/
create index idx_1 on tb0831(id1);
create index idx_2 on tb0831(id2);

==--搜集统计信息,注意加cascade=>true,表示对索引也搜集统计信息==
exec dbms_stats.gather_table_stats(user,'TB0831',cascade=>true);

从上面插入数据的脚本可看出,id1的值存储的更加紧凑,id2的值存储的更加松散。

SQL> select INDEX_NAME,NUM_ROWS,DISTINCT_KEYS,CLUSTERING_FACTOR,BLEVEL,LEAF_BLOCKS from dba_indexes where table_name='TB0831';

INDEX_NAME NUM_ROWS DISTINCT_KEYS CLUSTERING_FACTOR BLEVEL LEAF_BLOCKS
------------------------------------------------------------------------------------------ ---------- ------------- ----------------- ---------- -----------
IDX_1 10000 100 22 1 20
IDX_2 10000 100 1600 1 20

先执行如下sql:

explain plan for select * from tb0831 where id1=50;
select * from table(dbms_xplan.display);

0e9bc4e3c32f29fadfde621bbfd7faef.png

将id1换成id2再执行下面的sql:

explain plan for select * from tb0831 where id2=50;

select * from table(dbms_xplan.display);

2f951891b8b43693fd8784988ed6ae94.png

正是索引IDX_2的聚簇因子为1600,太大了,导致cbo在评估执行计划的时候,计算出全表扫描的cost要小于走索引idx_t02的cost。所以在有索引的情况下,cbo选择了走全表扫描。

如在一些场景下,ORACLE可能不会自动走索引,如果对业务清晰,可以尝试使用强制索引,测试查询语句的性能。
针对如下SQL进行index绑定:
select * from tb0831 where id2=50;

重写sql:

SQL> explain plan for select /*+index(TB0831,idx_2)*/ * from tb0831 where id2=50;

Explained.

SQL> select * from table(dbms_xplan.display);

1d7338da0c9350391c717111232e4000.png

上述案例,可看出聚簇因子值的大小对于是否走索引产生的影响。

如有一个索引他的聚簇因子很大,该如何优化呢?

  1. 重建索引并不能改变聚簇因子的大小,因索引是有序的,而导致聚簇因子值大的根本原因在于表上存储的数据太无序,以至于和索引中存储的顺序相差甚远。一个可行方案为定期表重构,将数据先临时存储在中间表中,truncate原始表,然后按照索引存储的顺序填充数据到原始表中。

  2. 尽可能的避免一个具有槽糕clustering factor值的索引,比如索引在创建的时候,应考虑按照经常频繁读取的大范围数据的读取顺序来创建索引。

文章至此。d8b2824be7538a09ef30f3a5c438fe5b.gif

欢迎关注个人微信公众号“一森咖记”

c7da8f27b17c87ba8827995cdc25c966.png

   

近期热文

你可能也会对以下话题感兴趣。点击链接便可查看。

  • 为什么不建议把数据库部署在docker容器内?

  • oracle异常恢复(一)dul和bbed的使用

  • Oracle Cloud云端账号的注册过程

  • MySQL基本知识点梳理和查询优化

  • 区块链上的数据库:CovenantSQL

  • MySQL数据延迟跳动的问题分析

  • MySQL 5.6和 5.7_同步账号修改密码方式:真的不一样

  • MySQL8.0 为嘛弃用Query Cache?

  • 你应该知道的分布式系统之奠基石CAP理论

  • MySQL数据延迟跳动的问题分析

  • 如何判断一个应用系统性能好不好?

  • MySQL Document Store 混合使用关系型数据与非关系型数据

  • 分布式一致性算法:Paxos算法学习

  • MySQL 中你不得不知的重要知识点

  • 神技_如何快捷下载Oracle补丁的方法?!

  • 趋势篇:oracle 11g,12c,18c,19c之support lifetime

  • Centos能不能替换RHEL?

  • Centos能不能替换RHEL?

  • 年末总结_聊一聊数据库行业的“继往开来”

  • 【干货篇】在国内外数据库百家争鸣的时代,DBA们该何去何从?

  • 实操:12C RAC环境下的ADG同步库搭建

  • 浅谈MySQL三种锁:全局锁、表锁和行锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值