一、Mysql数据类型设计规范
1.1 选择更小的数据类型
一般情况下,在满足存储要求的基础上,尽量选择小的存储类型。例如:存储0~200,tinyint和bigint都可以存储,那么选择tinyint
。原因:越小的数据类型运算速度更快,占用磁盘、内存以及CPU缓存更小
。
1.2 简单更好
简单的数据类型意味着操作需要更少的CPU周期
。例如:整型比字符操作代价要小很多,因此字符集和排序规则
使得字符比整型更加复杂。
1.3 避免使用NULL值
虽然NULL值也可以走索引,但对索引统计
,值比较逻辑
以及内存使用
等不太友好。
索引统计: 由于Mysql在执行查询优化时,会基于索引统计
信息来选择最优的执行计划。当列中包含null值时,因null值不参与统计,会对执行计划产生影响,导致选择的执行计划不是最优的;
值比较逻辑: 对null值的操作只能使用is null, is not null,<=>
,因此在进行范围查询或等值比较
时,需要进行额外的处理;
选择步骤:
- 选择合适的
大类型
。比如:整型,字符串或时间 - 选择具体的
小类型
。比如:tinyint,bigint, datetime, timestamp
等。
二、各种数据类型使用场景解析
2.1 整数和小数类型
2.1.1 整数
类型:tinyint, smallint, mediumint, int, bigint.分别占用1,2,3,4,8个字节的空间;
是否支持负数:支持
特点:
1.默认是有符号。有unsigned【无符号】属性可以选择。加上unsigned意味着只能是正数,表示范围扩大一倍;
2.有符号和无符号存储空间是相同的;
3.int(n)和int(m)存储空间是一样的,只不过显示宽度不一样而已.
2.1.2 小数
Mysql既支持精确类型
,也支持不精确类型
。
精确类型:float和double
- 使用标准的浮点运算进行【近似计算】
- 适用于不需要精准计算的场景
不精确类型:decimal
- 用于存储精确的小数
- 适用于需要精准计算的场景。一般用于存储金额,但在大数据量情况下,可以将金额换算成分,存储到bigint里,解决浮点存储计算不精确和decimal精确计算代价高的问题。
decimal也有正负之分,通过unsigned来设置。decimal的格式为:decimal(P,D)
P: 表示有效数字位的精度。范围为1-65
D:表示小数点后的位数。范围为0-30。Mysql要求D小于等于P。
Decimal的存储:
2.2 字符串类型
char和varchar
:
char和varchar的区别:
前提:假设每个字符占用4个字节
- 存储方式:
- char是定长字符串。当为char指定一个长度M时,会使用固定长度4M的空间来存储数据;
- varchar是变长字符串。使用可变长度【实际字符串长度+存储字符串长度的空间】的空间来存储数据
- 使用场景
- char更适合固定长度的字符串存储;
- varchar更适合存储不定长度的字符串
varchar(10)场景下:"hh"和"hhh"占用多个字节?
"hh": 2个字符 * 4 为8个字节,由于8小于255,用1个字节来存储字符串的长度,因此总体为9个字节
"hhh": 3个字符 * 4 为12个字节,由于12小于255,用1个字节来存储字符串的长度,因此总体为13个字节
varchar(6)和varchar(10)的区别:存储同样的字符串"hello"
1. 占用的磁盘空间大小是一样的。都是5个字符*4 + 1 = 21个字节;
2. 占用的内存空间不一样。MySQL通常会分配【固定大小的内存块】来保存内部值。尤其是使用临时表进行排序会操作时,会消耗更多的内存。在使用磁盘进行排序时,也是一样
blob和text
:
两者都是为了存储大数据设计的字符串类型。blob采用二进制存储,text采用字符存储.
Mysql为了存储blob和text,专门分配存储区域
来存储,然后在B+树上使用1-4字节的内存指针
,指向存储区域。
2.3 时间类型
目前常用的两种时间格式为:datetime和timestamp
。Mysql目前仅支持到毫秒
级别的存储。
DateTime:
- 范围:1001-9999
- 精度:秒
- 与时区无关
- 8字节存储
TimeStamp:
- 范围:1970-2038
- 精度:秒
- 与时区有关
- 4字节存储
使用场景:
1. 为时间创建索引或精确到毫秒:将时间转换为bigint类型存储,方便索引;
2. 对内存敏感的场景:使用TimeStamp
3. 对内存不敏感的场景:使用DateTime
其它数据类型用的比较少,如果要使用的话,可以查阅相关的资料即可。
三、Null值设计思考
建议
:建表时,尽量不要将字段设置为null,给字段设置一个默认值
3.1 null生效和不生效情况
不生效情况:查询运算符、like、between and、in、not in对null查询不生效
生效情况:is null,is not null,<=>(安全等于,既可以判断null值,也可以判断普通数值,可读性差,不建议使用)
3.2 聚合函数和null值的结合
count(字段): 不会统计为null的数据;
count(*): 会统计为null的数据
3.3 null值和主键的结合
当字段设置为主键时,字段会自动被设置为not null
3.4 null值存储在B+树的哪里
考虑到主键不能为null,因此允许null值创建的索引都是非聚簇索引。设计Innodb的大叔定义Null值大小为最小的:
We define the SQL null to be the smallest possible value of a field.
因此,null值索引在B+树中的位置,应该是最靠近左边
的。