问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

mysql建索引导致insert失败

发布网友 发布时间:2022-12-16 21:28

我来回答

2个回答

热心网友 时间:2023-09-11 02:01

经典问题:

1、如果 A,B 两列都有索引,那么

select * from Table where A=a or B=b;

会走索引码:

答案:会,因为 A,B都有索引;

2、如果 A,B有索引,但是C没有索引;

select * from Table where A=a or B=b or C =c;

会走索引吗?

答案:不会走,因为C是or的形式,且没有索引,看下面的分析:

3、如果 建了A B联合索引,但是查询的时候 是B A,会走索引吗?

select * from Table where B=b and A=a ;

答案: 会走索引,mysql会自动优化;

3、如果 建了A B联合索引,也建了 B,A 联合索引,但是查询的时候 是B A,会走那个索引吗?

select * from Table where B=b and A=a ;

答案: 不一定走 BA 索引,走那个索引,需要mysql会把sql优化,看 A列的数据过滤多,还是B的过滤多;,如果 A的列数据能过滤更多数据,那么会走AB,如果B的列能过滤更多数据,则走BA;

大家都知道,一条查询语句走了索引和没走索引的查询效率是非常大的,在我们建好了表,建好了索引后,但是一些不好的sql会导致我们的索引失效,下面介绍一下索引失效的几种情况

数据准备

新建一张学生表,并添加id为主键索引,name为普通索引,(name,age)为组合索引



