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

梦莱3年前技术文章1968

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 ;

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

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


相关文章

Clickhouse冷热数据分离实践

配置多卷存储策略使用Clickhouse的存储策略功能,可以实现冷热数据分离存储。我们可以将业务上访问频繁的数据放到热存储区(如高性能SSD磁盘),将业务上较少访问的数据放在冷存储区(如价格更便宜、空...

Helm部署

Helm部署

1、helm介绍在没使用helm之前,向Kubernetes部署应用,需要依次部署deployment、svc等,步骤教繁琐,况且随着很多项目微服务化,复杂的应用在容器中部署以及管理显得较为复杂,he...

详解迁云流程

详解迁云流程

一、现有云端环境梳理可以通过阿里云工单申请导出网络架构图,在图的信息上梳理阿里云现有架构二、制定迁移方案根据梳理的信息,确定实例迁移的方案,有夸账号迁移,跨地域迁移,IDC上云等不同场景。需要考虑的是...

SQL Server优化入门系列(四)——  找到Top SQL

SQL Server优化入门系列(四)—— 找到Top SQL

说明从会话信息中我们可以查看实例当前正在运行的SQL、当前被Block的SQL。但是如果要查看过去一段时间执行的SQL,我们有几个选择1、通过外部SQL审计平台记录所有SQL。2、通过SQL Serv...

EasyMR之Yarn资源队列管理

EasyMR之Yarn资源队列管理

设想一下,你现在所在的公司有一套线上的hadoop集群。A部门经常做一些定时的BI报表,B部门则经常使用一些软件做一些临时需求。那么他们肯定会遇到同时提交任务的场景,这个时候到底如何分配资源满足这两个...

Redis 慢查询相关配置

Redis 慢查询相关配置

一、查询生命周期一条查询的生命周期:发送命令命令排队执行命令返回结果Redis 慢日志只统计 “执行命令” 步骤 3 的耗时,所以没有慢查询并不代表客户端没有超时问题。二、慢日志配置参数慢日志相关的参...

发表评论    

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