在Oracle資料庫中,優化器欲產生最優的執行計劃,需要依賴於相關對象的統計信息的搜集。資料庫可以自動的搜集執行計劃,也可以使用程式包DBMS_STATS進行手動搜集,本篇對常規統計信息的搜集不做說明,重點演示下關於擴展的統計信息(Extended Statistics)的的搜集。 1 擴展的統計信 ...
在Oracle資料庫中,優化器欲產生最優的執行計劃,需要依賴於相關對象的統計信息的搜集。資料庫可以自動的搜集執行計劃,也可以使用程式包DBMS_STATS進行手動搜集,本篇對常規統計信息的搜集不做說明,重點演示下關於擴展的統計信息(Extended Statistics)的的搜集。
1 擴展的統計信息介紹
在執行SQL時,where條件後的單個列的統計信息很容易去決定對應列的謂詞的選擇性,但是,如果where條件後包含同一張表的多個列作為謂詞時,那麼單個列的統計信息就不能顯示出列之間的關係了,這時,優化器根據單列的統計信息得到的執行計劃就可能不是最優的了。這個問題可以通過列組(column group)來解決,通過對列組進行統計信息的搜集,來反映一組列的相互關係,從而使優化器選擇最優的執行計劃,列組的統計信息稱為擴展的統計信息。Oracle中,擴展的統計信息包含:
- 列組統計信息: 當一張表的多個列同時出現在一條SQL語句時,這種類型的擴展統計信息可以改進基數估計
- 表達式統計信息:當對謂詞使用表達式時,這種類型的統計信息可以改進優化器評估。
如圖:展示了sh.customers表中兩個列cust_state_province和contry_id列的統計信息,以及這兩個列組成的列組的統計信息,列組的名稱是由系統產生。
2 使用常規統計信息
1)實驗環境
SQL> select * from v$version;
BANNER CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production 0
PL/SQL Release 12.1.0.2.0 - Production 0
CORE 12.1.0.2.0 Production 0
TNS for Linux: Version 12.1.0.2.0 - Production 0
NLSRTL Version 12.1.0.2.0 - Production 0
2)構建測試數據
SQL> create table sh.customers_new as select * from sh.customers;
Table created.
SQL> exec dbms_stats.gather_table_stats('SH','CUSTOMERS_NEW',method_opt => 'for all columns size 1');
PL/SQL procedure successfully completed.
3)查詢列統計信息
SQL> select column_name,num_distinct,histogram
from dba_tab_col_statistics
where owner='SH' and table_name='CUSTOMERS_NEW' and column_name in('CUST_STATE_PROVINCE','COUNTRY_ID');
COLUMN_NAME NUM_DISTINCT HISTOGRAM
------------------------------ ------------ ---------------
CUST_STATE_PROVINCE 145 NONE
COUNTRY_ID 19 NONE
3)查詢表的總數和滿足cust_state_province='CA'的數據量
SQL> select count(1) from sh.customers_new;
COUNT(1)
----------
55500
SQL> select count(1) from sh.customers_new where cust_state_province='CA';
COUNT(1)
----------
3341
4)查看單列對應的執行計劃
SQL> explain plan for
2 select * from sh.customers_new where cust_state_province='CA';
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3410015392
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 383 | 72387 | 423 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| CUSTOMERS_NEW | 383 | 72387 | 423 (1)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
1 - filter("CUST_STATE_PROVINCE"='CA')
13 rows selected.
看下麵的計算,和優化器預估的行數相匹配:
SQL> select 55500/145 from dual;
55500/145
----------
382.758621
5)查看組合條件對應的執行計劃
SQL> explain plan for
2 select * from sh.customers_new where cust_state_province='CA' and country_id='52790';
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3410015392
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20 | 3780 | 423 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| CUSTOMERS_NEW | 20 | 3780 | 423 (1)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
1 - filter("CUST_STATE_PROVINCE"='CA' AND "COUNTRY_ID"=52790)
13 rows selected.
結果顯示,優化器預估的行數為20行,和下麵的計算相同,而實際的行數卻為3341行,為何會這樣呢?
SQL> select 55500/145/19 from dual;
55500/145/19
------------
20.1451906
首先,優化器不知道這兩列的關係,不知道CA在國家52790,從而大大低估了返回的數據行;
3 使用列組統計信息
通過上面的實驗,可以得知,如果列之間有一定的相互關係,且where條件出現組合條件時,優化器不能準確的評估返回的行數,那麼對於這種情況,可以對組合列進行統計信息的搜集。
1)搜集組合列統計信息
begin
dbms_stats.gather_table_stats('SH',
'CUSTOMERS_NEW',
method_opt => 'for all columns size 1,for columns (cust_state_province,country_id) size skewonly');
end;
/
PL/SQL procedure successfully completed.
2)查看組合條件對應的執行計劃
explain plan for
select * from sh.customers_new where cust_state_province='CA' and country_id='52790';
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3410015392
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3341 | 655K| 423 (1)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| CUSTOMERS_NEW | 3341 | 655K| 423 (1)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------------------
1 - filter("CUST_STATE_PROVINCE"='CA' AND "COUNTRY_ID"=52790)
13 rows selected.
可以看出預估的行數為3341,而實際的行數為3341,和真實結果一樣。
SQL> select count(1) from sh.customers_new where cust_state_province='CA' and country_id='52790';
COUNT(1)
----------
3341
3)刪除擴展統計信息
begin
dbms_stats.drop_extended_stats('sh',
'CUSTOMERS_NEW',
'(cust_state_province, country_id)');
end;
/
PL/SQL procedure successfully completed.
以上,就是對擴展統計信息中列組統計信息的演示。