您当前的位置:首页 > 电脑百科 > 数据库 > MYSQL

为什么不建议给MySQL设置Null值?

时间:2022-05-06 14:32:26  来源:博客园  作者:海椰人

之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时、空数组、null值数组时,会将其视为该字段没有值,最终还是需要使用exists或者null_value来处理空值

大多数ElasticSearch的数据都来自于各类数据库,这里暂且只针对于MySQL,各个开源软件中都默认兼容各种Null值,空数组等等

若从根源上截断就可以省很多事,直到现在很多开发小伙伴还是坚韧不拔的给字段的默认值还是Null

本期就来聊一聊为什么不建议给字段的默认值设置为Null

本期环境为:MySQL8.0.26

为什么不建议给MySQL设置Null值?

 

null

一、案例数据

创建表user

CREATE TABLE `user` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
 `age` tinyint(4) unsigned NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

添加数据,共计10条数据,有两条数据的name值为Null

INSERT INTO `user` (`name`, `age`) VALUES ('kaka', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('niuniu', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('yangyang', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('dandan', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('liuliu', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('yanyan', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('leilie', 26);
INSERT INTO `user` (`name`, `age`) VALUES ('yao', 26);
INSERT INTO `user` (`name`, `age`) VALUES (NULL, 26);
INSERT INTO `user` (`name`, `age`) VALUES (NULL, 26);

一、count数据丢失

在这期 MySQL统计总数就用count,别花里胡哨的《死磕MySQL系列 十》 文章中,已经对count的使用说的非常明白了。

那借着这个案例,来分析一下为什么数据会丢失,先看结果

select count(*) as num1 ,count(name) as num2 from user;
为什么不建议给MySQL设置Null值?

 

使用count字段名时出现了数据丢失,很明显是因为主键ID9、10这两条记录的name值为空造成的。

为什么会出现这种情况?

当count除了主键字段外,会有两种情况:

一种是字段为null,执行时,判断到有可能是null,但还要把值取出来再判断下,不是null的进行累加

另一种是字段为not null,执行时,逐行从记录里边读出这个字段,判断不是null,才进行累加

此时,咱们遇到的问题是name字段的值存在了null值,所以会走第一种情况,不进行统计null值

为什么建议大家都使用count(*)?

MySQL对于count做了专门的优化,跟字段不同的是并不是把所有带了*的值取出来,而是指定了count(*)肯定不是null,只需要按行累加即可

MySQL团队对count(*)做了什么优化?

MySQL系列文章至今已经更新了第十八期了,你有没有猜到原因呢?

现在你应该知道主键索引结构中叶子节点存储的是整行数据,而普通索引叶子节点存储的是主键ID

那对于普通索引来说肯定会比主键索引小,因为对于MySQL来说,不管遍历哪个索引结果都一样,所以优化器会主动去找到那颗最小的树进行遍历。

在逻辑正确的前提下,尽量减少访问数据量,是数据库系统设计通用法则之一。

最后给大家留一个问题,为什么Innodb存储引擎不跟Myisam存储一样存储一个count值呢?

如果不知道的话,可以看上文提到的count文章

二、为distinct打抱不平

在开发工作中使用Distinct进行去重的场景十分的少,大多数情况都是使用group by完成的

select distinct name from user;

可以看到此时的数据依然是正确的,对Null值做了去重的操作

为什么不建议给MySQL设置Null值?

 

为什么要说这个,因为咔咔在其它的平台上看到过有人这么使用count(distinct name,mobile),然后说是统计出来的数据不准确。

这种用法依然是count(字段)的用法,distinct本身是会对Null进行去重,去重后依然是需要判断name的值不为null时,才会进行累计。

所以,不要把锅甩给distinct

三、使用表达式数据丢失

在一些值为null时,使用表达式会造成数据的不一致,接下来一起看下

select * from user where name != 'kaka';
为什么不建议给MySQL设置Null值?

 

表达式造成数据丢失

这跟我们的预期结果不大一致,预期是想返回id2~10的数据

当然,这个问题也不是无解,MySQL同样也提供了方法

要解决这个问题,只能再加一个条件就是把字段值为null的再单独处理一下

为什么不建议给MySQL设置Null值?

 

isnull

四、空指针问题

如果一个列存在null值,使用MySQL的聚合函数后返回结果是null,而并非是0,就会造成程序执行时的指针异常

CREATE TABLE user_order (
 id INT PRIMARY KEY auto_increment,
 num int
) ENGINE='innodb';
insert into user_order(num) values(3),(6),(6),(NULL);

创建用户订单数量表,并插入4条数据,接下来演示一下产生的问题

select sum(num) from goods where id>4;
为什么不建议给MySQL设置Null值?

 

聚合函数产生的问题

可以看到当字段为null时,使用聚合函数返回值就是null,并非是0,那么这个问题要怎么处理呢?

同样MySQL也给大家提供了对应函数,就是ifnull

select ifnull(sum(num), 0) from goods where id>4;
为什么不建议给MySQL设置Null值?

 

在这里插入图片描述

五、这是在难为谁?

当一个字段的值存在null值,若要进行null值查询时,必须要使用isnull或者ifnull进行匹配查询,又或者使用is null,is not null。

而常用的表达式就不能再进行使用了,有工作经验的还好的,要是新人的话会很难受。

接下来看几个新人经常犯的错误

错误一

对存在null值的字段使用表达式进行过滤,正确用法应该是is null 或者 is not null

select * from user where name<>null;
为什么不建议给MySQL设置Null值?

 

在这里插入图片描述

错误二

依然是使用表达式,同样可以使用isnull

为什么不建议给MySQL设置Null值?

 

在这里插入图片描述

六、总结

说了这么多也都感觉到了字段设置为null的麻烦之处,不过幸好的是MySQL对使用is null、isnull()等依然可以使用上索引。

咔咔目前所在的公司存在大量字段默认值就是null,于是代码中就大量存储ifnull、is null、is not null等代码。

一般字段数值类型的默认值就给成0,字符串的给个空也行,千万不要给null了哈!

文章来自
https://www.cnblogs.com/fkaka/p/16227471.html



Tags:Null值   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
SQL的NULL值和处理方法
在 SQL 中,NULL 值是一种特殊的数据类型,表示一个缺失或未知的值。虽然 NULL 值在某些情况下是很有用的,但是它们也经常导致问题和困惑,因为它们具有特殊的性质。本文将详细讲解...【详细内容】
2023-03-21  Search: Null值  点击:(213)  评论:(0)  加入收藏
为什么不建议给MySQL设置Null值?
之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时、空数组、null值数组时,会将其视为该字段没有值,最终还是需要使...【详细内容】
2022-05-06  Search: Null值  点击:(453)  评论:(0)  加入收藏
▌简易百科推荐
MySQL 核心模块揭秘
server 层会创建一个 SAVEPOINT 对象,用于存放 savepoint 信息。binlog 会把 binlog offset 写入 server 层为它分配的一块 8 字节的内存里。 InnoDB 会维护自己的 savepoint...【详细内容】
2024-04-03  爱可生开源社区    Tags:MySQL   点击:(10)  评论:(0)  加入收藏
MySQL 核心模块揭秘,你看明白了吗?
为了提升分配 undo 段的效率,事务提交过程中,InnoDB 会缓存一些 undo 段。只要同时满足两个条件,insert undo 段或 update undo 段就能被缓存。1. 关于缓存 undo 段为了提升分...【详细内容】
2024-03-27  爱可生开源社区  微信公众号  Tags:MySQL   点击:(18)  评论:(0)  加入收藏
MySQL:BUG导致DDL语句无谓的索引重建
对于5.7.23之前的版本在评估类似DDL操作的时候需要谨慎,可能评估为瞬间操作,但是实际上线的时候跑了很久,这个就容易导致超过维护窗口,甚至更大的故障。一、问题模拟使用5.7.22...【详细内容】
2024-03-26  MySQL学习  微信公众号  Tags:MySQL   点击:(14)  评论:(0)  加入收藏
从 MySQL 到 ByteHouse,抖音精准推荐存储架构重构解读
ByteHouse是一款OLAP引擎,具备查询效率高的特点,在硬件需求上相对较低,且具有良好的水平扩展性,如果数据量进一步增长,可以通过增加服务器数量来提升处理能力。本文将从兴趣圈层...【详细内容】
2024-03-22  字节跳动技术团队    Tags:ByteHouse   点击:(29)  评论:(0)  加入收藏
MySQL自增主键一定是连续的吗?
测试环境:MySQL版本:8.0数据库表:T (主键id,唯一索引c,普通字段d)如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的,因为自增主键不...【详细内容】
2024-03-10    dbaplus社群  Tags:MySQL   点击:(14)  评论:(0)  加入收藏
准线上事故之MySQL优化器索引选错
1 背景最近组里来了许多新的小伙伴,大家在一起聊聊技术,有小兄弟提到了MySQL的优化器的内部策略,想起了之前在公司出现的一个线上问题,今天借着这个机会,在这里分享下过程和结论...【详细内容】
2024-03-07  转转技术  微信公众号  Tags:MySQL   点击:(33)  评论:(0)  加入收藏
MySQL数据恢复,你会吗?
今天分享一下binlog2sql,它是一款比较常用的数据恢复工具,可以通过它从MySQL binlog解析出你要的SQL,并根据不同选项,可以得到原始SQL、回滚SQL、去除主键的INSERT SQL等。主要...【详细内容】
2024-02-22  数据库干货铺  微信公众号  Tags:MySQL   点击:(54)  评论:(0)  加入收藏
如何在MySQL中实现数据的版本管理和回滚操作?
实现数据的版本管理和回滚操作在MySQL中可以通过以下几种方式实现,包括使用事务、备份恢复、日志和版本控制工具等。下面将详细介绍这些方法。1.使用事务:MySQL支持事务操作,可...【详细内容】
2024-02-20  编程技术汇    Tags:MySQL   点击:(54)  评论:(0)  加入收藏
MySQL数据库如何生成分组排序的序号
经常进行数据分析的小伙伴经常会需要生成序号或进行数据分组排序并生成序号。在MySQL8.0中可以使用窗口函数来实现,可以参考历史文章有了这些函数,统计分析事半功倍进行了解。...【详细内容】
2024-01-30  数据库干货铺  微信公众号  Tags:MySQL   点击:(55)  评论:(0)  加入收藏
mysql索引失效的场景
MySQL中索引失效是指数据库查询时无法有效利用索引,这可能导致查询性能显著下降。以下是一些常见的MySQL索引失效的场景:1.使用非前导列进行查询: 假设有一个复合索引 (A, B)。...【详细内容】
2024-01-15  小王爱编程  今日头条  Tags:mysql索引   点击:(88)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条