面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?
本文阅读时间大约6分钟。
其实写这篇文章,也是来自一个知识星球读者的提问,他在二面的过程中被问到了,由于他简历中写道有 MySQL 调优经验,但这个问题没有回答好,二面被刷了。
其实我们刚学习 C 语言的时候,就接触过 NULL,比如下面这句代码。
int *p = NULL;
它实际上表示将指针指向一块不被使用的内存地址,一般会在宏中定义好。
那么我们常用的 Java 语言,同样也用到 null,表示一个空引用,如果你不小心引用了,那么就会抛出 NullPointerException,就像昨天 Reddit 上面很火的一张图。
关于空指针异常,我之前写过一篇文章来介绍怎么防御《java.lang.NullPointerException》。但是这篇文章没有写全,今天在这里补充一下。
其实很早之前 guava 就提供了 Optional 容器类来处理 null,其目的便是避免猝不及防的空指针。后来 java8 直接引入了 Optional,功能一样,用法上稍稍有点变化。其实还有很多开源框架,比如 Spring,common lang3等,也提供了处理空的工具类,如。
StringUtils.isBlank();
CollectionUtils.isEmpty();
那么在 MySQL 中,NULL 表示不知道的数据。
我们在设计表的时候,经常会有老司机这么告诉我们。
字段尽可能用NOT NULL,而不是NULL,除非特殊情况。
这句话到底有没有错?
可以负责任的告诉你这句话没有错,也不是以讹传讹。
这句话首次出现在 MySQL 官网。
如果你读过《高性能 MySQL》这本书,你应该会看到这么一段,在 4.1 节提到。
由此看来,把 NULL 改成 NOT NULL 对索引的性能并没有明显的提升。避免使用 NULL 的目的,是便于代码的可读性和可维护性。同时也便于避免下文即将出现的一些稀奇古怪的错误。
好了,下面咱们通过实验来看看,使用 NULL 会出现那些稀奇古怪的错误呢?
跟我一样在本地建两个表 t1,t2;其中一个表 name 字段允许为空,另一个表 name 字段不允许为空,分别对 name 字段建立索引,SQL 语句如下。
1、NOT IN、!= 等负向条件查询在有 NULL 值的情况下返回非空行的结果集。
比如上例中的 t2,我执行如下 SQL 语句。
SELECT * from t2 where name != '张三'
你本打算返回 id 为 2 的那行数据,然而什么都没有。
又比如这条 SQL 语句。
select * from t2 where name not in (select name from t2 where id!=1)
也返回了空结果集。
2、使用 concat 函数拼接时,首先要对各个字段进行非 NULL 判断,否则只要任何一个字段为空都会造成拼接的结果为 NULL。
比如下面这条 SQL 语句。
SELECT CONCAT("1",NULL)
3、当用count函数进行统计时,NULL 列不会计入统计。
SELECT count(name) from t2
4、查询空行数据,用 is NULL。
SELECT * FROM t2 where name is NULL
5、NULL 列需要更多的存储空间,一般需要一个额外的字节作为判断是否为 NULL 的标志位。
如果你仔细观察 t1 和 t2 表的 key_len,会发现 t2 比 t1 多了一个字节。
explain SELECT * from t2 where name = '张三'
explain SELECT * from t1 where name = '张三'
key_len 的长度一般跟这三个因素有关,分别是数据类型,字符编码,是否为 NULL。
因此,t2 比 t1 多出的这一个字节,用于作为判断是否为 NULL 的标志位了。
马蛋,原来一切都在书中。如果面试的哪位同学多读几篇《高性能 MySQL》这本书,那个岗位就是他的了,但没有那么多如果。。。
在此,建议大家多看官方文档,多读点好书,多关注一些良心的原创技术自媒体,不要看那些无凭无据的文章,反而会以讹传讹,贻害无穷。
如果这篇文章对你有帮助,麻烦分享到你的朋友圈,来帮助更多的朋友。
参考
https://dev.mysql.com/doc/refman/5.7/en/dynamic-format.html
https://dev.mysql.com/doc/refman/5.5/en/problems-with-null.html
https://dev.mysql.com/doc/refman/5.5/en/multiple-column-indexes.html
https://dev.mysql.com/doc/internals/en/myisam-introduction.html
https://dev.mysql.com/doc/internals/en/innodb-field-contents.html
下方查看历史文章
025:为什么需要将Logger对象声明为private static final类型的
本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。
让我知道你“在看”
面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?的更多相关文章
- 面试官问,说一个你在工作非常有价值的bug
		
