`
安铁辉
  • 浏览: 241809 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

mysql 2个表字符集不同join时不能正确走索引

阅读更多
昨天一个同事做数据迁移引起一个故障,原因是2张表字符集一个为gbk,一个为utf8,并且join key为vachar类型,导致不能正确索引,导致数据库超时,修改字符集编码后正常。本地重现了一下:

一、搞测试数据,文章最后又脚本
二、建索引
--删除多余索引
drop INDEX index_student_s_age on student ;
drop INDEX index_student_s_no on student ;
drop INDEX index_score_point on score ;
drop INDEX index_score_c_id on score ;

--建索引,建标语句中有,可忽略
CREATE INDEX index_student_s_age on student (s_age);
CREATE INDEX index_student_s_no on student (s_no);
CREATE INDEX index_score_point on score (point);
CREATE INDEX index_score_c_id on score (c_id);


三、测试

1、
引用
explain select a.*,b.* from student a , score b where a.s_no=b.c_id and a.s_no=11 1 SIMPLE b const PRIMARY PRIMARY 4 const 1 1 SIMPLE a ref index_student_s_no index_student_s_no 5 const 1 Using where

可以走到索引


2、修改表编码:仍然可以走到索引,说明join key 都是数值仍然可以走到索引
ALTER TABLE student CONVERT TO CHARACTER SET utf8; 
explain select a.*,b.* from student a , score b 
where a.s_no=b.c_id and a.s_no=14
1	SIMPLE	b	const	PRIMARY	PRIMARY	4	const	            1	
1	SIMPLE	a	ref	    index_student_s_no	index_student_s_no	5	const	1	Using where



3、修改关联字段类型为不同类型,不能正确走到索引
ALTER TABLE score MODIFY c_id VARCHAR(32);
--ALTER TABLE student MODIFY s_no VARCHAR(32);


结论,因为字段类型,编码不同都回造成不能正确走到索引,如果都是数值类型的应该就没问题:
1、2表编码不同, join字段数值类型不同, 不能正常走索引,即使编码相同???
2、2表编码相同,join key都是数值类型,正确走到索引
3、2表编码相同,join key数值类型不同,不能正确走到索引


相关数据:
CREATE TABLE `student` (
  `s_no` int(11) DEFAULT NULL,
  `s_name` varchar(500) DEFAULT NULL,
  `s_age` int(11) DEFAULT NULL,
  `s_sex` varchar(10) DEFAULT NULL,
  KEY `index_student_s_no` (`s_no`),
  KEY `index_student_s_age` (`s_age`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;


CREATE TABLE `score` (
  `c_id` int(11) NOT NULL,
  `c_name` varchar(255) DEFAULT NULL,
  `point` int(11) DEFAULT NULL,
  KEY `index_course_point` (`point`),
  KEY `index_course_c_id` (`point`),
  KEY `index_score_point` (`point`),
  KEY `index_score_c_id` (`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

INSERT INTO `student` VALUES (1, '张无忌', 18, '男');
INSERT INTO `student` VALUES (2, '周芷若', 19, '女');
INSERT INTO `student` VALUES (3, '杨过', 19, '男');
INSERT INTO `student` VALUES (4, '赵敏', 18, '女');
INSERT INTO `student` VALUES (5, '小龙女', 17, '女');
INSERT INTO `student` VALUES (6, '张三丰', 18, '男');
INSERT INTO `student` VALUES (7, '令狐冲', 19, '男');
INSERT INTO `student` VALUES (8, '任盈盈', 20, '女');
INSERT INTO `student` VALUES (9, '岳灵珊', 19, '女');
INSERT INTO `student` VALUES (10, '韦小宝', 18, '男');
INSERT INTO `student` VALUES (11, '康敏', 17, '女');
INSERT INTO `student` VALUES (12, '萧峰', 19, '男');
INSERT INTO `student` VALUES (13, '黄蓉', 18, '女');
INSERT INTO `student` VALUES (14, '郭靖', 19, '男');
INSERT INTO `student` VALUES (15, '周伯通', 19, '男');
INSERT INTO `student` VALUES (16, '瑛姑', 20, '女');
INSERT INTO `student` VALUES (17, '李秋水', 21, '女');
INSERT INTO `student` VALUES (18, '黄药师', 18, '男');
INSERT INTO `student` VALUES (19, '李莫愁', 18, '女');
INSERT INTO `student` VALUES (20, '冯默风', 17, '男');
INSERT INTO `student` VALUES (21, '王重阳', 17, '男');
INSERT INTO `student` VALUES (22, '郭襄', 18, '女');


