為什麼進行統計分析執行效率反而更差呢?
有一個經典案例,在8i到10g版本中,我們執行統計分析後,感覺執行效率反而更差了,造成該原因是我們建立了一個function-based index,將會產生一個隱藏列,該隱藏列會參與到成本計算。
具體的實驗如下:
1、建立測試表
SQL> create table t1
as select 'a' col1, rpad('x', 200) col2 from all_objects where rownum<=100
SQL>insert into t1 select 'b' col1, rpad('x', 200) col2 from all_objects where rownum<=10000;
SQL>create index t1_idx on t1 (upper(col1));
2、統計分析後進行檢測:
SQL>exec dbms_stats.gather_table_stats(user, 't1', cascade=>true);
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5050 | 1001K| 70 (2)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 5050 | 1001K| 70 (2)| 00:00:01 |
--------------------------------------------------------------------------
10053跟蹤檔案如下:
SINGLE TABLE ACCESS PATH
Column (#3): SYS_NC00003$(CHARACTER)
AvgLen: 2.00 NDV: 2 Nulls: 0 Density: 0.5
Table: T1 Alias: T1
Card: Original: 10100 Rounded: 5050 Computed: 5050.00 Non Adjusted: 5050.00
Access Path: TableScan
Cost: 69.77 Resp: 69.77 Degree: 0
Cost_io: 69.00 Cost_cpu: 7351525
Resp_io: 69.00 Resp_cpu: 7351525
Access Path: index (AllEqRange)
Index: T1_IDX
resc_io: 159.00 resc_cpu: 3001659
ix_sel: 0.5 ix_sel_with_filters: 0.5
Cost: 159.31 Resp: 159.31 Degree: 1
Best:: AccessPath: TableScan
Cost: 69.77 Degree: 1 Resp: 69.77 Card: 5050.00 Bytes: 0
以上是隱藏列SYS_NC00003$被統計分析。
該隱藏列參與的CBO的成本計算,在計算CBO的時候全表掃描cost=69.77,而走索引的cost=159.31,所以選擇全表掃描
3、刪除索引和統計分析
SQL>exec dbms_stats.delete_table_stats(user, 't1');
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101 | 20503 | 11 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 101 | 20503 | 11 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 40 | | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
感覺是刪除了統計統計分析造成效率更高,其實不是,以下實驗是遮蔽掉隱藏列的統計分析。
SQL>drop index t1_idx;
SQL>exec dbms_stats.gather_table_stats(user, 't1', cascade=>true);
SQL>create index t1_idx on t1 (upper(col1));
SQL>exec dbms_stats.gather_index_stats(user, 't1_idx');
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101 | 20503 | 11 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 101 | 20503 | 11 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 40 | | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
10053 trace 檔案:
SINGLE TABLE ACCESS PATH
Column (#3): SYS_NC00003$(CHARACTER) NO STATISTICS (using defaults)
AvgLen: 1.00 NDV: 316 Nulls: 0 Density: 0.0031683
Table: T1 Alias: T1
Card: Original: 10100 Rounded: 101 Computed: 101.00 Non Adjusted: 101.00
Access Path: TableScan
Cost: 69.76 Resp: 69.76 Degree: 0
Cost_io: 69.00 Cost_cpu: 7252545
Resp_io: 69.00 Resp_cpu: 7252545
Access Path: index (AllEqGuess)
Index: T1_IDX
resc_io: 11.00 resc_cpu: 94356
ix_sel: 0.004 ix_sel_with_filters: 0.004
Cost: 11.01 Resp: 11.01 Degree: 1
Best:: AccessPath: IndexRange Index: T1_IDX
Cost: 11.01 Degree: 1 Resp: 11.01 Card: 101.00 Bytes: 0
注意一點隱藏列沒有被統計分析,他採用預設值,Density=0.0031683,造成參與成本計算的時候,全表掃描成本是69.76,索引的成本掃描只有11.01。
具體的實驗如下:
1、建立測試表
SQL> create table t1
as select 'a' col1, rpad('x', 200) col2 from all_objects where rownum<=100
SQL>insert into t1 select 'b' col1, rpad('x', 200) col2 from all_objects where rownum<=10000;
SQL>create index t1_idx on t1 (upper(col1));
2、統計分析後進行檢測:
SQL>exec dbms_stats.gather_table_stats(user, 't1', cascade=>true);
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5050 | 1001K| 70 (2)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 5050 | 1001K| 70 (2)| 00:00:01 |
--------------------------------------------------------------------------
10053跟蹤檔案如下:
SINGLE TABLE ACCESS PATH
Column (#3): SYS_NC00003$(CHARACTER)
AvgLen: 2.00 NDV: 2 Nulls: 0 Density: 0.5
Table: T1 Alias: T1
Card: Original: 10100 Rounded: 5050 Computed: 5050.00 Non Adjusted: 5050.00
Access Path: TableScan
Cost: 69.77 Resp: 69.77 Degree: 0
Cost_io: 69.00 Cost_cpu: 7351525
Resp_io: 69.00 Resp_cpu: 7351525
Access Path: index (AllEqRange)
Index: T1_IDX
resc_io: 159.00 resc_cpu: 3001659
ix_sel: 0.5 ix_sel_with_filters: 0.5
Cost: 159.31 Resp: 159.31 Degree: 1
Best:: AccessPath: TableScan
Cost: 69.77 Degree: 1 Resp: 69.77 Card: 5050.00 Bytes: 0
以上是隱藏列SYS_NC00003$被統計分析。
該隱藏列參與的CBO的成本計算,在計算CBO的時候全表掃描cost=69.77,而走索引的cost=159.31,所以選擇全表掃描
3、刪除索引和統計分析
SQL>exec dbms_stats.delete_table_stats(user, 't1');
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101 | 20503 | 11 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 101 | 20503 | 11 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 40 | | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
感覺是刪除了統計統計分析造成效率更高,其實不是,以下實驗是遮蔽掉隱藏列的統計分析。
SQL>drop index t1_idx;
SQL>exec dbms_stats.gather_table_stats(user, 't1', cascade=>true);
SQL>create index t1_idx on t1 (upper(col1));
SQL>exec dbms_stats.gather_index_stats(user, 't1_idx');
SQL>explain plan for select * from t1 where upper(col1)='A';
SQL>select * from table(dbms_xplan.display);
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101 | 20503 | 11 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 | 101 | 20503 | 11 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T1_IDX | 40 | | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
10053 trace 檔案:
SINGLE TABLE ACCESS PATH
Column (#3): SYS_NC00003$(CHARACTER) NO STATISTICS (using defaults)
AvgLen: 1.00 NDV: 316 Nulls: 0 Density: 0.0031683
Table: T1 Alias: T1
Card: Original: 10100 Rounded: 101 Computed: 101.00 Non Adjusted: 101.00
Access Path: TableScan
Cost: 69.76 Resp: 69.76 Degree: 0
Cost_io: 69.00 Cost_cpu: 7252545
Resp_io: 69.00 Resp_cpu: 7252545
Access Path: index (AllEqGuess)
Index: T1_IDX
resc_io: 11.00 resc_cpu: 94356
ix_sel: 0.004 ix_sel_with_filters: 0.004
Cost: 11.01 Resp: 11.01 Degree: 1
Best:: AccessPath: IndexRange Index: T1_IDX
Cost: 11.01 Degree: 1 Resp: 11.01 Card: 101.00 Bytes: 0
注意一點隱藏列沒有被統計分析,他採用預設值,Density=0.0031683,造成參與成本計算的時候,全表掃描成本是69.76,索引的成本掃描只有11.01。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/354732/viewspace-613784/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 分析:女神為什麼嫁得更差?
- 什麼時候使用繫結變數效能反而更差變數
- 為什麼python執行效率低?原來因為它!Python
- 為什麼你寫的Python執行的那麼慢呢?Python
- 架構設計要按照什麼原則進行呢?架構
- 為什麼網站做https改造 SEO排名反而下降呢?網站HTTP
- 從行為軌跡進行大資料分析有什麼好處?大資料
- Python為什麼執行效率低?受哪些因素影響?Python
- 系統為什麼會在執行時當機
- 我們為什麼需要原型設計,該如何進行原型設計呢?原型
- Web前端技術知識:為什麼要進行網站重構呢?Web前端網站
- 為什麼很多人要學習Linux雲端計算運維進入IT行業呢?Linux運維行業
- 好奇: windows10+都可以執行多個linux子系統了,為什麼不支援執行多個windows子系統呢?WindowsLinux
- 執行緒池管理(1)-為什麼需要執行緒池執行緒
- redis為什麼用單執行緒不用多執行緒Redis執行緒
- Netty是什麼,Netty為什麼速度這麼快,執行緒模型分析Netty執行緒模型
- Redis作為單執行緒 為什麼我用它還是出現了超賣呢?Redis執行緒
- 為什麼Podman執行容器更安全?
- python為什麼要用執行緒Python執行緒
- 為什麼要使用執行緒池執行緒
- ORACLE:什麼是執行計劃Oracle
- 恆訊科技分析域名怎麼進行繫結解析呢?
- 為什麼該SQL的執行計劃不走索引???SQL索引
- 系統程式是什麼?怎麼通過系統程式進行病毒分析?
- 前端進階演算法1:如何分析、統計演算法的執行效率和資源消耗?前端演算法
- 為什麼那麼多人都想進入IT行業?行業
- oracle使用profiler分析語句執行效率Oracle
- 為什麼redis是單執行緒的以及為什麼這麼快?Redis執行緒
- 如何建立一個執行緒池,為什麼不推薦使用Executors去建立呢?執行緒
- Redis不是一直號稱單執行緒效率也很高嗎,為什麼又採用多執行緒了?Redis執行緒
- Promise為什麼比setTimeout先執行?Promise
- ArrayList 為什麼執行緒不安全執行緒
- 為什麼要早點進入IT行業?行業
- switch執行效率
- 為什麼計算機採用補碼進行運算?計算機
- 為什麼以及如何要進行架構設計權衡?架構
- 怎麼對網站進行SEO呢?網站
- 程式執行緒新解:什麼是程式?什麼是執行緒?執行緒