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
数据初始化:
create table table1 (
`id` INT (11) NOT NULL,
`name` varchar(20) NOT NULL
) create table table2 (
`id` INT (11) NOT NULL,
`name` varchar(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)
+-------------+
| name |
|-------------|
+-------------+
(2) 列值允许为空,索引不存储null值,结果集中不会包含这些记录。
select * from table2 where name != 'zhaoyun'
+------+-------------+
| id | name |
|------+-------------|
| | |
+------+-------------+
select * from table2 where name != 'zhaoyun1'
+------+-------------+
| id | name |
|------+-------------|
| 1 | zhaoyun |
+------+-------------+
(3) 使用concat拼接时,首先要对各个字段进行非null判断,否则只要任何一个字段为空都会造成拼接的结果为null
select concat("1", null) from dual;
+--------------------+
| concat("1", null)|
|--------------------|
| NULL |
+--------------------+
(4) 当计算count时候null column不会计入统计
select count(name) from table2;
+--------------------+
| count(user_name) |
|--------------------|
| 2 |
+--------------------+
五 索引长度对比
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字段尽可能用NOT NULL
下面咱们要聊的是 MySQL 里的 null,在大量的 MySQL 优化文章和书籍里都提到了字段尽可能用NOT NULL,而不是NULL,除非特殊情况.但却都只给结论不说明原因,犹如鸡汤不给勺子一样, ...
- 数据库设计mysql字段不默认为NULL原因搜集
索引不会包含有NULL值的列 只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的.所以我们在数据库设计时不要让字段的默认值为NULL ...
- mysql TIMESTAMP 设置为可NULL字段
今天遇到问题是mysql新建表的时候TIMESTAMP 类型的字段 默认是NOT NULL 然后上网查了一下 发现 很多都说 就是不能为NULL的 这都什么心态 其实设置为空很简单 只要在字段后面加上 ...
- mysql innodb 唯一键里的字段为什么不能为NULL
mysql 唯一键失效 CREATE TABLE `studnet_unique` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100 ...
- MySQL字段属性NUll的注意点
MySQL字段属性应该尽量设置为NOT NULL 除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL.这看起来好像有点争议,请往下看. 空值("&quo ...
- 转!!mysql 字段 is not null 和 字段 !=null
今天在查询数据时,查到包含一条某个时间startTime(该字段默认为null ) 为null的记录,想把它过滤,加了 startTime != null 的条件,结果记录都没了,应该用条件 is ...
- mysql字段默认值不生效的问题解决(上)
在项目中使用mybatis做为持久层框架,mysql数据库.项目上线前,DBA要求我们将每张数据库表中的字段都设置默认值和not null.之前项目中有一些insert语句是将表中所有字段都列出来,然 ...
- 一次修改mysql字段类型引发的技术探究
说来,mysql数据库是我们项目中用的比较多的库,ORM工具喜欢采用细粒度的MyBatis.这里面就这么引出了两者之间的故事! 首先,说改字段吧,将一个表中的varchar字段改为enum字段.如下: ...
- 2-16 MySQL字段约束-索引-外键
一:字段修饰符 1:null和not null修饰符 我们通过这个例子来看看 mysql> create table worker(id int not null,name varchar(8) ...
随机推荐
- Poj 2165 Milking Grid(kmp)
Milking Grid Time Limit: 3000MS Memory Limit: 65536K Description Every morning when they are milked, ...
- Codeforces Round #564 比赛总结
这次是中国大佬出题,结果被虐惨了. A. Nauuo and Votes #include<bits/stdc++.h> #define Rint register int using n ...
- OpenGL+VS2010环境配置及遇到的问题
OpenGL+VS2010+GLUT工具包+WIN10系统: 第一步,安装GLUT工具包 Windows环境下的GLUT下载地址:(大小约为150k) http://www.opengl.org/re ...
- 安装curl依赖库后yum不能使用问题解决
安装curl 1) 进入/home目录下,解压curl-7.54.0.tar.gz [root@localhost home]# tar zxvf curl-7.54.0.tar.gz 2) 依次 ...
- Flutter移动电商实战 --(23)分类页_左侧类别导航制作
自动生成dart类 https://javiercbk.github.io/json_to_dart/ 生成的代码 class Autogenerated { String code; String ...
- (main)贝叶斯统计 | 贝叶斯定理 | 贝叶斯推断 | 贝叶斯线性回归 | Bayes' Theorem
2019年08月31日更新 看了一篇发在NM上的文章才又明白了贝叶斯方法的重要性和普适性,结合目前最火的DL,会有意想不到的结果. 目前一些最直觉性的理解: 概率的核心就是可能性空间一定,三体世界不会 ...
- 交互式绘图工具gunplot
Gnuplot是一个命令行的交互式绘图工具(command-driven interactive function plotting program).用户通过输入命令,可以逐步设置或修改绘图环境,并 ...
- linux中如何配置vim的别名为vi?
答: 向~/.bashrc中添加如下内容: alias vi=vim
- Servlet的运行原理
- 海康大华RTSP格式
海康实时流:rtsp://admin:12345@192.2.82.50:554/h264/ch4/main/av_stream海康回放流(模拟通道):rtsp://admin:12345@192.2 ...