高性能mysql笔记-schema设计及优化

选择优化的数据类型

  • 越小的越通常越好
  • 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行数据,随机更新这些行
  • 可以达到并行的处理,增加并发量