CREATE TABLE `student` (
`id` int NOT NULL COMMENT 'id',
`name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年龄',
`birthday` datetime DEFAULT NULL COMMENT '生日',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`) USING BTREE,
KEY `idx_name_age` (`name`,`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
插入数据

INSERT INTO `student` VALUES (1, '张三', 18, '2021-12-23 17:12:44');
INSERT INTO `student` VALUES (2, '李四', 20, '2021-12-22 17:12:48');



1.查询条件中有or,即使有部分条件带索引也会失效
例:

explain SELECT * FROM `student` where id =1

此时命中主键索引,当查询语句带有or后

explain SELECT * FROM `student` where id =1 or birthday = "2021-12-23"

发现此时type=ALL,全表扫描,未命中索引

总结:查询条件中带有or,除非所有的查询条件都建有索引,否则索引失效

2.like查询是以%开头


explain select * from student where name = "张三"

非模糊查询,此时命中name索引,当使用模糊查询后

explain select * from student where name like "%三"

发现此时type=ALL,全表扫描,未命中索引

3.如果列类型是字符串,那在查询条件中需要将数据用引号引用起来,否则不走索引


explain select * from student where name = "张三"
此时命中name索引,当数据未携带引号后

explain select * from student where name = 2222
此时未命中name索引,全表扫描

总结:字符串的索引字段在查询是数据需要用引号引用

4.索引列上参与计算会导致索引失效


explain select * from student where id-1 = 1
查询条件为id,但是并没有命中主键索引,因为在索引列上参与了计算

正例

select * from student where id = 2
总结:将参与计算的数值先算好,再查询

5.违背最左匹配原则


explain select * from student where age =18
age的索引是和建立再(name,age)组合索引的基础上,当查询条件中没有第一个组合索引的字段(name)会导致索引失效

正例

explain select * from student where age =18 and name ="张三"

此时才会命中name和(name,age)这个索引

6.如果mysql估计全表扫描要比使用索引要快,会不适用索引
7.other
1) 没有查询条件,或者查询条件没有建立索引

2) 在查询条件上没有使用引导列

3) 查询的数量是大表的大部分,应该是30%以上。

4) 索引本身失效

5) 查询条件使用函数在索引列上,或者 对索引列进行运算, 运算包括(+,-,*,/,! 等) 错误的例子:select * from test where id-1=9; 正确的例子:select * from test where id=10;

6) 对小表查询

7) 提示不使用索引

8) 统计数据不真实

9) CBO计算走索引花费过大的情况。其实也包含了上面的情况,这里指的是表占有的block要比索引小。

10)隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误. 由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效. 错误的例子:select * from test where tu_mdn=13333333333; 正确的例子:select * from test where tu_mdn='13333333333';

12) 1,<> 2,单独的>,<,(有时会用到,有时不会)

13,like "%_" 百分号在前.

4,表没分析.

15,单独引用复合索引里非第一位置的索引列.

16,字符型字段为数字时在where条件里不添加引号.

17,对索引列进行运算.需要建立函数索引.

18,not in ,not exist.

19,当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。

20,B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null 都会走

21,联合索引 is not null 只要在建立的索引列(不分先后)都会走, in null时 必须要和建立索引第一列一起使用,当建立索引第一位置条件是is null 时,其他建立索引的列可以是is null(但必须在所有列 都满足is null的时候),或者=一个值; 当建立索引的第一位置是=一个值时,其他索引列可以是任何情况(包括is null =一个值),以上两种情况索引都会走。其他情况不会走。

热心网友 时间:2023-09-11 02:02

我们知道,mysql 如果设置了主键或者唯一约束,再插入相同的值会报错。

假设表中设置name字段为唯一索引,在存在 name = '张三' 的情况下,再插入"张三",

insert into sc (name,class,score) values ('张三','三年二班',90);
报错信息如下:> 1062 - Duplicate entry '张三' for key 'name'

那么,对于这种存在唯一键冲突时,如何避免呢?下面,介绍三种方式:

1. insert ignore

insert ignore会忽略数据库中已经存在的数据(根据主键或者唯一索引判断),如果数据库没有数据,就插入新的数据,如果有数据的话就跳过这条数据.
insert ignore into sc (name,class,score) values ('张三','三年二班',90)
执行上面的语句,会发现并没有报错,但是主键还是自动增长了。

2. replace into

replace into 首先尝试插入数据到表中。如果发现表中已经有此行数据(根据主键或者唯一索引判断)则先删除此行数据,然后插入新的数据,否则,直接插入新数据。
使用replace into,你必须具有delete和insert权限
replace into sc (name,class,score) values ('张三','三年二班',90);
此时会发现吕布的班级跟年龄都改变了,但是id也变成最新的了,所以不是更新,是删除再新增.

3. insert on plicate key update

如果在insert into 语句末尾指定了on plicate key update,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则在出现重复值的行执行UPDATE;如果不会导致重复的问题,则插入新行,跟普通的insert into一样。
使用insert into,你必须具有insert和update权限
如果有新记录被插入,则受影响行的值显示1;如果原有的记录被更新,则受影响行的值显示2;如果记录被更新前后值是一样的,则受影响行数的值显示0
insert into sc (name,class,score) values ('张三','三年二班',90) on plicate key update score=100;
旧数据中张三是三年二班,90分,现在插入,最后发现只有分数变成了100,班级并没有改变。

id没有发生变化,数据只更新,但是auto_increment还是增长1了。

结论:

这三种方法都能避免主键或者唯一索引重复导致的插入失败问题。
insert ignore 能忽略重复数据,只插入不重复的数据。
replace into 和 insert … on plicate key update,都是替换原有的重复数据,区别在于replace into是删除原有的行后,再插入新行,如有自增id,这个会造成自增id的改变;insert … on plicate key update在遇到重复行时,会直接更新原有的行,具体更新哪些字段怎么更新,取决于update后的语句。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
为什么来大姨妈胸会胀 少儿学什么舞蹈 青年学什么舞蹈好 成年人学什么舞蹈 福州企业最低工资标准 2013年厦门的底薪是多少 生产要素的需求有哪些性质 生产要素的需求有何特点? 什么是生产要素需求 微观经济学要素需求什么是条件要素需求?它和要素需求有什么不同?_百度... oracle有没有类似 insert IGNORE处理 自己一个人怎么建群 linux TCP Fast Open开启和测试 江苏省社保全省联网了吗?比如:我在苏州的社保,在南京能否查询到呢? 08年在苏州交了两年社保现在能查到吗 苏州市园区社保卡在苏个区可以用吗l? 苏州工业园区社保卡的养老账户是全国通用吗 耽怎么组词? 耽可以换什么偏旁部首 “耽”有别的偏旁吗?十万火急 耽组词和部首 安徽君之莲商业管理服务有限公司怎么样? 内蒙古工业大学多少亩 内蒙古金川工业大学校区有没有疫情 不要太频繁给喜欢的人发信息 淘宝好评率如何计算的?还差多少个好评才能达到99.6%的好评率呢? 航发控制股票是什么板块?航发控制如果股价翻倍?航发控制股走势如何? 航发控制近半年走势?航发控制财务分析指标?航发控制的股价为何那么低? 航发动力走势分解?2021年航发动力股走势?航发动力股价比发行价低? 华为mediapadm5lite屏幕刷新率 银行员工为什么要离职? 我想问一下建行星级评定标准? 建行星级怎么评? 西湖游记英语作文 年底订宝马530多久能提车啊在苏州 宝骏530新车提车注意事项有哪些? 《秉烛[重生]》txt下载在线阅读全文,求百度网盘云资源 《一猫当仙》txt下载在线阅读全文,求百度网盘云资源 音序表的正确写法 e的正确写法以及汉语拼音字母的书写要求 我的猫咪怎么不吃饭呀! ige转tif Intel 酷睿i3 530 与G620哪个 好些? G620和I3-530哪个性能强 Intel 酷睿i3 530(盒) 和 Intel 奔腾 G620(盒)哪个好? 英特尔的G620,i3-530,i3-2120.性能相差多少。 关于i3集成显卡和g620或g530加独立显卡对比问题 i3 G620+风扇有G530好吗? 主板:华硕p67 内存:骇客神条DDR3 1866 CPU用g1630还是g620还是i3 53 g620 cpu和I3一样插槽吗? 丰田chr叫什么车?