据我了解,复合索引将完成以下情况所需的功能:
SELECT name FROM user WHERE id_city = 3 AND id_type = 5
INDEX 将为 (id_city, id_type)。只要所有查询始终过滤这 2 个组合字段,就不需要其他索引。
但是如果查询中某个字段用于 JOIN 语句而另一个字段用于 WHERE 语句呢?示例:
SELECT user.name AS name
FROM user JOIN friend ON friends.id_str = user.id_str
WHERE friends.id_user = 3
friends 表中的 (id_user, id_str) INDEX 是否足够? (顺便说一句,我不是在询问 user 表,这当然是另一种情况)。
最佳答案
对于您的初始查询,是的,(id_city, id_type)
任意顺序都是最佳选择。加上 name
last 会稍微好一点(因为被“覆盖”)。
继续...
对于该特定查询,具有以下索引:
friend: (id_user, id_str) -- in this order; "covering"
user: (id_str, name) -- in this order; "covering"
这是发生的事情:
- 优化器在
WHERE
中看到JOIN
以及有关其中一个表 (friends
) 的一些内容,因此决定从friend
。 - 要处理
WHERE
,它需要一个以WHERE
中的内容开始的索引,即id_str
。 - 由于
friend
不需要太多其他内容,因此我们将所有列放入索引中,从而“覆盖”。EXPLAIN
将通过Using index
来表明这一点。 - 现在,转到另一个表(
user
)。ON
子句需要id_str
,因此将其放在索引中第一个。 - 再次,让我们通过添加
名称
来玩覆盖游戏。
我更笼统地介绍这些内容 here .
如果您的真实查询看起来在任何方面有所不同,那么一切就都失败了。也就是说,我建议的索引可能也可能有益。
如果您想进一步讨论,请提供
显示创建表
- 真实查询。
关于MySQL 复合索引足以满足使用 JOIN 的查询吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50849345/