使用限制性 where 子句(非常小的行子集)的内部连接性能非常慢
Very slow performance for inner join with restrictive where clause (very small subset of rows)
我有两个大的 table 正在使用中间映射 table 加入(结构的详细信息如下)。
我正在尝试在 t1.date = t2.date
和 t1.id_a = int.id_a
以及 int.id_b = t2.id_b
上加入所有三个
我还有一个 where 子句,将数据限制在日期列的一个非常特定的范围内(结果集是 ~25k 行)。
运行 table 1 和 int table 的连接(使用 where 子句)或 table 2 与 int [=52= 的连接] (带有 where 子句)每个字面上需要 2 秒。然后加入这两个结果集应该是微不足道的,table 1 大约有 37k 行,table 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服务器说它会做:
- clustered index seek on t1, seeking my date range (cost 33%)
- compute scalar t.id_a (cost 0%)
- clustered index seek on t2, seeking my date range (cost 33%)
- nested loop to join [2] and [3] (cost 0%)
- non clustered index seek on t_int, seeking t_int.id_a = t1.id_a and t_int.id_b = t2.id_b (cost 33%)
- nested loop to join [4] and [5] (cost 0%)
- compute scalar t.date, t_int.id_b (cost 0%)
Table 1:
date,
id_a,
other columns
(320 万行,日期和 id_a 是聚簇索引的主键)
Table 2:
date,
id_b,
other columns
(1850 万行,日期和 id_b 是聚簇索引的主键)
映射table:
id_a,
id_b,
other columns
(35k 行,id_b 是聚集索引的主键,[id_a, id_b, other_col
] 上的附加 non_clustered 索引)
没有其他索引,也没有任何约束(除了提到的主键约束)。
我已经在 t2 上重建了索引
任何人都可以帮助我做些什么吗?
我已经在 t2 上重建了索引,因为它是碎片化的。但是我没有在 t1 或 t_int 上重建索引,因为它们看起来不错。
感谢 Mohammad Mohabbati 在评论中的建议,我重新构建了它们,查询现在运行不到 1 秒。
所以这里的答案是"rebuild all the indexes, even if they look fine"
,可能对其他有类似问题的人有用
我有两个大的 table 正在使用中间映射 table 加入(结构的详细信息如下)。
我正在尝试在 t1.date = t2.date
和 t1.id_a = int.id_a
以及 int.id_b = t2.id_b
我还有一个 where 子句,将数据限制在日期列的一个非常特定的范围内(结果集是 ~25k 行)。
运行 table 1 和 int table 的连接(使用 where 子句)或 table 2 与 int [=52= 的连接] (带有 where 子句)每个字面上需要 2 秒。然后加入这两个结果集应该是微不足道的,table 1 大约有 37k 行,table 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服务器说它会做:
- clustered index seek on t1, seeking my date range (cost 33%)
- compute scalar t.id_a (cost 0%)
- clustered index seek on t2, seeking my date range (cost 33%)
- nested loop to join [2] and [3] (cost 0%)
- non clustered index seek on t_int, seeking t_int.id_a = t1.id_a and t_int.id_b = t2.id_b (cost 33%)
- nested loop to join [4] and [5] (cost 0%)
- compute scalar t.date, t_int.id_b (cost 0%)
Table 1:
date,
id_a,
other columns
(320 万行,日期和 id_a 是聚簇索引的主键)
Table 2:
date,
id_b,
other columns
(1850 万行,日期和 id_b 是聚簇索引的主键)
映射table:
id_a,
id_b,
other columns
(35k 行,id_b 是聚集索引的主键,[id_a, id_b, other_col
] 上的附加 non_clustered 索引)
没有其他索引,也没有任何约束(除了提到的主键约束)。
我已经在 t2 上重建了索引
任何人都可以帮助我做些什么吗?
我已经在 t2 上重建了索引,因为它是碎片化的。但是我没有在 t1 或 t_int 上重建索引,因为它们看起来不错。
感谢 Mohammad Mohabbati 在评论中的建议,我重新构建了它们,查询现在运行不到 1 秒。
所以这里的答案是"rebuild all the indexes, even if they look fine"
,可能对其他有类似问题的人有用