为什么不建议将 NULL 作为 MySQL 的列默认值?

小夏 科技 更新 2024-02-18

今天我要分享一个高频面试问题,你可以在5分钟内理解。为什么MySQL不建议使用null作为列默认值?

这个问题的答案通常是“”。具有 null 值的列将使索引失效但是如果你实际测试它,你就知道 null 会使用索引,所以上面的语句有一个漏洞。

那些匆忙的人拉到底部看看结论。

前言

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.

null 值是对一个列的特殊约束,当我们创建一个新列时,如果数据列没有用关键字 not null 显式声明,MySQL 会默认为我们添加一个 null 约束。 一些开发人员在创建数据表时懒得使用 MySQL 的默认推荐设置(即允许字段使用 null 值)。 这种坏习惯很容易导致查询结果不确定,在使用 null 的情况下降低数据库性能。

介绍

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.

null 并不意味着什么都没有,我们需要注意 null 并遵循''(Null 值)是两个完全不同的值。 在MySQL中可以操作的空值运算符主要有三种类型。

is null

is not null

飞船运算符,这个运算符很像 =,select null<=>null 可以返回 true,但 select null=null 返回 false。

ifnull 函数。 如何使用它自己检查......无论如何,我会的。

example

null never returns true when comparing with any other values except null with “<=>”.

null 将通过将任何运算符与除 <=> 之外的任何其他值进行比较来获得。

root@localhost mysql3306.sock)[zlm]>create table test_null(

id int not null,> name varchar(10)

query ok, 0 rows affected (0.02 sec)

root@localhost mysql3306.sock)[zlm]>insert into test_null values(1,'zlm');

query ok, 1 row affected (0.00 sec)

root@localhost mysql3306.sock)[zlm]>insert into test_null values(2,null);

query ok, 1 row affected (0.00 sec)

root@localhost mysql3306.sock)[zlm]>select * from test_null;

id | name |

1 | zlm |

2 | null |

2 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 |

2 | null |

1 row in set (0.00 sec)

root@localhost mysql3306.sock)[zlm]>select * from test_null where name is not null;

id | name |

1 | zlm |

1 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 |

1 | zlm |

2 | null |

2 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.

null 表示一个不确定的值,即使它是两个 null,它们也不一定相等。 (就像 c 中未初始化的局部变量一样)。

root@localhost mysql3306.sock)[zlm]>select 0 is null, 0 is not null, '' is null, '' is not null;

0 is null | 0 is not null | '' is null | '' is not null |

1 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 1 = null, 1 <>null, 1 < null, 1 > null;

1 = null | 1 <>null | 1 < null | 1 > null |

null | null | null | null |

1 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.

任何返回值包含 null 的表达式都将获得另一个 null 值。

root@localhost mysql3306.sock)[zlm]>select ifnull(null,'first is null'),ifnull(null+10,'first is null'),ifnull(concat('abc',null),'first is null');

ifnull(null,'first is null') |ifnull(null+10,'first is null') |ifnull(concat('abc',null),'first is null') |

first is null | first is null | first is null |

1 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).

使用 count(*) 或 count(null column) 的结果不同,count(null column)<=count(*)。

root@localhost mysql3306.sock)[zlm]>select count(*)count(name) from test_null;

count(*)count(name) |

1 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.

虽然 select null=null 的结果是 false,但当我们使用 distinct、group by 和 order by 时,null 被认为是相同的值。

root@localhost mysql3306.sock)[zlm]>insert into test_null values(3,null);

query ok, 1 row affected (0.00 sec)

root@localhost mysql3306.sock)[zlm]>select distinct name from test_null;

name |

zlm |null |

2 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 |2 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 |

2 | null |

3 | null |

1 | zlm |

3 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).

MySQL 支持对具有 null 值的列进行索引,但 Oracle 不支持。 这就是我们通常所说的,如果一个列包含 null,它将使索引失效。

严格来说,这种说法对于MySQL来说是不准确的。

root@localhost mysql3306.sock)[sysbench]>show tables;

tables_in_sysbench |

sbtest1 |

sbtest10 |

sbtest2 |

sbtest3 |

sbtest4 |

sbtest5 |

sbtest6 |

sbtest7 |

sbtest8 |

sbtest9 |

10 rows in set (0.00 sec)

root@localhost mysql3306.sock)[sysbench]>show create table sbtest1\g

*1. row **

table: sbtest1

