
SQL INNER JOIN 与 OR:性能瓶颈
最近的性能优化工作突出了一个重要问题:在 OR 条件中使用 INNER JOIN 运算符。 以下查询举例说明了该问题:
<code class="language-sql">SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID OR ot.ID = mt.ParentID</code>
这个查询被证明很慢。 使用 LEFT JOIN 显着提高的性能重写它:
<code class="language-sql">SELECT mt.ID, mt.ParentID, CASE WHEN ot1.MasterID IS NOT NULL THEN ot1.MasterID ELSE ot2.MasterID END AS MasterID FROM dbo.MainTable AS mt LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL</code>
修改后的查询在几秒钟内执行,这是一个实质性的改进。 这引起了人们对 OR 在 JOIN 条件下的一般使用的担忧。
为什么 JOIN 中的 OR 可能会很慢
核心问题是 OR 条件中的 JOIN 会阻止 SQL Server 优化器利用高效的 HASH 或 MERGE 连接。这些优化的连接方法通常对于快速查询执行至关重要。 OR 条件阻止服务器识别查询与两个单独的等值连接的等价性:
<code class="language-sql">SELECT * FROM maintable m JOIN othertable o ON o.parentId = m.id UNION SELECT * FROM maintable m JOIN othertable o ON o.id = m.parentId</code>
这会迫使 SQL Server 选择效率较低的执行计划,从而导致性能下降。
最佳实践:在 OR 条件下避免 JOIN
虽然没有严格禁止,但在 OR 条件下使用 JOIN 通常会阻碍优化并导致性能下降。 对于多个连接条件,单独的等值连接(如上面所示的 LEFT JOIN 和 UNION 或 LEFT JOIN 和 CASE 语句)通常可以提供卓越的性能。 这使得查询优化器能够利用其最有效的算法。
以上是在 INNER JOIN 条件中使用'OR”是否总是对 SQL 性能不利?的详细内容。更多信息请关注PHP中文网其他相关文章!