MySQL索引对NULL值的处理
# 索引不会包含有NULL值的列 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
在很多库表设计规范、某某军规的文章中,是不是经常会看到类似这样的内容。小编也经常看到这样的内容,并且在编写规范的时候,准备也把这一条加进去。但在按部就班之余,小编抽空验证了一下,发现事实却并非如此!
小编使用的MySQL版本是社区版 5.7.21
新建测试表 t1,插入不含NULL值得100行数据,然后插入1行带NULL的数据 insert into t1(id) values(101); 表中有主键id,索引a
CREATE TABLE `t1` (`id` int(11) NOT NULL,`a` int(11) DEFAULT NULL,`b` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
测试1,包含NULL单列索引的查询,可以看到即使是查找 IS NULL的行,也是可以用上索引的
测试1:desc select * from t1 where a > 82; +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+ | 1 | SIMPLE | t1 | NULL | range | a | a | 5 | NULL | 18 | 100.00 | Using index condition | +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+desc select * from t1 where a is NULL; +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | t1 | NULL | ref | a | a | 5 | const | 1 | 100.00 | Using index condition | +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+desc select * from t1 where a = 20 or a is null; +----+-------------+-------+------------+-------------+---------------+--------+---------+-------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------------+---------------+--------+---------+-------+------+----------+--------------------------+ | 1 | SIMPLE | t1 | NULL | ref_or_null | idx_ab | idx_ab | 5 | const | 2 | 100.00 | Using where; Using index | +----+-------------+-------+------------+-------------+---------------+--------+---------+-------+------+----------+--------------------------+
注意对 NULL 值的检索只能使用 is null / is not null / <=>,不能使用=,<,>这样的运算符(mysql中可以用a <=> NULL 表示查找 a is NULL'的行)
测试2,包含NULL复合索引的查询,首先加一个复合索引 alter table t1 drop index a,add index idx_ab(a,b); 可以看到不管是指定 a is null ,或者指定 b is null ,都可以利用上索引 idx_ab(key_len 可以看出)
测试2:desc select * from t1 where a=50 and b>20; +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t1 | NULL | range | idx_ab | idx_ab | 10 | NULL | 1 | 100.00 | Using where; Using index | +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+desc select * from t1 where a=50 and b is null; +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+ | 1 | SIMPLE | t1 | NULL | ref | idx_ab | idx_ab | 10 | const,const | 1 | 100.00 | Using where; Using index | +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+desc select * from t1 where a is null and b>20; +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+ | 1 | SIMPLE | t1 | NULL | range | idx_ab | idx_ab | 10 | NULL | 1 | 100.00 | Using where; Using index | +----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+--------------------------+desc select * from t1 where a is null and b is null; +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+ | 1 | SIMPLE | t1 | NULL | ref | idx_ab | idx_ab | 10 | const,const | 1 | 100.00 | Using where; Using index | +----+-------------+-------+------------+------+---------------+--------+---------+-------------+------+----------+--------------------------+
由此,只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。这句的前半句是不对的(可参考官网说明: MySQL :: MySQL 5.7 Reference Manual :: 8.2.1.13 IS NULL Optimization),但是后半句的结论确是可以采纳的。
虽然MySQL可以在含有null的列上使用索引,但不代表null和其他数据在索引中是一样的。不建议列上允许为空,最好限制 not null ,并设置一个默认值,比如0和''空字符串等,如果是datetime类型,可以设置成'1970-01-01 00:00:00'这样的值。对MySQL来说,null 是一个特殊的值,Conceptually, NULL means “a missing unknown value” and it is treated somewhat differently from other values。 对null做算术运算的结果都是null,count时不会包括null行,null 比空字符串需要更多的存储空间等。
附:上面说到可用通过 key_len 看出使用了索引列的个数,a,b 都是 int 类型,4 byte,为什么 key_len 是 5 byte 和 10 byte 呢?是因为如果索引列定义时允许NULL,其key_len还需要再加 1 bytes. 参考好友王的文章,可以移步我们的站点查看详情: 10分钟让你明白MySQL是如何利用索引的 | | For DBA
MySQL索引对NULL值的处理相关推荐
- mysql中与null值不能比较
在mysql中,选择某field为不等于某值的时候,使用<>符号.但查bug时发现该field为null的并不能查出来. 查原因为: null值不能与其他值进行比较,只能使用is null ...
- mysql 索引列为Null的走不走索引及null在统计时的问题
要尽可能地把字段定义为 NOT NULL,即使应用程序无须保存 NULL(没有值),也有许多表包含了可空列(Nullable Column) 这仅仅是因为它为默认选项.除非真的要保存 NULL,否则就 ...
- Oracle技术之索引与Null值对于Hints及执行计划的影响
由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,某些Oracle查询不会使用索引. 很多时候,我们看似可以使用全索引扫描(Full Index Scan)的情况,可能Oracle ...
- mysql文件导出NULL值处理_Mysql select into outfile NULL值导出的处理方法
目录 1简介... 1 2 准备... 1 2.1 环境说明... 1 3 安装... 2 4 配置... 2 5 使用... 2 5.1 验证实验... 2 5.2 问题分析... 4 6 延展.. ...
- MySql中的NULL值和空值
定义: 空值:表示一个空字符或零长度的字符串,可以使用空引号""来表示: NULL值:MySql中,NULL表示缺少一个已知或适当的值. 除了整数类型的列外,所有其他类型的列(包括 ...
- MYSQL查询空值/NULL值
select * from XXXX where YYYY is NULL
- mysql左连接null值丢失、条件不起作用的问题
一.问题 在mysql左连接时, 写上where时,空值丢失,数据减少 不写where,只用and连接,主表条件不起作用,数据变多. 二.错误复现 1.当使用where+条件时,左连接查询空值丢失 S ...
- Mysql数据唯一约束与唯一索引案例总结及踩坑记(含NULL值与唯一约束唯一索引的搭配使用)
Mysql数据唯一索引与唯一约束案例总结 唯一约束的说明 唯一约束是约束(CONSTRAINT)里的一种,常见的还有主键.外检.默认值.是否为空.检查等.唯一约束即限制某个或某些字段具有唯一性(不能重 ...
- mysql null 排前面_Mysql实现null值排在最前/最后的方法示例
前言 我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作. 为了处理这种情况,MyS ...
最新文章
- 【ACM】杭电OJ 5055(Bob and math problem)
- 当前分支上有未提交的更改时签出另一个分支
- Hyperledger Fabric 链码(2) 接口
- 纯Python包发布setup脚本编写示例
- Linux 之八 完整嵌入式 Linux 环境、(交叉)编译工具链、CPU 体系架构、嵌入式系统构建工具
- iOS Hacker Keychain相关The executable was signed with invalid entitlements
- 最新PHP秒赞,快乐秒赞 php版
- layui-概念-入门-总结
- WebBrowser控件禁用超链接转向、脚本错误提示、默认右键菜单和快捷键
- T-SQL | 逻辑查询处理内幕学习
- dns是指网络域名系统_域名系统(DNS)是Internet的骨干。 这就是全部的运作方式。...
- 英语对IT从业者的影响
- 一键查询快递物流单号,分析提前签收
- pmp十大知识领域,49个过程的4W1H
- 正态分布的峰度和偏度分别为_偏度与峰度的正态性分布判断
- 从零开始学习CANoe(四)—— 设计panel
- Mysql之账号管理、建库以及四大引擎【入门篇】
- Oracle -PL/SQL Developer错误解决方案(ORA-02291)
- MyEclipse使用Maven创建web项目+搭建SSM框架教程
- 分析洋葱模型实现原理,在自己项目中接入洋葱模型
热门文章
- 三次握手和四次挥手之间的关系
- Web前端开发笔记——第二章 HTML语言 第二节 基本标签
- OpenStack的部署T版(七)——cinder模块
- linux jrdmm 命令 局部 编译,Cgminer-4.10.0 Linux 挖矿
- java多语言编程语言_为什么很多程序员信仰“Java是世界上最好的编程语言”
- arcgis导入excel数据_ArcGIS批量导入数据
- Java和C/C++程序实时通讯数据移植问题的研究
- 计算机模型机设计实验报告,基本模型机设计与实现 实验报告
- mysql命令查看过程内容_mysql查看存储过程命令
- 计算机文化基础性考二,电大计算机文化基础形考二答案