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=204+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个面的字符编码
![在这里插入图片描述]()
开始码位 结束码位 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