create table: create table `sbtest1` (

id` int(11) not null auto_increment,k` int(11) not null default '0',c` char(120) not null default '',pad` char(60) not null default '',primary key (`id`),key `k_1` (k`)

engine=innodb auto_increment=100001 default charset=utf8

1 row in set (0.00 sec)

root@localhost mysql3306.sock)[sysbench]>alter table sbtest1 modify k int null,modify c char(120) null,modify pad char(60) null;

query ok, 0 rows affected (4.14 sec)

records: 0 duplicates: 0 warnings: 0

root@localhost mysql3306.sock)[sysbench]>insert into sbtest1 values(100001,null,null,null);

query ok, 1 row affected (0.00 sec)

root@localhost mysql3306.sock)[sysbench]>explain select id,k from sbtest1 where id=100001;

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

1 | sbtest1 | null | const | primary | primary | 4 | const | 1 | 100.00 | null |

1 row in set, 1 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 |

1 | sbtest1 | null | ref | k_1 | k_1 | 5 | const | 1 | 100.00 | using where; using index |

1 row in set, 1 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.

这是我自己测试的一个例子。

mysql> select * from test_1;

name | code | id |

gaoyi | wo | 1 |

gaoyi | w | 2 |

chuzhong | wo | 3 |

chuzhong | w | 4 |

xiaoxue | dd | 5 |

xiaoxue | dfdf | 6 |

sujianhui | su | 99 |

sujianhui | null | 99 |

8 rows in set (0.00 sec)

mysql> explain select * from test_1 where code is null;

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

1 | test_1 | null | ref | index_code | index_code | 161 | const | 1 | 100.00 | using index condition |

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from test_1 where code is not null;

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

1 | test_1 | null | range | index_code | index_code | 161 | null | 7 | 100.00 | using index condition |

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from test_1 where code='dd';

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

1 | test_1 | null | ref | index_code | index_code | 161 | const | 1 | 100.00 | using index condition |

1 row in set, 1 warning (0.00 sec)

mysql> explain select * from test_1 where code like "dd%";

id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

1 | test_1 | null | range | index_code | index_code | 161 | null | 1 | 100.00 | using index condition |

1 row in set, 1 warning (0.00 sec)

总结

null value always leads to many uncertainties when disposing sql statement.it may cause bad performance accidentally.

在列中使用 null 值很容易导致不受控制的事情发生,有时还会严重降低系统的性能。

例如:不会在聚合函数 () 中估计 null 值,这可能会导致结果不准确

对具有 null 值的列执行统计计算,例如count()、max()、min(),结果不符合我们的预期。

null value will influence the beh**ior 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.

有时我们需要在 SQL 中使用 ifnull() 来确保结果是可控的,以消除 null 带来的技术债务,但这会使程序复杂化。

null value needs a extra 1 byte to store the null information in the rows.

null 值不存储在原始字段空间中,但请求一个额外的字节来注释该字段,并使用 null 约束添加该字段(就像额外的标志位一样)。

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.

基于以上缺点,我们不建议设置 null 作为列的默认值,可以使用 not null 来消除默认设置,使用 0 或''空字符串而不是 null。

译者丨guangsu

*丨***J**aguide(ID:J**aguide)。

DBAPLUS 社区欢迎 editor@dbaplus 技术人员的贡献cn

相似文章

    为什么不推荐NFC?

    在这个技术日新月异的时代,近场通信 NFC 技术已成为我们日常生活的一部分。从支付和运输到设备之间的快速配对,NFC带来的便利是不可否认的。然而,随着这项技术的普及,也出现了一些我们需要关注的问题。关于NFC技术的最大争议点是它的安全性。由于NFC通信的距离非常短,只有几厘米,因此理论上黑客需要非常...

    为什么不建议使用手掌垫

    在选择床垫时,棕榈垫因其天然 环保和健康的好处而受到许多人的青睐。然而,尽管有这些优点,但仍有一些人不建议使用棕榈垫。那么,为什么不建议使用棕榈垫呢?本文将深入探讨这一点 首先,让我们了解一下棕榈垫的优点。棕榈垫通常由棕榈树的纤维制成,经过加工后具有良好的弹性和透气性。此外,棕榈垫还具有天然的防潮和...

    为什么不建议使用手掌垫

    在现代家庭中,床垫的选择对人们的健康和睡眠质量有着至关重要的影响。在床垫材料方面,棕榈垫因其天然 环保 健康的特性而一直受到青睐。然而,在深入了解了棕榈垫的制造工艺和有效性后,一些专家和消费者不建议使用棕榈垫。本文将介绍不推荐使用棕榈垫的原因。首先,用于制作棕榈垫的材料主要是植物纤维,其中最常见的是...

    为什么不建议去道观

    不建议去道观的原因可能有几个 .宗教场所的特殊性 道观是道教信徒修行 拜拜 拜拜的场所,具有宗教场所的特殊性。在道观中,人们需要遵守一定的宗教仪式和规定,尊重道教的信仰和文化,如果缺乏必要的理解和尊重,可能会造成不必要的误解和冲突。.建筑风格和历史价值 道观是中国传统建筑的重要组成部分,具有独特的建...

    为什么不建议收养孩子

    不推荐 的原因。随着社会的发展和人们观念的改变,越来越多的人选择 但是,在 之前,我们需要认真考虑一些问题,以确保收养行为的可行性和对孩子未来的影响。本文将 为什么不推荐 .收养关系的复杂性。这是一个复杂的过程,涉及法律 心理 社会和其他方面。在收养过程中,需要遵循严格的法律程序,以确保收养的合法性...