SQL隐式转换导致索引失效_字符集不一致

梦莱2年前技术文章1870

3.字符集不一致导致索引失效

示例 SQL 如下,通过查看执行计划发现 XXX 和 XXXX 表在进行表关联的时候没有走索引,导致 SQL 扫描数量较大。核实表结构发现表关联对应列都存在索引,最终查看字符集发现,两个表的字符集不同存在隐式转换。

--当前SQL
--DB:lefit_live
SELECT ........
FROM XX lu
LEFT JOIN (
SELECT r.*
FROM XXXXX r
WHERE r.is_delete != 1
GROUP BY r.phone
) luw
ON lu.phone = luw.phone
LEFT JOIN XXX luc ON luc.user_id = lu.user_id
LEFT JOIN XXXX lcc ON lcc.channel_code = luc.channel_code
WHERE 1 = 1
AND lu.user_id = 11111
LIMIT 0, 2

查看表结构发现 lcc 表字符集为 utf8,但是 luc 表字符集为 utf8mb4。utf8mb4和utf8两种不同字符集(编码)类型的字符串在做⽐较时,MySQL会先把utf8 字符串转成utf8mb4 字符集,再做⽐较,这就导致了隐式转换的出现。

utf8mb4 是 utf8 的超集,在做隐式⾃动类型转换时,为了避免数据在转换过程中由于截断导致数据错误,会按数据长度增加的⽅向进⾏转换。

该情况可以通过两种方法进行优化。1.修改表字符集。ALTER table 表名 CHARACTER SET 字符集名称;但该方法一般不推荐,首先需要保证该表可以改为 utf8 字符集;其次还要保证修改后,其他使用该表进行表连接的 SQL 不会出现隐式转换问题;且本身 DDL 就是一个比较消耗资源的操作。2.通过修改 SQL 完成优化。可以通过给驱动表关联列加 convert() 函数,使其临时修改成一致的字符集,进行优化。具体改写 SQL 如下:

--改写后
SELECT lu.user_id, lu.phone, lu.nick_name, lu.head_img, lu.gender
, lu.birthday, lu.status, lu.ctime AS reg_time, luc.ctype, luc.channel_code
, lcc.name AS channel_name, luc.source_id, luw.nickname AS wx_nick_name, luw.unionid
FROM XX lu
LEFT JOIN (
SELECT r.*
FROM XXXXX r
WHERE r.is_delete != 1
GROUP BY r.phone
) luw
ON lu.phone = luw.phone
LEFT JOIN XXX luc ON luc.user_id = lu.user_id
LEFT JOIN XXXX lcc ON lcc.channel_code =convert(luc.channel_code USING utf8)
WHERE 1 = 1
AND lu.user_id = 11111
LIMIT 0, 2

--如需修改数据库字符集可以按照如下语句调整
ALTER TABLE biz_circulateitem DEFAULT CHARACTER SET utf8 ;

改写后,表关联列可以正常走上索引,扫描量大大减少。

表连接过程中,被驱动表的索引字段上加函数操作,会导致对被驱动表做全表扫描。因此在进行函数添加时,应选择将驱动表的字符集修改为被驱动表的字符集。


相关文章

Hbase rowkey设计原则

HBase 中的 rowkey 设计需要遵循以下原则:1 rowkey 唯一原则若在 HBase 中向同一张表插入相同 rowkey 的记录,如没有设置版本数量,则此 rowkey 原先的数据会被覆盖...

Mysql删除binlog

binlog 是记录所有数据库表结构变更(例如CREATE、ALTER TABLE…)以及表数据修改(INSERT、UPDATE、DELETE…)的二进制日志。一、手动删除直接在 /var/lib/m...

docker服务端口不通

docker服务端口不通

一、问题现象两台服务器在同一个安全组,docker启动的服务,从另一台机器telnet该docker服务的端口不通。二、排查过程1.从另一台机器telnet该机器的22端口,可以通。证明服务器的网络没...

Flink sql 集成hive metastore

Flink sql 集成hive metastore

1、前置条件**确认hive metastore版本(本次版本3.1.2) **hive metastore 部署成功hive依赖jar包分发到每个flink节点:/flink-1.13.6    ...

oracle adg容灾切换需要注意的参数

1.DG角色在线转换1.1 角色(主备)和DG有关的角色:primary database 主库,在线服务应用physical standby database 备库,物理备库,在线备份主库数据与主库...

hive创建hbase映射表

hive创建hbase映射表

hbase创建表,导入数据/opt/app/hbase-2.1.0/bin/hbase shell查看已有表,创建新表,查看表结构listcreate 'student', 'info', 'scor...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。