跳至内容
选择优化的数据类型
- 越小的越通常越好
- unsigned针对不存储负数更好
- 占用空间、内存、cpu缓存更少
简单最好
- 简单的数据类型,通常需要更少的cpu周期
- 使用mysql 内建数据,date,datetime timesamp比存储字符串更好
- 整类型比字符串代价更低,应为字符集和校对规则
- 尽量避免null
- 因为,查询包含null的列,对mysql来说更难优化,null使索引和索引统计、值比较更加复杂
- null列有索引,存储需要更多的空间,每个索引额外需要一个字节
- 通常null 改为not null性能提升较小,调优没有比较列为优化。创建schema可以考虑notnull
数据类型
datetime timesamp
timesamp
- 都可以精确到秒
- timesamp 只需要要datetime 一半的空间,4个字节
- timesamp可以包含时区
- timesamp 时间范围小 1970-2038
datetime
- datetime 从 1000-9999年 精度为秒
- 使用8个字节存储
整数类型(whole number)
- TINYINT、SMALLINT、MEDUIMINT、INT、IBGINT 分别使用 8、16、32、64位 范围从2n-1 到 2n+1
- tinyint(1) 这样是没有意义的,其实还是-127 – 127 之间,数据的类型已经决定了范围
实数类型(real number)
- 实数都是带有小数,类型:Decimal、Folat
- mysql 自身实现的decimal 计算 相对于cpu原生支持的cpu浮点计算,稍微慢一些,所以decimal 只是一种存储类型
- decimal 4个字节存9位,逗号单独一个字节
- mysql 5.0+ 版本中将decimal 打包成二级制字符串中
- 浮点存储同样数据占用空间比decimal 更少,float 使用4个字节,double 使用4个字节
- decimal 存储和计算开销,针对存储量很大的情况下,可以考虑使用bigInt * 10000 的方式来存储数据
字符串类型
varchar
- varchar 存储变长字段 ,他比定长类型更节省空间,因为他只是用必要的空间
- varchar 需要额外 1-2 个字节保存长度信息,小于255是一个字节,大于255是两个字节
- varchar 变长节省了空间对性能也有帮助
- varchar 变长也有一些缺点 : update 会更耗费时间,需要额外的操作,可能会分页
- varchar 适用于最大长度比平均长度大很多、列更新少
- varchar(10) 和varchar(200) 保存hello 用了同样空间,但是在内存中操作则会按最大空间来申请内存。所以尽量保证varchar长度够用
char
- char 是定长,占用固定空间
- char 适合存储比较短的字符串或者定长如: md5 、hash
- char 不容易产生碎片
- char 不需要额外字节记录长度
TEXT
- text 是字符串数据类型,blob是二进制
- text 有字符集和排序,blob 没有
选择标识符-主键
- 非分布式架构直接套用自增id做主键
- 小规模分布式架构用uuid或者自增id+步长做主键
- 大规模分布式架构用自建的id生成器做主键,参考twitter的[snowflake算法][2]
- 自增id 主键的好处有几点:索引有序插入,数据连续,insert性能相比较好uuid,不会产生分裂页。
- 自增使用uuid:方便水平和垂直扩展,insert性能差,索引不连续,select 性能比 自增id 差,应为相邻的逻辑行会分布到不同的磁盘和内存中,因为索引是有循序的
schema 设计现金
范式和反范式
范式
- 设计表时,不做冗余,对应关系
- 表相对会比较多,更新通常比反范式化快
- 范式化表更小,查询更快,更容易放到内存中
- 关联查询比较复杂
反范式
- 逻辑简单,适合用于逻辑少、项目较小的时候
- 会增加冗余,更新速度通常较慢
混合范式
缓存表、冗余表、累计表
- 针对一些group by 的操作,可以唯一张缓存表定时保存group by 后的数据,前提是可以忍受延迟
- 减少对主表的压力,可以使用不同的数据库引擎
- 可以导入到es搜索引擎,对原有表没有压力
- 可以通过影子表来重建缓存表,保持表不会有很多碎片一级完整顺序的索引(rename table xx to xx1,yy1 to yy),原子操作
计数表
- 单独创建一张计数表
- 预先增加100行数据,随机更新这些行
- 可以达到并行的处理,增加并发量