mysql为什么建议创建字段的时候not null

news2024/9/21 22:54:09

相信大家在建表或者给表新加字段的时候,一些老司机们都会建议我们,字段要定义为not null,原因呢是一是占用存储空间,另一个是避免出现一些意料之外的错误。当然针对这个问题,大家可能也会在网上去搜下,不过网上一些文章有的说不清楚,有的不仅解释不清楚,另外可能会让大家产生新的疑问。

所以今天呢,我们根据文档试着来梳理下not null相关的问题,希望能通过本篇文章让大家对这个null有个更进一步的认识,然后在平时的工作中不用再过多的纠结这个问题。

1. 列允许为null时的存储问题?

要搞清楚这个问题,其实就要了解MySQL表的存储行(row format)格式,当然我们只说InnoDB存储引擎这块。表的存储行格式决定了MySQL的行的物理存储方式,进而会影响查询和DML操作的性能。

MySQL当前版本8.0目前包含这四种格式:REDUNDANT,COMPACT,DYNAMIC,和COMPRESSED;而当前MySQL默认的格式是DYNAMIC;

查看表的存储行格式row_format:SHOW TABLE STATUS LIKE 'test' (test就是要查询的表名);

因为DYNAMIC有关null的存储和COMPACT是一致的,所以我们直接以COMPACT为例。这里根据官网文档及《Mysql技术内幕-InnoDB存储引擎》,简单画了一下COMPACT格式的存储方式:

当然这里,还会包含一个6字节的事务ID字段和一个7字节的回滚指针字段,另外如果没有为表定义主键,则还会包含一个6字节的row ID字段,这里不是我们本文的重点,这里就不多说了。

  • 根据文档,如果行中列为空,则会在null占位这里占用一位(1 bit),如果行中有两个列为null,则这里会占用两位,以此类推,然后存储的时候,不满8个bit,算1个字节;
  • 也就是说如果有1~8个null,那么会占用1个字节,9~16个null,会占用2个字节,如果为null的列的数量是N,那么最终需要的字节数是:CEILING(N/8)。
  • 另外,null除了在该位置处会占用空间外,其他不占用空间。官网来源:

The variable-length part of the record header contains a bit vector for indicatingNULLcolumns. If the number of columns in the index that can beNULLisN, the bit vector occupiesCEILING(N/8)bytes. (For example, if there are anywhere from 9 to 16 columns that can beNULL, the bit vector uses two bytes.) Columns that areNULLdo not occupy space other than the bit in this vector.

其实,到这里大家应该对null的占用空间问题清楚了吧 。接下来我们来梳理下null的一些特殊处理场景,这些场景才是我们值得注意的。

2. Mysql针对null的一些特殊逻辑处理

2.1 比较问题

如果查询字段是否为null,需要使用is null;如果要查询不为某个特定值(该值可能为null),如果使用!=,返回结果将不包含为null的数据。

比如想查询test表中 id不为1的记录,我们使用:

select * from demo where abc != 1;

那么查询等同于:

select * from demo where abc != 1 and abc is not null;

2.2 null不能用于范围查询,不能与非null进行比较

这块可以直接看官网的截图:

2.3 null与count

COUNT(column):统计结果不包含为null的行;COUNT(*) :对所有行进行统计,不管是否包含null,类似count(1);当然不仅仅是count方法,min,sum方法都是类似的:

mysql> SELECT COUNT(*), COUNT(age) FROM person; // output:3,2

这里参考自官网:MySQL :: MySQL 5.7 Reference Manual :: B.3.4.3 Problems with NULL Values

2.4 null与order by/group by

根据Mysql文档,order by中,如果使用asc进行排序,那么null值会排在最前面;desc的话,null会排在最后面;

For sorting with ORDER BY, NULL values sort before other values for ascending sorts, after other values for descending sorts.

而group by的话,所有为null的都是相同的,所以group by的时候会为一行;还有DISTINCT操作是一样的;

这里来源:MySQL :: MySQL 5.7 Reference Manual :: 9.1.7 NULL Values

2.5 null与索引

MYSQL 走索引的方式,目前只有 is NULL的情况下会走索引,当前如果联合索引中的查询符合条件也是生效的:

MySQL can perform the same optimization on col_name IS NULL that it can use for col_name = constant_value. For example, MySQL can use indexes and ranges to search for NULL with IS NULL.

来源:MySQL :: MySQL 5.7 Reference Manual :: 8.2.1.13 IS NULL Optimization

当null列被索引的时候,除了正常的数据类型占用的空间,需要额外占用一个字节的存储空间,这点我们一般可以通过执行计划看一下key_en的值,另外这里参考:

Due to the key storage format, the key length is one greater for a column that can beNULLthan for aNOT NULLcolumn.

