再谈Oracle统计信息

1. 何为Oracle统计信息

ORACLE数据库里的统计信息是这样的一组数据:它存储在数据字典里,且从多个维度描述了ORACLE数据库里对象的详细信息。

2. 收集统计信息的方法与区别

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| ANALYZE | DBMS_STATS |
| 可用于索引、表、列、数据字典统计信息 | 可用于索引、表、列、数据字典统计信息 |
| 无法收集系统表统计信息,如xbh: SQL\> analyze table xbh compute statistics; analyze table xbh compute statistics \* ERROR at line 1: ORA-02030: can only select from fixed tables/views | 可用于收集**系统表**统计信息: SQL\> exec dbms_stats.gather_table_stats('SYS','XBH'); PL/SQL procedure successfully completed. |
| 不能准确的收集分区表的统计信息:如对于有子分区的分区表,会先收集子分区的统计信息然后再汇总、推导出分区和表级的统计信息,但有的统计信息能从下一级对象推导,如表的行数,而有的不行,如num_distinct、density等 | 可以准确的收集分区表的统计信息 |
| 不能并行收集统计信息 | 可以并行收集统计信息 |
| 可以用来分析和收集如行迁移、行链接的数量,分析索引的结构 | 只能收集与CBO相关的统计信息,而与CBO无关的额外信息则无法收集 |

3. 表统计信息

上图的红框用于描述表的详细统计信息,包含了记录数、表块(表里的数据块)的数量、平均行长度等典型

的纬度。这些纬度信息都存储在数据字典基表TAB、TABPART、TABSUBPART$等中,可以通过数据字典

DBA_TABLES、DBA_TAB_PARTITIONS、DBA_TAB_SUBPARTITIONS来分别查看表、分区表的分区和分区表的子分区

的统计信息。

4. 索引统计信息

ORACLE数据库中,如果要 降低目标B树索引的层级 ,可以通过 rebuild该索引的 方式来实现。

5. 聚簇因子

聚簇因子是基于索引的值去比较表中行的顺序,如果聚簇因子的值接近与块的数量(4),说明表的顺序是良好的,这种情况下,一个叶块的索引项通常指向的是同一个数据块中的行。

如果聚簇因子的值接近与行的值(20),说明的表的顺序是不好的,这种情况下,同一个叶块的索引项可能没有指向同一个数据块。

通过order by id 重建的话,使 id (按照索引的键值顺序)按照顺序的插入表中,降低目标聚簇因子的值,

但是会增加这张表上其他索引聚簇因子

6. 列统计信息

7. 谓词越界

如果对目标列指定的where查询条件不在该列的最大值(high_value)与最小值(low_value)之间,CBO就无法

判断出针对该列的查询条件的可选择率,所以只能用一个估算值来作为针对该目标列的查询条件的可选择率。

没有使用 index range scan, index range scan是单块读,index fast full scan是多块读(效率更高)

继续插入数据:(不收集它的统计信息)

执行计划选择了单块读的index range scan ,并且 Rows和Bytes是1和4 ,对于查询10000条数据,这里的估值存在了很大的偏差

对test表重新收集的统计信息,再次的查看执行计划,执行计划是正确的了。

对CBO而言,他会默认的认为目标列的数据在其最小值(low_value)和最大值(high_value)之间是均匀分布的,并且按照均匀分布的原则来计算

对目标列施加查询条件以后的可选择率以及结果集,进而计算成本并选择执行计划,但是目标列数据均匀分部的这个原则,并不是永远正确的,因为在实际中,目标列的数据分布是不均匀的,甚至是极度倾斜,那根据这样的计算的成本和执行计划都可能是不合理的,甚至是错误的,这时候oracle引入了直方图。

8. 直方图

直方图是一种按数据出现的频率来进行分类存储的方法.在oracle中直方图是用来描述表中列数据的分布情况。

数据分布极不均衡而导致CBO选错执行计划的例子:

T1

1有10000条,2有1条,并且创建索引,以不收集直方图的方式(columns size 1),进行索引的统计信息收集

执行了b=2 的语句:

为了解决上面的问题,oracle引入了直方图,详细的描述了列的数据分布情况。

oracle 只对用过的列收集直方图统计信息,(也就是在where条件中出现过的列)

ENDPOINT_NUMBER用来记录Bucket号,从0号开始一直到N。其中0号Bucket里存储的是目标列的最小值;

ENDPOINT_VALUE实际上存放的是到此记录所描述的Buckets为止,之前所有Bucket描述的记录里目标列的最大值。

除了0号Bucket之外,其他所有记录的ENDPOINT_VALUE值都是用如下公式来计算的:

//目标表总记录数为M,需要使用的Bucket 数量为N

//每个Bucket里所存放的记录数为O,O = M/N

select max(目标列) from (select 目标列 from 表 order by 目标列) where rownum <= O; //1号桶

select max(目标列) from (select 目标列 from 表 order by 目标列) where rownum <= O*2; //2号桶

select max(目标列) from (select 目标列 from 表 order by 目标列) where rownum <= O*3; //3号桶

...

select max(目标列) from (select 目标列 from 表 order by 目标列) where rownum <= O*(N-1); //N-1号桶

select max(目标列) from (select 目标列 from 表 order by 目标列) where rownum <= O*N; //N号桶

ENDPOINT_NUMBER中没有2号,是因为数据字典中把ENDPOINT_NUMBER不同而ENDPOINT_VALUE相同的,进行合并。

3和5被忽略了

显然Top Frequency直方图他的计算更加精确,

对于distinct 超过254 且倾斜数据占据表中大量行的情况下,显然12c中的Top Frequency直方图估算的row更加准确。

在12c中oracle这样推混合直方图(Hybird Histogram)和Top Frequency直方图,其实都是相应的弥补了高平衡直方图的不足的地方

oracle是怎么产生这四种的直方图的条件:

NDV>n distince values大于桶数

Frequency Histogram 频率直方图

Height-Balanaced Histogram 高平衡直方图

Hybird Histogram 混合直方图

Top Frequency 高频率直方图

一文搞懂 Oracle 统计信息

• 直方图类型

• Frequency ---- 列的NDV<=254

• Top-frequency----列的NDV>254 但是高频的254个列值占总行数比例大于100-100/n

• Hybrid Histogram ---列的NDV>254 但是高频的254个列值占总行数比例小于100-100/n

• Height-balanced---如果使用了AUTO_SAMPLE_SIZE将不再创建这个类型的直方图

--转载于恩墨大课堂

相关推荐
倔强的石头_12 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou642 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤3 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区4 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1774 天前
《从零搭建NestJS项目》
数据库·typescript
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏4 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再4 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest4 天前
数据库SQL学习
数据库·sql