12條語句學會oracle cbo計算(七)
12條語句學會oracle cbo計算(七)
工作中,你可能會遇到統計資料正確,但就是不走你想要的執行計劃的情況,最後一般透過hint或sql_profile解決.一條sql語句的效能主要依賴於好的物理結構,準確的系統統計資料,準確的物件統計資料,合理的查詢最佳化器引數,合理的系統引數.這些因素也就是cost計算基本引數.因此產生的sql最佳化技術有很多,大概包含:改變訪問結構,修改sql語句,加hint,改變執行環境,sql profile,stored outlines,sql plan baseline.其實無外乎就是透過調整sql適應環境或者透過調整環境適應sql.如果清楚Cost值的演算法,就可以透過演算法的對比,找到問題的真正原因,更有針對性的去解決問題.
全文主要參考Jonathan Lewis的<>和黃瑋(fuyuncat)的<>,特別黃瑋(fuyuncat)的這本,是非常值得去學習的.
準備用14篇來描述完,前2篇是統計資料,演算法公式說明,後12篇用12條語句分別去套用說明.
本篇例子的特徵是單表,索引唯一掃描,條件值常量,無直方圖,單條件,排序,和上一篇差別是索引唯一掃描
--產生測試資料
drop table scott.t_test1 purge;
create table scott.t_test1 as select * from dba_objects;
create unique index scott.idx_t_test1 on scott.t_test1(object_id);
begin
dbms_stats.gather_table_stats('scott','t_test1');
end;
--產生語句的執行計劃
--這裡我是在pl/sql developer,是因為不用象10053那麼麻煩就可以產生想要的幾個值用以對比.
explain plan for select * from scott.t_test1 where object_id=40;
SELECT lpad(' ', 2 * (LEVEL - 1)) || operation operation,
options,
object_name,
cardinality,
bytes,
io_cost,
cpu_cost,
cost,
time
FROM plan_table
START WITH id = 0
CONNECT BY PRIOR id = parent_id;
/*
OPERATION OPTIONS OBJECT_NAME CARDINALITY BYTES IO_COST CPU_COST COST TIME
SELECT STATEMENT 1 98 2 15723 2 1
TABLE ACCESS BY INDEX ROWID T_TEST1 1 98 2 15723 2 1
INDEX UNIQUE SCAN IDX_T_TEST1 1 1 8171 1 1
*/
--查詢表的統計資料
select rpad(table_name, 10, ' ') table_name,
rpad(num_rows, 10, ' ') num_rows,
rpad(blocks, 10, ' ') blocks,
avg_row_len
from dba_tables
where owner = 'SCOTT'
and table_name = 'T_TEST1';
/*
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN
T_TEST1 86335 1261 98
*/
--查詢列的統計資料
select rpad(column_name, 12, ' ') column_name,
rpad(num_distinct, 8, ' ') num_distinct,
rpad(utl_raw.cast_to_number(low_value), 15, ' ') low_value,
rpad(utl_raw.cast_to_number(high_value), 10, ' ') high_value,
rpad(nullable, 8, ' ') nullable,
rpad(num_nulls, 8, ' ') num_nulls,
rpad(avg_col_len, 6, ' ') avg_col_len,
rpad(density, 20, ' ') density,
histogram
from dba_tab_columns
where owner = 'SCOTT'
and table_name = 'T_TEST1'
and column_name ='OBJECT_ID';
/*
COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE NULLABLE NUM_NULLS AVG_COL_LEN DENSITY HISTOGRAM
OBJECT_ID 86335 2 87731 Y 0 5 .0000115827879770661 NONE
*/
--查詢索引的統計資料
select index_name,
rpad(blevel, 8, ' ') blevel,
rpad(leaf_blocks, 8, ' ') leaf_blocks,
rpad(distinct_keys, 8, ' ') distinct_keys,
rpad(clustering_factor, 15, ' ') clustering_factor,
num_rows
from dba_indexes
where owner = 'SCOTT'
and table_name = 'T_TEST1';
/*
INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS
IDX_T_TEST1 1 179 86335 1311 86335
*/
--查詢最佳化器引數
select rpad(name,40,' ') name,rpad(value,20,' ') value,isdefault
from (select nam.ksppinm name,
val.KSPPSTVL value,
--nam.ksppdesc description,
val.ksppstdf isdefault
from sys.x$ksppi nam, sys.x$ksppcv val
where nam.inst_id = val.inst_id
and nam.indx = val.indx)
where name in
('_db_file_optimizer_read_count', 'db_file_multiblock_read_count',
'_optimizer_block_size', '_table_scan_cost_plus_one',
'_optimizer_ceil_cost', '_optimizer_cost_model',
'_optimizer_cache_stats', '_smm_auto_min_io_size',
'_smm_auto_max_io_size', '_smm_min_size', '_smm_max_size',
'_smm_px_max_size', 'sort_area_retained_size', 'sort_area_size',
'workarea_size_policy','_optimizer_percent_parallel','optimizer_index_cost_adj');
/*
NAME VALUE ISDEFAULT
db_file_multiblock_read_count 116 TRUE
_db_file_optimizer_read_count 8 TRUE
sort_area_size 65536 TRUE
sort_area_retained_size 0 TRUE
_optimizer_cost_model CHOOSE TRUE
_optimizer_cache_stats FALSE TRUE
optimizer_index_cost_adj 100 TRUE
_table_scan_cost_plus_one TRUE TRUE
workarea_size_policy AUTO TRUE
_smm_auto_min_io_size 56 TRUE
_smm_auto_max_io_size 248 TRUE
_smm_min_size 286 TRUE
_smm_max_size 57344 TRUE
_smm_px_max_size 143360 TRUE
_optimizer_percent_parallel 101 TRUE
_optimizer_block_size 8192 TRUE
_optimizer_ceil_cost TRUE TRUE
*/
--查詢系統統計資料
select rpad(pname, '20', ' ') pname,
rpad(pval1, '20', ' ') pval1,
rpad(pval2, '20', ' ') pval2
from SYS.AUX_STATS$
where sname = 'SYSSTATS_MAIN';
/*
PNAME PVAL1 PVAL2
CPUSPEED
CPUSPEEDNW 3074.07407407407
IOSEEKTIM 10
IOTFRSPEED 4096
MAXTHR
MBRC
MREADTIM
SLAVETHR
SREADTIM
*/
--需要應用第二篇中的公式:
(1)NDV=dba_tab_co1umns.num_distinct
(2)DENS=dba_tab_co1umns.DENSITY
(3)ALLROWS=dba_tab1es.NUM_ROWS
(6)COLNB=dba_tab_co1umns.NULLABLE
(9)OPTICA=最佳化器系統引數optimizer_index_cost_adj
(11)MBRC=最佳化器系統引數_db_fi1e_optimizer_read_count
(14)OPTBLKSIZE=最佳化器系統引數_optimizer_b1ock_size
(21)CPUSPEED=系統統計資料CPUSPEEDNW
(22)IOTFRSPEED=系統統計資料IOTFRSPEED
(23)IOSEEKTIM=系統統計資料IOSEEKTIM
(24)SREADTIM = IOSEEKTIM + OPTBLKSIZ/IOTFRSPEED
(25)MREADTIM = IOSEEKTIM + MBRC * OPTBLKSIZ/IOTFRSPEED
(29)=的選擇率為: GREATEST(1/NDV,DENS)*DECODE(COLNB,Y,1,NNV/ALLROWS)
(73)CPUCOST = #CPUCYCLES /(CPUSPEED*SREADTIM)/1000
(78)IOCOST = BLVL
(79)IOCOST=ROUND((BLVL + CEIL(LBLKS*INDACCSEL) +CEIL(CLUF*INDFLTSEL))*OPTICA/100)
--套用上面的公式及資料進行計算
表名:T_TEST1
(3)ALLROWS=dba_tab1es.NUM_ROWS=86335
列名:OBJECT_ID
(1)NDV=dba_tab_co1umns.num_distinct=86335
(2)DENS=dba_tab_co1umns.DENSITY=.0000115827879770661
(6)COLNB=dba_tab_co1umns.NULLABLE=Y
索引列:OBJECT_ID
BLVL=dba_indexes.BLEVEL=1
CLUF=dba_indexes.CLUSTERING_FACTOR=1311
LBLKS=dba_indexes.LEAF_BLOCKS=179
(9)OPTICA=最佳化器系統引數optimizer_index_cost_adj=100
(11)MBRC=最佳化器系統引數_db_fi1e_optimizer_read_count=8
(14)OPTBLKSIZE=最佳化器系統引數_optimizer_b1ock_size=8192
(21)CPUSPEED=系統統計資料CPUSPEEDNW=3074.07407407407
(22)IOTFRSPEED=系統統計資料IOTFRSPEED=4096
(23)IOSEEKTIM=系統統計資料IOSEEKTIM=10
(24)SREADTIM = IOSEEKTIM + OPTBLKSIZ/IOTFRSPEED=10+8192/4096=12
(25)MREADTIM = IOSEEKTIM + MBRC * OPTBLKSIZ/IOTFRSPEED=10+8*8192/4096=26
(29)=的選擇率為: GREATEST(1/NDV,DENS)*DECODE(COLNB,Y,1,NNV/ALLROWS)
SEL= GREATEST(1/86335,.0000115827879770661)*DECODE('Y','Y',86335/86335,1)
=1.15827879770661E-5
ROWS=ALLROWS*SEL=86335*1.15827879770661E-5=1
--INDEX UNIQUE SCAN
(78)IOCOST = BLVL
=1
--TABLE ACCESS BY INDEX ROWID
INDACCSEL=SEL=1.15827879770661E-5
由於沒有其他過濾條件,所以INDFLTSEL=INDACCSEL=1.15827879770661E-5
(79)IOCOST=ROUND((BLVL + CEIL(LBLKS*INDACCSEL) +CEIL(CLUF*INDFLTSEL))*OPTICA/100)
--對於唯一索引的TABLE ACCESS BY INDEX ROWID,IOCOST調整為
IOCOST=ROUND((BLVL +CEIL(CLUF*INDFLTSEL))*OPTICA/100
=ROUND((1 + CEIL(1311*1.15827879770661E-5))*100/100)
=2
(73)CPUCOST = #CPUCYCLES /(CPUSPEED*SREADTIM)
= 15723/(3074.07407407407/12)/1000
=0.061376530120482
COST=IOCOST+CPUCOST=2+0.061376530120482=2
--可以看到,結果與執行計劃基本相同
ROWS=ALLROWS*SEL=86335*1.15827879770661E-5=1
IOCOST[INDEX UNIQUE SCAN]=1
IOCOST[TABLE ACCESS BY INDEX ROWID]=2
IOCOST=IOCOST[TABLE ACCESS BY INDEX ROWID]=2
CPUCOST = 15723/(3074.07407407407/12)/1000 =0.061376530120482
COST=IOCOST+CPUCOST=2+0.061376530120482=2.061376530120482=2
工作中,你可能會遇到統計資料正確,但就是不走你想要的執行計劃的情況,最後一般透過hint或sql_profile解決.一條sql語句的效能主要依賴於好的物理結構,準確的系統統計資料,準確的物件統計資料,合理的查詢最佳化器引數,合理的系統引數.這些因素也就是cost計算基本引數.因此產生的sql最佳化技術有很多,大概包含:改變訪問結構,修改sql語句,加hint,改變執行環境,sql profile,stored outlines,sql plan baseline.其實無外乎就是透過調整sql適應環境或者透過調整環境適應sql.如果清楚Cost值的演算法,就可以透過演算法的對比,找到問題的真正原因,更有針對性的去解決問題.
全文主要參考Jonathan Lewis的<>和黃瑋(fuyuncat)的<
準備用14篇來描述完,前2篇是統計資料,演算法公式說明,後12篇用12條語句分別去套用說明.
本篇例子的特徵是單表,索引唯一掃描,條件值常量,無直方圖,單條件,排序,和上一篇差別是索引唯一掃描
--產生測試資料
drop table scott.t_test1 purge;
create table scott.t_test1 as select * from dba_objects;
create unique index scott.idx_t_test1 on scott.t_test1(object_id);
begin
dbms_stats.gather_table_stats('scott','t_test1');
end;
--產生語句的執行計劃
--這裡我是在pl/sql developer,是因為不用象10053那麼麻煩就可以產生想要的幾個值用以對比.
explain plan for select * from scott.t_test1 where object_id=40;
SELECT lpad(' ', 2 * (LEVEL - 1)) || operation operation,
options,
object_name,
cardinality,
bytes,
io_cost,
cpu_cost,
cost,
time
FROM plan_table
START WITH id = 0
CONNECT BY PRIOR id = parent_id;
/*
OPERATION OPTIONS OBJECT_NAME CARDINALITY BYTES IO_COST CPU_COST COST TIME
SELECT STATEMENT 1 98 2 15723 2 1
TABLE ACCESS BY INDEX ROWID T_TEST1 1 98 2 15723 2 1
INDEX UNIQUE SCAN IDX_T_TEST1 1 1 8171 1 1
*/
--查詢表的統計資料
select rpad(table_name, 10, ' ') table_name,
rpad(num_rows, 10, ' ') num_rows,
rpad(blocks, 10, ' ') blocks,
avg_row_len
from dba_tables
where owner = 'SCOTT'
and table_name = 'T_TEST1';
/*
TABLE_NAME NUM_ROWS BLOCKS AVG_ROW_LEN
T_TEST1 86335 1261 98
*/
--查詢列的統計資料
select rpad(column_name, 12, ' ') column_name,
rpad(num_distinct, 8, ' ') num_distinct,
rpad(utl_raw.cast_to_number(low_value), 15, ' ') low_value,
rpad(utl_raw.cast_to_number(high_value), 10, ' ') high_value,
rpad(nullable, 8, ' ') nullable,
rpad(num_nulls, 8, ' ') num_nulls,
rpad(avg_col_len, 6, ' ') avg_col_len,
rpad(density, 20, ' ') density,
histogram
from dba_tab_columns
where owner = 'SCOTT'
and table_name = 'T_TEST1'
and column_name ='OBJECT_ID';
/*
COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE NULLABLE NUM_NULLS AVG_COL_LEN DENSITY HISTOGRAM
OBJECT_ID 86335 2 87731 Y 0 5 .0000115827879770661 NONE
*/
--查詢索引的統計資料
select index_name,
rpad(blevel, 8, ' ') blevel,
rpad(leaf_blocks, 8, ' ') leaf_blocks,
rpad(distinct_keys, 8, ' ') distinct_keys,
rpad(clustering_factor, 15, ' ') clustering_factor,
num_rows
from dba_indexes
where owner = 'SCOTT'
and table_name = 'T_TEST1';
/*
INDEX_NAME BLEVEL LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR NUM_ROWS
IDX_T_TEST1 1 179 86335 1311 86335
*/
--查詢最佳化器引數
select rpad(name,40,' ') name,rpad(value,20,' ') value,isdefault
from (select nam.ksppinm name,
val.KSPPSTVL value,
--nam.ksppdesc description,
val.ksppstdf isdefault
from sys.x$ksppi nam, sys.x$ksppcv val
where nam.inst_id = val.inst_id
and nam.indx = val.indx)
where name in
('_db_file_optimizer_read_count', 'db_file_multiblock_read_count',
'_optimizer_block_size', '_table_scan_cost_plus_one',
'_optimizer_ceil_cost', '_optimizer_cost_model',
'_optimizer_cache_stats', '_smm_auto_min_io_size',
'_smm_auto_max_io_size', '_smm_min_size', '_smm_max_size',
'_smm_px_max_size', 'sort_area_retained_size', 'sort_area_size',
'workarea_size_policy','_optimizer_percent_parallel','optimizer_index_cost_adj');
/*
NAME VALUE ISDEFAULT
db_file_multiblock_read_count 116 TRUE
_db_file_optimizer_read_count 8 TRUE
sort_area_size 65536 TRUE
sort_area_retained_size 0 TRUE
_optimizer_cost_model CHOOSE TRUE
_optimizer_cache_stats FALSE TRUE
optimizer_index_cost_adj 100 TRUE
_table_scan_cost_plus_one TRUE TRUE
workarea_size_policy AUTO TRUE
_smm_auto_min_io_size 56 TRUE
_smm_auto_max_io_size 248 TRUE
_smm_min_size 286 TRUE
_smm_max_size 57344 TRUE
_smm_px_max_size 143360 TRUE
_optimizer_percent_parallel 101 TRUE
_optimizer_block_size 8192 TRUE
_optimizer_ceil_cost TRUE TRUE
*/
--查詢系統統計資料
select rpad(pname, '20', ' ') pname,
rpad(pval1, '20', ' ') pval1,
rpad(pval2, '20', ' ') pval2
from SYS.AUX_STATS$
where sname = 'SYSSTATS_MAIN';
/*
PNAME PVAL1 PVAL2
CPUSPEED
CPUSPEEDNW 3074.07407407407
IOSEEKTIM 10
IOTFRSPEED 4096
MAXTHR
MBRC
MREADTIM
SLAVETHR
SREADTIM
*/
--需要應用第二篇中的公式:
(1)NDV=dba_tab_co1umns.num_distinct
(2)DENS=dba_tab_co1umns.DENSITY
(3)ALLROWS=dba_tab1es.NUM_ROWS
(6)COLNB=dba_tab_co1umns.NULLABLE
(9)OPTICA=最佳化器系統引數optimizer_index_cost_adj
(11)MBRC=最佳化器系統引數_db_fi1e_optimizer_read_count
(14)OPTBLKSIZE=最佳化器系統引數_optimizer_b1ock_size
(21)CPUSPEED=系統統計資料CPUSPEEDNW
(22)IOTFRSPEED=系統統計資料IOTFRSPEED
(23)IOSEEKTIM=系統統計資料IOSEEKTIM
(24)SREADTIM = IOSEEKTIM + OPTBLKSIZ/IOTFRSPEED
(25)MREADTIM = IOSEEKTIM + MBRC * OPTBLKSIZ/IOTFRSPEED
(29)=的選擇率為: GREATEST(1/NDV,DENS)*DECODE(COLNB,Y,1,NNV/ALLROWS)
(73)CPUCOST = #CPUCYCLES /(CPUSPEED*SREADTIM)/1000
(78)IOCOST = BLVL
(79)IOCOST=ROUND((BLVL + CEIL(LBLKS*INDACCSEL) +CEIL(CLUF*INDFLTSEL))*OPTICA/100)
--套用上面的公式及資料進行計算
表名:T_TEST1
(3)ALLROWS=dba_tab1es.NUM_ROWS=86335
列名:OBJECT_ID
(1)NDV=dba_tab_co1umns.num_distinct=86335
(2)DENS=dba_tab_co1umns.DENSITY=.0000115827879770661
(6)COLNB=dba_tab_co1umns.NULLABLE=Y
索引列:OBJECT_ID
BLVL=dba_indexes.BLEVEL=1
CLUF=dba_indexes.CLUSTERING_FACTOR=1311
LBLKS=dba_indexes.LEAF_BLOCKS=179
(9)OPTICA=最佳化器系統引數optimizer_index_cost_adj=100
(11)MBRC=最佳化器系統引數_db_fi1e_optimizer_read_count=8
(14)OPTBLKSIZE=最佳化器系統引數_optimizer_b1ock_size=8192
(21)CPUSPEED=系統統計資料CPUSPEEDNW=3074.07407407407
(22)IOTFRSPEED=系統統計資料IOTFRSPEED=4096
(23)IOSEEKTIM=系統統計資料IOSEEKTIM=10
(24)SREADTIM = IOSEEKTIM + OPTBLKSIZ/IOTFRSPEED=10+8192/4096=12
(25)MREADTIM = IOSEEKTIM + MBRC * OPTBLKSIZ/IOTFRSPEED=10+8*8192/4096=26
(29)=的選擇率為: GREATEST(1/NDV,DENS)*DECODE(COLNB,Y,1,NNV/ALLROWS)
SEL= GREATEST(1/86335,.0000115827879770661)*DECODE('Y','Y',86335/86335,1)
=1.15827879770661E-5
ROWS=ALLROWS*SEL=86335*1.15827879770661E-5=1
--INDEX UNIQUE SCAN
(78)IOCOST = BLVL
=1
--TABLE ACCESS BY INDEX ROWID
INDACCSEL=SEL=1.15827879770661E-5
由於沒有其他過濾條件,所以INDFLTSEL=INDACCSEL=1.15827879770661E-5
(79)IOCOST=ROUND((BLVL + CEIL(LBLKS*INDACCSEL) +CEIL(CLUF*INDFLTSEL))*OPTICA/100)
--對於唯一索引的TABLE ACCESS BY INDEX ROWID,IOCOST調整為
IOCOST=ROUND((BLVL +CEIL(CLUF*INDFLTSEL))*OPTICA/100
=ROUND((1 + CEIL(1311*1.15827879770661E-5))*100/100)
=2
(73)CPUCOST = #CPUCYCLES /(CPUSPEED*SREADTIM)
= 15723/(3074.07407407407/12)/1000
=0.061376530120482
COST=IOCOST+CPUCOST=2+0.061376530120482=2
--可以看到,結果與執行計劃基本相同
ROWS=ALLROWS*SEL=86335*1.15827879770661E-5=1
IOCOST[INDEX UNIQUE SCAN]=1
IOCOST[TABLE ACCESS BY INDEX ROWID]=2
IOCOST=IOCOST[TABLE ACCESS BY INDEX ROWID]=2
CPUCOST = 15723/(3074.07407407407/12)/1000 =0.061376530120482
COST=IOCOST+CPUCOST=2+0.061376530120482=2.061376530120482=2
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28539951/viewspace-1662851/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 12條語句學會oracle cbo計算(五)Oracle
- 12條語句學會oracle cbo計算(四)Oracle
- 12條語句學會oracle cbo計算(三)Oracle
- 12條語句學會oracle cbo計算(二)Oracle
- 12條語句學會oracle cbo計算(一)Oracle
- 12條語句學會oracle cbo計算(十四)Oracle
- 12條語句學會oracle cbo計算(十三)Oracle
- 12條語句學會oracle cbo計算(十一)Oracle
- 12條語句學會oracle cbo計算(十)Oracle
- 12條語句學會oracle cbo計算(九)Oracle
- 12條語句學會oracle cbo計算(六)Oracle
- 12條語句學會oracle cbo計算(十二)Oracle
- oracle中的條件語句Oracle
- Oracle分頁查詢語句(七)Oracle
- 學習Rust 條件語句Rust
- 初學Python(七)——控制語句Python
- oracle基於cbo成本計算方式說明Oracle
- 【cbo計算公式】CBO基本概念(一)公式
- CBO成本計算初探
- 草根學Python(五) 條件語句和迴圈語句Python
- 條件語句
- Java 數學運算與條件語句全解析Java
- Python學習筆記3(條件語句+迴圈語句)Python筆記
- Python學習筆記(三)——條件語句、迴圈語句Python筆記
- shell程式設計之條件語句程式設計
- 七週學會七種語言:學習程式語言的實用指南
- 實現四則運算的一條sql語句SQL
- Go 條件語句 - Go 學習記錄Go
- GO 條件語句Go
- javaScript條件語句JavaScript
- 02 shell程式設計之條件語句程式設計
- Oracle 使用一條insert語句完成多表插入Oracle
- day2-計算符和if語句
- 9,javase程式碼實戰-條件語句——switch語句根據使用者消費金額計算折扣(四)Java
- 【cbo計算公式】No Bind Peeking(五)公式
- Swift學習筆記(二十七)——條件語句和Switch-case語句Swift筆記
- Go:條件控制語句Go
- if條件語句sed命令