【问题标题】:Does JOIN or LEFT JOIN keep checking in a SELECT query?JOIN 或 LEFT JOIN 是否继续检查 SELECT 查询?
【发布时间】:2019-11-01 15:32:45
【问题描述】:

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

【问题讨论】:

  • 每个用户只有一条消息吗?
  • 请在代码问题中给出minimal reproducible example--剪切&粘贴&运行代码;具有期望和实际输出的示例输入(包括逐字错误消息);标签和明确的规范和解释。对于包含 DBMS/产品和 DDL 的 SQL,其中包括约束、索引和基表初始化。对于包含 EXPLAIN 结果的 SQL 性能。 (约束、索引和计划对性能至关重要。)
  • @Don'tPanic 每个用户可以有很多条消息
  • 阅读一本关于关系查询实现/优化的教科书。阅读手册重新索引和优化中的所有内容,包括专门的连接优化。您应该在考虑提出问题并将您对这些问题的任何剩余问题相关联之前完成此操作。请参阅 How to Ask、其他 help center 链接和投票箭头鼠标悬停文本。

标签: mysql sql performance join select


【解决方案1】:
SELECT id FROM users WHERE id = :id

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

如果id 上有UNIQUEPRIMARY KEY,则只会检查一行。

如果有一个普通的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. 对于每个这样的行,根据ON 子句访问users
  3. 可能有多行(同样,取决于索引或缺少此类)。

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2015-02-22
    • 2012-09-05
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    相关资源
    最近更新 更多