直方圖,一種特殊類型的列的統計信息,它能提供表中列的更詳細的數據分佈信息,直方圖將值存放於桶(buckets)中。基於不一樣值的數目和數據的分佈,數據庫選擇要建立的直方圖類型,直方圖的類型有以下幾種:算法
默認狀況下,優化器假定列的不一樣值之間時均勻分佈的。對於包含數據傾斜列(列中數據的分佈不均勻的列),直方圖使優化器可以爲涉及這些列的過濾或鏈接謂詞生成更準確的基數的估計值,從而生成更精確的執行計劃。sql
使用DBMS_STATS蒐集表的統計信息,查詢引用表中的列時,數據庫會根據以前的查詢負載來自動的建立直方圖。基本過程以下:數據庫
示例:測試
1)建立測試表優化
SQL> create table sh.sales_new as select * from sh.sales; Table created.
2)查看統計信息this
SQL> select column_name,notes,histogram from dba_tab_col_statistics where owner='SH' and table_name='SALES_NEW'; COLUMN_NAME NOTES HISTOGRAM ------------------------------ ------------------------------ --------------- AMOUNT_SOLD STATS_ON_LOAD NONE QUANTITY_SOLD STATS_ON_LOAD NONE PROMO_ID STATS_ON_LOAD NONE CHANNEL_ID STATS_ON_LOAD NONE TIME_ID STATS_ON_LOAD NONE CUST_ID STATS_ON_LOAD NONE PROD_ID STATS_ON_LOAD NONE 7 rows selected.
3)執行查詢spa
SQL> select column_name,notes,histogram from dba_tab_col_statistics where owner='SH' and table_name='SALES_NEW'; COLUMN_NAME NOTES HISTOGRAM ------------------------------ ------------------------------ --------------- AMOUNT_SOLD STATS_ON_LOAD NONE QUANTITY_SOLD STATS_ON_LOAD NONE PROMO_ID STATS_ON_LOAD NONE CHANNEL_ID STATS_ON_LOAD NONE TIME_ID STATS_ON_LOAD NONE CUST_ID STATS_ON_LOAD NONE PROD_ID STATS_ON_LOAD NONE 7 rows selected.
4)蒐集統計信息code
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','SALES_NEW',OPTIONS=>'GATHER AUTO'); PL/SQL procedure successfully completed.
5)查看統計信息blog
SQL> select column_name,notes,histogram from dba_tab_col_statistics where owner='SH' and table_name='SALES_NEW'; COLUMN_NAME NOTES HISTOGRAM ------------------------------ ------------------------------ --------------- AMOUNT_SOLD STATS_ON_LOAD NONE QUANTITY_SOLD STATS_ON_LOAD NONE PROMO_ID STATS_ON_LOAD NONE CHANNEL_ID STATS_ON_LOAD NONE TIME_ID STATS_ON_LOAD NONE CUST_ID STATS_ON_LOAD NONE PROD_ID HISTOGRAM_ONLY FREQUENCY 7 rows selected.
6)查看列的使用it
SQL> select * from sys.col_usage$ where obj#=93264; OBJ# INTCOL# EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP ---------- ---------- -------------- -------------- ----------------- ----------- ---------- ---------- --------- 93264 1 1 0 0 0 0 0 25-APR-20
前面講過,直方圖有多種類型,那麼建立直方圖時,數據庫如何選擇直方圖的類型呢?這裏有幾個參考變量:
下圖展現的是直方圖建立時的決策樹:
對於直方圖,基數的算法取決於端點數和值等因素,以及列值是否受歡迎。
端點編號是惟一標識桶的編號,在頻率和混合直方圖中,端點編號是當前桶和以前桶中包含的全部值的累計頻率,例如:端點編號是100的桶表示當前桶和之前全部桶的值的總頻率是100,在高度平衡的直方圖中,優化器按順序給桶編號,從0或1開始。在全部狀況下,端點編號就是桶號。
端點值是桶中值範圍內的最大值,例如,若是一個桶只包含52794和52795,那麼端點值是52795。
直方圖中某個值的受歡迎程度會影響基數估值算法,具體以下:
在某些狀況下,爲了減小桶的總數,優化器將多個桶壓縮到一個桶中,例如,下面的頻率直方圖表示第一個桶數是1,最後一個桶數是23:
ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 6 52793 8 52794 9 52795 10 52796 12 52797 14 52798 23 52799
能夠看到,有幾個桶「丟失」了,最初,桶2到桶6每一個都包含一個值爲52793的實例,優化器將全部這些桶壓縮到具備最高端點數(桶6)的桶中,該桶如今包含5個實例的值52793,這個值是受歡迎的,由於當前桶和前一個桶的端點數之差爲5,所以,在壓縮以前,52793是5個桶的端點。下圖展現了哪些桶是壓縮的,哪些值是受歡迎的:
ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 -> nonpopular 6 52793 -> buckets 2-6 compressed into 6; popular 8 52794 -> buckets 7-8 compressed into 8; popular 9 52795 -> nonpopular 10 52796 -> nonpopular 12 52797 -> buckets 11-12 compressed into 12; popular 14 52798 -> buckets 13-14 compressed into 14; popular 23 52799 -> buckets 15-23 compressed into 23; popular
在頻率直方圖中,每一個不一樣的列值對應一個直方圖桶,因爲每一個值都有本身的專用桶,因此有些桶會有不少值,而有些則不多。
當知足下面的條件時,數據庫建立頻率直方圖:
本實驗在sh.countries_new的列country_subregion_id產生頻率直方圖。
1)生成測試數據
SQL> create table sh.countries_new as select * from sh.countries; Table created. SQL> select country_subregion_id,count(1) from sh.countries_new group by country_subregion_id order by 1; COUNTRY_SUBREGION_ID COUNT(1) -------------------- ---------- 52792 1 52793 5 52794 2 52795 1 52796 1 52797 2 52798 2 52799 9 8 rows selected.
2)蒐集統計信息
begin dbms_stats.gather_table_stats(ownname => 'SH', tabname => 'COUNTRIES_NEW', method_opt => 'for columns country_subregion_id'); end; / PL/SQL procedure successfully completed.
3)查看列統計信息
SQL> select column_name,notes,histogram from dba_tab_col_statistics where owner='SH' and table_name='COUNTRIES_NEW'; COLUMN_NAME NOTES HISTOGRAM ------------------------------ ------------------------------ --------------- COUNTRY_NAME_HIST STATS_ON_LOAD NONE COUNTRY_TOTAL_ID STATS_ON_LOAD NONE COUNTRY_TOTAL STATS_ON_LOAD NONE COUNTRY_REGION_ID STATS_ON_LOAD NONE COUNTRY_REGION STATS_ON_LOAD NONE COUNTRY_SUBREGION_ID FREQUENCY COUNTRY_SUBREGION STATS_ON_LOAD NONE COUNTRY_NAME STATS_ON_LOAD NONE COUNTRY_ISO_CODE STATS_ON_LOAD NONE COUNTRY_ID STATS_ON_LOAD NONE 10 rows selected.
可看到COUNTRY_SUBREGION_ID已蒐集了直方圖信息。
4)查看直方圖信息
select t.endpoint_number, t.endpoint_value from dba_histograms t where t.owner = 'SH' and t.table_name = 'COUNTRIES_NEW' and t.column_name = 'COUNTRY_SUBREGION_ID'; ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 6 52793 8 52794 9 52795 10 52796 12 52797 14 52798 23 52799 8 rows selected.
5)優化器評估52799的基數
SQL> select count(1) from sh.countries_new; COUNT(1) ---------- 23 SQL> select count(1) from sh.countries_new where country_subregion_id=52799; COUNT(1) ---------- 9
cardinality of popular value = (num of rows in table) * (num of endpoints spanned by this value / total num of endpoints)
即:C=23*(9/23)=9
和查詢的結果相同
最高頻率直方圖是頻率直方圖的一種變種,它忽略了統計上不重要的不受歡迎的值。
若是一小部分值佔了大部分行,那麼在這一小部分值上建立一個頻率直方圖是頗有用的,即便NDV大於請求的直方圖的桶的數量。爲受歡迎的值建立一個更高質量的直方圖,優化器將忽略不受歡迎的值並建立一個直方圖。
當知足下面的條件時,數據庫建立最高頻率直方圖:
本實驗在sh.countries_new的列country_subregion_id產生頻率直方圖。
1)生成測試數據
SQL> select country_subregion_id,count(1) from sh.countries_new group by country_subregion_id order by 1; COUNTRY_SUBREGION_ID COUNT(1) -------------------- ---------- 52792 1 52793 5 52794 2 52795 1 52796 1 52797 2 52798 2 52799 9 8 rows selected.
2)蒐集統計信息
begin dbms_stats.gather_table_stats(ownname => 'SH', tabname => 'COUNTRIES_NEW', method_opt => 'for columns country_subregion_id size 7 '); end; / PL/SQL procedure successfully completed.
3)查看列統計信息
SQL> select column_name,notes,histogram from dba_tab_col_statistics where owner='SH' and table_name='COUNTRIES_NEW'; COLUMN_NAME NOTES HISTOGRAM ------------------------------ ------------------------------ --------------- COUNTRY_NAME_HIST STATS_ON_LOAD NONE COUNTRY_TOTAL_ID STATS_ON_LOAD NONE COUNTRY_TOTAL STATS_ON_LOAD NONE COUNTRY_REGION_ID STATS_ON_LOAD NONE COUNTRY_REGION STATS_ON_LOAD NONE COUNTRY_SUBREGION_ID TOP-FREQUENCY COUNTRY_SUBREGION STATS_ON_LOAD NONE COUNTRY_NAME STATS_ON_LOAD NONE COUNTRY_ISO_CODE STATS_ON_LOAD NONE COUNTRY_ID STATS_ON_LOAD NONE 10 rows selected.
可看到COUNTRY_SUBREGION_ID已蒐集了最高頻率直方圖( TOP-FREQUENCY)信息。
4)查看直方圖信息
select t.endpoint_number, t.endpoint_value from dba_histograms t where t.owner = 'SH' and t.table_name = 'COUNTRIES_NEW' and t.column_name = 'COUNTRY_SUBREGION_ID'; ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 6 52793 8 52794 9 52796 11 52797 13 52798 22 52799 7 rows selected.
在高度平衡直方圖中,將列值劃分爲桶,以便每一個桶包含大約相同的數據行。
待續。。。