在上一个问题中,我得到了有关 Oracle 统计信息的评论:
Oracle 不知道 50M 大于行数。当然,它有统计数据,但它们可能是旧的和错误的——Oracle 永远不会仅仅因为统计数据错误而允许自己提供不正确的结果
我很确定 Oracle 在准备查询执行计划时依赖于统计信息。在版本 10 之前,建议不时刷新统计信息,并且从 10g 开始,Oracle 会自动收集统计信息。
有人能解释一下 Oracle 查询分析器在多大程度上依赖于统计数据吗?
在上一个问题中,我得到了有关 Oracle 统计信息的评论:
Oracle 不知道 50M 大于行数。当然,它有统计数据,但它们可能是旧的和错误的——Oracle 永远不会仅仅因为统计数据错误而允许自己提供不正确的结果
我很确定 Oracle 在准备查询执行计划时依赖于统计信息。在版本 10 之前,建议不时刷新统计信息,并且从 10g 开始,Oracle 会自动收集统计信息。
有人能解释一下 Oracle 查询分析器在多大程度上依赖于统计数据吗?
Oracle 大量使用统计信息来生成查询执行计划。它不(也不应该)做的是以会影响查询结果的方式使用这些统计信息,这就是您尝试使用“ROWNUM < 50000000”所做的事情。统计数据可能已过时或丢失。但是,这仅意味着 Oracle 生成正确结果的速度可能很慢,并不意味着 Oracle 会返回不正确的结果。
如果 Oracle 像您希望的那样工作,那么它可能会决定“ROWNUM < 50000000”意味着“获取所有行”,即使该表现在包含 60,000,000 行(但过时的统计数据显示它仅包含 49,000,000)。幸运的是它没有。
统计信息对于查询优化器非常重要。应定期自动或手动收集它们。
执行查询时,Oracle 将生成一个可用执行计划池以满足您的查询。从这些执行计划的角度来看,它们是相同的,它们将返回相同的确切结果,这只是实现一个计划比另一个计划更有效率的途径。为了确定这种效率,Oracle 使用每个执行计划中使用的对象生成的统计信息来确定它们的单独成本。如果这些统计数据不存在或陈旧,则与每个计划相关的成本将不太准确,因此可能不会选择最佳计划。
以下是 Oracle 用于确定此成本的一些关键统计数据:
表统计
* Number of rows * Number of blocks * Average row length
列统计
* Number of distinct values (NDV) in column * Number of nulls in column * Data distribution (histogram) * Extended statistics
指数统计
* Number of leaf blocks * Levels * Clustering factor
系统统计
* I/O performance and utilization * CPU performance and utilization
Oracle 基于成本的优化器 (CBO) 使用统计数据来计算执行查询的不同方式的相对成本,以便选择最合适的方式。
总的来说,这工作非常好,并且正在不断改进。例如,在 11g 中,您可以收集多列直方图,这对于在相关列上具有谓词的查询有很大帮助(例如,强相关,如出生月份和星号,或者更弱相关,如性别和身高)。
然而它并不完美。例如,估计两个表之间连接的结果集的基数是相当准确的,就像从过滤操作估计基数一样,但是将两者结合起来需要大量估计,这很容易不准确。在某些情况下,这些问题可以通过提示或使用全局临时表来解决中间结果集。
统计数据的另一个问题是更改它们会改变执行计划,因此最近有更多的运动来阻止持续收集统计数据,或者在实施统计数据之前分析更改对统计数据的影响。
寻找乔纳森·刘易斯的书——它对这个主题进行了非常彻底的处理。