3. 总结

根据MySQL的官网文档及《mysql技术内幕-存储引擎》和《高性能Mysql》一说,MySQL中存储null的确为额外占用一些空间,但将这些列从null优化为not null,并非会有很大的性能提升。

null的问题主要还是一些逻辑方面的问题,比如可能会使计算复杂些,会让我们处理的时候要多考虑些,亦或者是和其他中间件进行结合的时候,其他中间件对null的处理不太友好而出现一些问题等。

另外再说一点,建议大家多去看下MySQL官网的文档,另外如果英文不太好的小伙伴,可以使用Chrome浏览器的翻译功能,从我个人的体验来说,这个翻译功能还是很不错的。

其他:

为什么开发规范中不推荐NULL?
开发规范中不推荐使用NULL,并且倾向于使用NOT NULL约束,这样做有几个好处:

数据完整性:使用NOT NULL可以确保列中始终有值,这有助于维护数据的完整性和一致性。
避免歧义:NULL在SQL中是一个特殊的值,表示“未知”或“不存在”。它不同于空字符串或0,而且在进行比较和计算时,NULL会导致一些意想不到的结果。避免使用NULL可以减少这种歧义。
性能优化:不使用NULL可以简化数据库的内部处理。例如,您提到的NULL值列表就是InnoDB为了跟踪哪些列包含NULL值而维护的额外数据结构。如果表中的所有列都不允许NULL值,那么InnoDB就不需要维护这个列表,从而节省了空间并可能提高性能。
关于NULL值列表的处理过程简要概括一下:

InnoDB首先会确定哪些列允许存储NULL值。这包括那些没有明确设置为NOT NULL的列。
对于允许NULL值的列,InnoDB会为它们分配一个二进制位,这些位组合在一起形成了NULL值列表。这个列表用于跟踪每一行中哪些列的值是NULL。
二进制位的排列是逆序的,这意味着表中的第一列(如果它允许NULL值)将对应于列表中的最后一个二进制位,而最后一列将对应于第一个二进制位。
当二进制位的值为1时,表示对应的列值为NULL;当值为0时,表示对应的列值不为NULL。
通过这种方式,InnoDB能够高效地存储和检索NULL值信息,尽管这会增加一些额外的存储开销。但是,如果表中的所有列都设置为NOT NULL,那么这个NULL值列表就完全不需要了,从而节省了这部分空间。这也是为什么开发规范中经常推荐尽量避免使用NULL的原因之一。

mysql隐藏列?

每行数据除了用户定义的列之外,还包含两个隐藏列:6字节的事务ID列和7字节的回滚指针列。
对于NULL值,它只占用NULL标志位,不占用额外的存储空间。
此外,如果表没有定义主键,InnoDB还会为每行添加一个6字节的rowid列。这些隐藏列和rowid列对于保证事务的ACID特性和数据的恢复至关重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153522.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言中的一些小知识(三)

一、你了解printf()吗? 你知道下面代码的输出结果吗? int a123; printf("%2d \n",a); printf() 函数是 C 语言中用于格式化输出的标准函数,它允许你将数据以特定的格式输出到标准输出设备(通常是屏幕)。p…

20240921全国计算机二级Python考试(大头博士计算二级)

一、背景需求: 20240921我在上海应用技术大学44号楼考场参加2024年9月的全国计算机二级(Python语言程序设计)考试。 时隔多年,再次来到大学校园,恍若隔世 扫码找考场在哪里 考场须知 1、进考场,先刷身份证…

有关elementui form验证问题,有值却仍然显示不通过

参考链接 有关elementui form验证问题,有值却仍然显示不通过 - 一棵写代码的柳树 - 博客园 需要保证表单上的 :model" "和prop" "对应的属性相同 el-form 绑定数据:model 和 规则:rules input 绑定 数据表单里的数据 其父组件提供校验所绑定的…

Mybatis的XML实现方法

Mybatis的开发有两种方式: 1、注解 2、XML 使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。 Mybatis的XML的实现需要以下…

leetcode练习 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:3提示: 树中节点的数量在 [0, 104] 区间内。-100 …

java使用ByteBuffer进行多文件合并和拆分

1.背景 因为验证证书的需要,需要把证书文件和公钥给到客户,考虑到多个文件交互的不便性,所以决定将2个文件合并成一个文件交互给客户。刚开始采用字符串拼接2个文件内容,但是由于是加密文件,采用字符串形式合并后&…

fastadmin 部署后前台会员中心出现404错误

访问前台会员中心出现404错误。 解决:nginx访问站点增加伪静态 location / {if (!-e $request_filename){rewrite ^(.*)$ /index.php?s$1 last; break;} }在phpstydy中增加伪静态,如图:

