数据类型
更小通常更好 选择不会超过范围的最小类型
简单更好 简单数据类型操作代价低
尽量避免 NULL 值 索引会变得复杂,但不要极端
整数类型
类型 | 存储空间 |
---|---|
tinyint | 8 bit |
smallint | 16 bit |
mediumint | 24 bit |
int | 32 bit |
bigint | 64 bit |
UNSIGNED
属性不影响性能。
整数计算一般(某些聚合函数使用 decimal double)使用 64 位,与类型定义和环境无关。
为整数类型指定宽度(int(10)
)不会改变存储和计算的方式,不会限制值的合法范围。
实数类型
类型 | 存储空间 |
---|---|
float | 4 byte |
double | 8 byte |
decimal | 每 4 byte / 9 个数字 小数点 1 byte |
浮点计算内部使用 double 类型。
decimal 类型计算由 MySQL 自身实现,速度不如浮点;可以用来存储比 bigint 大的整数;数据量大时考虑用 bigint 代替 decimal 计算(乘以倍数后存储)。
字符串类型
注意字符串长度定义是字符数,多字节字符集需要更多存储空间
varchar 和 char
varchar 使用额外字节记录字符串的长度(<=255 一字节 否则两字节),如 varchar(1000) 需要 1002 字节。若 update 使得字符串变长,MyISAM 将行拆成不同的片段存储,InnoDB 则分裂页使行可以放入。用更长的列存储短字符串虽然空间开销一样,但会消耗更多内存。
- 字符串列的最大长度比平均长度大很多;
- 列的更新很少;
- 使用了每个字符字节数不同的复杂字符集(如 UTF-8);
char 会删除值末尾的空格,并根据需要填充空格以方便比较。因为定长,不宜产生碎片,没有额外字节。
- 较短字符串(如 char(1) Y/N);
- 经常变更的数据;
- 所有值接近一个长度;
blob 和 text
blob 是 smallblob 的同义词,采用二进制方式存储,没有排序规则或字符集;text 是smalltext 的同义词,采用字符方式存储,有排序规则和字符集(两者仅有的不同)。
blob 或 text 值太大时,每个值会通过行内 1~4 个字节的指针指向存储区域中实际的值。
enum
MySQL 内部将每个值在列表中的位置保存为整数,并在 .frm 文件中保存映射表。
enum 按照定义时的顺序(即存储的整数)而非字符串进行排序。显示指定:
1 | select e from enum_table order by field(e, 'a', 'b', 'c'); |
某些情况下,char/varchar 列与枚举列进行连接可能比直接连接 char/varchar 列更慢。(采用整数主键而避免采用基于字符串的值进行关联)。
日期和时间类型
类型 | 存储空间 | 时区 | 格式 |
---|---|---|---|
datetime | 8 bit (1001 - 9999) | 无关 | YYYYMMDDHHMMSS 整数 |
timestamp | 4 bit (1970 - 2038) | 依赖 | UNIX 时间戳 |
比秒更小的粒度可以考虑 bigint (时间戳)或 double (秒后小数部分)。
位数据类型
bit 在 MySQL 中作为字符串类型,而非数字类型;但在数字上下文中将是位字符串转换成的数字:
1 | create table bittest(a bit(8)); |
set 多选字符串数据类型,适合存储“多个值”。
设定set的格式:
字段名称 SET(‘选项1’, ‘选项2’, …, ‘选项n’)set 的每个选项值也对应一个数字,依次是1,2,4,8,16…,最多有64个选项。
使用的时候,可以使用 set 选项的字符串本身(多个选项用逗号分隔),也可以使用多个选项的数字之和(比如:1+2+4=7)。
范式
范式优缺点
- 更新操作比范式化快
- 重复数据很少或没有,修改更少的数据
- 表更小,执行操作更快
- 检索时更少需要 distinct 或 group by 语句
- 需要关联,产生额外代价
- 列存放在不同的表中,可能使一些索引无效
反范式优缺点
- 避免关联,顺序 I/O (与引擎有关)。
- 使用更有效的索引
- ……略
混用范式化和反范式化
从父表冗余一些数据到子表以方便排序。
缓存衍生值,避免性价比不高的子查询。
缓存表和汇总表
更快的读,更慢的写
缓存表(Cache Table)指那些包含能够轻松从Schema中获得的数据的表(但每次获取的速度慢),即表中的数据是逻辑冗余(Logically Redundant)。
汇总表(Summary/Roll-up Table)是说包含通过聚合函数得到的数据的表,例如表中数据是通过GROUP BY得到的。对优化搜索和检索查询语句很有效。
最常见的场景就是报表等统计工作。生成这些统计数据要扫描大量数据,实时计算成本很高且很多时候没有必要。而且查询这些数据还要加大量组合索引才能提高性能,然而这些索引又会对平时的更新和插入等操作造成影响。于是常用技术就是添加中间表到其他引擎(利用MyISAM更小的索引和全文检索能力),甚至其他系统(Lucene或Sphinx)。
计数表
解决独立表并发问题可以建多行,根据id随机更新,然后统计时 sum() 。
1 | CREATE TABLE hit_counter( |
可以按天或小时单独建行,旧时间可定时任务合并到统一的一行。
1 | CREATE TABLE daily_hit_counter( |
加速 alert table 操作
先禁用(删除)非唯一索引,导入数据之后重新启用索引。