ADMIN_TIME_FILTER 包含一系列变更日期范围,这些日期范围经常通过自动化进行更新。我们有共同的日期范围(ThisYear,ThisDay等)和一些更深奥的范围。该表严格存在于从连接中的TEST_RUNS中过滤数据的方法。
TEST_RUNS 包含我们关心的实际数据,并且拥有数百万行。我们有一堆定义的视图将这两个表连接在一起,因此我们只需更新ADMIN_TIME_FILTER表并将更改传播到视图。除了日期之外,没有行将这两个表链接在一起。
问题是估计的行数大幅下降,导致查询效果不佳。这是一个简单的查询,展示了糟糕的估计:
with test as (
SELECT a.* FROM TEST_RUNS a
INNER JOIN ADMIN_TIME_FILTER b ON b.ID = 5 -- ID for ThisYear range
AND a.date_time BETWEEN b.start_date AND b.end_date
)
select count(*) from test
以下是查询计划:
统计不是问题。我可以运行以下查询并获得准确的行估计值
with test as (
select tr.* from test_runs tr
where tr.date_time between '2012-01-01 00:00:00' and '2012-12-31 00:00:00'
)
select count(*) from test
切换我们的连接方法不是一项简单的任务,所以我正在寻找一种替代方法来改进行估计。
由于性能影响,索引视图似乎不是一个可行的选择。
答案 0 :(得分:2)
问题不在于行数。您的查询被设置为非等值连接。除了使用嵌套循环之外,SQL Server没有其他办法来处理连接。
如果您在“a”表中有ID,则以下内容可能有所帮助:
with test as (
SELECT a.*
FROM TEST_RUNS a INNER JOIN
ADMIN_TIME_FILTER b
ON a.id = b.id and b.ID = 5 and -- ID for ThisYear range
a.date_time BETWEEN b.start_date AND b.end_date
)
select count(*) from test
通过匹配表之间的“id”,SQL Server可以考虑其他连接算法,例如合并连接或散列连接。
我怀疑可能有另一种解决方法。 B使用的索引是什么?我建议(id,start_date,end_date)。引擎可能决定使用日期索引来满足查询。