保姆级教程教你如何安装Hadoop,实现Hadoop单机(非分布式)配置

下载Ubutu镜像 前往阿里镜像站https://mirrors.aliyun.com/oldubuntu-releases/releases/16.04.0/?spma2c6h.25603864.0.0.6be57ff3u2zMGR 选择下载ubuntu-16.04-desktop-amd64.iso 下载时间较久,请耐心等待 创建实验用虚拟机 选择创建新的虚拟机 选择典型并下一…

伊犁-linux 硬盘添加,分区,格式化

主要是linux 下操作硬盘分区,格式化 这样1个sata 盘就添加成功了 !  继续添加三块 sata1 hda sata hdb sata hdc sata hdd scsi sda 作为启动盘 进行操作系统的引导 如果scsi 往下调整 先敲enter 在用- 号往下 如果是往上调整敲…

win7自带壁纸丢失主题丢失

有时候盗版破解或者其他美化工具会导致win7自带的壁纸丢失,从个性化管理里面无法恢复原始的壁纸(如下图),但是由于工作原因公司的电脑又不方便设置第三方的壁纸,所以找了一下解决方案。 经典问题,百度找到的…

华为全联接大会HUAWEI Connect 2024印象(二):昇腾AI端侧推理

此次参加HUAWEI Connect 2024最主要目标是了解昇腾AI端侧推理技术,希望将其融合到我现在嵌入式系统课程中,不过刚开始在一楼找到一个小展台,看到了香橙派Orange Pi。香橙派是深圳迅龙的一个品牌,他们和很多芯片厂商都合作过&#…

创建Application(Qt)模板项目时的 Base class选择

在Qt中,当你使用Qt Creator新建一个Qt Widgets Application项目时,选择Base class是一个重要的步骤,因为它决定了你的主窗口或对话框将继承自哪个类,从而决定了你的应用程序将具有哪些基本的功能和外观。以下是一些常见的Base cla…

毕业设计选题:基于ssm+vue+uniapp的校园商铺系统小程序

开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…

动手学深度学习(李沐)PyTorch 第 1 章 引言

在线电子书 深度学习介绍 安装 使用conda环境 conda create -n d2l-zh python3.8 pip安装需要的包 pip install jupyter d2l torch torchvision下载代码并执行 wget https://zh-v2.d2l.ai/d2l-zh.zip unzip d2l-zh.zip jupyter notebookpip install rise如果不想使用jupyt…

NAT和代理服务

文章目录 NAT和代理服务1、NAT技术背景2、NAT 技术 IP 转换过程3、NAPT4、NAT 技术的缺陷5、代理服务器5.1、正向代理5.1.1、概念5.1.2、工作原理5.1.3、功能特点5.1.4、应用场景 5.2、反向代理5.2.1、概念5.2.2、工作原理5.2.3、应用场景 6、NAT 和代理服务器 NAT和代理服务 …

实景三维+耕地保护:构建耕地资源管理的全闭环新模式

在耕地资源日益珍贵的今天,如何高效、精准地实施耕地保护,成为了我国农业可持续发展与生态文明建设的关键课题。“实景三维耕地保护”的创新模式,能够为这一挑战提供突破性的解决方案,打造一个从前端监测到后端管理的全闭环耕地保…

Global Attention Decoder for Chinese Spelling Error Correction(ACL2021)

Global Attention Decoder for Chinese Spelling Error Correction(ACL2021) 一.概述 作者认为现有的纠错方法大多是基于局部上下文信息进行纠错,没有考虑句子中错词的影响。将注意力放在错误上下文信息上可能会误导并降低CSC(Chinese Spelling Correction)的整体性…

【计算机网络】网络层协议解析

网络层的两种服务IPv4分类编址划分子网无分类地址 IPv4地址应用IP数据报的发送和转发过程主机发送IP数据报路由器转发IP数据报 IPv4数据报首部格式ICMP网际控制报文协议虚拟专用网VPN与网络地址转换NAT 网络层主要任务是实现网络互连,进而实现数据包在各网络之间的传…

快速掌握Matlab R2016a安装,就是这么简单

Matlab R2016a下载方法: Matlab R2016a安装教程: 1、右击下载好的压缩包,选择解压到Matlab R2016a 2、打开文件夹【R2016a_win64】,右击下面的setup.exe,选择【以管理员身份运行】 3、点击选择【使用文件安装密钥】&a…

2024华为杯研究生数学建模,代码思路和参考文章

F题X射线脉冲星光子到达时间建模, E题高速公路应急车道紧急启用模型, D题大数据驱动的地理综合问題, C题数据驱动下磁性元件的磁芯损耗建模, B题W LAN 组网中网络吞吐量建模, A题风电场有功功率优化分配&#xff…