在 2 个谓词上使用 OR 连接与 2 个单独连接每个 1 个谓词的性能比较

Performance comparison on Join with OR on 2 predicates vs 2 separate joins 1 predicate each

像这样在 ON 子句上使用带有 OR 的 2 个谓词的连接对性能有何影响:

 SELECT GS.GuitarType,GD,GuitarColor
 FROM Prod.Guitars GS
 LEFT JOIN Prod.Guitar_Detail GD ON (GS.GuitarID = GD.GuitarID OR GS.GuitarID  = GD.GuitarCatNum)

VS.像这样:

 SELECT GS.GuitarType,GD,GuitarColor
 FROM Prod.Guitars GS
 LEFT JOIN Prod.Guitar_Detail GD ON GS.GuitarID = GD.GuitarID 
 LEFT JOIN Prod.Guitar_Detail GD2 ON GS.GuitarID  = GD.GuitarCatNum

注意事项: 我们必须使用 LEFT JOIN 不能使用 INNER。 我已经 运行 两个查询,后者执行得更好。

还有一个问题,第二个不会return多行吧?因为它们都在同一个 table 上连接,所以它们应该只保留 GS table 对吗?

第一个查询是否必须匹配两次?或者为什么它的表现与第二个不同?

让我倒序回答。

Also another question, the 2nd won't return more rows right? Because they're both being joined on the same table, they should both preserve the GS table only right?

查询不同(区别在于如何处理空值),并且应该预期不同的执行时间。一切都归结为如何使用 GD.GuitarID 和 GD.GuitarCatNum。

a) 如果设置了 GD.GuitarID 并且 GD.GuitarCatNum 为 null,则查询将 return 相同的数据。
b) 如果设置了 GD.GuitarID 并且 GD.GuitarCatNum 包含与 GD.GuitarID 相同的值,则第二个查询将 return 重复行。
c) 如果 GD.GuitarID 为 null 并且设置了 GD.GuitarCatNum,则查询将 return 相同的行数,但 GD.GuitarColor 将被 return 编辑为 null。

现在,假设情况 a),执行计划如下所示:

案例 1)

SELECT 
  GS.GuitarType,
  GD.GuitarColor 
FROM 
  Guitars GS 
  LEFT JOIN Guitar_Detail GD 
  ON (GS.GuitarID = GD.GuitarID OR 
      GS.GuitarID = GD.GuitarCatNum)

Access Plan:
-----------
    Total Cost:         18.3602
    Query Degree:       1

              Rows 
             RETURN
             (   1)
              Cost 
               I/O 
               |
                3 
             >NLJOIN
             (   2)
             18.3602 
                2 
         /-----+------\
        2               1.5 
     TBSCAN           TBSCAN
     (   3)           (   4)
     8.99536          9.07676 
        1                1 
       |                |
        2                2 
 TABLE: DB2INST1    TABLE: DB2INST1  
     GUITARS       GUITAR_DETAIL
       Q2               Q1

案例二)

SELECT 
  GS.GuitarType,
  GD.GuitarColor 
FROM 
  Guitars GS 
  LEFT JOIN Guitar_Detail GD 
  ON GS.GuitarID = GD.GuitarID 
  LEFT JOIN Guitar_Detail GD2 
  ON GS.GuitarID = GD.GuitarCatNum

    Total Cost:         27.2798
    Query Degree:       1

                               Rows 
                              RETURN
                              (   1)
                               Cost 
                                I/O 
                                |
                                 2 
                              >NLJOIN
                              (   2)
                              27.2798 
                                 3 
                 /--------------+---------------\
                2                                  1 
             HSJOIN<                            NLJOIN
             (   3)                             (   6)
             18.0326                            9.01796 
                2                                  1 
         /-----+------\                     /-----+------\
        2                2                0.5               2 
     TBSCAN           TBSCAN            TBSCAN           TBSCAN
     (   4)           (   5)            (   7)           (   8)
     8.99536          8.99536           0.0226           8.99536 
        1                1                 0                1 
       |                |                 |                |
        2                2                 1                2 
 TABLE: DB2INST1    TABLE: DB2INST1    TABFNC: SYSIBM    TABLE: DB2INST1  
  GUITAR_DETAIL       GUITARS           GENROW        GUITAR_DETAIL
       Q2               Q1                Q4               Q6

希望对您有所帮助。

OR 通常表现不佳,尤其是在联接中。最好将数据库设计为不需要这些类型的连接。

然而,我们有时都受困于设计,在这种情况下,使用 UNION ALL 通常性能更高(如果两个连接字段相互排斥)。如果字段不互斥并且您不希望重复,则 UNION 会更慢但更好。