表设计原则
mysql存储原理
记录存储方式
- 记录按行存储在页内
- 按照主键顺序
- 页内单向链表
- 页间双向链表
基本数据类型
tinyint,smallint,mediumint,int,bigint,
float, double,decimal(存储类型,cup不支持直接计算)
varchar,char
MySQL的数据类型中长度的含义
- 字节:8位=1个字节
- 字符:gbk编码中一个字符占2个字节,utf-8编码中一个字符占3个字节
- 对于gbk类型,行长度最大为65535,则varchar列的最大长度算法就是 (65535-2)/2 =32766.5,所以此处就是32766了。
- 对于utf8还是有很大的差别,对应的是3个字节,所以需要除以3,按照(65535-2)/3,最大值就是21844了。
- char(n)和varchar(n)中的n代表字符的长度
- 整数类型的字段长度已经被系统固定死,所以int(n)中n几乎没有任何使用场景,它的含义是“显示位宽”,这个n无论填任何数,不影响存储环节,仅影响在检索时的输出格式
这5种整型的占用空间分别是:
序号 | 类型 | 长度 | 范围(无符号) | 范围有符号 |
---|---|---|---|---|
1 | tinyint | 1个字节 | 0 ~ 2^8 -1 | -2^8 ~ 2^8-1 |
2 | smallint | 2个字节 | 0 ~ 2^(8x2)-1 | -2^(8x2) ~ 2^(8x2)-1 |
3 | mediumint | 3个字节 | 0 ~ 2^(8x3)-1 | -2^(8x3) ~ 2^(8x3)-1 |
4 | int | 4个字节 | 0 ~ 2^(8x4)-1 | -2^(8x4) ~ 2^(8x4)-1 |
5 | bigint | 8个字节 | 0 ~ 2^(8x8)-1 | -2^(8x8) ~ 2^(8x8)-1 |
索引
索引使用技巧
- 联合索引:优于多列独立索引
- 索引顺序:选择性高的在前面
- 覆盖索引:二级索引存储主键值更有利
- 索引排序:索引同时满足查询和排序
- 使用独立列:索引不能是表达式,不能是函数的参数
- 建议多使用EXPLAIN 分析查询
主键索引
InnoDB会自动在表的主键上创建索引,数据结构使用B+Tree,主键索引也称为聚簇索引,它的索引结构和实际数据是存储在一起的,B+Tree叶子节点存储的就是实际的记录。
非主键索引
非主键索引是先通过自身索引结构找到主键值,然后再用主键值再聚簇索引上找打相应的记录,InnoDB就是这么做的,非主键索引也称为二级索引,特点是:
- 除了主键以意以外的索引
- 索引结构的叶子节点中的Data是主键值
- 一次查询需要查找自身和主键两个索引
联合索引
也称作多列索引,索引结构的key包含多个字段,排序时先按第一列比较,如果相同再按第二列比较,以此类推。联合索引上的查询需要满足一下特点:
- key按照最左原则开始查找,否则无法使用索引
- 跳过中间列,会导致后面的列不能使用索引
- 某列使用范围查找时,后面的列不能使用到索引
- 根据前缀索引特性,联合索引(a,b,c),可以满足(a),(a,b),(a,b,c)三种索引查询,但是不满足(a,c),(b,c)索引查询
主键选择
- 业务主键:更符合业务的查询需求。写入、查询效率和磁盘利用率低,可以使用一级索引,覆盖索引
- 自增主键:主键值传递,数据是顺序插入的,所以在页内数据物理连续,写满一页后再顺序分配下一页,再没有删除操作的情况下,磁盘利用率高,且随机IO很低,插入效率很高
- 随机主键:写入、查询效率和磁盘利用率低,每次查询走两级索引
索引个数
- 由于过多的索引会造成索引文件过大,所以索引个数最好不多于五个
列(字段)类型选择
- 通常越小、越简单越好,例如bool字段统一用tinyint,枚举类型也用tinyint,交易金额用long,针对金额数据,虽然InnoDB提供了支持精确计算的DECIMAL类型,但DECIMAL是存储类型不算数据类型,不支持cup原生计算,所以将小数点后的小数经处理转换成整数long存储
分表策略
- 首先要明确数据库出现性能问题一般都是在数据量到达一定的量级以后
- 提前做好预估,不要等需要拆分的时候再拆,一般把数据量控制再千万级别
- 常用分表策略有:按key取模,按时间分,两种,冷热数据明确。