INSERT INTO `score` VALUES (1, '企业管理', 2);
INSERT INTO `score` VALUES (10, '线性代数', 17);
INSERT INTO `score` VALUES (11, '计算机基础', 13);
INSERT INTO `score` VALUES (12, 'AUTO CAD制图', 15);
INSERT INTO `score` VALUES (13, '平面设计', 11);
INSERT INTO `score` VALUES (14, 'Flash动漫', 1);
INSERT INTO `score` VALUES (15, 'Java开发', 9);
INSERT INTO `score` VALUES (16, 'C#基础', 2);
INSERT INTO `score` VALUES (17, 'Oracl数据库原理', 10);
INSERT INTO `score` VALUES (2, 'max, 8);
INSERT INTO `score` VALUES (3, 'UML', 6);
INSERT INTO `score` VALUES (4, '数据库', 7);
INSERT INTO `score` VALUES (5, '逻辑电路', 6);
INSERT INTO `score` VALUES (6, '英语', 3);
INSERT INTO `score` VALUES (7, '电子电路', 5);
INSERT INTO `score` VALUES (8, 'maozedong思想概论', 4);
INSERT INTO `score` VALUES (9, '西方哲学史', 12);



分享到:
评论

相关推荐

    MySQL中因字段字符集不同导致索引不能命中的解决方法

    索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去...

    mysql查询不走索引及解决方法

    mysql查询,通过explain 分析,没有利用到索引,查询效率不高等出现的问题。

    mysql中or是否走索引详解

    NULL 博文链接:https://bugyun.iteye.com/blog/2242094

    MySQL的or、in、union与索引优化

    一:union all 肯定是能够命中索引的 二:简单的in能够命中索引 三:对于or,新版的MySQL能够命中索引 四、对于!=,负向查询肯定不能命中索引 五、其他方案

    MYSQL字符串强转的方法示例

    注意:需转换的类型必须是left join 后表的字段,否则不走索引 因为联表字段类型不一致,所以不走索引 select t.* from A tleft join B t1 on t.id = t1.id  第一种转换类型 select t.* from A tleft join B t1 ...

    MySQL Order By索引优化方法

    在一些情况下,MySQL可以直接使用索引来满足一个 ORDER BY 或 GROUP BY 子句而无需做额外的排序

    MySQL 函数索引的优化方案

    很多开发人员在使用MySQL时经常会在部分列上进行函数计算等,导致无法走索引,在数据量大的时候,查询效率低下。针对此种情况本文从MySQL5.7 及MySQL8.0中分别进行不同方式的优化。 1、 MySQL5.7 MySQL5.7版本中不...

    oracel 分区表索引失效的问题

    讲解oracle分区表的索引问题,有具体的例子和实验分析

    MySQL前缀索引导致的慢查询分析总结

    前缀索引,并不是一个万能药,他的确可以帮助我们对一个写过长的字段上建立索引。但也会导致排序(order by ,group by)查询上都是无法使用前缀索引的

    Mysql 5.6 隐式转换导致的索引失效和数据不准确的问题

    背景 在一次进行SQl查询时,我试着对where条件中vachar类型的字段去掉单引号查询,这个时候发现这条本应该很快的语句竟然很慢。这个varchar字段有一个复合索引。...没有使用单引号的没有走索引,进行了全表扫描。

    oracle 三种索引

    oracle 三种索引的简单描述,位图、B树、全文索引。

    MySQL去重该使用distinct还是group by?

    走索引时分组种类少distinct快。关于网上的结论做一次验证。 准备阶段屏蔽查询缓存 查看MySQL中是否设置了查询缓存。为了不影响测试结果,需要关闭查询缓存。 show variables like '%query_cache%'; 查看是否开启...

    MYSQL中常用的强制性操作(例如强制索引)

    对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法。同样,在mysql里,也有类似的hint功能。

    ORACLE索引介绍与高性能SQL优化

    ORACLE索引介绍与高性能SQL优化的相关知识

    Oracle索引

    关于Oracle索引的详细介绍,索引的基本概念,怎么创建单列、符合索引。

    高性能MySQL实战课

    通过深入理解 MySQL 的索引结构 B+Tree ,学员能够从根本上弄懂为什么有些 SQL 走索引、有些不走索引,从而彻底掌握索引的使用和优化技巧,能够避开很多实战中遇到的“坑”。 二、MySQL 8.0新特性篇: 主要包括...

    一文解决MySQL大部分问题

    2、空间换时间:建立索引,走索引,避免全表扫描 select id ,name from t where name is null -- 空值不能利用索引,所以还是全表扫描 select id ,name from t where id in(1,2,3) -- 全表扫描 select id,name from...

    Oracle使用强制索引的方法与注意事项

    Oracle使用强制索引 在一些场景下,可能ORACLE不会自动走索引,这时候,如果对业务清晰,可以...--强制索引,/*.....*/第一个星星后不能有空格,里边内容结构为:加号index(表名 空格 索引名)。 --如果表用了别名,注

Global site tag (gtag.js) - Google Analytics