服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - mysql 字段定义不要用null的原因分析

mysql 字段定义不要用null的原因分析

2021-09-02 17:44balfish Mysql

这篇文章主要介绍了mysql 字段定义不要用null的原因分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一 NULL 为什么这么经常用

(1) java的null

null是一个让人头疼的问题,比如java中的NullPointerException。为了避免猝不及防的空指针,需要小心翼翼地各种if判断,麻烦又臃肿.

为此有很多的开源包都有诸多处理

common lang3的StringUtils.isBlank(); CollectionUtils.isEmpty();

guava的Optional

甚至java8也引入了Optional来避免这一问题(和guava的大同小异,用法稍有一点点变化)

(2) mysql的null为什么横行滥用

(a) 创建不规范 null是创建数据表时候默认的,一些mysql客户端的自动生成表语句里面可能也没有not null的指定。

(b) 错误认识 会有人觉得not null需要更多的空间

(c) 图省事 null在开发中不用判断插入数据,写sql更方便

二 官方文档

NULL columns require additional space in the rowto record whether their values are NULL. For MyISAM tables, each NULL columntakes one bit extra, rounded up to the nearest byte.

Mysql难以优化引用可空列查询,它会使索引、索引统计和值更加复杂。可空列需要更多的存储空间,还需要mysql内部进行特殊处理。可空列被索引后,每条记录都需要一个额外的字节,还能导致MYisam 中固定大小的索引变成可变大小的索引。 —— 出自《高性能mysql第二版》

如此看来,不指定not null并没有性能上的优势。

三 mysql不用null的理由

(1)所有使用NULL值的情况,都可以通过一个有意义的值的表示,这样有利于代码的可读性和可维护性,并能从约束上增强业务数据的规范性。

(2)NULL值到非NULL的更新无法做到原地更新,更容易发生索引分裂,从而影响性能。(null -> not null性能提升很小,除非确定它带来了问题,否则不要当成优先的优化措施)

(3)NULL值在timestamp类型下容易出问题,特别是没有启用参数explicit_defaults_for_timestamp

(4)NOT IN、!= 等负向条件查询在有 NULL 值的情况下返回永远为空结果,查询容易出错

四 null引发的bad case

数据初始化:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
create table table1 (
    `id` INT (11) NOT NULL,
    `name` varchar(20) NOT NULL
)
 
 
create table table2 (
    `id` INT (11) NOT NULL,
    `namevarchar(20)
)
 
insert into table1 values (4,"zhaoyun"),(2,"zhangfei"),(3,"liubei")
insert into table2 values (1,"zhaoyun"),(2, null)

(1)NOT IN子查询在有NULL值的情况下返回永远为空结果,查询容易出错

select name from table1 where name not in (select name from table2 where id!=1)

?
1
2
3
4
+-------------+
|      name   |
|-------------|
+-------------+

(2) 列值允许为空,索引不存储null值,结果集中不会包含这些记录。

select * from table2 where name != 'zhaoyun'

?
1
2
3
4
5
+------+-------------+
|   id |      name   |
|------+-------------|
|      |             |
+------+-------------+

select * from table2 where name != 'zhaoyun1'

?
1
2
3
4
5
+------+-------------+
|   id |      name   |
|------+-------------|
|   1  |  zhaoyun    |
+------+-------------+

(3) 使用concat拼接时,首先要对各个字段进行非null判断,否则只要任何一个字段为空都会造成拼接的结果为null

select concat("1", null) from dual;

?
1
2
3
4
5
+--------------------+
|   concat("1", null)|
|--------------------|
|               NULL |
+--------------------+

(4) 当计算count时候null column不会计入统计

select count(name) from table2;

?
1
2
3
4
5
+--------------------+
|   count(user_name) |
|--------------------|
|                  1 |
+--------------------+

五 索引长度对比

?
1
2
3
4
alter table table1 add index idx_name (name);
alter table table2 add index idx_name (name);
explain select * from table1 where name='zhaoyun';
explain select * from table2 where name='zhaoyun';

table1的key_len = 82

table2的key_len = 83

key_len 的计算规则和三个因素有关:数据类型、字符编码、是否为 NULL

key_len 82 = 20 * 4(utf8mb4 - 4字节, utf8 - 3字节) + 2(存储varchar变长字符长度为2字节,定长字段无需额外的字节)

key_len 83 = 20 * 4(utf8mb4 - 4字节, utf8 - 3字节) + 2(存储varchar变长字符长度为2字节,定长字段无需额外的字节) + 1(是否为null的标志)

所以说索引字段最好不要为NULL,因为NULL会使索引、索引统计和值更加复杂,并且需要额外一个字节的存储空间。

到此这篇关于mysql 字段定义不要用null的分析的文章就介绍到这了,更多相关mysql 字段定义null内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/balfish/p/7905100.html

延伸 · 阅读

精彩推荐
  • MysqlCentos5.5中安装Mysql5.5过程分享

    Centos5.5中安装Mysql5.5过程分享

    这篇文章主要介绍了Centos5.5中安装Mysql5.5过程分享,本文使用编译方法安装MySQL,并给出了一些可能遇到的错误和解决方法,需要的朋友可以参考下 ...

    MYSQL教程网5112020-04-28
  • MysqlMySQL中有哪些情况下数据库索引会失效详析

    MySQL中有哪些情况下数据库索引会失效详析

    这篇文章主要给大家介绍了关于MySQL中有哪些情况下数据库索引会失效的相关资料,文中通过图文介绍的非常详细,对大家学习或者使用mysql具有一定的参考...

    MicroHeart!2002019-07-07
  • MysqlMySQL入门教程(七)之视图

    MySQL入门教程(七)之视图

    视图是从一个或多个表中导出来的虚拟表。视图就像一个窗口,通过这个窗口可以看到系统专门提供的数据。本文给大家介绍MySQL入门教程(七)之视图,...

    MYSQL教程网3822020-06-03
  • MysqlMySQL 8.0.23中复制架构从节点自动故障转移的问题

    MySQL 8.0.23中复制架构从节点自动故障转移的问题

    这篇文章主要介绍了MySQL 8.0.23中复制架构从节点自动故障转移的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋...

    网络4452021-04-06
  • MysqlMySQL mysqldump命令使用详解

    MySQL mysqldump命令使用详解

    MySQL有很多可以导入数据的方法,然而这些只是数据传输中的一半,另外的一般是从MySQL数据库中导出数据。有许多的原因我们需要导出数据。一个重要的原...

    MySQL教程网12022021-08-29
  • MysqlMySql新手入门的基本操作汇总

    MySql新手入门的基本操作汇总

    MySQL是目前来说最好的 RDBMS应用软件之一,这篇文章主要给大家介绍了关于MySql基本操作的相关资料,非常适合mysql新手入门,需要的朋友们下面随着小编来...

    @红茶不加糖9312021-07-13
  • MysqlMySQL 在触发器里中断记录的插入或更新?

    MySQL 在触发器里中断记录的插入或更新?

    MySQL 不象其它有些数据库可以在触发器中抛出异常来中断当然触发器的执行以阻止相应的SQL语句的执行。在MySQL的目录版本中还无法直接抛出异常。这样我...

    mysql教程网2432019-10-31
  • MysqlMySQL实现当前数据表的所有时间都增加或减少指定的时间间隔(推荐)

    MySQL实现当前数据表的所有时间都增加或减少指定的时间间隔(推

    这篇文章主要介绍了MySQL实现当前数据表的所有时间都增加或减少指定的时间间隔,非常不错,具有参考借鉴价值,需要的朋友可以参考下...

    李宗禹4502020-07-16