相信很多用了mysql很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问:

  1. 我字段类型是not null,为什么我可以插入空值
  2. 为毛not null的效率比null高
  3. 判断字段不为空的时候,到底要 select * from table where column <> '' 还是要用 select * from table where column is not null 呢。

带着上面几个疑问,我们来深入研究一下null 和 not null 到底有什么不一样。 首先,我们要搞清楚“空值” 和 “NULL” 的概念: 1. 空值是不占用空间的 2. mysql中的NULL其实是占用空间的,下面是来自于MYSQL官方的解释

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

打个比方来说,你有一个杯子,空值代表杯子是真空的,NULL代表杯子中装满了空气,虽然杯子看起来都是空的,但是区别是很大的。

搞清楚“空值”和“NULL”的概念之后,问题基本就明了了,我们搞个例子测试一下:

CREATE TABLE  `test` (
`col1` VARCHAR( 10 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`col2` VARCHAR( 10 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL
) ENGINE = MYISAM ;

插入测试

mysql> insert into test values(null,1);
ERROR 1048 (23000): Column 'col1' cannot be null mysql> insert into test values('',null);
Query OK, 1 row affected (0.00 sec) mysql> insert into test values('',1);
Query OK, 1 row affected (0.00 sec) mysql> insert into test values('NULL',1);
Query OK, 1 row affected (0.00 sec) mysql> select * from test;
+------+------+
| col1 | col2 |
+------+------+
| | NULL |
| | 1 |
| NULL | 1 |
+------+------+
3 rows in set (0.00 sec)

可见,NOT NULL 的字段是不能插入NULL的,只能插入“空值”,上面的问题1也就有答案了。读者需要注意的是,最后插入的NULL并非NULL,而是字符串"NULL"。并且对于InnoDB引擎的表具有相同的测试效果。

对于问题2,上面我们已经说过了,NULL 其实并不是空值,而是要占用空间,所以mysql在进行比较的时候,NULL 会参与字段比较,所以对效率有一部分影响。 而且B树索引(MyISAM 表)时不会存储NULL值的,所以如果索引的字段可以为NULL,索引的效率会下降很多。 值得注意的是:尽量避免NULL

  1. 很多表都包含可为NULL的列,即使应用程序并不需要保存NULL也是如此,这是因为可为NULL是列的默认属性(TIMESTAMP除外),然而通常情况下最好指定列为NOT NULL,除非真的需要存储NULL值。
  2. 如果查询中包含可为NULL的列,对MySQL来说更难优化,因为可为NULL的列使得索引统计和值比较更加复杂。可为NULL的列会使用更多的存储空间,在MySQL里也需要特殊的处理。当可为NULL的字段被索引时,每个索引记录需要一个额外的字节,在MyASIM里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引。
  3. 通常把可为NULL的列改为NOT NULL 带来的性能提升比较小,所以(调忧时)没有必要首先在现有schema中查找并修改这种情况,除非确定这会导致问题。但是,如果计划在列上建索引,就应该尽量避免设计为NULL的列。当然也有一些例外,例如值得一提的是,InnoDB使用单独的位(Bit)存储NULL值,所以对于稀疏数据(很多值为NULL,只有少数行是非NULL)有很好的空间效率。但这一点不适用于MyISAM。

---引用自《高性能MySQL-第三版》第四章 Schema与数据类型优化

解决最后一个疑问 现在根据需求,我要统计test表中col1不为空的所有数据,我是该用“<> ''” 还是 “IS NOT NULL” 呢,让我们来看一下结果的区别。

mysql> SELECT * FROM `test` WHERE col1 IS NOT NULL;
+------+------+
| col1 | col2 |
+------+------+
| NULL | 1 |
| | 1 |
| | NULL |
+------+------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM `test` WHERE col1 <> '';
+------+------+
| col1 | col2 |
+------+------+
| NULL | 1 |
+------+------+
1 row in set (0.00 sec)

可以看到,结果迥然不同,所以我们一定要根据业务需求,搞清楚到底是要用那种搜索条件。

【MySQL】探究之null与not null的更多相关文章

  1. mysql探究之null与not null

    相信很多用了mysql很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 1.我字段类型是not null,为什么我可以插入空值 2.为毛not null的效率比null高 3.判断字段 ...

  2. MySQL中order by中关于NULL值的排序问题

    MySQL中order by 排序遇到NULL值的问题 MySQL数据库,在order by排序的时候,如果存在NULL值,那么NULL是最小的,ASC正序排序的话,NULL值是在最前面的. 如果我们 ...

  3. Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to connect

    Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to co ...

  4. MySQL null与not null和null与空值''的区别

    参考连接:https://segmentfault.com/a/1190000009540449 相信很多用了MySQL很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 我字段类型是n ...

  5. MySQL学习笔记:少用Null

    在实际编程中,Null容易引起很多问题,例如在Java里NullPointerException猝不及防的空指针异常,因此需要过多的if判断,甚是麻烦. 在MySQL数据库中也要少用Null,尽量保持 ...

  6. 转!!mysql 字段 is not null 和 字段 !=null

      今天在查询数据时,查到包含一条某个时间startTime(该字段默认为null ) 为null的记录,想把它过滤,加了 startTime != null 的条件,结果记录都没了,应该用条件 is ...

  7. mysql 查询出的数组为null怎么转换成0

    mysql 查询出的数组为null怎么转换成0 IFNULL(b.dayPay,0) as yesterdayPay,

  8. 面试官问我,为什么老司机建议MySQL列属性尽量用 NOT NULL ?

    本文阅读时间大约6分钟. 其实写这篇文章,也是来自一个知识星球读者的提问,他在二面的过程中被问到了,由于他简历中写道有 MySQL 调优经验,但这个问题没有回答好,二面被刷了. 其实我们刚学习 C 语 ...

  9. mysql 设置字段是否可以为null

    //不允许为null alter table table1 change id id ) not null; //允许为null alter table table1 change id id ) n ...

随机推荐

  1. Search Insert Position [LeetCode]

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  2. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  3. Windows Store App 用户库文件分组

    在Windows应用商店应用程序中浏览用户库中的文件时,可以将文件或者文件夹分组显示,以便于进行分类浏览,这类似于音乐库中的文件可以按照艺术家名称.创建日期或者评级等多种方式进行分类.本节内容将会介绍 ...

  4. systemctl命令

    systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起. 任务 旧指令 新指令 使某服务自动启动 chkconfig --level 3 ...

  5. php常用加密算法

    php加密函数: 不可逆的加密函数为:md5().crypt() md5() 用来计算 MD5 哈稀.语法为:string md5(string str); crypt() 将字符串用 UNIX 的标 ...

  6. poj 2777

    题意:两个操作:c l r x   l到r之间的颜色变成x q l r      询问l到r有多少种颜色 思路:记一个整数表示哪种颜色是否取了 这里真的是煞笔了,看到这一题第一直觉是异或,但是A^A= ...

  7. 通过MD5排除重复文件

    今天下载了好多美女图片壁纸,可是看了一下发现好多图片重复了,有强迫症的我必须把重复的都给剔除掉,首先想到的当然是百度了,问问度娘有没有什么图片去重的工具,搜了一下还真有.奈何本人智商捉急用不来这高级的 ...

  8. innerHTML,innertext ,textcontent,write()

    innerhtml属于对象的一个属性,一般用于向已经存在的标签中写入内容,或者读取标签的内容. innertext属于对象的一个属性,一般只能用于写入内容,或者读取内容,不能读取dom 中的标签,且只 ...

  9. IOS照片框架

    介绍 每天,用 iPhone 拍摄的照片数量超过了任何相机.每年 iOS 设备上的显示效果变得越来越好,回到 iPad 刚出现还没有 Retina 显示屏的时代,大屏幕的杀手级功能之一就是可以展示用户 ...

  10. [GodLove]Wine93 Tarining Round #2

    比赛链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=44704#overview 题目来源: ZOJ Monthly, June 2 ...