mysql表连接,因类型不匹配而导致索引失效的场景

一,场景说明

表A字段:

a1 手机号,有索引

b1 关联用字段,bigint 数字类型

其他字段

表B字段:

b1 关联用字段,varchar 字符串类型,有索引

其他字段

现在计划将两个表通过b1字段进行连接,注意,两个表的b1字段类型不同。

二,错误的sql

select *

from A

join B on A.b1=B.b1

where a.phone=xxx;

三,现象

1,上述sql执行会非常慢,表B的b1字段有索引但是没什么用。

2,上述sql用explain解析后,在key列中显示,会使用B.b1字段索引。

3,上述sql用explain解析后,在row列中显示,行数几乎等于表B的所有行。

四,知识点

1,字段关联时,如果字段类型不同,会触发隐式转换。

当关联的两个字段类型不同时,MySQL会进行隐式转换,上述sql相当于执行了:

select *

from A

join B on A.b1=CAST(B.b1 AS UNSIGNED)

where a.phone=xxx;

关联表B时,使用了函数,所以索引会失效。

2,隐式转换的策略,数字优先。

既然会隐式转换,那么问题来了:MySQL为什么选择把表B的b1转换成数字,而不是把表A的b1转换成字符串,这样关联表B时不就能用索引了么?

因为,MySQL做隐式转换是有优先级的,数字类型(INT, DECIMAL等) > 字符串类型(VARCHAR, CHAR等)

也就是说,当数字 = 字符串时,MySQL会将字符串转换为数字。

这个优先级的设定也能解释一个更常见的索引失效场景:

1,当字段col是数字时,where col='123'; 能用索引。因为字段类型是数字,MySQL会把字符串隐式转成数字,索引生效。

2,当字段col是字符串时,where col=123; 不能用索引。因为字段类型是字符串,MySQL不会把数字隐式转为字符串,索引无效。

3,explain结果中key列的索引,包含索引扫描和索引查询两种。

索引扫描和索引查询都会使explain结果的key列显示目标索引,Extra列也都会显示Using index,但这不代表此索引就会高效生效。

索引扫描:把索引列拿出来用了。基本要扫描索引的每一行,所以效率基本等于全表扫描,真正需要查询时不一定用的上索引。

索引查询:查询时先用索引匹配目标行,再查询行中其他字段信息。这是"真使用索引"。

在上面的例子中,MySQL只是把表B的b1字段索引列拿出来批量做了一下隐式转换,真正查询表B的时候是用数字类型查的,用不上索引。

4,explain的结果不能只看key列。

key列能表示是否用到索引,而rows列能体现索引性能,如果发现key列有值,而rows的数字几乎等于全表数据量,基本可以认定是只命中了索引扫描,但查询性能不高。

五,解决方案

解决方案按实际情况和业务内容进行处理,比如显式进行数字到字符串的类型转换:

select *

from A

join B on cast(A.b1 as char)=B.b1

where a.phone=xxx;

相关推荐
会博通·代码搬运工几秒前
疾控档案落地难点:异构业务系统并存,高价值纸质凭证如何回流业务闭环
数据库·档案管理·档案管理系统·智能扫描设备·会博通
数智启示录2 分钟前
Apache Kafka Consumer 扩到 40 个仍不提速:Partition 上限锁死有效并行度 【Kafka合集】
数据库·经验分享·分布式·缓存·面试·kafka·apache
数智启示录9 分钟前
Apache Kafka 幂等 Producer 的边界:Exactly-Once 到了 MySQL 为什么失效 【Kafka合集】
数据库·经验分享·分布式·mysql·面试·kafka·apache
Java小白笔记11 分钟前
Java 实现阿里云 OSS 文件上传链路:普通上传、秒传、分片与断点续传
java·开发语言·数据库·spring·阿里云
—Miss. Z—12 分钟前
计算机三级数据库技术—填空题
数据库·mysql
数智启示录36 分钟前
Apache Kafka 同 Key 仍会乱序:从分区 Offset 到业务可见的四道边界 【Kafka 合集】
大数据·数据库·经验分享·分布式·面试·kafka·apache
烬羽1 小时前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
星云API技术支持1 小时前
企业微信二次开发外部群:群聊数据与联系人信息如何建立关联
数据库·php·企业微信
我不是程序员三三1 小时前
桌面管理软件哪个最好?从一次上线翻车事故,拆解选型评估与配置落地全流程
数据库
落木萧萧8251 小时前
MyBatis 关联查询的四种写法,为什么最后都变回了手写 XML
java·数据库·后端