我有一个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行?
答案 0 :(得分:1)
SELECT id FROM users WHERE id = :id
如果id
上没有索引,则会扫描整个表。
如果UNIQUE
上有PRIMARY KEY
或id
,将仅检查一行。
如果有一个普通的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
它将执行“嵌套循环连接”:
messages
中找到满足m.user_id = :user_id
的事件(见上文)。users
子句进入ON
。因此,您的问题“如何优化它,使其仅搜索1行”:
UNIQUE
。INDEX
。但是不必担心要检查额外的行;它不是那么昂贵。您说“只有1个具有该ID的用户”,但未指定哪个表中的ID。
但这还不是故事的结局...
LEFT JOIN
可能变成JOIN
。在这种情况下,users
可能是第一个要查看的表。还要注意,优化器足够聪明,可以推断出您想要u.id = :user_id
。无论如何,NLJ将从users
开始,然后进入messages
。同样,索引的类型很重要。
请为两个表提供SHOW CREATE TABLE
。然后,我可以将答案压缩到相关部分。请提供EXPLAIN SELECT ...
以确认我在说什么。