使用限制性where子句(非常小的行子集)的内部联接的性能非常低

时间:2018-12-11 04:12:41

标签: sql sql-server indexing inner-join query-planner

我有两个要使用中间映射表连接的大表(以下结构的详细信息)。

我正在尝试加入t1.date = t2.datet1.id_a = int.id_aint.id_b = t2.id_b上的所有三个

我还有一个where子句,用于将数据限制在date列的特定范围内(结果集为〜25k行)。

运行表1和int表的联接(带有where子句),或者运行表2和int表的联接(带有where子句),每个过程实际上花费2秒。然后,将这两个结果集(表1的行约37k行和表2的行约200k行)连接起来并不容易。

相反,此查询始终需要8分钟:

select t1.date, t1.id_b, t1.other_cols, t2.other_cols
from t1 
inner join t_int on t1.id_a = t_int.id_a
inner join t_2 on t2.date = t1.date and t2.id_b = t_int.id_b
where t1.date between '2018-10-21' and '2018-12-10'

在估计的(和实际的)执行计划中,SQL Server表示将这样做:

  
      
  1. 在t1上寻找聚集索引,寻找我的日期范围(费用为33%)
  2.   
  3. 计算标量t.id_a(成本为0%)
  4.   
  5. t2上的聚集索引查找,查找我的日期范围(费用为33%)
  6.   
  7. 嵌套循环以加入[2]和[3](费用为0%)
  8.   
  9. 在t_int上进行非聚集索引查找,查找t_int.id_a = t1.id_a和t_int.id_b = t2.id_b(费用为33%)
  10.   
  11. 嵌套循环以加入[4]和[5](费用为0%)
  12.   
  13. 计算标量t.date,t_int.id_b(成本为0%)
  14.   
Table 1:
date,
id_a,
other columns

(320万行,日期和id_a是具有聚集索引的主键)

Table 2:
date,
id_b,
other columns

(1,850万行,日期和id_b是具有聚集索引的主键)

映射表:

id_a,
id_b,
other columns

(35,000行,id_b是具有聚集索引的主键,[id_a, id_b, other_col上的其他非聚集索引)

没有其他索引,也没有约束(除了提到的主键约束)。

我已经在t2上重建了索引

有人可以帮我做什么吗?

1 个答案:

答案 0 :(得分:0)

我已经在t2上重建了索引,因为它是零散的。但是我没有在t1或t_int上重建索引,因为它们看起来还不错。

感谢穆罕默德·穆哈巴蒂(Mohammad Mohabbati)在评论中的建议,我重新构建了所有内容,现在查询运行时间不到1秒。

因此,这里的答案可能对“重建所有索引,即使它们看起来不错”也可能有用,对其他遇到类似问题的人来说