如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...
 - 面试官问我,Redis分布式锁如何续期?懵了。
		
前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...
 - 当面试官问我ArrayList和LinkedList哪个更占空间时,我这么答让他眼前一亮
		
前言 今天介绍一下Java的两个集合类,ArrayList和LinkedList,这两个集合的知识点几乎可以说面试必问的. 对于这两个集合类,相信大家都不陌生,ArrayList可以说是日常开发中用的 ...
 - 面试官问:HashMap在并发情况下为什么造成死循环?一脸懵
		
这个问题是在面试时常问的几个问题,一般在问这个问题之前会问Hashmap和HashTable的区别?面试者一般会回答:hashtable是线程安全的,hashmap是线程不安全的. 那么面试官就会紧接 ...
 - 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?
		
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...
 - [每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?
		
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
 - [每日一题]面试官问:for in和for of 的区别和原理?
		
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
 - 每日一问:面试结束时面试官问"你有什么问题需要问我呢",该如何回答?
		
面试结束时面试官问"你有什么问题需要问我呢",该如何回答?
 - 面试官问:JS的this指向
		
前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...
 
随机推荐
- 了解html标签
			
<title></title> 1.网页标题 2.当我们收藏网页时,默认标题就是网页标题 3.seo(搜索引擎优化) <h1></h1>~<h6& ...
 - vim目录树
			
使用vim插件:显示树形目录插件NERDTree 安装方法很简单,先把压缩文件下载下来,解压后将plugin目录下的NERD_tree.vim拷贝~/.vim/plugin以及doc目录下的NERD_ ...
 - 使用jQuery的replaceWith()方法要注意的地方
			
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
 - CF1187D Subarray Sorting(神奇思路,线段树)
			
说实话,$2200$ 的题做不出来也有点丢脸了…… 当然要先判所有数出现次数相同. 首先区间排序就相当于交换相邻两个数,前面的数要大于后面的数才能交换. 然后就不会了…… 我们考虑 $b_1$ 到 $ ...
 - CF1136E Nastya Hasn't Written a Legend(线段树)
			
还能说什么呢,简直太妙了. $$a_{i+1}<a_i+k_i$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i+k_i-k_i-k_{i-1}-\cdots- ...
 - Linux性能优化实战学习笔记:第十六讲
			
一.free数据的来源 1.碰到看不明白的指标时该怎么办吗? 不懂就去查手册.用 man 命令查询 free 的文档.就可以找到对应指标的详细说明.比如,我们执行 man fre... 2.free数 ...
 - 【可视化】Vue基础
			
作者 | Jeskson 来源 | 达达前端小酒馆 Vue简介 Vue框架,框架的作者,尤雨溪,组件化,快速开发的特点. 生命周期 beforeCreate:组件刚刚被创建 created:组件创建完 ...
 - ROS融合IMU笔记
			
ROS官网有一个叫robot_pose_ekf的包,是专门处理传感器融合的包,具体介绍:http://wiki.ros.org/robot_pose_ekf 其中主要功能是订阅主题包括odom(里程计 ...
 - RGB灯
			
robotbit扩展板4个rgb灯,r-红,g-绿,b-蓝,值为0~255,可模拟出256*256*256种颜色. from microbit import * import neopixel r = ...
 - 明解C语言 入门篇 第六章答案
			
练习6-1 /* 求两个整数中的最小值 */ #include <stdio.h> /*--- 返回三个整数中的最小值 ---*/ int min2(int a, int b) { int ...