我们有按日期分区的TABLE A,不包含今天的数据,它只包含前一天的数据和今年的数据。
我们还有按日期划分的表B,其中包含今天的数据以及前一天到今年的数据。在表B的顶部有一个视图,View_B
连接View_C
,View_D
和左外连接表E. View_C
和View_D
均选择来自1个表,并且没有加入任何其他表。所以View_B
看起来像
SELECT b.Foo, c.cItem, d.dItem, E.eItem
FROM TABLE_B b JOIN View_C c on c.cItem = b.cItem
JOIN View_D d on b.dItem = d.dItem
LEFT OUTER JOIN TABLE_E on b.eItem = e.eItem
View_AB
将表A和View_B
连接到提取日期以及另一个约束。所以它看起来像:
SELECT a.Col_1, b.Col_2, ...
FROM TABLE_A a LEFT OUTER JOIN View_B b
on a.ExtractDate = b.ExtractDate and a.Foo=b.Foo
-- no where clause
当从前一天以外的任何事物中搜索数据时,查询分析器会执行预期的操作并执行哈希匹配连接以完成外部联接并从表B读取大约116页的数据。如果运行前一天但是,查询优化器吓坏了并使用嵌套连接,扫描表7000次以上并在连接中读取8,000,000多页。
我们可以伪造它/通过使用连接提示强制它使用不同的查询计划,但是这会导致查看表B的视图中的任何约束导致优化器抛出查询无法完成的错误由于加入提示。
编辑以添加页面/扫描=与前一天运行的一次扫描时相同的数字,优化程序正确选择哈希而不是嵌套连接。
正如评论中所提到的,我们通过在TABLE_B
上创建覆盖索引来覆盖View_B
中的联接,从而严重降低了影响,但IO仍然高于优化程序选择的IO正确的计划,特别是因为除了前一天的搜索之外,索引基本上是多余的。
sqlplan位于http://pastebin.com/m53789da9,抱歉这不是格式化的版本。
答案 0 :(得分:1)
如果您可以为每个查询发布.sqlplan,这肯定会有所帮助,但我的预感是您在查询当天之前的日期时获得并行计划,并且嵌套循环可能 在表中包含的分区上的一个常量循环,然后为每个分区生成一个工作线程(有关这方面的更多信息,请参阅SQLCAT post on parallel plans with partitioned tables in Sql2005)。但是,如果没有看到计划,则无法验证是否是这种情况。
答案 1 :(得分:0)
如果有人碰到这个问题,问题似乎只与分区方案有关。即使我们每晚都运行统计信息更新,但它似乎是SQL Server
我们通过CREATE STATISTICS TABLE_A_ExtractDate_Stats ON TABLE_A WITH FULLSCAN
解决了这个问题。现在搜索前一天和随机抽样的天数似乎可以生成正确的计划。