直方图,一种特殊类型的列的统计信息,它能提供表中列的更详细的数据分布信息,直方图将值存放于桶(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.
在高度平衡直方图中,将列值划分为桶,以便每一个桶包含大约相同的数据行。
待续。。。