在测试这种方法时,我发现了一些对我来说没有多大意义的东西.当我在事实视图上过滤“分区列”时,优化器仅搜索相关表.此外,如果我在维度表上过滤该列,则优化程序会删除不必要的表.
但是,如果我过滤维度的某些其他方面,则优化程序会查找每个基表的PK / CI.
以下是有问题的查询:
select od.[Year],AvgValue = avg(ObservationValue) from dbo.v_Observation o join dbo.ObservationDates od on o.ObservationDateKey = od.DateKey where o.ObservationDateKey >= 20000101 and o.ObservationDateKey <= 20051231 group by od.[Year]; select od.[Year],AvgValue = avg(ObservationValue) from dbo.v_Observation o join dbo.ObservationDates od on o.ObservationDateKey = od.DateKey where od.DateKey >= 20000101 and od.DateKey <= 20051231 group by od.[Year]; select od.[Year],AvgValue = avg(ObservationValue) from dbo.v_Observation o join dbo.ObservationDates od on o.ObservationDateKey = od.DateKey where od.[Year] >= 2000 and od.[Year] < 2006 group by od.[Year];
Here’s a link到sql Sentry Plan Explorer会话.
我正在研究实际上对较大的表进行分区,以查看是否可以以类似的方式响应分区.
我确实获得了对维度的一个方面进行过滤的(简单)查询的分区消除.
https://gist.github.com/swasheck/9a22bf8a580995d3b2aa
“旧的”基数估算器获得了一个更便宜的计划,但这是因为每个(不必要的)索引搜索的基数估计值较低.
我想知道是否有一种方法可以让优化器在按维度的另一个方面进行过滤时使用密钥列,以便它可以消除对不相关表的搜索.
sql Server版本:
Microsoft sql Server 2014 - 12.0.2000.8 (X64) Feb 20 2014 20:04:26 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
解决方法
我还必须发出:
UPDATE STATISTICS dbo.ObservationDates WITH ROWCOUNT = 73049;
获得下面显示的计划.上传时缺少此表的统计信息. 73,049这个数字来自Plan Explorer附件中的Table Cardinality信息.我使用sql Server 2014 SP1 CU4(内部版本12.0.4436)和两个逻辑处理器,最大内存设置为2048 MB,除了4199之外没有跟踪标志.
然后,您应该获得具有动态分区消除功能的执行计划:
select od.[Year],AvgValue = avg(ObservationValue) from dbo.v_Observation o join dbo.ObservationDates od on o.ObservationDateKey = od.DateKey where od.[Year] >= 2000 and od.[Year] < 2006 group by od.[Year] option (querytraceon 4199);
计划片段:
这看起来可能更糟,但过滤器都是启动过滤器.示例谓词是:
每次迭代循环时,都会测试启动谓词,并且只有当它返回true时才会执行下面的Clustered Index Seek.因此,动态分区消除.
这可能不如静态消除那么有效,特别是如果计划是平行的.
您可能需要在视图上尝试MAXDOP 1,FAST 1或FORCESEEK等提示以获得相同的计划.分区视图(如分区表)的优化程序成本选择可能很棘手.
关键是您需要一个具有启动过滤器的计划,以通过分区视图来消除动态分区.