0

我有一个 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 行?

4

1 回答 1

1
SELECT id FROM users WHERE id = :id

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

如果有 aUNIQUEPRIMARY KEYon id,则只会检查一行。

如果有一个 plain 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子句达到 into。
  3. 可能有多行(同样,取决于索引或缺少这样的索引)。

所以,你的问题“我怎样才能优化它,使它只搜索 1 行”得到了回答:

  • 如果只能有一行,请声明它UNIQUE
  • 如果有时超过on,那么INDEX。但是不要担心检查额外的行;它不是那么昂贵。

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

但这不是故事的结局……

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

请提供SHOW CREATE TABLE两张桌子。然后我可以将答案浓缩到相关部分。请EXPLAIN SELECT ...确认我在说什么。

于 2019-06-19T01:49:28.230 回答