我有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&表2。所以我的查询很简单:
SELECT ... FROM Table1 INNER JOIN Table2 ON Table1.P = Table2.P
结果更令人惊讶:从几个小时(第一个案例)的执行时间减少到2-3秒!
为什么这么不同?这是否意味着复杂的条件总是会降低性能?我该如何改善这个问题?可能是P1,P2索引会有帮助吗?我想保持第一个数据库架构,而不是移动到一个字段P。
答案 0 :(得分:4)
查询不同的原因是优化程序使用的连接策略。基本上有四种方法可以连接两个表:
(并且有这些变体,例如使用索引而不是表,使用分区,以及处理多个处理器。)不幸的是,在SQL Server Management Studio中,(3)和(4)都显示为嵌套循环连接。如果仔细观察,可以区分节点中的参数。
在任何情况下,您的原始联接是前三个之一 - 而且速度很快。这些连接基本上只能用于“等连接”。也就是说,当连接两个表的条件包括相等运算符时。
当您从单个相等切换到“in”或一组“或”条件时,连接条件已从等值连接变为非等值连接。我的观察是SQL Server在这种情况下做了一个糟糕的优化工作(并且,公平地说,我认为其他数据库的功能几乎完全相同)。从良好的连接算法到嵌套循环算法,您的性能受到了打击。
如果不进行测试,我可能会提出以下一些策略。
假设这些是1-1连接,您也可以将其作为一组多个连接执行:
从table1 t1左外连接 table2 t2_11 在t1.p1 = t2_11.p1左外连接 table2 t2_12 在t1.p1 = t2_12.p2左外连接 table2 t2_21 在t1.p2 = t2_21.p2左外连接 table2 t2_22 在t1.p2 = t2_22.p2
然后在SELECT中使用case / coalesce逻辑来获取您实际需要的值。虽然这可能看起来更复杂,但应该非常有效。
答案 1 :(得分:2)
你可以使用4个查询和Union那里结果
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
答案 2 :(得分: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
我怀疑,就处理器而言,上述只是针对相同复杂条件的不同语法。