不知道是啥原因也不知道啥时候, 江湖上流传着这么一个说法 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不能走索引?相关推荐

  1. 阿里云mysql强制走索引_MYSQL中常用的强制性操作(例如强制索引)

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  2. mysql中的强制索引_MYSQL中常用的强制性操作(例如强制索引)

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

  3. mysql b-a全局索引_MySQL中B+树索引的使用

    1)         不同应用中B+树索引的使用 对于OLTP应用,由于数据量获取可能是其中一小部分,建立B+树索引是有异议时的 对OLAP应用,情况比较复杂,因为索引的添加应该是宏观的而不是微观的. ...

  4. mysql 隐式主键_MySQL中复合主键性能的缺点

    我们有一个表,该表具有由三个字段组成的复合主键(在MySQL 5.1中是这样). 该表上每秒有近200个插入和200个选择,并且表的大小约为100万行,并且还在不断增加. 我的问题是:"复合 ...

  5. mysql复合主键优缺点_MySQL中的复合主键性能缺陷

    INSERT 和 UPDATE 性能变化很小: (INT) 和 (INT, INT) 键几乎相同 . SELECT 复合 PRIMARY KEY 的性能取决于很多因素 . 如果您的表是 InnoDB ...

  6. mysql not null 索引_MySQL中 IS NULL、IS NOT NULL、!= 能用上索引吗?

    看面试题的时候,总能看到MySQL在什么情况下用不上索引,如下: MySQL的WHERE子句中包含 IS NULL.IS NOT NULL.!= 这些条件时便不能使用索引查询,只能使用全表扫描. 不耽 ...

  7. mysql is not null不生效_MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

    转:https://mp.weixin.qq.com/s/CEJFsDBizdl0SvugGX7UmQ 不知道从什么时候开始,网上流传着这么一个说法: MySQL的WHERE子句中包含 IS NULL ...

  8. mysql教程联合索引_MySQL中的联合索引学习教程

    联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b| ...

  9. mysql null的作用_MySQL中对于NULL值的理解和使用教程

    NULL值的概念是造成SQL的新手的混淆的普遍原因,他们经常认为NULL是和一个空字符串''的一样的东西.不是这样的!例如,下列语句是完全不同的: ?12mysql>INSERT INTO my ...

最新文章

  1. linux服务器lvs,Linux的企业-LVS(Linux虚拟服务器)及FULLNAT设置
  2. java中日期怎么比较_如何比较Java中的日期?
  3. 没有人比你更在乎你的未来--李开复
  4. python zlib字符串压缩
  5. 机器学习 美股_我如何使用机器学习来探索英美文学之间的差异
  6. Chapter 5 Exercises Problems
  7. 【转】Linux的.a、.so和.o文件
  8. node.js包管理器和代码调式
  9. python爬虫高级知识点_Python爬虫知识点梳理总结,殿堂级小白入门必读
  10. java caller_js中的caller和callee属性
  11. 新手网页设计提高设计水平的法宝,临摹练习!
  12. 照片有灵异鬼影?伯克利 x 陈启峰培育高能FCN“除灵师” | CVPR论文
  13. 栈和队列的Java实现
  14. 毕设题目:Matlab电子琴
  15. java上路系列之一
  16. 一个亿,啪一下就没了!
  17. Win11 任意版本 直接安装 Android 应用 教程(最详细)
  18. im即时通讯开发:万人群聊技术方案实践
  19. 微信分享按钮隐藏、显示问题和注意事项
  20. 【HTML】铺满背景图片

热门文章

  1. windows系统设置QOS限速分配,巧妙网络资源利用率提高网络服务质量,任务进程限速出站上传速率
  2. 7-1 城市间紧急救援 (25 分)
  3. 直播卡顿问题及优化方案
  4. C++ isalpha()
  5. Matlab中向量的交集、并集、差集等集合运算
  6. ubuntu 16.04 安装微信 (亲测有效)
  7. 阿里面试乔戈里被问:MySql数据是如何存储在磁盘上存储的?
  8. Android系统镜像之4种刷机方法(一键批量刷机)
  9. 模型显存占用及其计算量
  10. js-onbeforepaste详解