比如一个联合索引 index('user_id', 'created_at')
,我写了下面的 SQL
语句
select
*
from
tweet
where
created_at < '2021-11-11'
and user_id = 1
优化器会把上面的语句优化为下面的语句吗?
select
*
from
tweet
where
user_id = 1
and created_at < '2021-11-11'
比如一个联合索引 index('user_id', 'created_at')
,我写了下面的 SQL
语句
select
*
from
tweet
where
created_at < '2021-11-11'
and user_id = 1
优化器会把上面的语句优化为下面的语句吗?
select
*
from
tweet
where
user_id = 1
and created_at < '2021-11-11'
@唯一丶 已经回答的很好了,我再补充一点,那就是即便 MySql 自己优化了,结果也未必说“最优”的。
因为 MySql 的优化策略是“基于成本模型的优化”(Optimizer Cost Model),所以并不会把所有的优化可能都生成并对比一遍。尤其是各版本 MySql 优化器底层实现的还不一样(比如 5.6 和 5.7 的优化器就完全是俩),就导致优化策略也未必相同。所以即便是有优化,也不一定会把你的条件顺序调整成最优的,尤其是当你有多个看似都符合最左前缀原则的索引的情况下。
所以某些情况下需要我们能主动告知 MySql 一种查询方式、使之加入到优化器的对比序列中,也就是需要自己指定好查询条件的顺序。
15 回答11.6k 阅读✓ 已解决
9 回答1.7k 阅读✓ 已解决
3 回答1.6k 阅读✓ 已解决
5 回答1.1k 阅读
2 回答982 阅读✓ 已解决
4 回答1.5k 阅读
4 回答1.4k 阅读✓ 已解决
你对左前缀理解错了。
你这种情况是可以用到索引的。
左前缀是指这种情况走不了索引
而这种情况可以
因为
user_id
在联合索引的左边。如果有索引 (a, b, c) 那么
where a, b, c
、where a, b
、where a
(where 后的顺序无关,可以随意组合,但是跟出现的字段有关)都是可以走到索引的。但是where b, c
就不走索引了,因为按照左前缀原则,这里必须要出现a
才行。使用如下。
上表中,第二行,
a, c
虽然是联合索引(a, b, c)
中有两个字段,但是因为这里没有出现b
,按照做前缀原则就断开了,所以只能使用到a
注意上文中 where 顺序可以随意组装,比如
a, b, c
你可以写成a, c, b
、c, a, b
等,这些都不影响,但是出现的字段必须是上面写到的。除了 where 外,还有 order。
where a order c
这个就只会用到 (a, b, c) 中的(a)
,而如果是where a order b
则能用到(a, b)