关系型数据库是绝大多数系统的数据核心,这个关键设施也往往是性能的瓶颈。以下是一些使用建议。
按业务场景设计表结构
业务场景: 一个mysql的用户表,1000万条记录,如何查询出当天生日的用户?
表结构通用规则
- 所有字段必须非空而且有默认值。
- 一般都有创建时间和更新时间字段,mysql5.6+ 支持数据库本身更新此字段。
- 尽可能不使用TEXT、BLOB类型.
- 表字符集尽量选择UTF8MB4,mysql的utf8不是标准的字符集,utf8mb4可以存储表情字符。
- 索引字段尽可能使用int/long, 索引为字符型不能超过32个字符。
- 注释尽量清楚
- 建表的时候应该考虑最终的数据量,mysql单表应该不超过1000万,分布式数据库按业务字段分区。
- 不使用外键,尽量少用联合唯一束缚。联合主键酌情使用。
查询最佳实践
互联网业务场景,数据库瓶颈一般出现在查询。
- 查询一般不关联超过3个表。
- 查询扫码记录数超过10万条,必须命中索引。
- 避免使用inner join,left join 语句中的主表应该是结果数据量最少的表。
- where语句最左原则,最靠近where的条件应该是索引,应该是可以最大限度缩小查询范围的条件。
- 避免破坏索引的不规范语句,比如id=‘1’,类型转换会忽略索引,比如 like %xxx%,模糊匹配也会破坏索引。
- 尽量少用数据库特殊函数,影响性能也不好迁移。
- 尽量少用group by/max/sum,如果是高频调用的sql, 意味着表结构不合理。
- 禁止使用 select *,不知道需要返回的字段,意味着不理解业务。
通用最佳实践
- 查询语句复杂,往往是缺状态字段或者缺统计表。
- 应该手写sql,反对使用所谓面向对象的orm中间件,比如hibernate,mybaits-plus。
- 单个api的sql语句一般不超过3条。 3次以上数据库交互,响应速度就很差。
- 读写分离,实时性要求不高的查询,应该走从库。互联的mysql 一般是1主3+从.
- 数据强一致,并且并发高的情况下(间隙锁),事务提交不能解决问题的话,考虑乐观事务(version字段)以及分布式全局锁(redis/zookeeper)