mysql默认空列的弊端

java后台开发中,设计表时,经常设置字符串类型字段的默认值为null,殊不知字段默认值为null,有哪些性能或存储空间浪费等细微问题。数据量小时,问题不容易发现,但是数据量上亿,细微问题将影响我们的应用性能。

概括
null列在查询的时候容易照成误解
null列在使用count的时候必须要多注意,COUNT(bindTime)不计算null值。
null作为索引需要更多空间,让索引变得复杂

问题一
问题二
新建一个表

CREATE TABLE `t_car` (
  `carId` BIGINT(20) NOT NULL,
  `plateNumber` VARCHAR(50) NOT NULL COMMENT '车牌号',
  `memberId` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '车主',
  `logoId` TINYINT(6) DEFAULT NULL COMMENT '车标',
  `carColor` TINYINT(4) DEFAULT NULL COMMENT '车辆颜色',
  `plateColor` TINYINT(4) DEFAULT NULL COMMENT '车牌颜色',
  `carType` TINYINT(4) NOT NULL COMMENT '车辆类型,0:小型车,1:中型车,2:大型车',
  `feeType` TINYINT(4) NOT NULL COMMENT '付费类型,0:免费,1:收费',
  `bindTime` DATETIME DEFAULT NULL COMMENT '绑定时间',
  `unBindTime` DATETIME DEFAULT NULL COMMENT '解绑时间',
  `createdTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updatedTime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `D` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '0:正常,1:删除',
  `energyType` TINYINT(4) DEFAULT NULL COMMENT '计费类型,1:新能源,2:燃油车',
  PRIMARY KEY (`carId`),
  UNIQUE KEY `plateNumber_2` (`plateNumber`,`plateColor`),
  KEY `plateNumber` (`plateNumber`),
  KEY `memberId` (`memberId`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='车辆表';
#查询总记录数
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car #1320336
#查询bindTime 为null的记录总数
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car  WHERE bindTime IS NULL;# 1097206
#查询bindTime不为null的记录总数
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car  WHERE bindTime IS NOT NULL;#218802
#查询bindTime不等于'2017-11-24 17:51:35'的记录总数(不包含bindTime为null的记录)
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car  WHERE bindTime NOT IN ('2017-11-24 17:51:35'); #208455
#查询bindTime等于'2017-11-24 17:51:35'的记录总数(不包含bindTime为null的记录)
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car  WHERE bindTime  IN ('2017-11-24 17:51:35'); #10347
##查询bindTime不等于''的记录总数(不包含bindTime为null的记录)
SELECT COUNT(*) FROM `prod_cod_busiconfdb`.t_car  WHERE bindTime NOT IN ('');#218802

问题三
null作为索引需要更多空间,让索引变得复杂
有很多会认为null值可能不需要消耗空间,实际上是错误的,空和空字符串是两码事,我没有研究过源码,但是很容易想到的是,mysql一定需要标记这个空字段,既然需要标记,那么就需要空间。
utf8字符集时,varchar(20)的索引keyLength=203+2=62
utf8mb4字符集时,varchar(20)的索引keyLength=20
4+2=82
如果索引字段允许为空,则keyLength=20*3+2 + 1=62+1=63
但是索引字段默认值为空串,则keyLength=62.

更多字段值为null的情况分析:
https://dev.mysql.com/doc/refman/5.6/en/working-with-null.html

UTF8和UTFMB4字符集比较

一、简介
MySQL在5.5.3之后增加了这个utf8mb4的编码,mb4就是most bytes 4的意思,专门用来兼容四字节的unicode。好在utf8mb4是utf8的超集,除了将编码改为utf8mb4外不需要做其他转换。当然,为了节省空间,一般情况下使用utf8也就够了。
二、内容描述
那上面说了既然utf8能够存下大部分中文汉字,那为什么还要使用utf8mb4呢? 原来mysql支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode字符,都无法使用 Mysql 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上),和很多不常用的汉字,以及任何新增的 Unicode 字符等等。
三、问题根源
   最初的 UTF-8 格式使用一至六个字节,最大能编码 31 位字符。最新的 UTF-8 规范只使用一到四个字节,最大能编码21位,正好能够表示所有的 17个 Unicode 平面。
   utf8 是 Mysql 中的一种字符集,只支持最长三个字节的 UTF-8字符,也就是 Unicode 中的基本多文本平面。
   Mysql 中的 utf8 为什么只支持持最长三个字节的 UTF-8字符呢?我想了一下,可能是因为 Mysql 刚开始开发那会,Unicode 还没有辅助平面这一说呢。那时候,Unicode 委员会还做着 “65535 个字符足够全世界用了”的美梦。Mysql 中的字符串长度算的是字符数而非字节数,对于 CHAR 数据类型来说,需要为字符串保留足够的长。当使用 utf8 字符集时,需要保留的长度就是 utf8 最长字符长度乘以字符串长度,所以这里理所当然的限制了 utf8 最大长度为 3,比如 CHAR(100)  Mysql 会保留 300字节长度。至于后续的版本为什么不对 4 字节长度的 UTF-8 字符提供支持,我想一个是为了向后兼容性的考虑,还有就是基本多文种平面之外的字符确实很少用到。
   要在 Mysql 中保存 4 字节长度的 UTF-8 字符,需要使用 utf8mb4 字符集,但只有 5.5.3 版本以后的才支持(查看版本: select version();)。我觉得,为了获取更好的兼容性,应该总是使用 utf8mb4 而非 utf8.  对于 CHAR 类型数据,utf8mb4 会多消耗一些空间,根据 Mysql 官方建议,使用 VARCHAR  替代 CHAR

unicode_17个面的字符编码

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200114153037641.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zNzUyOTY0MQ==,size_16,color_FFFFFF,t_70)
开始码位	结束码位	Block名称(英文)	Block名称(中文)
0000	007F	Basic Latin	基本拉丁字母
0080	00FF	Latin-1 Supplement	拉丁字母补充-1
0100	017F	Latin Extended-A	拉丁字母扩充-A
0180	024F	Latin Extended-B	拉丁字母扩充-B
0250	02AF	IPA Extensions	国际音标扩充
02B0	02FF	Spacing Modifier Letters	进格修饰字符
0300	036F	Combining Diacritical Marks	组合附加符号
0370	03FF	Greek and Coptic	希腊文和哥普特文
0400	04FF	Cyrillic	西里尔文
0500	052F	Cyrillic Supplement	西里尔文补充
0530	058F	Armenian	亚美尼亚文
0590	05FF	Hebrew	希伯来文
0600	06FF	Arabic	基本阿拉伯文
0700	074F	Syriac	叙利亚文
0750	077F	Arabic Supplement	阿拉伯文补充
0780	07BF	Thaana	塔纳文
07C0	07FF	NKo	N'Ko字母表
0900	097F	Devanagari	天成文书(梵文)
0980	09FF	Bengali	孟加拉文
0A00	0A7F	Gurmukhi	锡克教文
0A80	0AFF	Gujarati	古吉拉特文
0B00	0B7F	Oriya	奥里亚文
0B80	0BFF	Tamil	泰米尔文
0C00	0C7F	Telugu	泰卢固文
0C80	0CFF	Kannada	卡纳达文
0D00	0D7F	Malayalam	德拉维族文
0D80	0DFF	Sinhala	僧伽罗文
0E00	0E7F	Thai	泰文
0E80	0EFF	Lao	老挝文
0F00	0FFF	Tibetan	藏文
1000	109F	Myanmar	缅甸文
10A0	10FF	Georgian	格鲁吉亚文
1100	11FF	Hangul Jamo	朝鲜文
1200	137F	Ethiopic	埃塞俄比亚文
1380	139F	Ethiopic Supplement	埃塞俄比亚文补充
13A0	13FF	Cherokee	切罗基文
1400	167F	Unified Canadian Aboriginal Syllabics	加拿大印第安方言
1680	169F	Ogham	欧甘文
16A0	16FF	Runic	北欧古字
1700	171F	Tagalog	塔加路文
1720	173F	Hanunoo	哈努诺文
1740	175F	Buhid	布迪文
1760	177F	Tagbanwa	Tagbanwa文
1780	17FF	Khmer	高棉文
1800	18AF	Mongolian	蒙古文
1900	194F	Limbu	林布文
1950	197F	Tai Le	德宏傣文
1980	19DF	New Tai Lue	新傣文
19E0	19FF	Khmer Symbols	高棉文
1A00	1A1F	Buginese	布吉文
1B00	1B7F	Balinese	巴厘文
1D00	1D7F	Phonetic Extensions	拉丁字母音标扩充
1D80	1DBF	Phonetic Extensions Supplement	拉丁字母音标扩充增补
1DC0	1DFF	Combining Diacritical Marks Supplement	组合附加符号补充
1E00	1EFF	Latin Extended Additional	拉丁字母扩充附加
1F00	1FFF	Greek Extended	希腊文扩充
2000	206F	General Punctuation	一般标点符号
2070	209F	Superscripts and Subscripts	上标和下标
20A0	20CF	Currency Symbols	货币符号
20D0	20FF	Combining Diacritical Marks for Symbols	符号用组合附加符号
2100	214F	Letterlike Symbols	似字母符号
2150	218F	Number Forms	数字形式
2190	21FF	Arrows	箭头符号
2200	22FF	Mathematical Operators	数学运算符号
2300	23FF	Miscellaneous Technical	零杂技术用符号
2400	243F	Control Pictures	控制图符
2440	245F	Optical Character Recognition	光学字符识别
2460	24FF	Enclosed Alphanumerics	带括号的字母数字
2500	257F	Box Drawing	制表符
2580	259F	Block Elements	方块元素
25A0	25FF	Geometric Shapes	几何形状
2600	26FF	Miscellaneous Symbols	零杂符号
2700	27BF	Dingbats	杂锦字型
27C0	27EF	Miscellaneous Mathematical Symbols-A	零杂数学符号-A
27F0	27FF	Supplemental Arrows-A	箭头符号补充-A
2800	28FF	Braille Patterns	盲文
2900	297F	Supplemental Arrows-B	箭头符号补充-B
2980	29FF	Miscellaneous Mathematical Symbols-B	零杂数学符号-B
2A00	2AFF	Supplemental Mathematical Operators	数学运算符号
2B00	2BFF	Miscellaneous Symbols and Arrows	零杂符号和箭头
2C00	2C5F	Glagolitic	格拉哥里字母表
2C60	2C7F	Latin Extended-C	拉丁字母扩充-C
2C80	2CFF	Coptic	科普特文
2D00	2D2F	Georgian Supplement	格鲁吉亚文补充
2D30	2D7F	Tifinagh	提非纳字母
2D80	2DDF	Ethiopic Extended	埃塞俄比亚文扩充
2E00	2E7F	Supplemental Punctuation	标点符号补充
2E80	2EFF	CJK Radicals Supplement	中日韩部首补充
2F00	2FDF	Kangxi Radicals	康熙字典部首
2FF0	2FFF	Ideographic Description Characters	汉字结构描述字符
3000	303F	CJK Symbols and Punctuation	中日韩符号和标点 
3040	309F	Hiragana	平假名
30A0	30FF	Katakana	片假名
3100	312F	Bopomofo	注音符号
3130	318F	Hangul Compatibility Jamo	朝鲜文兼容字母
3190	319F	Kanbun	日文的汉字批注
31A0	31BF	Bopomofo Extended	注音符号扩充
31C0	31EF	CJK Strokes	中日韩笔划
31F0	31FF	Katakana Phonetic Extensions	片假名音标扩充
3200	32FF	Enclosed CJK Letters and Months	带括号的中日韩字母及月份
3300	33FF	CJK Compatibility	中日韩兼容字符
3400	4DBF	CJK Unified Ideographs Extension A	中日韩统一表意文字扩充A
4DC0	4DFF	Yijing Hexagram Symbols	易经六十四卦象
4E00	9FFF	CJK Unified Ideographs	中日韩统一表意文字
A000	A48F	Yi Syllables	彝文音节
A490	A4CF	Yi Radicals	彝文字根
A700	A71F	Modifier Tone Letters	声调修饰字母
A720	A7FF	Latin Extended-D	拉丁字母扩充-D
A800	A82F	Syloti Nagri	Syloti Nagri字母表
A840	A87F	Phags-pa	Phags-pa字母表
AC00	D7AF	Hangul Syllables	朝鲜文音节
D800	DB7F	High Surrogates	高位替代
DB80	DBFF	High Private Use Surrogates	高位专用替代
DC00	DFFF	Low Surrogates	低位替代
E000	F8FF	Private Use Area	专用区
F900	FAFF	CJK Compatibility Ideographs	中日韩兼容表意文字
FB00	FB4F	Alphabetic Presentation Forms	字母变体显现形式
FB50	FDFF	Arabic Presentation Forms-A	阿拉伯文变体显现形式-A 
FE00	FE0F	Variation Selectors	字型变换选取器
FE10	FE1F	Vertical Forms	竖排标点符号
FE20	FE2F	Combining Half Marks	组合半角标示
FE30	FE4F	CJK Compatibility Forms	中日韩兼容形式
FE50	FE6F	Small Form Variants	小型变体形式
FE70	FEFF	Arabic Presentation Forms-B	阿拉伯文变体显现形式-B 
FF00	FFEF	Halfwidth and Fullwidth Forms	半角及全角字符
FFF0	FFFF	Specials	特殊区域
10000	1007F	Linear B Syllabary	线形文字B音节文字
10080	100FF	Linear B Ideograms	线形文字B表意文字
10100	1013F	Aegean Numbers	爱琴海数字
10140	1018F	Ancient Greek Numbers	古希腊数字
10300	1032F	Old Italic	古意大利文
10330	1034F	Gothic	哥特文
10380	1039F	Ugaritic	乌加里特楔形文字
103A0	103DF	Old Persian	古波斯文
10400	1044F	Deseret	德塞雷特大学音标
10450	1047F	Shavian	肃伯纳速记符号
10480	104AF	Osmanya	Osmanya字母表
10800	1083F	Cypriot Syllabary	塞浦路斯音节文字
10900	1091F	Phoenician	腓尼基文
10A00	10A5F	Kharoshthi	迦娄士悌文
12000	123FF	Cuneiform	楔形文字
12400	1247F	Cuneiform Numbers and Punctuation	楔形文字数字和标点
1D000	1D0FF	Byzantine Musical Symbols	东正教音乐符号
1D100	1D1FF	Musical Symbols	音乐符号
1D200	1D24F	Ancient Greek Musical Notation	古希腊音乐符号
1D300	1D35F	Tai Xuan Jing Symbols	太玄经符号
1D360	1D37F	Counting Rod Numerals	算筹
1D400	1D7FF	Mathematical Alphanumeric Symbols	数学用字母数字符号
20000	2A+B316DF	CJK Unified Ideographs Extension B	中日韩统一表意文字扩充 B
2F800	2FA1F	CJK Compatibility Ideographs Supplement	中日韩兼容表意文字补充
E0000	E007F	Tags	标签
E0100	E01EF	Variation Selectors Supplement	字型变换选取器补充
F0000	FFFFF	Supplementary Private Use Area-A	补充专用区-A
100000	10FFFF	Supplementary Private Use Area-B	补充专用区-B

参考:
https://dev.mysql.com/doc/refman/5.6/en/working-with-null.html
https://blog.csdn.net/PROGRAM_anywhere/article/details/83243040
http://blog.sina.com.cn/s/blog_94479040010159j7.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值