JOIN或LEFT JOIN是否继续检查SELECT查询?

时间:2019-06-18 23:52:55

标签: mysql sql performance join select

我有一个JOIN查询,但我需要对其进行优化以提高性能。

例如,在此查询中:

"SELECT id FROM users WHERE id = :id"

由于查询末尾没有LIMIT 1,因此该选择查询将继续搜索。如果我在该查询的末尾添加LIMIT 1,它将仅选择一个并停止搜索更多内容。

这是我的问题和疑问:

"SELECT messages.text, users.name
FROM messages
LEFT JOIN users
ON messages.from_id = users.id
WHERE messages.user_id = :user_id"

JOIN users ON messages.from_id = users.id部分中,由于只有1个具有该ID的用户,在找到该查询后它将继续搜索吗?如果可以,如何优化它,使其仅搜索1行?

1 个答案:

答案 0 :(得分:1)

SELECT id FROM users WHERE id = :id

如果id上没有索引,则会扫描整个表。

如果UNIQUE上有PRIMARY KEYid,将仅检查一行。

如果有一个普通的INDEX,它将从第一个匹配项开始扫描,直到找到不匹配的id

为此:

SELECT  m.text, u.name
    FROM  messages AS m
    LEFT JOIN  users AS u  ON m.from_id = u.id
    WHERE  m.user_id = :user_id

它将执行“嵌套循环连接”:

  1. messages中找到满足m.user_id = :user_id的事件(见上文)。
  2. 对于每个这样的行,请基于users子句进入ON
  3. 可能有多行(同样,取决于索引或缺少该行)。

因此,您的问题“如何优化它,使其仅搜索1行”:

  • 如果只有一行,请声明UNIQUE
  • 如果有时还有更多,则INDEX。但是不必担心要检查额外的行;它不是那么昂贵。

您说“只有1个具有该ID的用户”,但未指定哪个表中的ID。

但这还不是故事的结局...

LEFT JOIN 可能变成JOIN。在这种情况下,users可能是第一个要查看的表。还要注意,优化器足够聪明,可以推断出您想要u.id = :user_id。无论如何,NLJ将从users开始,然后进入messages。同样,索引的类型很重要。

请为两个表提供SHOW CREATE TABLE。然后,我可以将答案压缩到相关部分。请提供EXPLAIN SELECT ...以确认我在说什么。