MySql:分库、分表、分区,我平时常用分区和归档分表,系统总结一下

原则上来说,分库、分表、分区可以同时存在
单表抗2000万数据量问题不大,但具体的数据里还是要看记录大小、存储引擎设置、硬件配置等(简单来说就是B+树最多三层,别超过了)
阿里巴巴建议:单表行数超过 500 万行或者单表容量超过 2GB之后,才需要考虑做分库分表了,小于这个数据量,遇到性能问题先建议大家通过其他优化来解决。
分库
- 目的:解决的是并发量大的问题
- 例子:
- 微服务拆分的时候:按照业务边界,把各个业务的数据从一个单一的数据库中拆分开,分别把订单、物流、商品、会员等数据,分别放到单独的数据库中。
- 历史订单归档到历史库里面去。这也是分库的一种具体做法
分表
- 目的:解决的是数据量大的问题。通过将数据拆分到多张表中,来减少单表的数据量,从而提升查询速度。
- 方案
- 水平拆分
把数据库表中的数据会分散到多张分表中,使得每一个单表中的数据的条数都有所下降 - 垂直拆分
把数据库表中的数据的字段分散到多张分表中,使得每一个单表中的数据的存储有所下降。比如我可以把订单的商品详情信息、价格信息等等分别拆分到不同的表中
- 水平拆分
分区
mysql支持水平分区,正常情况下来说,根据年份啥的分区即可
- 分区和分表的区别
- 分区后还是同一个表,分表后是不同的表了,对于开发来说,分区简单,代码逻辑简单
- 先考虑分区,分区搞不定再考虑分表
原则上来说,分库、分表、分区可以同时存在
分表字段如何选择?(电商行业举例)
买家id、卖家id、订单号、时间、地区等等都可以选,没有特殊需求,如地区汇总、月份汇总啥的,可以选择买家id分表
不使用卖家id,是因为卖家的订单量极其不均衡,会产生数据倾斜,就是有的表数据多有的少
分表路由设定规则,比如想要分1024张表,那么可以用买家ID或者买家ID的hashcode对1024取模,结果是0000-1023,那么就存储到对应的编号的分表中就行了
会产生一个问题:卖家怎么查询数据
可以监听binlog同步数据生成一个以卖家为维度的表,只供查询,而且不局限于msyql了,es、hadoop都可以使用
分表算法都有哪些?
- 直接取模
知道要分多少表时 - 按照关键字
知道要分多少表,或者怎么分表时,例如固定几个枚举、年月等 - Hash取模
知道要分多少表时 - 一致性Hash
需要扩容,二次分表时
分表后全局ID如何生成?
- UUID
不推荐,UUID太长了,其次字符串的查询效率也比较慢,而且没有业务含义,根本看不懂。而且当索引时也不顺序 - 基于某个单表做自增主键
这个单表会变成整个系统的瓶颈,也存在单点问题,一旦挂了,整个数据库就都无法写入 - 基于多个单表+步长做自增主键
举个例子,假设四个表
第一个表主键1 至 1万
第二个表主键2万+1 至 3万
第二个表主键3万+1 至 4万
第二个表主键4万+1 至 5万 - 雪花算法(文案copy与互联网)
雪花算法生成的主键主要由 4 部分组成,1bit符号位、41bit时间戳位、10bit工作进程位以及 12bit 序列号位。
时间戳占用41bit,精确到毫秒,总共可以容纳约69年的时间。
工作进程位占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。
序列号占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。
所以,一个雪花算法可以在同一毫秒内最多可以生成1024 X 4096 = 4194304个唯一的ID
分库分表后可能的问题
- 跨库事务
分布式事务(这个没咋使用过)
使用队列,最终一致性可以 - 分页查询
可以看上面的 分表字段如何选择?以时间换空间
假设买家查询,同一个表没问题,卖家及别人查,同步一个新的表及使用别的大数据方案 - 二次分表
一致性哈希解决,但是需要数据迁移 - join 怎么搞
- 全加载入内存处理 性能不好
- 数据冗余,不再使用连表 增加空间
- 使用数据库中间件 复杂
- 把常用的字段组合异步放在ES类似的搜索引擎里
- 模糊搜索咋搞
不用管,直接上ES
分库分表中,如何预估需要分多少个库?多少张表?(网上搜索,经验整理总结,未生产环境实操)
- 分表数量
一般是一般是结合存量数据,以及增量数据的情况来看要分多少张表。知道存量已经有多少数据量了,以及一年大概增长多少,还要知道业务上希望你的数据保留多久。
分表数量= (订单存量总数 + 预计年增长量 * 保留年限)/2000万 => 向上取最接近的2的幂
2000万,是Innodb 理论上的单表极限(这里的极限指的是性能不变差的极限)。所以公式里的2000万可以改小,如 1000万
- 分库数量(感觉不对,正常情况下以模块分库即可,并发大,主从啊)
分库数量 = 分表数量 / 8
例如:
16库,128张表
8库,64张表
如果分表数量本身是小于8的,那要么是2,要么是4,那么直接分库数量=分表数量即可