Preface
 
    Null is a special constraint of columns.The columns in table will be added null constrain if you do not define the column with "not null" key words explicitly when creating the table.Many programmers like to define columns by default because of the conveniences(reducing the judgement code of nullibility) what consequently cause some uncertainty of query and poor performance of database.
 
Introduce

    Null is null means it is not anything at all,we cannot think of null is equal to '' and they are totally different.MySQL provides three operators to handle null value:"IS NULL","IS NOT NULL","<=>" and a function ifnull().
    IS NULL: It returns true,if the column value is null.
    IS NOT NULL: It returns true,if the columns value is not null.
    <=>: It's a compare operator similar with "=" but not the same.It returns true even for the two null values.(eg. null <=> null is legal)
    IFNULL(): Specify two input parameters,if the first is null value then returns the second one.It's similar with Oracle's NVL() function.
 
Example
 
Null never returns true when comparing with any other values except null with "<=>".
 (root@localhost mysql3306.sock)[zlm]>create table test_null(
-> id int not null,
-> name varchar()
-> );
Query OK, rows affected (0.02 sec) (root@localhost mysql3306.sock)[zlm]>insert into test_null values(,'zlm');
Query OK, row affected (0.00 sec) (root@localhost mysql3306.sock)[zlm]>insert into test_null values(,null);
Query OK, row affected (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null;
+----+------+
| id | name |
+----+------+
| | zlm |
| | NULL |
+----+------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where name=null;
Empty set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where name is null;
+----+------+
| id | name |
+----+------+
| | NULL |
+----+------+
row in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where name is not null;
+----+------+
| id | name |
+----+------+
| | zlm |
+----+------+
row in set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where null=null;
Empty set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where null<>null;
Empty set (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select * from test_null where null<=>null;
+----+------+
| id | name |
+----+------+
| | zlm |
| | NULL |
+----+------+
rows in set (0.00 sec) //null<=>null always return true,it's equal to "where 1=1".
Null means "a missing and unknown value".Let's see details below.
 (root@localhost mysql3306.sock)[zlm]>SELECT  IS NULL,  IS NOT NULL, '' IS NULL, '' IS NOT NULL;
+-----------+---------------+------------+----------------+
| IS NULL | IS NOT NULL | '' IS NULL | '' IS NOT NULL |
+-----------+---------------+------------+----------------+
| | | | |
+-----------+---------------+------------+----------------+
row in set (0.00 sec) //It's not equal to zero number or vacant string.
//In MySQL,0 means fasle,1 means true. (root@localhost mysql3306.sock)[zlm]>SELECT = NULL, <> NULL, < NULL, > NULL;
+----------+-----------+----------+----------+
| = NULL | <> NULL | < NULL | > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
row in set (0.00 sec) //It cannot be compared with number.
//In MySQL,null means false,too.
It truns null as a result if any expression contains null value.
 (root@localhost mysql3306.sock)[zlm]>select ifnull(null,'First is null'),ifnull(null+,'First is null'),ifnull(concat('abc',null),'First is null');
+------------------------------+---------------------------------+--------------------------------------------+
| ifnull(null,'First is null') | ifnull(null+,'First is null') | ifnull(concat('abc',null),'First is null') |
+------------------------------+---------------------------------+--------------------------------------------+
| First is null | First is null | First is null |
+------------------------------+---------------------------------+--------------------------------------------+
row in set (0.00 sec) //null value needs to be disposed with ifnull() function,what usually causes sql statement more complex.
//As we all know,MySQL does not support funcion index.Therefore,indexes on the column may not be used.That's really worse.
It's diffrent when using count(*) & count(null column).
 (root@localhost mysql3306.sock)[zlm]>select count(*),count(name) from test_null;
+----------+-------------+
| count(*) | count(name) |
+----------+-------------+
| | |
+----------+-------------+
row in set (0.00 sec) //count(*) returns all rows ignore the null while count(name) returns the non-null rows in column "name".
//This will also leads to uncertainty if someone is unaware of the details above.
When using distinct,group by,order by,all null values are considered as the same value.
 (root@localhost mysql3306.sock)[zlm]>insert into test_null values(,null);
Query OK, row affected (0.00 sec) (root@localhost mysql3306.sock)[zlm]>select distinct name from test_null;
+------+
| name |
+------+
| zlm |
| NULL |
+------+
rows in set (0.00 sec) //Two rows of null value returned one and the result became two. (root@localhost mysql3306.sock)[zlm]>select name from test_null group by name;
+------+
| name |
+------+
| NULL |
| zlm |
+------+
rows in set (0.00 sec) //Two rows of null value were put into the same group.
//By default,group by will also sort the result(null row showed first). (root@localhost mysql3306.sock)[zlm]>select id,name from test_null order by name;
+----+------+
| id | name |
+----+------+
| | NULL |
| | NULL |
| | zlm |
+----+------+
rows in set (0.00 sec) //Three rows were sorted(two null rows showed first).
MySQL supports to use index on column which contains null value(what's different from oracle).
 (root@localhost mysql3306.sock)[sysbench]>show tables;
+--------------------+
| Tables_in_sysbench |
+--------------------+
| sbtest1 |
| sbtest10 |
| sbtest2 |
| sbtest3 |
| sbtest4 |
| sbtest5 |
| sbtest6 |
| sbtest7 |
| sbtest8 |
| sbtest9 |
+--------------------+
rows in set (0.00 sec) (root@localhost mysql3306.sock)[sysbench]>show create table sbtest1\G
*************************** . row ***************************
Table: sbtest1
Create Table: CREATE TABLE `sbtest1` (
`id` int() NOT NULL AUTO_INCREMENT,
`k` int() NOT NULL DEFAULT '',
`c` char() NOT NULL DEFAULT '',
`pad` char() NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `k_1` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8
row in set (0.00 sec) (root@localhost mysql3306.sock)[sysbench]>alter table sbtest1 modify k int null,modify c char() null,modify pad char() null;
Query OK, rows affected (4.14 sec)
Records: Duplicates: Warnings: (root@localhost mysql3306.sock)[sysbench]>insert into sbtest1 values(,null,null,null);
Query OK, row affected (0.00 sec) (root@localhost mysql3306.sock)[sysbench]>explain select id,k from sbtest1 where id=;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| | SIMPLE | sbtest1 | NULL | const | PRIMARY | PRIMARY | | const | | 100.00 | NULL |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
row in set, warning (0.00 sec) (root@localhost mysql3306.sock)[sysbench]>explain select id,k from sbtest1 where k is null;
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+--------------------------+
| | SIMPLE | sbtest1 | NULL | ref | k_1 | k_1 | | const | | 100.00 | Using where; Using index |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+--------------------------+
row in set, warning (0.00 sec) //In the first query,the newly added row is retrieved by primary key.
//In the second query,the newly added row is retrieved by secondary key "k_1"
//It has been proved that indexes can be used on the columns which contain null value.
//column "k" is int datatype which occupies 4 bytes,but the value of "key_len" turn out to be 5.what's happed?Because null value needs 1 byte to store the null flag in the rows.
Summary
  • null value always leads to many uncertainties when disposing sql statement.It may cause bad performance accidentally.
  • null value will not be estimated in aggregate function(eg. count(),max(),min()) which may cause inaccurate results.
  • null value will influence the behavior of the operations such as "distinct","group by","order by" which causes wrong sort.
  • null value needs ifnull() function to do judgement which makes the program code more complex.
  • null value needs a extra 1 byte to store the null information in the rows.
  • As these above drawbacks,it's not recommended to define columns with default null.
  • We recommand to define "not null" on all columns and use zero number & vacant string to substitute relevant data type of null.
 

MySQL为何不建议使用null列的更多相关文章

  1. 50多条mysql数据库优化建议

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的.在非群集索引下,数据在物理上随机存 ...

  2. MySQL优化小建议

    背景 "那啥,你过来一下!" "怎么了?我代码都单元测试了的,没出问题啊!"我一脸懵逼跑到运维大佬旁边. "你看看!你看看!多少条报警,赶快优化一下! ...

  3. MySQL高性能优化规范建议,速度收藏

    数据库命令规范 •所有数据库对象名称必须使用小写字母并用下划线分割•所有数据库对象名称禁止使用 MySQL 保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)•数据库对象的命名要能做到见 ...

  4. (1) Mysql高性能优化规范建议

    数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意 ...

  5. WebAPI调用笔记 ASP.NET CORE 学习之自定义异常处理 MySQL数据库查询优化建议 .NET操作XML文件之泛型集合的序列化与反序列化 Asp.Net Core 轻松学-多线程之Task快速上手 Asp.Net Core 轻松学-多线程之Task(补充)

    WebAPI调用笔记   前言 即时通信项目中初次调用OA接口遇到了一些问题,因为本人从业后几乎一直做CS端项目,一个简单的WebAPI调用居然浪费了不少时间,特此记录. 接口描述 首先说明一下,基于 ...

  6. Mysql高性能优化规范建议

    数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意 ...

  7. 从原理上理解MySQL的优化建议

    从原理上理解MySQL的优化建议 预备知识 B+树索引 mysql的默认存储引擎InnoDB使用B+树来存储数据的,所以在分析优化建议之前,了解一下B+树索引的基本原理. 上图是一个B+树索引示意图, ...

  8. MySQL 高性能优化规范建议

    数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用 MySQL 保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名 ...

  9. MySQL 运行环境建议规范

    一.操作系统环境 操作系统版本选择 CentOS/RHRL/ORACLE Linux 5.x/6.x x86_64 发行版 建议磁盘分区规则 MySQL 运行环境建议规范 挂载点 大小 分区类型 分区 ...

随机推荐

  1. rail 怎样在已有数据库上继续开发

    今天刷贴看到了这篇文章http://ruby-china.org/topics/16493,老大回复的很有意义,在这里备份一个 而要把现有的数据库纳入 Migration,一个简单方法: 创建一个空 ...

  2. Clouder Manager安装时出现please remove the following file: /etc/cloudera-scm-server/db.properties问题解决(图文详解)

    问题详情 bigdata@ubuntucmbigdata1:/opt/softwares/cm-$ sudo ./cloudera-manager-installer.bin This install ...

  3. [DDD]學習筆記 第15章 精煉(Distillation)

    核心領域(Core-Domain) 為了使領域模型成為企業真正的資產, 模型中的關鍵核心部份需要足夠靈活和充分利用來創建應用程序的功能; 簡而言之, 核心領域是系統中最有價值的部份. 濃縮模型, 將最 ...

  4. vue的ajax

    vue的ajax常见的有两种 ,一种是 vue-resource,一种是axios vue-resource: 是vue的插件,非官方库, vue1.x 使用广泛 如何使用: 先在vue的脚本架上安装 ...

  5. SAP R/3 IDES 4.71 编译前后硬盘空间大小比较

    使用SGEN编译前 使用SGEN编译后

  6. 【Node.js】Stream(流)的学习笔记

    最近学习使用Node.js创建http proxy server,少不了要跟Stream打交道.昨天开始查阅一些资料,多少有了一些粗浅了解.整理在这里,供学习之用. 从Node.js API文档中可知 ...

  7. 自顶向下理解Java集合框架(三)Map接口

    Map基本概念 数据结构中Map是一种重要的形式.Map接口定义的是查询表,或称查找表,其用于储存所谓的键/值对(key-value pair),其中key是映射表的索引. JDK结构中还存在实现Ma ...

  8. java:图片压缩

    java使用google开源工具实现图片压缩 :http://www.cnblogs.com/linkstar/p/7412012.html

  9. Leetcode 78. Subsets (backtracking) 90 subset

    using prev class Solution { List<List<Integer>> res = new ArrayList<List<Integer&g ...

  10. char 与 signed char 和 unsigned char三者之间的关系

    # char 与 signed char 和 unsigned char三者之间的关系 三者都占用 1个字节,即 8 bit signed char取值范围(-128, 127) unsigned c ...