周日,我们在 Oracle 11R2 RAC 集群上运行了每周计划的架构范围统计信息更新。其中一个查询没有明显的数据或代码更改,但现在运行 3 小时而不是 20 分钟。查看 dba_hist_sqlstat ,它运行与以前相同的 SQL,但具有不同的计划。统计数据似乎对其产生了负面影响。因为它是一个涉及几十个表的大型查询,所以他们已经决定恢复受影响表上的统计信息不是一种选择。
通过执行以下命令,我制定了旧的(更好的)和新的(糟糕的)计划:
select * from TABLE(DBMS_XPLAN.DISPLAY_AWR('sqlid'));
但它们是如此不同,以至于它不是一个小的手动调整来让它们回来。
考虑到数据库仍然有很多可用的信息,有没有办法强制它回到旧计划?(而且我们没有调整包。)
您需要使用 SQL 基线来强制执行计划。
此博客描述了所涉及的步骤。您将需要
sql_id
for 语句和plan_hash_value
旧计划的 the。如果您有调整包许可证 - 非常推荐 - 您可以使用 dbms_sqltune 获得更好的计划并为其创建配置文件。如果 sql_id 有一个配置文件,如果启用,数据库将使用它。它还可以与 SQL Plan Stability 完美配合;当您使用 SQL Plan Baselines 时,会自动为配置文件的计划创建和接受基线。
另一方面,看起来你的统计数据确实有问题。很可能存在一种临时内容的表存在问题,即定期清空和填充。如果收集例程在“错误”时刻运行,它会为此类表提供 - 例如 - 0 行,因为它只是在收集时刻被清空并填充了 > 1 的任意数量的行,从而对您的性能造成严重破坏。如果其中有 0 或 1 行,则可能会选择扫描甚至笛卡尔积,这在连接中工作得非常糟糕,其中的数据似乎比统计数据试图告诉的要多。
最简单的方法是恢复参与表的统计信息。
如果您使用的是标准版,请查看Stored Outlines。该功能在 11g 上已弃用,但它是该版本唯一可用的计划稳定性选项。 这是一个很好的例子。