当前位置:网站首页>索引失效的几种情况
索引失效的几种情况
2022-07-01 11:05:00 【菜鸟猫喵喵】
本文只是个人笔记,如有错误还望提醒
最佳左前缀法则
范围查询右边失效
like索引失效原理
隐式转换造成的索引失效
看这个表
CREATE TABLE `test1` (
`id` int(11) NOT NULL,
`num1` int(11) NOT NULL DEFAULT '0',
`num2` varchar(11) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `num1` (`num1`),
KEY `num2` (`num2`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SQL 测试
先来看这组 SQL,一共四条,我们的测试数据表num1是int类型,num2是varchar类型,但是存储的数据都是跟主键id一样的顺序数字,两个字段都建立有索引。
1: SELECT * FROM `test1` WHERE num1 = 10000;
2: SELECT * FROM `test1` WHERE num1 = '10000';
3: SELECT * FROM `test1` WHERE num2 = 10000;
4: SELECT * FROM `test1` WHERE num2 = '10000';
其中 124 三条 SQL 基本都是瞬间出结果,大概在 0.001 ~ 0.005 秒,在千万级的数据量下这样的结果可以判定这三条 SQL 性能基本没差别了。但是第三条 SQL,多次测试耗时基本在 4.5~4.8 秒之间。
为什么 34 两条 SQL 效率相差那么大,但是同样做对比的 12 两条 SQL 却没什么差别呢?查看一下执行计划,下边分别 1234 条 SQL 的执行计划数据:
可以看到,124 三条 SQL 都能使用到索引,连接类型都为ref,扫描行数都为 1,所以效率非常高。再看看第三条 SQL,没有用上索引,所以为全表扫描,rows直接到达 1000 万了,所以性能差别才那么大。
查阅 MySQL 相关文档发现是隐式转换造成的,看一下官方的描述:
官方文档: 12.2 Type Conversion in Expression Evaluation
当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。某些转换是隐式发生的。例如,MySQL会根据需要自动将字符串转换为数字,反之亦然。以下规则描述了比较操作的转换方式:
- 两个参数至少有一个是NULL时,比较的结果也是NULL,特殊的情况是使用<=>对两个NULL做比较时会返回1,这两种情况都不需要做类型转换
- 两个参数都是字符串,会按照字符串来比较,不做类型转换
- 两个参数都是整数,按照整数来比较,不做类型转换
- 十六进制的值和非数字做比较时,会被当做二进制串
- 有一个参数是TIMESTAMP或DATETIME,并且另外一个参数是常量,常量会被转换为timestamp
- 有一个参数是decimal类型,如果另外一个参数是decimal或者整数,会将整数转换为decimal后进行比较,如果另外一个参数是浮点数,则会把decimal转换为浮点数进行比较
- 所有其他情况下,两个参数都会被转换为浮点数再进行比较
根据官方文档的描述,我们的第 23 两条 SQL 都发生了隐式转换,第 2 条 SQL 的查询条件num1 = ‘10000’,左边是int类型右边是字符串,第 3 条 SQL 相反,那么根据官方转换规则第 7 条,左右两边都会转换为浮点数再进行比较。
先看第 2 条 SQL:SELECT * FROMtest1WHERE num1 = ‘10000’; 左边为 int 类型10000,转换为浮点数还是10000,右边字符串类型’10000’,转换为浮点数也是10000。两边的转换结果都是唯一确定的,所以不影响使用索引。
第 3 条 SQL:SELECT * FROMtest1WHERE num2 = 10000; 左边是字符串类型’10000’,转浮点数为 10000 是唯一的,右边int类型10000转换结果也是唯一的。但是,因为左边是检索条件,‘10000’转到10000虽然是唯一,但是其他字符串也可以转换为10000,比如’10000a’,‘010000’,'10000’等等都能转为浮点数10000,这样的情况下,是不能用到索引的。
查阅相关资料发现规则如下:
- 不以数字开头的字符串都将转换为0。如’abc’、‘a123bc’、'abc123’都会转化为0;
- 以数字开头的字符串转换时会进行截取,从第一个字符截取到第一个非数字内容为止。比如’123abc’会转换为123,'012abc’会转换为012也就是12,'5.3a66b78c’会转换为5.3,其他同理。
分析和总结
通过上面的测试我们发现 MySQL 使用操作符的一些特性:
- 当操作符左右两边的数据类型不一致时,会发生隐式转换。
- 当 where 查询操作符左边为数值类型时发生了隐式转换,那么对效率影响不大,但还是不推荐这么做。
- 当 where 查询操作符左边为字符类型时发生了隐式转换,那么会导致索引失效,造成全表扫描效率极低。
- 字符串转换为数值类型时,非数字开头的字符串会转化为0,以数字开头的字符串会截取从第一个字符到第一个非数字内容为止的值为转化结果。
所以,我们在写 SQL 时一定要养成良好的习惯,查询的字段是什么类型,等号右边的条件就写成对应的类型。特别当查询的字段是字符串时,等号右边的条件一定要用引号引起来标明这是一个字符串,否则会造成索引失效触发全表扫描。
字符集和排序规则不相同导致索引失效
其它:
- 最好全值匹配
- 不要在索引上做任何操作(计算、函数、自动/手动类型转换),不然会导致索引失效而转向全表扫描
explain select * from ti where b+1=5; -- 对字段操作走不了索引
- 尽量使用覆盖索引(只查询索引的列(索引列和查询列一致)),减少select *
- 索引字段上使用(!= 或者 < >)判断时,会导致索引失效而转向全表扫描
- 索引字段上使用 is null / is not null 判断时,会导致索引失效而转向全表扫描
- 索引字段使用 or 时,会导致索引失效而转向全表扫描
边栏推荐
- Combinaison Oracle et json
- Can I choose to open an account on CICC securities? Is it safe?
- 数据库实验报告(一)
- mysql如何把 一个数据库中的表数据 复制到 另一个数据库中(两个数据库不在同一个数据库链接下)
- Compliance management of fund managers
- 442. duplicate data in array
- 个人商城二开逍遥B2C商城系统源码-可商用版/拼团拼购优惠折扣秒杀源码
- 想请教一下,我在广州,到哪里开户比较好?现在网上开户安全么?
- 基金管理人的合规管理
- Export and import of incluxdb on WIN platform
猜你喜欢

金融壹账通拟7月4日香港上市:2年亏近30亿 市值蒸发超90%

2022年已经过去一半了,是不是很突然呢?

Uncover the secrets of new products! Yadi Guanneng 3 multi product matrix to meet the travel needs of global users

京东与腾讯续签合作:向腾讯发行A类股 价值最高达2.2亿美元

Google's new paper Minerva: solving quantitative reasoning problems with language models

12款大家都在用的产品管理平台

12 plateformes de gestion de produits utilisées par tout le monde

CVPR 2022 | self enhanced unpaired image defogging based on density and depth decomposition

LeetCode.515. 在每个树行中找最大值___逐一BFS+DFS+按层BFS
![[.NET6]使用ML.NET+ONNX预训练模型整活B站经典《华强买瓜》](/img/b3/b117481fba7257453011e4cdb1eaaa.png)
[.NET6]使用ML.NET+ONNX预训练模型整活B站经典《华强买瓜》
随机推荐
[AI information monthly] 350 + resources! All the information and trends that can't be missed in June are here! < Download attached >
金鱼哥RHCA回忆录:DO447使用Ansible与API通信--使用Ansible Tower API启动作业
Cvpr22 | CMT: efficient combination of CNN and transformer (open source)
价值1000毕业设计校园信息发布平台网站源码
Face detection and recognition system based on mtcnn+facenet
Node version manager NVM installation and switching
基金管理人的内部控制
442. duplicate data in array
Suggest collecting | what to do when encountering slow SQL on opengauss?
Get key code
12款大家都在用的產品管理平臺
[encounter Django] - (II) database configuration
金融壹账通拟7月4日香港上市:2年亏近30亿 市值蒸发超90%
选择在中金证券上炒股开户可以吗?安全吗?
BAIC bluevale: performance under pressure, extremely difficult period
Google's new paper Minerva: solving quantitative reasoning problems with language models
Want to open an account, is it safe to open an account of Huatai Securities online?
LeetCode 438. 找到字符串中所有字母异位词__滑动窗口
Wireshark TS | confusion between fast retransmission and out of sequence
Mall applet source code open source version - two open