- 避免使用存储过程、触发器、自定义函数等 , 容易将业务逻辑和DB耦合在一起 , 后期做分布式方案时会成为瓶颈 。
- 考虑使用 UNION ALL , 减少使用 UNION , 因为 UNION ALL 不去重 , 而少了排序操作 , 速度相对比 UNION 要快 , 如果没有去重的需求 , 优先使用 UNION ALL 。
- 考虑使用 limit N , 少用 limit M , N , 特别是大表或 M 比较大的时候 。
- 减少或避免排序 , 如:group by 语句中如果不需要排序 , 可以增加 order by null 。
- 统计表中记录数时使用 COUNT(*) , 而不是 COUNT(primary_key) 和 COUNT(1) 。
- InnoDB 表避免使用 COUNT(*) 操作 , 计数统计实时要求较强可以使用 Memcache 或者 redis , 非实时统计可以使用单独统计表 , 定时更新 。
- 做字段变更操作(modify column/change column)的时候必须加上原有的注释属性 , 否则修改后 , 注释会丢失 。
- 使用 prepared statement 可以提高性能并且避免 SQL 注入 。
- SQL 语句中 IN 包含的值不应过多 。
- UPDATE、DELETE 语句一定要有明确的 WHERE 条件 。
- WHERE 条件中的字段值需要符合该字段的数据类型 , 避免 MySQL 进行隐式类型转化 。
- SELECT、INSERT 语句必须显式的指明字段名称 , 禁止使用 SELECT * 或是 INSERT INTO table_name values() 。
- INSERT 语句使用 batch 提交(INSERT INTO table_name VALUES(),(),()……) , values 的个数不应过多 。
业务层优化应该是收益最高的优化方式了 , 而且对于业务层完全可见 , 主要有业务拆分 , 数据拆分和两类常见的优化场景(读多写少 , 读少写多)!
文章插图
①业务拆分
业务拆分分为如下两个方面:
- 将混合业务拆分为独立业务
- 将状态和历史数据分离
对于状态和历史数据分离 , 我可以举一个例子来说明 。
例如:我们有一张表 Account , 假设用户余额为 100 。
文章插图
我们需要在发生数据变更后 , 能够追溯数据变更的历史信息 , 如果对账户更新状态数据 , 增加 100 的余额 , 这样余额为 200 。
这个过程可能对应一条 update 语句 , 一条 insert 语句 。对此我们可以改造为两个不同的数据源 , account 和 account_hist 。
在 account_hist 中就会是两条 insert 记录 , 如下:
文章插图
而在 account 中则是一条 update 语句 , 如下:
文章插图
这也是一种很基础的冷热分离 , 可以大大减少维护的复杂度 , 提高业务响应效率 。
②数据拆分
按照日期拆分:这种使用方式比较普遍 , 尤其是按照日期维度的拆分 , 其实在程序层面的改动很小 , 但是扩展性方面的收益很大 。
- 数据按照日期维度拆分 , 如 test_20191021 。
- 数据按照周月为维度拆分 , 如 test_201910 。
- 数据按照季度 , 年维度拆分 , 如 test_2019 。
推荐阅读
- 夏季如何预防蚊虫 千万别点蚊香
- 一条MySQL报警的分析思路
- 千万级 高并发“秒杀”架构设计
- MySQL 8.0 InnoDB无锁化设计的日志系统
- 湖南石门,政府招标采购千万良种茶苗公告
- MySql主从复制,从原理到实践
- 泰安市近千万元专项扶持资金促推泰山茶发展
- 历时七天,史上最强MySQL优化总结,从此优化So Easy
- 汽车维修后千万别错过这2个检查
- 房贷没放款前千万不要做的事 房贷没放款能领结婚证么