mysql is null走索引_mysql中IS NULL、IS NOT NULL不能走索引?
不知道是啥原因也不知道啥时候, 江湖上流传着这么一个说法 mysql查询条件包含IS NULL、IS NOT NULL、!=、like %* 、like %*%,不能使用索引查询,只能使用全表扫描。
刚入行时我也是这么认为的,还奉为真理!
但是时间工作中你会发现还是走索引啊!下面我们来一一探究其中的奥秘。
一、首先验证一下是会走索引的
创建一个表,结构如下:
create table user_info(
id int PRIMARY key auto_increment,
name varchar(16) default '',
age tinyint default 0,
address varchar(32) default '',
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `address_2` (`address`,`name`)
);
ALTER TABLE user_info ADD INDEX (NAME);
ALTER TABLE user_info ADD INDEX (address);
数据1
INSERT INTO user_info(NAME,age,address)
VALUES (9,9,'shenzhen9');
BEGIN
DECLARE i INT DEFAULT 1000;
WHILE i < 9000 DO
INSERT INTO user_info (`NAME`, `age`, `address`)
VALUES
(NULL, i , SUBSTRING(MD5(RAND()),1,10) ) ;
SET i = i+ 1 ;
END WHILE ;
① EXPLAIN SELECT * FROM user_info WHERE `name` IS NOT NULL
② EXPLAIN SELECT * FROM user_info WHERE `name` !='9'
③ EXPLAIN SELECT * FROM user_info WHERE `name` is null
数据2
INSERT INTO user_info(NAME,age,address)
VALUES (null,9,'shenzhen9');
BEGIN
DECLARE i INT DEFAULT 1000;
WHILE i < 9000 DO
INSERT INTO user_info (`NAME`, `age`, `address`)
VALUES
(REPLACE(UUID(),'-',''), i , SUBSTRING(MD5(RAND()),1,10) ) ;
SET i = i+ 1 ;
END WHILE ;
④ EXPLAIN SELECT * FROM user_info WHERE `name` IS NOT NULL
⑤ EXPLAIN SELECT * FROM user_info WHERE `name` !='9'
⑥ EXPLAIN SELECT * FROM user_info WHERE `name` is null
执行数据1 会发现sql①②走索引,③不走索引
执行数据2 会发现sql⑥走索引,④⑤不走索引
二、B+树数据排列规则
1、聚簇索引索引:
①页面中的记录是按照主键值进行排序的;
②B+树每一层节点(页面)都是按照页中记录的主键值大小进行排序的;
③B+树叶子节点对应的页面中存储的是完整的用户记录(就是一条记录中包含我们定义的所有列值,还包含一些InnoDB自己添加的一些隐藏列);
2、二级索引:
①页面中的记录是按照给定的索引列的值进行排序的。
②B+树每一层节点(页面)都是按照页中记录的给定的索引列的值进行排序的。
③B+树叶子节点对应的页面中存储的只是索引列的值 + 主键值。
二级索引值能为空。那对于索引列值为NULL的二级索引记录,在B+树的哪个位置呢?
在B+树的最左边。如下图
至于为什么,InnoDB是这样的规定:SQL中的NULL值是列中最小的值
什么时候索引又不生效了呢?
对比数据1和数据2两个数据中null值的数量不一样,当null值占多数时is not null 和!=走索引 ,is null不走索引了,数据2刚好相反。
估计大家都能看出什么来了。带索引字段使用null做判断是否走索引与数据量有关,归纳起来就是成本问题(关于mysql索引扫描成本计算详细分析建议大家可以去看一下掘金小册《mysql是怎样运行的:从根上理解mysql》)。
索引(二级索引)扫描成本:
1、读取索引记录成本
2、反查主键索引查找完整数据成本即回表
如果查询读取的二级索引越多那么需要回表查询的次数就会越多,达到一定的比例就会变成全部查询了,也就是上面null 查询时索引有时不生效的原因。
综上MySQL中决定使不使用某个索引执行查询的依据是成本大小。而不是在WHERE子句中用了IS NULL、IS NOT NULL、!=这些条件
三、如何让like‘%字符串%’,‘字符串%’时走索引
通常情况下我们使用like %*%、%*的确不会走索引 但是并不代表就一定不能走索引,我们对上面表中name和age建立复合索引
explain select name from user_info where name like '%a%';
1 SIMPLE user_info index idx_n_a 53 6 16.67 Using where; Using index
explain select name,age from user_info where name like '%a%';
1 SIMPLE user_info index idx_n_a 53 6 16.67 Using where; Using index
以下两个例子是查询了不在复合索引中的列进而造成全表扫描
explain select name,age,address from user_info where name like '%a%';
1 SIMPLE user_info ALL 6 16.67 Using where
explain select * from user_info where name like '%a%';
1 SIMPLE user_info ALL 6 16.67 Using where
所以like走不走索引并不是绝对的,要看使用条件!
mysql is null走索引_mysql中IS NULL、IS NOT NULL不能走索引?相关推荐
- 阿里云mysql强制走索引_MYSQL中常用的强制性操作(例如强制索引)
{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...
- mysql中的强制索引_MYSQL中常用的强制性操作(例如强制索引)
mysql常用的hint 对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法.同样,在mysql里,也有类似的hint功能.下面介绍一些常用的 ...
- mysql b-a全局索引_MySQL中B+树索引的使用
1) 不同应用中B+树索引的使用 对于OLTP应用,由于数据量获取可能是其中一小部分,建立B+树索引是有异议时的 对OLAP应用,情况比较复杂,因为索引的添加应该是宏观的而不是微观的. ...
- mysql 隐式主键_MySQL中复合主键性能的缺点
我们有一个表,该表具有由三个字段组成的复合主键(在MySQL 5.1中是这样). 该表上每秒有近200个插入和200个选择,并且表的大小约为100万行,并且还在不断增加. 我的问题是:"复合 ...
- mysql复合主键优缺点_MySQL中的复合主键性能缺陷
INSERT 和 UPDATE 性能变化很小: (INT) 和 (INT, INT) 键几乎相同 . SELECT 复合 PRIMARY KEY 的性能取决于很多因素 . 如果您的表是 InnoDB ...
- mysql not null 索引_MySQL中 IS NULL、IS NOT NULL、!= 能用上索引吗?
看面试题的时候,总能看到MySQL在什么情况下用不上索引,如下: MySQL的WHERE子句中包含 IS NULL.IS NOT NULL.!= 这些条件时便不能使用索引查询,只能使用全表扫描. 不耽 ...
- mysql is not null不生效_MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!
转:https://mp.weixin.qq.com/s/CEJFsDBizdl0SvugGX7UmQ 不知道从什么时候开始,网上流传着这么一个说法: MySQL的WHERE子句中包含 IS NULL ...
- mysql教程联合索引_MySQL中的联合索引学习教程
联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b| ...
- mysql null的作用_MySQL中对于NULL值的理解和使用教程
NULL值的概念是造成SQL的新手的混淆的普遍原因,他们经常认为NULL是和一个空字符串''的一样的东西.不是这样的!例如,下列语句是完全不同的: ?12mysql>INSERT INTO my ...
最新文章
- linux服务器lvs,Linux的企业-LVS(Linux虚拟服务器)及FULLNAT设置
- java中日期怎么比较_如何比较Java中的日期?
- 没有人比你更在乎你的未来--李开复
- python zlib字符串压缩
- 机器学习 美股_我如何使用机器学习来探索英美文学之间的差异
- Chapter 5 Exercises Problems
- 【转】Linux的.a、.so和.o文件
- node.js包管理器和代码调式
- python爬虫高级知识点_Python爬虫知识点梳理总结,殿堂级小白入门必读
- java caller_js中的caller和callee属性
- 新手网页设计提高设计水平的法宝,临摹练习!
- 照片有灵异鬼影?伯克利 x 陈启峰培育高能FCN“除灵师” | CVPR论文
- 栈和队列的Java实现
- 毕设题目:Matlab电子琴
- java上路系列之一
- 一个亿,啪一下就没了!
- Win11 任意版本 直接安装 Android 应用 教程(最详细)
- im即时通讯开发:万人群聊技术方案实践
- 微信分享按钮隐藏、显示问题和注意事项
- 【HTML】铺满背景图片