0

  • 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 

这是查询计划:

查询计划

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

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

帮助

放弃我们的连接方法并不是一项简单的任务,因此我正在寻找一种替代方法来改进行估计。

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

4

1 回答 1

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

于 2012-10-05T20:46:53.170 回答