MySQL内连接VS左连接w/IS NOT NULL?

Bri*_*ian 6 mysql

以下是否存在性能差异?

SELECT person.id
FROM person
LEFT JOIN address ON person.id = address.personID
WHERE address.personID IS NOT NULL
Run Code Online (Sandbox Code Playgroud)

VS

SELECT person.id
FROM person
INNER JOIN address ON person.id = address.personID
Run Code Online (Sandbox Code Playgroud)

此查询应显示具有地址记录的所有人员ID(并非所有人都这样做).这里合乎逻辑的做法是使用内部连接,如第二个示例所示.由于不完全重要的原因(查询是从查询构建器生成的),我可能必须使用第一种方法.

好奇是什么影响.MySQL在LEFT JOIN中做了很多额外的工作,然后将该字段与null进行比较以减少设置吗?也许这就是INNER JOIN如何在幕后工作?

spe*_*593 5

如下所示,这两个查询可能有不同的执行计划:

SELECT p.*, s.*
  FROM p
  LEFT
  JOIN s ON s.col = p.col
 WHERE s.col IS NOT NULL

SELECT p.*, s.*
  FROM p
 INNER
  JOIN s ON s.col = p.col

id select_type table  type poss key  key_len ref   rows Extra
-- ----------- ------ ---- ---- ---- ------- ----- ---- --------
 1 SIMPLE      p      ALL  -    -    -       -        3
 1 SIMPLE      s      ref  s_ix s_ix 9       p.col    1

id select_type table  type poss key  key_len ref   rows Extra
-- ----------- ------ ---- ---- ---- ------- ----- ---- -----------------------------
 1 SIMPLE      s      ALL  s_ix -    -       -        2
 1 SIMPLE      p      ALL  p_ix -    -       -        3 Using where; Using join buffer
Run Code Online (Sandbox Code Playgroud)

因此,我们必须得出结论,性能可能存在差异。在小型设备上,差异可以忽略不计。大集合可能会在性能上表现出显着差异;我们希望 INNER JOIN 更加高效。完全有可能有一个测试用例可以证明 LEFT JOIN 的更好性能,但我还没有找到。


Bil*_*win 3

这可能取决于MySQL的版本,因为优化器代码在每个版本中都有改进。这可能是旧版本对左外连接做了更多工作,导致表扫描,即使找到特定的然后以相反方向进行连接person会更有效。address

@spencer7593 演示了两种连接类型导致优化器对表进行不同排序的情况,这意味着左连接强制首先访问左表。(尽管在他的示例中,“使用连接缓冲区”表明连接没有索引,因此这可能是异常情况。)

但我见过优化器检测到查询相当于内部联接的情况,因为“外部”表的 WHERE 子句中有条件。因此,它为左外连接生成与内连接完全相同的优化计划,并允许表重新排序。