MySQL插入中文1366报错以及索引失效的小问题

MySQL插入中文1366报错以及索引失效的小问题中文插入失败原理和姐姐方法 InnoDB 的 B tree 数据结构中导致索引失效的情况和原理剖析 mysql1366

大家好,欢迎来到IT知识分享网。

今天在日常维护中遇到几个个小问题,比较有意思

1.  在数据迁移后,重新数据失败,发现报错

ERROR 1136 (21S01): 。。。。。

2.  在接口调用时,发现查询效率极其低下,估计是索引失效

这里新建一个表复现一下

目录

1. 插入中文报错1366

2. 索引失效的小问题

总结:


1. 插入中文报错1366

MySQL插入中文1366报错以及索引失效的小问题MySQL插入中文1366报错以及索引失效的小问题

新建一个test数据库以及一个emp表

create table emp( id int unique primary key, name varchar(10), age int, gender char(1) )

依次展开故事

此时insert插入数据

 insert into emp values(1,'张三',12,'男'),(2,'李四',18,'女');

会发现报一个错

MySQL插入中文1366报错以及索引失效的小问题

1366,这个错误就是在mysql表中有一个或者多个字段的编码不是utf-8

解决:

通过show create table emp 查看,发现数据表中的内容为latin1字符集

MySQL插入中文1366报错以及索引失效的小问题

于是,给这张表重新设置字符集

alter table emp default character set utf8;

 MySQL插入中文1366报错以及索引失效的小问题

然后,重新去插入数据

MySQL插入中文1366报错以及索引失效的小问题

依然报错,查看建表语句,发现字符集确实是utf8

MySQL插入中文1366报错以及索引失效的小问题

是因为表设置了,但是行依然是latin1字符集

给行也设置

 alter table emp change gender gender varchar(20) character set utf8;

 此时再去插入就OK了

MySQL插入中文1366报错以及索引失效的小问题

2. 索引失效的小问题

在发现问题后,通过慢日志,profile等,发现了是索引失效的问题

首先给张张表建立一下索引

1. 默认的唯一主键索引

2. age的常规索引

3. name和gender的联合索引

MySQL插入中文1366报错以及索引失效的小问题

 再添加一个字段tap,不设置索引MySQL插入中文1366报错以及索引失效的小问题

1. 首先,就是 “ 最左前缀法则 ”  

     这里不多演示,就是一句话,联合查询带头大哥不能不在,后边的兄弟不能乱

2. 头部模糊搜索导致索引失效

这里先演示一下

MySQL插入中文1366报错以及索引失效的小问题

 发现第一次查询时, 索引是OK的,但是当头部模糊搜索后,type成了ALL,索引失效了

所有,在日常维护和开发中,要避免对头部的模糊搜索,后续会讲原理

3. or链接导致的索引失效

演示

MySQL插入中文1366报错以及索引失效的小问题

 对于or链接来说,当or 两侧都有索引时,or后的索引就会失效

4. 对于索引列进行运算导致索引失效

MySQL插入中文1366报错以及索引失效的小问题

此处对有索引的age进行简单运算-,但是索引就会失效 


总结:

MySQL默认的InnoDB引擎使用的是B+tree的数据结构,一个节点只存一个键值对

从本质上来说,联合索引也是一个B+树,和单值索引不同的是,联合索引的键值对不是1,而是大于1个。
a, b 排序分析
a顺序:1,1,2,2,3,3
b顺序:1,2,1,4,1,2
可以发现a字段是有序排列,b字段是无序排列(因为B+树只能选一个字段来构建有序的树),在a相等的情况下,b字段是有序的。
平时中我们要对两个字段排序,是不是先按照第一个字段排序,如果第一个字段出现相等的情况,就用第二个字段排序。这个排序方式同样被用到了B+树里。
分析最佳左前缀原理
先举一个遵循最佳左前缀法则的例子
select * from testTable where a=1 and b=2
分析如下:
首先a字段在B+树上是有序的,所以我们可以通过二分查找法来定位到a=1的位置。
其次在a确定的情况下,b是相对有序的,因为有序,所以同样可以通过二分查找法找到b=2的位置。
再来看看不遵循最佳左前缀的例子
select * from testTable where b=2

分析如下:
我们来回想一下b有顺序的前提:在a确定的情况下。
现在你的a都飞了,那b肯定是不能确定顺序的,在一个无序的B+树上是无法用二分查找来定位到b字段的。
所以这个时候,是用不上索引

like索引失效原理
where name like “a%”

where name like “%a%”

where name like “%a”

我们先来了解一下%的用途

  • %放在右边,代表查询以”a”开头的数据,如:abc
  • 两个%%,代表查询数据中包含”a”的数据,如:cab、cba、abc
  • %放在左边,代表查询以”a”为结尾的数据,如cba

为什么%放在右边有时候能用到索引

  • %放右边叫做:前缀
  • %%叫做:中缀
  • %放在左边叫做:后缀

没错,这里依然是最佳左前缀法则这个概念

开始分析
一、%号放右边(前缀)
由于B+树的索引顺序,是按照首字母的大小进行排序,前缀匹配又是匹配首字母。所以可以在B+树上进行有序的查找,查找首字母符合要求的数据。所以有些时候可以用到索引。
二、%号放右边
是匹配字符串尾部的数据,我们上面说了排序规则,尾部的字母是没有顺序的,所以不能按照索引顺序查询,就用不到索引。
三、两个%%号
这个是查询任意位置的字母满足条件即可,只有首字母是进行索引排序的,其他位置的字母都是相对无序的,所以查找任意位置的字母是用不上索引的。

一句话,InnoDB是B+tree数据结构,检索时,条件不满足当然就会索引失效了

当然,导致索引失效的原因远远不止这些,此上只是我早上遇到的问题

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/154360.html

(0)
上一篇 2025-02-26 16:15
下一篇 2025-02-26 16:25

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信