mysql调优之schema优化
1. 合理使用范式和反范式
MySQL的三范式:
1NF(第一范式):字段不可分;
2NF(第二范式):有主键,非主键字段依赖主键;
3NF(第三范式):非主键字段不能相互依赖;
解释:
1NF:原子性 字段不可再分,否则就不是关系数据库;
2NF:唯一性 一个表只说明一个事物;
3NF:每列都与主键有直接关系,不存在传递依赖;
在企业中很难能做到严格意义上的范式或者反范式,一般需要混合使用
范式设计和反范式设计的案例:
订单表如果完全按照范式设计,查询订单对应的用户信息时,会用到很多联合查询;如果用反范式设计,会明显提高查询效率。
2. 主键的选择
代理主键:与业务无关的,无意义的数字序列,比如:id
自然主键:事物属性中的自然唯一标识,比如:身份证号
推荐使用代理主键:
- 它们不与业务耦合,因此更容易维护
- 一个大多数表,最好是全部表,通用的键策略能够减少需要编写的源码数量,减少系统的总体拥有成本
3. 字符集的选择
- 纯拉丁字符能表示的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省大量的存储空间。mysql默认是latin1。
- 如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费。
- MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。
- 如果不存储中文,用latin1就足够了;如果要存储中文,就用utf8mb4。utf8mb4是一种最常用的方式。
4. 存储引擎的选择
mysql默认存储引擎是InnoDB
5. 适当的数据冗余
- 被频繁引用且只能通过 Join 2张(或者更多)大表的方式才能得到的独立字段。
- 这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的 IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新。
6. 适当拆分
当我们的表中存在类似于 TEXT 或者是很大的 VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率。