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. Kudu compaction design

    不多说,直接上干货! http://blog.csdn.net/lookqlp/article/details/51438109

  2. Linux网卡操作

    单个网卡操作 [root@localhost ~]# ifdown eth0 #关闭网络 [root@localhost ~]# ifup eth0 #启动网络 网络服务: [root@localho ...

  3. stm32 输入捕获学习(二)

    (本文参考STM32  开发指南 V1.3   -- ALIENTEK 战舰 STM32 开发板库函数教程 ) 1. 实验设计 我们用 TIM5 的通道 1(PA0)来做输入捕获,捕获 PA0 上高电 ...

  4. GOPS 2018全球运维大会上海站 参会感悟梳理

    今天遇到很多优秀的讲师.业界的大伽,很开心 现在把get到的信息梳理一下:(1)想解决性能问题,一定要在缓存上下功夫:[nginx上有好多文章可以做,真是博大精深呢<深入理解Nginx:模块开发 ...

  5. GPU学习随笔

    NVML   NVAPI   GDK GDK包含NVML NVAPI库不能提供获取GPU使用率的接口 NVML能提供但不支持geforce系列 NVAPI.dll NVAPI64.dll动态加载可以查 ...

  6. mysql+C#

    MySqlParameter[] prams = ]; prams[] = new MySqlParameter("@personindex", personindex); pra ...

  7. golang中并发的相关知识

    golang中done channel理解:https://segmentfault.com/a/1190000006261218 golang并发模型之使用Context:https://segme ...

  8. WinForm皮肤 支持.NET4.0 IrisSkin4多彩皮肤演示和下载

    IrisSkin4是一款.NET平台非常优秀的Winform皮肤,链接库文件仅544kb,使用方法也非常简单 IrisSkin4(IrisSkin4.dll + 73套皮肤)[下载地址] 使用方法: ...

  9. 在DataColumn.Expression把DateTime转换成String的问题

    我在使用MySql5.1的数据库中,使用winForm的DataGridView要把数据库中全称DateTime格式,转换成Date格式,就是把日期时间转换成日期,不要时间.如‘2013-07-08 ...

  10. maven课程 项目管理利器-maven 3-4 eclipse安装maven插件和新建maven项目

    本节主要讲了两个主要内容, 1       eclipse安装maven插件 2 新建maven项目 3 本人实操 1       eclipse安装maven插件 eclipse4.0以上和myec ...