Oracle日期范围不一致

时间:2011-11-16 18:49:42

标签: performance oracle range long-integer

我在特定的日期范围内运行了一个相当大的查询。当我执行10/01 / 2011-10 / 31/2011的范围时,查询大约需要30秒。由于某种原因,范围永远不会完成。例如01/01 / 2011-01 / 31/2011,几乎所有其他范围,都在预期的时间内完成。

另外,我注意到较小的范围(如一周)需要比较大的范围更长。

1 个答案:

答案 0 :(得分:2)

当Oracle收集表的统计信息时,它会在日期列中记录低值和高值,并使用它来估计谓词的基数。如果在列上创建直方图,它将收集有关列中数据分布的更多详细信息。否则,Oracle的基于成本的优化器(CBO)将采用统一分布。

例如,如果您有一个包含100万行的表和一个DATE列,其值较低的值为2001年1月1日,而值较高的值为2011年1月1日,那么它将假设大约10%数据在2001年1月1日至2002年1月1日的范围内,大约0.027%的数据将来自2008年3月3日的某些时间(1 /(10年*每年365天+闰日)。

只要您的查询使用已知范围内的日期,优化程序的基数估算通常都非常好,因此它对使用计划的决定非常好。如果你超出上限或下限,估计仍然相当不错,因为优化器假设可能存在的数据大于或小于它在采样数据以收集统计数据时所看到的数据。但是当你离优化器统计数据预期看到的范围太远时,优化器的基数估计值太过分了,它最终会选择一个糟糕的计划。在您的情况下,在刷新统计信息之前,优化程序预期的最大值可能是2011年9月25日或26日。当您的查询查找2011年10月份的数据时,优化程序很可能期望查询将返回很少的行,并选择了针对该场景优化的计划,而不是实际返回的大量行。鉴于返回的实际数据量,这导致计划更加糟糕。

在Oracle 10.2中,当Oracle执行硬解析并为加载到共享池中的查询生成计划时,它会查看绑定变量值并使用这些值来估计查询将返回的行数和因此是最有效的查询计划。一旦创建了查询计划,并且直到计划从共享池中老化,相同查询的后续执行将使用相同的查询计划,而不管绑定变量的值如何。当然,下次因为计划已经过时而需要对查询进行硬分析,Oracle将会查看并且可能会看到新的绑定变量值。

Bind variable peeking不是特别受欢迎的功能(11g中的自适应光标共享很多更好)因为它使DBA或开发人员很难预测什么计划是将在任何特定时刻使用,因为您永远不确定优化程序在硬解析期间看到的绑定变量值是否代表您通常看到的绑定变量值。例如,如果您搜索的是1天范围,则索引扫描几乎肯定会更有效。如果您在5年范围内进行搜索,表格扫描几乎肯定会更有效率。但是你最终会使用在硬解析期间选择的任何计划。

最有可能的是,您可以简单地通过确保在基于单调增加值的范围经常查询的表上更频繁地收集统计信息来解决问题(日期列是迄今为止最常见的此类列)。在您的情况下,自问题出现之前收集统计数据大约需要6周时间,因此确保每月或每隔几周收集统计数据可能是安全的,具体取决于收集统计数据的成本。

您还可以使用DBMS_STATS.SET_COLUMN_STATS过程更频繁地明确设置此列的统计信息。这需要更多编码和工作,但可以节省您收集统计信息的时间。这在数据仓库环境中非常有用,但在更普通的OLTP环境中可能会过度。

相关问题