【问题标题】:SELECT with JOIN where joined row is NULLSELECT with JOIN 其中连接行为 NULL
【发布时间】:2014-01-28 04:41:26
【问题描述】:

我正在尝试从一个表中选择在另一个表中没有对应关系的行。

为此,我目前正在使用LEFT JOINWHERE joined_table.any_column IS NULL,但我认为这不是最快的方法。

SELECT * FROM main_table mt LEFT JOIN joined_table jt ON mt.foreign_id=jt.id WHERE jt.id IS NULL

此查询有效,但正如我所说,我正在寻找更快的替代方法。

【问题讨论】:

  • 这就是要走的路。试试explain select ... 看看你可能需要在哪里添加索引。
  • @juergend 问题是我的实际查询要长得多,复杂得多,所以它太慢了,以至于 MySQL 服务器在 10 分钟后超时。所以我正在尝试对查询的各个部分进行优化。

标签: mysql query-optimization


【解决方案1】:

您的查询是对此的标准查询:

SELECT *
FROM main_table mt LEFT JOIN
     joined_table jt
     ON mt.foreign_id=jt.id
WHERE jt.id IS NULL;

你也可以试试这个:

SELECT mt.*
FROM main_table mt
WHERE not exists (select 1 from joined_table jt where mt.foreign_id = jt.id);

在某些版本的 MySQL 中,它可能会产生更好的执行计划。

【讨论】:

    【解决方案2】:

    根据我使用 MSSQL 的经验,使用的语法(通常)产生与 WHERE NOT EXISTS() 语法完全相同的查询计划,但是这是 mysql,所以我不能确定性能!!

    也就是说,我更喜欢使用 WHERE NOT EXISTS() 语法,原因如下:

    • 更易于阅读。如果你会说一点英语,任何人都可以推断出查询的含义
    • 它更加万无一失,我见过人们在可 NULL 字段上测试 NULL
    • 由于 JOIN,它不会产生像“双重记录”这样的副作用。如果引用的字段是唯一的,则没有问题,但是我再次看到人们选择“键不足”导致主表对连接表多次命中的情况......当然,他们使用 DISTINCT 再次解决了它(aarrgg!!! =)

    至于性能,请确保在引用的字段上有一个(唯一的)索引,如果可能的话,在两个表之间放置一个 FK 关系。查询方面,我怀疑您是否可以从中榨取更多。

    我的 2 美分。

    【讨论】:

    • 谢谢。如果我在两列上都有索引,但没有 FK 关系,在性能方面会不会很重要?
    • 与很多数据库一样:找出答案的唯一方法就是尝试一下。
    【解决方案3】:

    您正在运行的查询通常是最快的选项,只需确保您有一个 mt.foreign_id 和 jt.id 的索引。

    您提到此查询更复杂,因此问题可能出在查询的另一部分。你应该检查执行计划,看看有什么问题并修复它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多