Gre*_*reg 6 performance sql-server-2005 join sql-server
我有一个超过一百万行的表。这些行可以在同一个表中有一个父记录,通过在 6 个不同的列上连接到它自己(即没有单列ParentID
)。根据这些连接,每个孩子都恰好有 1 个父级,并且每个记录要么是父级记录,要么是子级记录(即没有祖父级记录)。
SELECT *
FROM TheTable AS ChildRecords
JOIN TheTable AS ParentRecords
ON ChildRecords.Column1 = ParentRecords.Column1
AND ChildRecords.Column2 = ParentRecords.Column2
AND ChildRecords.Column3 = ParentRecords.Column3
AND ChildRecords.Column4 = ParentRecords.Column4
AND ChildRecords.Column5 = ParentRecords.Column5
AND ChildRecords.Column10 = ParentRecords.Column6
Run Code Online (Sandbox Code Playgroud)
注意第 10 列连接到第 6 列,但该列本身没有找到唯一的父级 - 可能有多个带有column10
= 的“父级” column6
。
这通常工作正常,但是如果我们将它作为更大查询的一部分,SQL Server 通常会先尝试解析此连接,然后再解析其他连接。当它处于 CTE 或加入 CTE 时尤其如此。它通常是查询计划中发生的第一个连接。这通常会导致数以万计的连接,然后再过滤到我感兴趣的 100 条左右的记录。发生这种情况时,查询需要几分钟才能运行。
我注意到我可以通过使其成为左连接来影响查询计划。这是有道理的,因为如果它是左联接,那么 SQL Server 不知道每个孩子都有 1 个父级,因此它总是必须首先找到子级记录。
SELECT *
FROM TheTable AS ChildRecords
LEFT JOIN TheTable AS ParentRecords
ON ChildRecords.Column1 = ParentRecords.Column1
AND ChildRecords.Column2 = ParentRecords.Column2
AND ChildRecords.Column3 = ParentRecords.Column3
AND ChildRecords.Column4 = ParentRecords.Column4
AND ChildRecords.Column5 = ParentRecords.Column5
AND ChildRecords.Column10 = ParentRecords.Column6
Run Code Online (Sandbox Code Playgroud)
当它以这种方式运行查询时,它将时间从几分钟减少到 < 2 秒。
因为每个孩子都有一个父级,左联接给出与内联接相同的结果,但是感觉不对——它应该是内联接。
我已经检查过这个表上的索引设置是否正确,我已经尝试添加和编辑我们拥有的索引,但它不会改变查询计划。时间似乎是因为它正在查询获得每个孩子/父母组合,然后才将其限制为我想要的组合。
我可以强制 SQL Server 按照我指定的顺序运行连接,而不是让它尝试重新排序查询吗?
看来我可以在查询末尾指定 OPTION (FORCE ORDER),这将使连接以正确的顺序发生。有很多人警告不要这样做,因为它会阻止 SQL 优化我的查询,所以我肯定会谨慎使用它(并密切关注这些查询)。
归档时间: |
|
查看次数: |
3353 次 |
最近记录: |