直方圖,一種特殊類型的列的統計信息,它能提供表中列的更詳細的數據分佈信息,直方圖將值存放於桶(buckets)中。基於不同值的數目和數據的分佈,資料庫選擇要創建的直方圖類型,直方圖的類型有如下幾種: 頻率直方圖和頂頻直方圖:Frequency histograms and to frequency ...
直方圖,一種特殊類型的列的統計信息,它能提供表中列的更詳細的數據分佈信息,直方圖將值存放於桶(buckets)中。基於不同值的數目和數據的分佈,資料庫選擇要創建的直方圖類型,直方圖的類型有如下幾種:
- 頻率直方圖和頂頻直方圖:Frequency histograms and to frequency histograms;
- 高度平衡直方圖(遺留):Height-Balanced hitograms;
- 混合柱狀圖:Hybrid histograms;
1 直方圖介紹
1.1 使用直方圖的目的
預設情況下,優化器假定列的不同值之間時均勻分佈的。對於包含數據傾斜列(列中數據的分佈不均勻的列),直方圖使優化器能夠為涉及這些列的過濾或連接謂詞生成更準確的基數的估計值,從而生成更精確的執行計劃。
1.2 何時資料庫創建直方圖
使用DBMS_STATS搜集表的統計信息,查詢引用表中的列時,資料庫會根據之前的查詢負載來自動的創建直方圖。基本過程如下:
- 使用DBMS_STATS搜集表的統計信息,且指定METHOD_OPT參數預設為SIZE AUTO;
- 用戶查詢對應的表;
- 資料庫記錄前面查詢時使用的謂詞,並更新數據字典表SYS.COL_USAGE$;
- 再次運行DBMS_STATS時,DBMS_STATS會查詢SYS.COL_USAGE$視圖並根據前面的查詢負載決定哪些列需要直方圖。
示例:
1)創建測試表
SQL> create table sh.sales_new as select * from sh.sales;
Table created.
2)查看統計信息
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)執行查詢
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)搜集統計信息
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','SALES_NEW',OPTIONS=>'GATHER AUTO');
PL/SQL procedure successfully completed.
5)查看統計信息
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)查看列的使用
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
1.3 如何選擇直方圖類型
前面講過,直方圖有多種類型,那麼創建直方圖時,資料庫如何選擇直方圖的類型呢?這裡有幾個參考變數:
- NDV:表示列的不同值的數量;
- n:表示直方圖桶(buckets)的數量,預設時254;
- p:表示內部百分比閾值,等於(1-(1/n))*100;
- DBMS_STATS中estimate_percent參數是否設置為auto_sample_size(預設值)。
下圖展示的是直方圖創建時的決策樹:
2 直方圖基數演算法
對於直方圖,基數的演算法取決於端點數和值等因素,以及列值是否受歡迎。
2.1 端點編號和值(Endpoint Numbers and Values)
端點編號是唯一標識桶的編號,在頻率和混合直方圖中,端點編號是當前桶和之前桶中包含的所有值的累計頻率,例如:端點編號是100的桶表示當前桶和以前所有桶的值的總頻率是100,在高度平衡的直方圖中,優化器按順序給桶編號,從0或1開始。在所有情況下,端點編號就是桶號。
端點值是桶中值範圍內的最大值,例如,如果一個桶只包含52794和52795,那麼端點值是52795。
2.2 受歡迎和不受歡迎值(Popular and Nopopular Values)
直方圖中某個值的受歡迎程度會影響基數估值演算法,具體如下:
- 受歡迎值:受歡迎值出現在多個桶的端點值,優化器通過檢查某個值是否是桶的端點值來確定該值是否受歡迎,如果是,那麼對於頻率直方圖,優化器將從當前桶的端點數減去前一個桶的端點數,混合直方圖存儲了每個端點的信息,如果這個值大於1,那麼該值是受歡迎的。對於受歡迎的值,優化器通過下麵的公式計算基數估計:cardinality of popular value = (num of rows in table) * (num of endpoints spanned by this value / total num of endpoints);
- 不受歡迎值:所有不是受歡迎的值都是不受歡迎的值,對於不受歡迎的值,,優化器通過下麵的公式計算基數估計:cardinality of nonpopular value = (num of rows in table) * density。
2.3 桶壓縮(Bucket Compression)
在某些情況下,為了減少桶的總數,優化器將多個桶壓縮到一個桶中,例如,下麵的頻率直方圖表示第一個桶數是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
3 頻率直方圖
在頻率直方圖中,每個不同的列值對應一個直方圖桶,由於每個值都有自己的專用桶,所以有些桶會有很多值,而有些則很少。
3.1 頻率直方圖滿足的條件
當滿足下麵的條件時,資料庫創建頻率直方圖:
- NDV少於或等於桶數(預設為254);
- DBMS_STATS對應的過程的參數設置為AUTO_SAMPLE_SIZE或指定一個具體的值;
3.2 生成頻率直方圖
本實驗在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
和查詢的結果相同
4 最高頻率直方圖
最高頻率直方圖是頻率直方圖的一種變種,它忽略了統計上不重要的不受歡迎的值。
4.1 最高頻率直方圖滿足的條件
如果一小部分值占了大部分行,那麼在這一小部分值上創建一個頻率直方圖是很有用的,即使NDV大於請求的直方圖的桶的數量。為受歡迎的值創建一個更高質量的直方圖,優化器將忽略不受歡迎的值並創建一個直方圖。
當滿足下麵的條件時,資料庫創建最高頻率直方圖:
- NDV大於直方圖桶的數量(預設為254);
- 前n個頻率值占用的行數百分比等於或大於閾值p,p等於(1-(1/n))*100;
- BMS_STATS對應的過程的參數設置為AUTO_SAMPLE_SIZE;
4.2 生成最高頻率直方圖
本實驗在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.
5 高度平衡直方圖(遺留)
在高度平衡直方圖中,將列值劃分為桶,以便每個桶包含大約相同的數據行。
待續。。。