执行计划的cardinality基数(rows)评估:
执行计划的cardinality列(基数)是说从数据表结果集或者索引返回多少行数据。
基数=表行数据*选择率。所以讲基数重点是讲选择率,选择率的计算!
Cardinality的值对于CBO做出正确的执行计划来说至关重要。 如果CBO获得的Cardinality值不够准确(通常是没有做过分析或者分析数据过旧造成),在执行计划成本计算上就会出现偏差,从而导致CBO错误的制定出执行计划。
如果表没有做过分析,那么CBO可以通过动态采样的方式来获取分析数据,执行获取的执行计划可能会出现偏差,可能是正确的执行计划也可能是错误的执行计划。
如果表分析过,但是分析信息过旧,这时CBO就不会在使用动态采样,而是使用这些旧的分析数据,从而也可能导致错误的执行计划。
查询sql访问的谓词如果超出了数据库中统计信息记录的值限,比如,某个数值范围是1~100,当访问200的取值,超出了这个范围,由于统计信息收集通常是通过采样,定时来实现的,所以真实的数据中可能仍然存在满足条件的数据,这时数据库会估算指定一个density(比重)用于cardinality的计算。
----查询sql访问的谓词超出了数据库中统计信息记录的值限分析实验:
1.环境准备
sys@ORCL>create user shall identified by shall;
User created.
sys@ORCL>grant connect,resource to shall;
sys@ORCL>grant dba to shall;
Grant succeeded.
shall@ORCL>create table zhong as select rownum numid from dba_objects where rownum<20001;
shall@ORCL>insert into zhong select * from zhong;
20000 rows created.
shall@ORCL>insert into zhong select * from zhong;
40000 rows created.
shall@ORCL>insert into zhong select * from zhong;
80000 rows created.
shall@ORCL>commit;
Commit complete.
2.收集该表统计信息
shall@ORCL>exec dbms_stats.gather_table_stats(user,'ZHONG');
PL/SQL procedure successfully completed.
----查询记录一下相关的统计信息
shall@ORCL>select table_name,num_rows,blocks,avg_row_len,sample_size from user_tables where table_name='ZHONG';
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE
------------------------------ ---------- ---------- ----------- -----------
ZHONG 160000 249 4 160000
shall@ORCL>select column_name,data_type,num_distinct,density,1/num_distinct,last_analyzed,sample_size,histogram from user_tab_cols where table_name='ZHONG';
COLUMN_NAME DATA_TYPE NUM_DISTINCT DENSITY 1/NUM_DISTINCT LAST_ANALYZED SAMPLE_SIZE HISTOGRAM
----------- ----------- ------------ ---------- -------------- ------------------- ----------- ---------------
NUMID NUMBER 20128 .000049682 .000049682 2016-05-28 16:25:44 160000 NONE
------注意以上的density(比重)计算,在不存在柱状图时,density=1/num_distinct,此时计算cardinality(基数)时,会选择使用公式:
cardinalily=num_rows/num_distinct=num_rows*(1/num_distinct)
3.数据库中的基本信息如下
shall@ORCL>select max(numid) from zhong;
MAX(NUMID)
----------
20000
shall@ORCL>select count(*) from zhong;
COUNT(*)
----------
160000
shall@ORCL>select count(*) from zhong where numid=1000;
COUNT(*)
----------
8
4.开启10053事件跟踪查询
shall@ORCL>alter session set events '10053 trace name context forever,level 1';
Session altered.
shall@ORCL>explain plan for select count(*) from zhong where numid=1000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=10000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=25000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=30000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=40000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=50000;
Explained.
shall@ORCL>select value from v$diag_info where name = 'Default Trace File';
VALUE
-----------------------------------------------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_22824.trc
shall@ORCL> alter session set events '10053 trace name context off';
Session altered.
5.分析跟踪文件
shall@ORCL>ho vim /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_22824.trc
5.1 numid为1000
QUERY BLOCK TEXT
****************
select count(*) from zhong where numid=1000
---------------------
----首先基于统计信息部分,我们可以看到关于表中行数、数据块数、平均行长等信息:
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: ZHONG Alias: ZHONG
#Rows: 160000 #Blks: 249 AvgRowLen: 4.00
----在单表访问路径部分,紧接着的信息是cardinality(基数)的评估,评估的结果有:
Access path analysis for ZHONG
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for ZHONG[ZHONG]
Table: ZHONG Alias: ZHONG
Card: Original: 160000.000000 Rounded: 8 Computed: 7.95 Non Adjusted: 7.
95
----全表访问路径的成本是70.04
Access Path: TableScan
Cost: 70.04 Resp: 70.04 Degree: 0
Cost_io: 69.00 Cost_cpu: 33773239
Resp_io: 69.00 Resp_cpu: 33773239
Best:: AccessPath: TableScan
Cost: 70.04 Degree: 1 Resp: 70.04 Card: 7.95 Bytes: 0
***************************************
----这个查询最后的执行计划,其rows就是评估的8,完全符合真实的数据情况:
Starting SQL statement dump
user_id=91 user_name=SHALL module=SQL*Plus action=
sql_id=b33sadfyttasm plan_hash_value=-411406617 problem_type=3
----- Current SQL Statement for this session (sql_id=b33sadfyttasm) -----
explain plan for select count(*) from zhong where numid=1000
sql_text_length=61
sql=explain plan for select count(*) from zhong where numid=1000
----- Explain Plan Dump -----
----- Plan Table -----
============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------+-----------------------------------+
| 0 | SELECT STATEMENT | | | | 70 | |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
| 2 | TABLE ACCESS FULL | ZHONG | 8 | 32 | 70 | 00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter("NUMID"=1000)
Content of other_xml column
===========================
db_version : 11.2.0.1
parse_schema : SHALL
plan_hash : 3883560679
plan_hash_2 : 2551558790
5.2 numid为25000时
----当查询块访问numid=25000时,超出了最大数据范围:
****************
QUERY BLOCK TEXT
****************
select count(*) from zhong where numid=25000
---------------------
---在统计信息中显示。注意,此时oracle分配了一个估算密度,0.000037为out-of-range的计算,对于此次查询,估算的cardinality是6行
Access path analysis for ZHONG
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for ZHONG[ZHONG]
Using prorated density: 0.000037 of col #1 as selectvity of out-of-range/non-
existent value pred
Table: ZHONG Alias: ZHONG
Card: Original: 160000.000000 Rounded: 6 Computed: 5.96 Non Adjusted: 5.
96
Access Path: TableScan
Cost: 70.04 Resp: 70.04 Degree: 0
Cost_io: 69.00 Cost_cpu: 33773239
Resp_io: 69.00 Resp_cpu: 33773239
Best:: AccessPath: TableScan
Cost: 70.04 Degree: 1 Resp: 70.04 Card: 5.96 Bytes: 0
***************************************
----其执行计划如下
Starting SQL statement dump
user_id=91 user_name=SHALL module=SQL*Plus action=
sql_id=cha9b2hzv327m plan_hash_value=-411406617 problem_type=3
----- Current SQL Statement for this session (sql_id=cha9b2hzv327m) -----
explain plan for select count(*) from zhong where numid=25000
sql_text_length=62
sql=explain plan for select count(*) from zhong where numid=25000
----- Explain Plan Dump -----
----- Plan Table -----
============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------+-----------------------------------+
| 0 | SELECT STATEMENT | | | | 70 | |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
| 2 | TABLE ACCESS FULL | ZHONG | 6 | 24 | 70 | 00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter("NUMID"=25000)
Content of other_xml column
===========================
db_version : 11.2.0.1
parse_schema : SHALL
plan_hash : 3883560679
plan_hash_2 : 2551558790
----当numid更加远离实际值时,则prorated density趋向于一个确定的值:
Using prorated density: 0.000003 of col #1 as selectvity of out-of-range/non-
existent value pred
----此时的cardinality估算为1
Table: ZHONG Alias: ZHONG
Card: Original: 160000.000000 Rounded: 1 Computed: 0.50 Non Adjusted: 0.
50
----执行计划显示如下:
============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------+-----------------------------------+
| 0 | SELECT STATEMENT | | | | 70 | |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
| 2 | TABLE ACCESS FULL | ZHONG | 1 | 4 | 70 | 00:00:01 |
--------------------------------------+-----------------------------------+
6.当统计信息过旧时,如下
----环境准备,接上
shall@ORCL>insert into zhong select * from zhong;
160000 rows created.
shall@ORCL>commit;
Commit complete.
shall@ORCL>select count(*) from zhong;
COUNT(*)
----------
320000
shall@ORCL>select count(*) from zhong where numid=2000;
COUNT(*)
----------
16
shall@ORCL>select max(numid) from zhong ;
MAX(NUMID)
----------
20000
----此时,不再做统计信息收集,然后开启10053事件跟踪查询
shall@ORCL>alter session set events '10053 trace name context forever,level 1';
Session altered.
shall@ORCL>explain plan for select count(*) from zhong where numid=1000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=10000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=20000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=30000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=40000;
Explained.
shall@ORCL>explain plan for select count(*) from zhong where numid=50000;
Explained.
shall@ORCL>alter session set events '10053 trace name context off';
Session altered.
----再次分析下跟踪文件,当numid小于20000时,cardinality(基数)的评估结果还是8行
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for ZHONG[ZHONG]
Table: ZHONG Alias: ZHONG
Card: Original: 160000.000000 Rounded: 8 Computed: 7.95 Non Adjusted: 7.
95
Access Path: TableScan
Cost: 70.04 Resp: 70.04 Degree: 0
Cost_io: 69.00 Cost_cpu: 33773239
Resp_io: 69.00 Resp_cpu: 33773239
Best:: AccessPath: TableScan
Cost: 70.04 Degree: 1 Resp: 70.04 Card: 7.95 Bytes: 0
***************************************
----当numid大于20000时,oracle分配了一个估算密度,0.000025为out-of-range的计算,对于此次查询,估算的cardinality是4行
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for ZHONG[ZHONG]
Using prorated density: 0.000025 of col #1 as selectvity of out-of-range/non-
existent value pred
Table: ZHONG Alias: ZHONG
Card: Original: 160000.000000 Rounded: 4 Computed: 3.97 Non Adjusted: 3.
97
Access Path: TableScan
Cost: 70.04 Resp: 70.04 Degree: 0
Cost_io: 69.00 Cost_cpu: 33773239
Resp_io: 69.00 Resp_cpu: 33773239
Best:: AccessPath: TableScan
Cost: 70.04 Degree: 1 Resp: 70.04 Card: 3.97 Bytes: 0
***************************************
----所以如果表分析过,但是分析信息过旧时,这时CBO就不会在使用动态采样,而是使用这些旧的分析数据,从而也可能导致错误的执行计划。
7.如果表未做过分析,那么在执行时会进行动态采样,如下:
----首先基于统计信息部分,可以看到关于表中行数、数据块数、平均行长等信息:(注意此时,这里的rows为2941是采样估算值,实际表中的记录为160000条)
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: ZHONG Alias: ZHONG (NOT ANALYZED)
#Rows: 2941 #Blks: 36 AvgRowLen: 100.00
----紧接着的信息是cardinality(基数)的评估,但是因为之前表并未进行分析,所以这里通过动态采样的方式来获取分析数据,动态采样level为2:
Access path analysis for ZHONG
***************************************
SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for ZHONG[ZHONG]
*** 2016-05-28 17:07:28.850
** Performing dynamic sampling initial checks. **
** Dynamic sampling initial checks returning TRUE (level = 2).
** Dynamic sampling updated table stats.: blocks=249
----评估的结果大约4行:
Table: ZHONG Alias: ZHONG
Card: Original: 148957.333333 Rounded: 4 Computed: 3.95 Non Adjusted: 3.
95
----全表访问路径成本是69.98
Access Path: TableScan
Cost: 69.98 Resp: 69.98 Degree: 0
Cost_io: 69.00 Cost_cpu: 31564805
Resp_io: 69.00 Resp_cpu: 31564805
Best:: AccessPath: TableScan
Cost: 69.98 Degree: 1 Resp: 69.98 Card: 3.95 Bytes: 0
***************************************
----最后的执行计划如下:
============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id | Operation | Name | Rows | Bytes | Cost | Time |
--------------------------------------+-----------------------------------+
| 0 | SELECT STATEMENT | | | | 70 | |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | TABLE ACCESS FULL | ZHONG | 4 | 52 | 70 | 00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter("NUMID"=1000)
Content of other_xml column
===========================
db_version : 11.2.0.1
parse_schema : SHALL
dynamic_sampling: 2
plan_hash : 3883560679
plan_hash_2 : 2551558790
--------------------------------------reference eygle DBA手记2
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30130773/viewspace-2108486/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30130773/viewspace-2108486/