【MySQL】探究之null与not null

相信很多用了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)

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

时间: 2024-08-09 02:20:33

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

mysql探究之null与not null

相信很多用了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 到底有什么不一样. 首

MySQL中的字段约束 null、not null、default、auto_increment

在MySQL中,每个字段定义都包含附加约束或者修饰符,这些可以用来增加对所输入数据的约束.今天我们来看一下MySQL的字段约束:NULL和NOT NULL修饰符.DEFAULT修饰符,AUTO_INCREMENT修饰符. NULL 和 NOT NULL 修饰符: 可以在每个字段后面都加上这NULL 或 NOT NULL 修饰符来指定该字段是否可以为空(NULL),还是说必须填上数据(NOT NULL).MySQL默认情况下指定字段为NULL修饰符,如果一个字段指定为NOT NULL,MySQL则

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

MySQL中order by 排序遇到NULL值的问题 MySQL数据库,在order by排序的时候,如果存在NULL值,那么NULL是最小的,ASC正序排序的话,NULL值是在最前面的. 如果我们想让NULL排在后面,让非NULL的行排在前面该怎么做呢? MySQL数据库在设计的时候,如果字段允许NULL值,那么对该字段进行排序的时候需要注意那些值为NULL的行. 我们知道NULL的意思表示什么都不是,或者理解成"未知"也可以,它与任何值比较的结果都是false, 默认情况下,My

mysql中Null与not null的区别(转载)

相信很多用了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 到底有什么不一样. 首

数据库表字段,DEFAULT NULL与NOT NULL DEFAULT

为什么要把字段设置成not 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 byt

How to perform a SQL query for fields that are null (or not null)

Okay, maybe this is lame, but when I've been away from writing SQL database queries for a while I can never remember how to search for database table fields that are either NULL, or NOT NULL. I always try to use the = operator or something else. So,

2&gt;&1 &gt;/dev/null & 与/dev/null 2&gt;&1含义

/dev/null 代表空设备文件 > 代表重定向到哪里,例如:echo "123" > /home/123.txt 1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null" 2 表示stderr标准错误 & 表示等同于的意思,2>&1,表示2的输出重定向等同于1 1>/dev/null 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到

原!! java直接打印一个对象时,并不是直接调用该类的toString方法 ,而是会先判断是否为null,非null才会调用toString方法

网上看了好多java直接打印一个对象时,直接调用该类的toString方法 . 但是: Object obj=null; System.out.println(obj);//没有报错 System.out.println(obj.toString());//报空指针异常 System.out.println(obj);既然也是直接调用toString方法,为什么不报错??? 原因总结如下: 1.调用Object类的toString方法,必须保证object不是null值,否则将抛出NullPoi

SQL语句中=null和is null

平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS NOT NULL去做条件判断,因为SQL默认情况下对WHERE XX!= Null的判断会永远返回0行,却不会提示语法错误. 这是为什么呢? SQL Server文档中对Null值的比较运算定义了两种规则,如在SQL Server 2000中: 规则一是是ANSISQL(SQL-92)规定的Null