公司原来的MYSQL服务器版本为5.5,现在要升级为5.6。
由于数据量不大,我们决定直接导出数据到新建的5.6版本的数据库中。
原来5.5版数据库字符集是 utf8
迁移5.6版数据库字符集是 utf8mb4数据迁移后,第二天发现有大量的查询SQL占用CUP资源,
排查这些SQL来源于开发人员创建的自定义函数。
这些函数内容比较简单(类似与根据 ID 获取一些信息),
理想中都应该走索引的,基本上不消耗多长时间就可查询出结果。
MYSQL针对函数或存储过程中传递进的参数,如果是varchar类型
时则默认会进行转换字符集校对规则与数据库保持一致。执行的时候,使用 SHOW FULL PROCESSLIST;命令查询执行中的SQL如下:
select msisdn注意到上面的“utf8mb4_general_ci”字符集校对规则,
用 SHOW FULL COLUMNS FROM t_app_users 查看该表的user_id字段的字符集校对规则。
结果发现是user_id字段字符集校对规则是utf8_general_ci。
---------------------------------------------------------------------------------------Field------Type-----------Collation ....
....## 省略USER_ID----varchar(32)----- utf8_general_ci ....
....## 省略当函数或存储过程中参数与查询关联的字段 字符集校对规则不一样时,将
导致该字段上的索引失效!!!
问题的原因在于当初从5.5版本DUMP数据时没有指定字符集!
导出数据时切记加上指定字符集参数:
mysqldump --default-character-set='utf8mb4' ....
1. 一开始根本没有怀疑索引失效,采用 show profiles; 命令查看执行的状态。
(1)SET profiling = 1;
(2)SELECT func_get_msisdn(a.USER_ID) msisdn
FROM t_user_recharge a WHERE a.id = 178213;
(3)SHOW profiles; 展示的主要信息如下:
------------------------------------------------------------------------------------------------------------------------------(4)SHOW profile ALL FOR QUERY 184;
## 或查询系统信息表 information_schema.PROFILING 进行查询
发现状态“status” 为“Sending data”最耗时和性能!!!其他步骤都很好。
------------------------------------------------------------------------------------------------------------------------------Status----------Duration-----------CPU_user------CPU_system....
.... ## 省略
Sending data-----4.846844----------------3.834224 -----------0.04....
.... ## 省略(5) 感到困惑的时,函数中的SQL 拿出来在查询分析器中执行 几乎秒出数据,
而且查询执行计划也是使用上索引了。问题出在哪?(6) 采用 SHOW STATUS 或借助mysql可视化开发工具即可查看以上SQL的执行状态。
最终发现参数 “Handler_read_rnd_next” 几乎和表的总记录一样!!!“Handler_read_rnd_next” 官方文档解释:
Number of requests to read the next row in the data file.
This value is high if you are doing a lot of table scans.
在数据文件中读下一行的请求数。如果你正进行大量的表扫描,
该值较高。通常说明你的表索引不正确或写入的查询没有利用索引。(7) 将表索引去除后查询看看,发现和函数执行的耗时一样。
总总迹象表明确实是没用上索引或是说索引几乎无效。
(8) 后来在 www.baidu.com 上找寻答案,总之找了很久无法解答这个问题。
再后来 有同事在国外网站上找到一个相关的论坛,里面描述的和我们
遇到的问题情况很相似。以下是论坛主要描述内容:
This could be a character set issue.(9) 最后发现 确实是 字符集校对规则不一样时,将导致该字段上的索引失效!!!
问题原因在上面第二点已经述说过了。 这里感谢同事们一起努力帮助解决问题。