优秀的编程知识分享平台

网站首页 > 技术文章 正文

MySQL的这两个坑你踩过吗?两个非常隐蔽的场景!会让索引失效...

nanyue 2024-10-28 16:39:57 技术文章 7 ℃


有两类非常隐蔽的场景,会让数据库索引失效,而导致全表扫描。

场景一

假设我们有一个超级大的user表,表结构如下:

列名

类型

id

int

phone

varchar(16)

...


我们想查询电话号码为:“13512345678” 的用户:

select * from user where phone=13512345678

上面的查询会导致全表扫描,所以会经历一个漫长的等待......,然后返回空集。

为什么会这样呢?phone列上不是建有索引吗?

phone是varchar类型,而查询条件中13512345678会被当成整型看待,当“列类型”与“where值类型”不符时,不会命中索引。

结论1:“列类型”与“where值类型”不符,不能命中索引,会导致全表扫描。


场景二

如果说场景一比较容易避免,场景二则更加隐蔽

假设我们有两个表:user表和order表。由于某种原因,两个表使用了不同的字符编码,user表 charset=latin1,而 order 表 charset=utf8。两个表的结构如下:

user表:

列名

类型

id

int

...

...

order表:

列名

类型

id

int

user_id

int

...

...

其中order表的user_id列上建有索引。

我们想查询某个用户的所有订单:

select * from user, order where user.id=order.user_id and user.id=1

我们在order表的user_id列上建了索引,所以,我们期望,user表和order相连接时,会使用索引,查询会很快。

然而,经过漫长的等待....

为什么这个简单的联合查询要耗费这么长时间呢?

字符集不同,存储空间不同,所以user表和order表相连接时,索引无效,会扫描order表的所有记录。当order表数据量很大时,执行时间是无法忍受的...

结论2:相连接的两个表的字符编码不同,不能命中索引。


总结

两类隐蔽的不能利用索引的场景:

(1)列类型与where值类型不一致。

(2)联合查询的两个表,字符编码不同。

本文测试于 MySQL5.6。


关注【老张聊架构】,前迅雷大数据CTO,带你成为百万年薪架构师!

最近发表
标签列表