数据库收集的统计数据有时对真实的数据没有代表性。Oracle提供了在某些情况下收集扩展统计数据(extended statistics)的能力,以减轻统计数据收集中的问题。扩展统计数据包括对列组进行多列统计数据的收集,以及在基于函数的列上收集表达式统计数据。以下介绍这两种类型的扩展优化程序统计数据。
1.多列统计数据
当Oracle收集表上的统计数据时,它分别估计每个列的选择性,即使两个或多个列紧密相关时也是如此。Oracle假定各列的选择估计是相互独立的,简単地将独立属性的选择性相乘得出属性组的选择性。这种方法导致低佔列组的真实选择性。你可以收集一组列的统计数据以避免这种低估。
我们用一个简单的例子说明,为什么在列相关时,收集列组而不是单个列的统计数据是一个好办法。在SH.CUSTOMERS表中,CUST_STATE_PROVINCE和COUNTRY_ID列是相关的,前者的值确定了后者的值。下面是一个说明两列之间的关系的查询:
SELECT count(*) FROM sh.customers WHERE cust_state_province='CA';
此査询只使用一个列CUST_STATE_PROVINCE,它得出来自省份"CA"的顾客的数目。下面的査询 还涉及COUNTRY_ID列,返回相同的计数3341。
SELECT count(*) FROM customers WHERE cust_state_province = 'CA' AND country_id=52790;
显然,具有不同COUNTRY_ID列值的相同査询将返回不同的计数(很可能是0,因为CA代表California,另一国家出现相同名字的城市不太可能)。可以收集一组相关的列上的统计数据,如通过估计CUST_STATE_PROVINCE和COUNTRY_ID两列的组合选择性,收集这两个列上的统计数据。数据库可基于数据库负荷收集列组的统计数据。如下一节所述,你可以用DBMS_STATS.CREATE_EXTENDED_STATS 函数建立列组。
2.建立列组
执行CREATE_EXTENDED_STATS函数建立列组,如下例所示:
declare
cg_name varchar2(30);
begin
cg_name := dbms_stats.create_extended_stats(null,'customers','(cust_state_province,country_id)');
end;
/
如这里所示建立列组后,数据库将自动收集列组的统计数据,而不是作为单个实体收集两个列的统计数据。下面的査询验证新列组的成功创建:
SELECT cxtension_name, extension FROM dba_stat_extensions WHERE table_name='CUSTOMERS';
可执行 DROP_EXTENDED_STATS 函数删除一个列组:
exec dbms_stats.drop_extended_stats('sh','customers1','(cust_state_province,country_id)');
3.收集列组的统计数据
可以执行值为for all columns ... 的METHOD_OPT参数的GATHER_TABLE_STATS过程,收集列组的统计数据。通过增加FOR COLUMNS子句,可以让数据窿创建新列组并对它收集统计数据,这些操作全都在一个步骤中完成,如下例所示:
exec dbms_stats.gather_table_stats(
ownname=>null,
tabname=>'customers',
method_opt=>'for all columns size skewonly,for columns (cust_state_province,country_id) size skewonly');
4.表达式统计数据
如果你对某个列应用一个函数,列值将会变化。例如,下面例子中的LOWER函数返回小写串:
SELECT count(*) FROM customers WHERE LOWER(cust_state_province)='ca';
虽然LOWER函数通过把CUST_STATE_PROVINCE列的值转换成小写来转换该列的值,但优化程序只具有原列的估计,没有变化了的列的估计.因此,优化程序并不知道转换后的列值的真实的选择性。你可以收集某些类型的列表达式上的表达式统计数据,在这些情况下,函数保留原列上的原数据分布特性。在你应用TO_NUMBER等函数时就是这样。你可以对用户定义的函数以及基于函数的索引使用基于函数的表达式。
表达式统计数据特性依赖于Oracle的虚拟列功能。可执行 CREATE_EXTENDED_STATS 函数建立列表达式上的统计数据,如下例所示:
SELECT dbms_stats.create_extended_stats(null,'customers','(lower(cust_state_province))') FROM dual;
也可以执行 GATHER_TABLE_STATS 函数建立表达式统计数据:
cxcc dbms_stats.gather_table_stats(null,'customers',
method_opt=>'for all columns size skewonly, for columns (lower(cust_state_province)) size skewonly');
正如对列组统计数据一样,你可以査询DBA_STAT_EXTENSIONS视图找出关于表达式统计数据的详细信息。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




