文章整理来源于: 剑破冰山之Oracle开发 http://www.dbform.com/html/2010/1200.html --下面来先关组下ORACLE的预测行对执行计划的影响。 DROP TABLE T PURGE; CREATE TABLE T(ID,COL1,COL2) AS SELECT ROWNUM,CASE WHEN ROWNUM >100 THEN 200 ELSE ROWNUM END,ROWNUM FROM DUAL CONNECT BY LEVEL <=10000; CREATE INDEX T_COL1 ON T(COL1); admin@ORCL> SELECT COUNT(*) FROM T WHERE COL1=200; COUNT(*) ---------- 9900 admin@ORCL> SELECT COUNT(*) FROM T WHERE COL1<>200; COUNT(*) ---------- 100 --收集表统计信息,但不收集直方图(SIZE 1即不收集) admin@ORCL> BEGIN 2 DBMS_STATS.GATHER_TABLE_STATS( 3 'ADMIN', 4 'T', 5 CASCADE=>TRUE, 6 ESTIMATE_PERCENT=>100, 7 METHOD_OPT=>'FOR ALL COLUMNS SIZE 1', 8 NO_INVALIDATE=>FALSE); 9 END; 10 / --查看执行计划,返回的行数实际上应为为9900,而Oracle预估的返回行数为99,导致Oracle认为走索引效率比较高。这是个比较错误的执行计划。 admin@ORCL> SELECT * FROM T WHERE COL1 = 200; 已选择9900行。 执行计划 ---------------------------------------------------------- Plan hash value: 1192298089 -------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99 | 990 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 99 | 990 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | T_COL1 | 99 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("COL1"=200) 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 1363 consistent gets 0 physical reads 0 redo size 212731 bytes sent via SQL*Net to client 7634 bytes received via SQL*Net from client 661 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 9900 rows processed --了解下Oracle在没有收集直方图的情况下,如何计算出COL1 = 200的返回行数 admin@ORCL> SELECT COUNT(DISTINCT COL1) FROM T; COUNT(DISTINCTCOL1) ------------------- 101 admin@ORCL> SELECT COUNT(*) FROM T; COUNT(*) ---------- 10000 --Oracle 会认为COL1每个值都是均匀分布的 admin@ORCL> select round(10000/101) from dual; ROUND(10000/101) ---------------- 99 --全面收集行的直方图 admin@ORCL> BEGIN 2 DBMS_STATS.GATHER_TABLE_STATS( 3 'ADMIN', 4 'T', 5 CASCADE=>TRUE, 6 ESTIMATE_PERCENT=>100, 7 METHOD_OPT=>'FOR ALL COLUMNS SIZE 254', 8 NO_INVALIDATE=>FALSE); 9 END; 10 / --Oracle选择了正确的执行计划:全表扫描,逻辑读也从1363->685 admin@ORCL> SELECT * FROM T WHERE COL1 = 200; 已选择9900行。 执行计划 ---------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 9900 | 99000 | 8 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| T | 9900 | 99000 | 8 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("COL1"=200) 统计信息 ---------------------------------------------------------- 1 recursive calls 0 db block gets 685 consistent gets 0 physical reads 0 redo size 212731 bytes sent via SQL*Net to client 7634 bytes received via SQL*Net from client 661 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 9900 rows processed --我们来仔细研究下Oracle是如何存储列的直方图信息 --直方图的类型有三种 None: 没有直方图 Frequency: 频率直方图 HEIGHT BALANCED: 等高直方图 --当该列的distinct值数量<=bucket数量时,直方图的类型为FREQUENCY,否者为HEIGHT BALANCE admin@ORCL> SELECT COLUMN_NAME,NUM_DISTINCT,NUM_BUCKETS,HISTOGRAM FROM DBA_TAB_COL_STATISTICS WHERE TABLE_NAME = 'T' AND OWNER = 'ADMIN'; COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM -------------------- ------------ ----------- --------------- ID 10000 254 HEIGHT BALANCED COL1 101 101 FREQUENCY COL2 10000 254 HEIGHT BALANCED --col1的直方图类型为Frequency, --在DBA_TAB_HISTOGRAMS视图中,字段endpoint_value就对应字段COL1的值, --而endpoint_number对应字段COL1值的记录条数。注意:这里的记录条数是累加的。 admin@ORCL> SELECT COLUMN_NAME, ENDPOINT_NUMBER, ENDPOINT_VALUE 2 FROM DBA_TAB_HISTOGRAMS 3 WHERE OWNER = 'ADMIN' 4 AND TABLE_NAME = 'T' 5 AND COLUMN_NAME = 'COL1'; COLUMN_NAME ENDPOINT_NUMBER ENDPOINT_VALUE -------------------- --------------- -------------- COL1 1 1 COL1 2 2 COL1 3 3 COL1 4 4 COL1 5 5 COL1 6 6 COL1 7 7 COL1 8 8 COL1 9 9 COL1 10 10 .... .. .. COL1 98 98 COL1 99 99 COL1 100 100 COL1 10000 200 --Frequency直方图的统计方式应该就等同于下面的sql admin@ORCL> SELECT COL1 AS ENDPONT_VALUE,COUNT(*) AS CNT,SUM(COUNT(*)) OVER(ORDER BY COL1) AS ENDPOINT_NUM FROM T GROUP BY COL1 ORDER BY COL1 ENDPONT_VALUE CNT ENDPOINT_NUM ------------- ---------- ------------ 1 1 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1 6 7 1 7 8 1 8 9 1 9 10 1 10 .. . .. 98 1 98 99 1 99 100 1 100 200 9900 10000 已选择101行。 --我们看看直方图类型为HEIGHT BALANCE类型时,是如何存储的 --为了方便演示,这里SIZE 250表示250个bucket来存放数据 admin@ORCL> BEGIN 2 DBMS_STATS.GATHER_TABLE_STATS( 3 'ADMIN', 4 'T', 5 CASCADE=>TRUE, 6 ESTIMATE_PERCENT=>100, 7 METHOD_OPT=>'FOR ALL COLUMNS SIZE 250', 8 NO_INVALIDATE=>FALSE); 9 END; 10 / PL/SQL 过程已成功完成。 --查看直方图信息 admin@ORCL> SELECT COLUMN_NAME,NUM_DISTINCT,NUM_BUCKETS,HISTOGRAM FROM DBA_TAB_COL_STATISTICS WHERE TABLE_NAME = 'T' AND OWNER = 'ADMIN'; COLUMN_NAME NUM_DISTINCT NUM_BUCKETS HISTOGRAM -------------------- ------------ ----------- --------------- ID 10000 250 HEIGHT BALANCED COL1 101 101 FREQUENCY COL2 10000 250 HEIGHT BALANCED admin@ORCL> SELECT COLUMN_NAME, ENDPOINT_NUMBER, END 2 FROM DBA_TAB_HISTOGRAMS 3 WHERE OWNER = 'ADMIN' 4 AND TABLE_NAME = 'T' 5 AND COLUMN_NAME = 'ID'; COLUMN_NAME ENDPOINT_NUMBER ENDPOINT_VALUE -------------------- --------------- -------------- ID 0 1 ID 1 40 ID 2 80 ID 3 120 ID 4 160 ID 5 200 ID 6 240 ID 7 280 ID 8 320 ID 9 360 ID 10 400 .. .. ... ID 248 9920 ID 249 9960 ID 250 10000 --这里的ENDPOINT_NUMBER不再表示记录的条数,它标示BUCKET(桶)的编号,ENDPOINT_VALUE的算法如下: --记录条数为10000条,共分配到250个桶中,那么每个桶的数据量为40条记录 第一个ENDPOINT_VALUE的值相当于如下SQL的返回值。 admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40; MAX(ID) ---------- 40 第二个ENDPOINT_VALUE的值相当于如下SQL的返回值。 admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40*2; MAX(ID) ---------- 80 第三个ENDPOINT_VALUE的值相当于如下SQL的返回值。 admin@ORCL> select max(ID) from (select ID from t order by ID) where rownum<=40*3; MAX(ID) ---------- 120 /* 依次类推。正是这样的信息告诉了Oracle数据的分布情况,试想一下,如果连续3个bucket的ENDPOINT_VALUE值都10, 那么也就是说至少有2个bucket中的记录N2字段都是10,也就是说ID=10的记录至少有80条,越多的bucket有越多相同的ENDPOINT_VALUE值, 就表明数据分布越不均匀。 有一点需要额外注意的是:如果某几个bucket的ENDPOINT_VALUE值相同,那么在视图中只会记录最后一个bucket的信息。 */ --何时应该收集直方图 首先我们要明确直方图信息是有存在的必要的,但是只应该存在在那些应该要存在的列上。或者说我们希望对不不同的字段值走不同的执行计划时 才考虑收集直方图。 --反过来说,什么情况下我们不需要直方图呢?或者说直方图的存在是没有意义的呢? 1. 当此列不用于查询时,也就是这个字段永远不会出现在where条件中(注意:即使是用于表连接那也算是出现在where条件中)。 2. 当此列无论给予什么比较值,我们都希望永远是一种执行计划时。
相关推荐
Oracle 直方图计算公式,对于Oracle cbo优化器的探究又进入一步
### Oracle直方图解析深度解读 #### 一、直方图概述 直方图作为一种统计学工具,在Oracle数据库中扮演着关键角色。本质上,直方图是对数据分布情况的一种图形化表示,它通过一系列相连的矩形来展示数据在各个区间...
Oracle直方图是数据库优化的重要工具,特别是在Oracle关系型数据库中,它对于Cost-Based Optimizer (CBO)的成本估算起到关键作用。直方图能够帮助CBO更准确地理解数据表列的数据分布,从而制定出更高效的查询执行...
### 结合实例深入讲解Oracle中的直方图Histogram #### 一、直方图的基本概念 直方图是一种统计图表,在多种领域中都有广泛的应用,它并非Oracle数据库所独有的功能。直方图通常用来描绘一组数据的分布情况,通过一...
在探讨Oracle优化直方图之前,需要对优化器的概念有所了解。优化器在数据库中扮演着非常重要的角色,它负责生成执行计划,决定如何高效地从数据库中检索数据。优化器有两种类型:基于规则的优化器(RBO)和基于成本...
### Oracle CBO优化器与直方图(Histogram)解析 #### 概述 在数据库管理领域,Oracle CBO(Cost-Based Optimizer)成本基于优化器是Oracle数据库管理系统中用于确定查询执行计划的一种重要机制。通过分析SQL语句,...
数据可以从数据库查询得到,通过ADO.NET连接Oracle数据库,执行SQL语句获取数据,然后对数据进行分组和计算频率,最后根据结果绘制直方图。 饼图则用于显示一个数据系列中各项的大小与各项总和的比例关系。在C#中,...
标题中提及的“一个直方图问题引发的思考”指向的是在Oracle数据库环境下,对直方图和SQL执行计划的深入分析和优化过程。直方图是Oracle数据库中用于记录列内值分布的统计工具,它在优化器选择执行计划时起到关键...
在使用直方图时,Oracle优化器会根据直方图信息来调整其基数估计方法,以便更准确地预测查询结果的行数。这些调整包括对特定查询谓词(如等值、范围和不等于)的处理。 例如,对于等值谓词,优化器将基于直方图的桶...
文章提到,收集准确的统计信息,特别是直方图的收集,对于Oracle能否选择最优的执行计划至关重要。通过实验验证,直方图对SQL执行计划的影响非常明显,可以清楚地指导数据库管理员在哪些情况下需要收集直方图。 ...
总结来说,直方图在Oracle数据库中对执行计划有着显著影响。它可以纠正CBO对数据分布的错误假设,避免因数据倾斜而导致的不理想执行计划,如全表扫描,而选择更适合的索引操作。在处理倾斜数据或需要精确统计信息的...
3. **直方图统计**:支持创建直方图来更好地描述列值的分布情况,这对于处理数据倾斜的情况非常有用。 #### 五、`dbms_stats`的主要参数详解 - **options参数**:控制Oracle统计的刷新方式。提供了四种预设方法: ...
- 介绍了直方图(Histogram)的概念、收集方法及其对选择性的影响。 - 讨论了表连接的不同方式,如排序-合并连接(SMJ)、嵌套循环(NL)、哈希连接(HJ)等,并比较了它们的特点。 - 分析了笛卡儿乘积产生的原因...
影响Oracle数据库索引的几个因素包括选择性、集群因子、二元高度和直方图等。本文通过对索引的概念和作用的剖析,以及对影响索引的几个因素的分析,旨在帮助数据库管理员更好地理解和应用索引技术。 六、参考文献 ...
综上所述,Oracle SQL的规则与优化涉及了从SQL语句的分类、执行流程、解析策略到绑定变量的使用、直方图的构建等多个方面。理解并熟练应用这些知识点,不仅可以提升SQL执行效率,还能为整个系统的性能优化打下坚实的...
- 直方图可以帮助Oracle更准确地估计查询的行数。 - 聚簇因子表示索引条目与实际数据之间的距离,其值越低表明索引的效率越高。 - 动态采样技术可以使Oracle更精确地估算查询成本,从而选择更优的执行计划。 - *...
- **2**:包含哈希表直方图 (Hashtab Histogram)。 - **3**:包含对象句柄 (Object Handle)。 - **4**:包含对象结构 (Heap0)。 通过调整 `n` 的值,可以获取Library Cache的不同层面的信息。 ##### 3\. Row ...