【12c】帶你瞭解Oracle 12c數據庫擴展的統計信息(Extended Statistics)的蒐集

在Oracle數據庫中,優化器欲產生最優的執行計劃,須要依賴於相關對象的統計信息的蒐集。數據庫能夠自動的蒐集執行計劃,也能夠使用程序包DBMS_STATS進行手動蒐集,本篇對常規統計信息的蒐集不作說明,重點演示下關於擴展的統計信息(Extended Statistics)的的蒐集。sql

1 擴展的統計信息介紹

在執行SQL時,where條件後的單個列的統計信息很容易去決定對應列的謂詞的選擇性,可是,若是where條件後包含同一張表的多個列做爲謂詞時,那麼單個列的統計信息就不能顯示出列之間的關係了,這時,優化器根據單列的統計信息獲得的執行計劃就可能不是最優的了。這個問題能夠經過列組(column group)來解決,經過對列組進行統計信息的蒐集,來反映一組列的相互關係,從而使優化器選擇最優的執行計劃,列組的統計信息稱爲擴展的統計信息。Oracle中,擴展的統計信息包含:數據庫

  • 列組統計信息: 當一張表的多個列同時出如今一條SQL語句時,這種類型的擴展統計信息能夠改進基數估計
  • 表達式統計信息:當對謂詞使用表達式時,這種類型的統計信息能夠改進優化器評估。

如圖:展現了sh.customers表中兩個列cust_state_province和contry_id列的統計信息,以及這兩個列組成的列組的統計信息,列組的名稱是由系統產生。ide

 

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)查詢列統計信息code

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'的數據量orm

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.

看下面的計算,和優化器預估的行數相匹配:blog

SQL> select 55500/145 from dual;hash

 

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.

以上,就是對擴展統計信息中列組統計信息的演示。

相關文章
相關標籤/搜索