表达式统计信息收集

在数据库优化领域,理解和应用表达式统计信息是提升查询性能的关键。,特别是当查询涉及到使用函数对列进行操作时。

在执行SQL查询时,如果WHERE子句中包含使用表达式的谓词,例如 function(column) = constant ,优化器默认情况下可能无法准确估计谓词的选择性。这是因为除非存在基于函数的索引,否则优化器不知道该函数如何影响列的分布和谓词的基数。为了解决这个问题,Oracle提供了一种名为表达式统计信息的功能,通过收集有关表达式本身的统计信息来提供更准确的估计。

表达式统计信息的重要性

当优化器没有访问表达式统计信息时,它只能依赖于列本身的统计信息来生成查询计划。这可能导致优化器生成次优计划,特别是在查询中使用了转换或函数操作列时。通过为这些表达式收集统计信息,优化器可以获得更准确的估计,从而生成更优的执行计划。

示例:优化基于函数的查询

考虑以下两个查询,它们都旨在从 sh.customers 表中检索位于加利福尼亚州(CA)的客户数量。第一个查询使用了直接的列比较:

SELECT COUNT(*) FROM sh.customers WHERE cust_state_province = 'CA';

该查询返回3341,这是一个精确的结果。

然而,当我们应用一个函数到列上,比如使用 LOWER() 函数来进行不区分大小写的比较:

SELECT * FROM sh.customers WHERE LOWER(cust_state_province) = 'ca';

如果没有适当的表达式统计信息,优化器生成的计划可能基于不准确的行估计值,如以下执行计划所示:

Plan hash value: 2008213504


-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |   555 |   108K|   406   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |   555 |   108K|   406   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
  1 - filter(LOWER("CUST_STATE_PROVINCE")='ca')

在这个例子中,由于缺少表达式 LOWER(cust_state_province)='ca' 的统计信息,优化器估计只有555行匹配,这明显偏离了实际的行数。

解决方案:收集表达式统计信息

为了解决这个问题,我们可以使用 DBMS_STATS 包来为特定表达式收集统计信息。这将使优化器能够访问与查询中使用的表达式相对应的统计信息,从而产生更准确的估计和更优的执行计划。


BEGIN

 DBMS_STATS .GATHER_TABLE_STATS (
   ownname => 'sh' ,
   tabname => 'customers' ,
   method_opt => 'FOR ALL COLUMNS SIZE AUTO FOR COLUMNS (LOWER(cust_state_province))'
  ) ;
END ;

通过收集表达式统计信息,优化器现在可以准确评估基于函数的谓词的选择性,从而生成更接近实际情况的执行计划。



请使用浏览器的分享功能分享到微信等