2

我有一个非常简单的查询,它给了我意想不到的结果。欢迎提供有关在何处进行故障排除的提示。

简化,查询是:

SELECT Obs.obsDate, 
       Obs.obsValue, 
       ObsHead.name
  FROM ml.Obs Obs 
  JOIN ml.ObsHead ObsHead ON ObsHead.hdId = Obs.hdId
 WHERE obs.hdId IN (53, 54)

这给了我一个查询成本:963。但是,如果我将查询更改为:

SELECT Obs.obsDate, 
       Obs.obsValue, 
       ObsHead.name
  FROM ml.Obs Obs 
  JOIN ml.ObsHead ObsHead ON ObsHead.hdId = Obs.hdId
 WHERE ObsHead.name IN ('BP SYSTOLIC', 'BP DIASTOLIC')

尽管它(应该)返回相同的数据,但估计成本会飙升至17688。这里的问题可能出在哪里?谢谢。

编辑:查询计划说索引ObsHead.Name用于范围扫描,而 ObsHead 上的表访问成本仅为 4。还有另一个索引Obs.hdId用于范围扫描,成本为 94:它是表之间的嵌套循环连接最高可达 17K。

4

4 回答 4

1

可能有一个索引hdId(如果它是主键,我怀疑是这种情况)而不是name它意味着第二个查询必须进行全表扫描。

于 2010-03-10T14:35:35.657 回答
1

成本仅对比较一个查询的不同计划有用;它们对于比较不同的查询不是那么有用。

您需要查看计划并根据它们执行的操作来比较它们。

我怀疑这些查询的实际性能将是相似的 - 但是知道第一个查询是否使用哈希连接会很有趣,如果obs匹配的记录百分比很大,这可能会有所帮助。

于 2010-03-11T02:33:36.797 回答
1

我发现优化器提供的成本很有趣,但不是特别有用。我发现比较查询的最佳方法是运行它们并查看它们相对于彼此的执行情况。

分享和享受。

于 2010-03-11T12:09:58.230 回答
1

如前所述,该计划的成本不用于比较两个不同的查询,仅用于比较同一查询的不同路径。

这只是一个猜测,但在这种情况下,计划的基数字段可能对您更有用。如果 OBSHEAD 上的索引不是唯一的并且统计信息是使用估计值收集的,那么优化器可能不知道在查询该表时需要多少行。基数会告诉您这是否正确(理想情况下,您将看到 OBSHEAD 的基数为 2)。

另一个建议是检查 OBS 的统计信息。这似乎是一个经常增长的表,在这种情况下,1 月 28 日还不足以收集统计数据。假设对该表启用了监控,下面的查询可以告诉您统计信息是否过时并且需要刷新。

select owner, table_name, last_analyzed, stale_stats
from all_tab_statistics
where owner = 'ML' and table_name = 'OBS';

select owner, index_name, last_analyzed, stale_stats
from all_ind_statistics
where owner = 'ML' and table_name = 'OBS';
于 2010-03-12T22:27:27.423 回答