错误的行估计在日期范围内连接两个表

时间:2012-10-05 20:21:19

标签: sql sql-server-2005 inner-join

  • TEST_RUNS(ID int,Date_Time datetime,Row1 int,Row2 int,Row3 int,Row4 int)
  • ADMIN_TIME_FILTER(ID int,Name varchar(20),Start_Date datetime,End_Date datetime)

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 

以下是查询计划:

queryplan

统计不是问题。我可以运行以下查询并获得准确的行估计值

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

帮助

切换我们的连接方法不是一项简单的任务,所以我正在寻找一种替代方法来改进行估计。

由于性能影响,索引视图似乎不是一个可行的选择。

1 个答案:

答案 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)。引擎可能决定使用日期索引来满足查询。