现有两张表goods
和category
(注意两张表的字符集不同):
CREATE TABLE `goods` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id ',
`goods_no` char(10) CHARACTER SET sjis NOT NULL COMMENT '商品编码',
`goods_name` varchar(255) CHARACTER SET sjis NOT NULL COMMENT '商品名称',
`category_no` char(10) NOT NULL COMMENT '所属分类编码',
PRIMARY KEY (`id`),
KEY `idx_goods_no` (`goods_no`),
KEY `idx_category_no` (`category_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
CREATE TABLE `category` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`category_no` char(10) CHARACTER SET utf8 NOT NULL COMMENT '商品分类编码',
`category_name` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '名称',
PRIMARY KEY (`id`),
KEY `idx_category_no` (`category_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='商品分类表';
其中goods
表中的category_no
关联category
表中的category_no
现在要关联查询两张表,分别用三条sql查询,分析执行计划:
1,EXPLAIN SELECT g.* FROM goods g LEFT JOIN category c ON g.category_no = c.category_no where goods_no='10000';
执行计划如下:
2,EXPLAIN SELECT g.* FROM goods g LEFT JOIN category c ON CONVERT ( g.category_no USING utf8 ) = c.category_no where goods_no='10000';
执行计划如下:
3,EXPLAIN SELECT g.* FROM goods g LEFT JOIN category c ON g.category_no = CONVERT ( c.category_no USING utf8mb4 ) where goods_no='10000';
执行计划如下:
看到没,第3条sql即使转换了字符集,也和第1条执行计划一样(这里possible_keys显示为空,key显示用到了索引;实际我在线上遇到的是key列也没有走索引的,导致查询很慢)
而第二条sql,将字符集转换convert放到了=
前边,执行计划中 type列为ref,用到了索引。
疑问 有没有大神知道这是为什么?字符集转换convert放到=
左边和右边有什么区别?为什么放到左边才会走索引?