MySQL千万级大表优化,看这一篇就忘不掉了( 五 )


有些应用架构看起来是按照分布式部署的 , 但在数据库层的调用方式是基于存储过程 , 因为存储过程封装了大量的逻辑 , 难以调试 , 而且移植性不高 。
这样业务逻辑和性能压力都在数据库层面了 , 使得数据库层很容易成为瓶颈 , 而且难以实现真正的分布式 。
所以有一个明确的改进方向就是对于存储过程的改造 , 把它改造为 SQL 调用的方式 , 可以极大地提高业务的处理效率 , 在数据库的接口调用上足够简单而且清晰可控 。
降维策略 2:DDL 操作转换为 DML 操作
有些业务经常会有一种紧急需求 , 总是需要给一个表添加字段 , 搞得 DBA 和业务同学都挺累 , 可以想象一个表有上百个字段 , 而且基本都是 name1 , name2……name100 , 这种设计本身就是有问题的 , 更不用考虑性能了 。
究其原因 , 是因为业务的需求动态变化 , 比如一个游戏装备有 20 个属性 , 可能过了一个月之后就增加到了 40 个属性 , 这样一来 , 所有的装备都有 40 个属性 , 不管用没用到 , 而且这种方式也存在诸多的冗余 。
我们在设计规范里面也提到了一些设计的基本要素 , 在这些基础上需要补充的是 , 保持有限的字段 , 如果要实现这些功能的扩展 , 其实完全可以通过配置化的方式来实现 , 比如把一些动态添加的字段转换为一些配置信息 。
配置信息可以通过 DML 的方式进行修改和补充 , 对于数据入口也可以更加动态、易扩展 。
降维策略 3:Delete 操作转换为高效操作
有些业务需要定期来清理一些周期性数据 , 比如表里的数据只保留一个月 , 那么超出时间范围的数据就要清理掉了 。
而如果表的量级比较大的情况下 , 这种 Delete 操作的代价实在太高 , 我们可以有两类解决方案来把 Delete 操作转换为更为高效的方式 。
第一种是根据业务建立周期表 , 比如按照月表、周表、日表等维度来设计 , 这样数据的清理就是一个相对可控而且高效的方式了 。
第二种方案是使用 MySQL rename 的操作方式 , 比如一张 2 千万的大表要清理 99% 的数据 , 那么需要保留的 1% 的数据我们可以很快根据条件过滤补录 , 实现“移形换位” 。
②SQL 优化
其实相对来说需要的极简的设计 , 很多点都在规范设计里面了 , 如果遵守规范 , 八九不离十的问题都会杜绝掉 。
在此补充几点:

  • SQL 语句简化 , 简化是 SQL 优化的一大利器 , 因为简单 , 所以优越 。
  • 尽可能避免或者杜绝多表复杂关联 , 大表关联是大表处理的噩梦 , 一旦打开了这个口子 , 越来越多的需求需要关联 , 性能优化就没有回头路了 , 更何况大表关联是 MySQL 的弱项 , 尽管 Hash Join 才推出 , 不要像掌握了绝对大杀器一样 , 在商业数据库中早就存在 , 问题照样层出不穷 。
  • SQL 中尽可能避免反连接 , 避免半连接 , 这是优化器做得薄弱的一方面 , 什么是反连接 , 半连接?
  • 其实比较好理解 , 举个例子:not in , not exists 就是反连接 , in , exists 就是半连接 , 在千万级大表中出现这种问题 , 性能是几个数量级的差异 。
③索引优化
应该是大表优化中需要把握的一个度:
  • 首先必须有主键 , 规范设计中第一条就是 , 此处不接收反驳 。
  • 其次 , SQL 查询基于索引或者唯一性索引 , 使得查询模型尽可能简单 。
  • 最后 , 尽可能杜绝范围数据的查询 , 范围扫描在千万级大表情况下还是尽可能减少 。
管理优化
这部分应该是在所有的解决方案中最容易被忽视的部分了 , 我放在最后 , 在此也向运维同事致敬 , 总是为很多认为本应该正常的问题尽职尽责(背锅) 。
MySQL千万级大表优化,看这一篇就忘不掉了

文章插图
 
千万级大表的数据清理一般来说是比较耗时的 , 在此建议在设计中需要完善冷热数据分离的策略 , 可能听起来比较拗口 , 我来举一个例子 , 把大表的 Drop 操作转换为可逆的 DDL 操作 。


推荐阅读