我遇到查询问题,其中查询计划表明15%的执行成本是针对一个表的。但是,这个表非常小(只有9行)。
显然,如果查询中涉及的最小表具有最高成本,则会出现问题。
我的猜测是,查询一次又一次地循环遍历同一个表,而不是缓存结果。
我该怎么办?
抱歉,我无法粘贴确切的代码(这非常复杂),但这里有类似的内容:
SELECT Foo.Id
FROM Foo
-- Various other joins have been removed for the example
LEFT OUTER JOIN SmallTable as st_1 ON st_1.Id = Foo.SmallTableId1
LEFT OUTER JOIN SmallTable as st_2 ON st_2.Id = Foo.SmallTableId2
WHERE (
-- various where clauses removed for the example
)
AND (st_1.Id is null OR st_1.Code = 7)
AND (st_2.Id is null OR st_2.Code = 4)
答案 0 :(得分:2)
将这些执行计划统计数据与一小部分盐进行比较。如果这个表相对于所有其他表来说“不成比例地小”,那么这些成本统计可能实际上并不意味着一个小山豆。
我的意思是......想一想...... : - ) ...如果它是一张小桌子,实际上是什么呢?可能,“它是某个文件中某个糟糕的4K存储页面。”我们读了一次,我们得到了它,期间。故事结局。什么(实际上......)没有索引;没有(实际......)需要来索引它;并且,在一天结束时,DBMS将像我们一样理解这一点。别担心。
现在,说了 ......还有一件事:确保似乎归因于“小桌子”的“成本”实际上不是 通过非常昂贵的访问加入的表格而引起的。如果那些表没有合适的索引,或者如果写入的查询不是能够有效地使用它们,那么就是你的实际问题; 那是查询优化器实际上试图告诉你的内容。 (“它只是一台计算机......有时它会反过来。”)
答案 1 :(得分:2)
如果没有查询计划,这里很难解决您的问题,但您的示例中有一条明显的线索:
AND (st_1.Id is null OR st_1.Code = 7)
AND (st_2.Id is null OR st_2.Code = 4)
对于SQL Server来说,这将是非常难以优化的,因为几乎不可能准确地估计基数。将鼠标悬停在查询计划的元素上,查看EstimatedRows vs. ActualRows和EstimatedExecutions与ActualExecutions。我的猜测是关闭的。
不确定整个查询是什么样的,但您可能想看看是否可以使用UNION运算符将其重写为两个查询,而不是使用OR逻辑。
答案 2 :(得分:0)
嗯,由于可用的信息有限,我可以建议您确保所有用于比较的列都已正确编入索引。
此外,您尚未说明是否存在实际性能问题。即使这些表访问占用了查询时间的90%,如果仅查询,则很可能不会出现问题(例如)十分之一秒。