MYSQL LEFT JOIN连接优化案例一则

mysql环境及表信息

SELECT VERSION(); -- 5.6.28-cdb2016-log
SELECT COUNT(*) FROM T_COLUMN; -- 180
SELECT COUNT(*) FROM BSUSER; -- 500105
SELECT COUNT(*) FROM T_TOPIC; -- 29
SELECT VERSION(); -- 5.6.28-cdb2016-log SELECT COUNT(*) FROM T_COLUMN; -- 180 SELECT COUNT(*) FROM BSUSER; -- 500105 SELECT COUNT(*) FROM T_TOPIC; -- 29

问题描述

T_TOPIC和T_COLUMN表分别于BSUSER表做left join查询,两表的记录数及索引相似,但是关联查询语句的执行时间却相差很大。

MySQL在执行join时会把join分为system/const/eq_ref/ref/range/index/ALL等好几类,连接的效率从前往后依次递减。

问题分析及解决

mysql处理多表关联时,当关联列的数据类型和大小相同时,可以更高效的使用列上的索引。当关联列为字符类型时,关联列的字符集如果不同,则不能使用列上的索引。

三个表中的关联字段定义如下

BSUSER:`F_ZGBH` varchar(36) COLLATE gbk_bin NOT NULL DEFAULT

T_COLUMN :`F_CREATE_USERID` varchar(36) COLLATE gbk_bin DEFAULT NULL

T_TOPIC:`F_CREATE_USERID` varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL

可以看到BSUSER和T_COLUMN 关联字段的字符集相同,而和T_TOPIC的关联字段的字符集不同,所以出现了“问题描述”中执行计划和执行时间的差异。

修改T_TOPIC的F_CREATE_USERID字段的字符集后,差异消失。

mysql环境及表信息 SELECT VERSION(); -- 5.6.28-cdb2016-log SELECT COUNT(*) FROM T_COLUMN; -- 180 SELECT COUNT(*) FROM BSUSER; -- 500105 SELECT COUNT(*) FROM T_TOPIC; -- 29 问题描述 T_TOPIC和T_COLUMN表分别于BSUSER表做left join查询,两表的记录数及索引相似,但是关联查询语句的执行时间却相差很大。 MySQL在执行join时会把join分为system/const/eq_ref/ref/range/index/ALL等好几类,连接的效率从前往后依次递减。 问题分析及解决 mysql处理多表关联时,当关联列的数据类型和大小相同时,可以更高效的使用列上的索引。当关联列为字符类型时,关联列的字符集如果不同,则不能使用列上的索引。 三个表中的关联字段定义如下 BSUSER:`F_ZGBH` varchar(36) COLLATE gbk_bin NOT NULL DEFAULT T_COLUMN :`F_CREATE_USERID` varchar(36) COLLATE gbk_bin DEFAULT NULL T_TOPIC:`F_CREATE_USERID` varchar(36) COLLATE utf8mb4_unicode_ci DEFAULT NULL 可以看到BSUSER和T_COLUMN 关联字段的字符集相同,而和T_TOPIC的关联字段的字符集不同,所以出现了“问题描述”中执行计划和执行时间的差异。 修改T_TOPIC的F_CREATE_USERID字段的字符集后,差异消失。
经验分享 程序员 微信小程序 职场和发展