1

我有 2 个表,其中有几个相同的字段需要在 JOIN 条件下链接。例如,在每个表中都有字段:P1、P2。我想编写以下连接查询:

SELECT ... FROM Table1
   INNER JOIN
   Table2
      ON    Table1.P1 = Table2.P1
         OR Table1.P2 = Table2.P2
         OR Table1.P1 = Table2.P2
         OR Table1.P2 = Table2.P1

在我有巨大表的情况下,这个请求执行了很多时间。

我试图测试仅具有一个条件的查询请求多长时间。首先,我以这种方式修改了表格,所有来自 P2 和 P1 的数据都作为新行复制到了 Table1 和 Table2 中。所以我的查询很简单:

SELECT ... FROM Table1 INNER JOIN Table2 ON Table1.P = Table2.P

结果更令人惊讶:执行时间从数小时(第一种情况)减少到 2-3 秒!

为什么如此不同?这是否意味着复杂的条件总是会降低性能?我该如何改善这个问题?可能是 P1,P2 索引会有所帮助吗?我想保留第一个数据库模式,而不是移动到一个字段 P。

4

3 回答 3

4

查询不同的原因是优化器使用了连接策略。基本上有四种方法可以连接两个表:

  1. “哈希连接”:在其中一个表上创建一个哈希表,用于查找第二个表中的值。
  2. “Merge join”:按 key 对两个表进行排序,然后按顺序读取 join 的结果。
  3. “索引查找”:使用索引在一个表中查找值。
  4. “嵌套循环”:将每个表中的每个值与另一个表中的所有值进行比较。

(而且还有一些变化,例如使用索引而不是表、使用分区以及处理多个处理器。)不幸的是,在 SQL Server Management Studio 中,(3) 和 (4) 都显示为嵌套循环连接。如果仔细观察,可以从节点中的参数中看出区别。

无论如何,您的原始连接是前三个连接之一——而且速度很快。这些连接基本上只能用于“等连接”。也就是说,当连接两个表的条​​件包括相等运算符时。

当您从单个相等切换到“in”或一组“or”条件时,连接条件已从等连接变为非等连接。我的观察是,在这种情况下,SQL Server 在优化方面做得很糟糕(而且,公平地说,我认为其他数据库也做同样的事情)。您的性能影响是从一个好的连接算法到嵌套循环算法的影响。

如果不进行测试,我可能会建议以下一些策略。

  1. 在两个表中的 P1 和 P2 上建立索引。SQL Server 甚至可以将索引用于非等连接。
  2. 使用另一个解决方案中建议的联合查询。每个查询都应该正确优化。
  3. 假设这些是 1-1 连接,您也可以将其作为一组多个连接来执行:

    从 t1.p1 上的 table1 t1 左外连接 table2 t2_11 = t2_11.p1 t1.p1 上的左外连接 table2 t2_12 = t2_12.p2 t1.p2 上的左外连接 table2 t2_21 = t2_21.p2 t1 上的左外连接 table2 t2_22。 p2 = t2_22.p2

然后在 SELECT 中使用 case/coalesce 逻辑来获得您真正想要的值。尽管这可能看起来更复杂,但它应该非常有效。

于 2012-09-09T23:51:06.160 回答
2

你可以使用 4 查询和联合那里的结果

SELECT ... FROM Table1
INNER JOIN
Table2
  ON    Table1.P1 = Table2.P1
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON   Table1.P1 = Table2.P2
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON    Table1.P2 = Table2.P1
UNION
SELECT ... FROM Table1
INNER JOIN
Table2
  ON   Table1.P2 = Table2.P2
于 2012-09-09T11:30:56.243 回答
0

使用 CTE 是否有助于提高绩效?

;WITH Table1_cte 
AS
(
SELECT 
      ...
      [P] = P1
FROM Table1
UNION   
SELECT 
      ...
      [P] = P2
FROM Table1
)
, Table2_cte 
AS
(
SELECT 
      ...
      [P] = P1
FROM Table2
UNION   
SELECT 
      ...
      [P] = P2
FROM Table2
)
SELECT ... FROM Table1_cte x
   INNER JOIN
   Table2_cte y
      ON x.P = y.P

我怀疑,就处理器而言,以上只是相同复杂条件的不同语法。

于 2012-09-09T14:35:56.783 回答