数据库-垂直水平分库 - hanease - 博客园(很全面)
✅ 什么是分库分表?(知识库)
21. 运维-分库分表-Mycat分片-水平分表_哔哩哔哩_bilibili(视频教程,讲得一般,还行吧)
问题
为什么和怎么分?
什么情况下需要分库?
两个方面,一个是数据量大需要扩展了,一个是读写操作QPS/TPS太高(通过读写分离无法解决)。
- 一般是单个库数据量太大,从而导致IO请求的瓶颈。
- TPS太高通过 读写分离 无法解决,需要水平横向扩展数据库,解决QPS过高和并发写DB的压力(参考redis分片集群)
- 或者单个数据库连接数不够。
如果是写请求TPS太高可能需要分库,那读请求QPS太高一般怎么处理?
- 加缓存。如果是某些固定且经常读数据可以加,但是某些比如limit这种读就不方便了。
- MySQL读写分离,用主库写,从库读。
- 读写分离也不行,才进行分库。
什么是垂直分库
按业务进行拆分,以表为依据,将不同的表放到不同的库中(类似于微服务,或者说微服务是一种实现)
- 比如订单相关的表放到一个库,用户相关的表放到一个数据库。
水平分库
将一个数据库中的表,拆分到多个数据库中的表中,表的字段都是相同的。(类似于redis的分片集群。)
- 为了解决单个数据库QPS过高的问题。
- 在水平分库之前可以考虑读写分离,但是读写分离智能解决高并发读,不能解决高并发写的问题。(redis分片集群也是解决这个缺点)
- 一般mysql单机也就1000左右的QPS,如果超过1000就要考虑分库。
什么情况下需要分表?什么情况下垂直分,什么情况下水平分?
看是水平分还是垂直分?
什么情况分表?
- 单表数据大
- 磁盘文件大
什么情况下垂直分表?
- 大宽表数据量大。
- 并且存在冷热数据,就是有的列访问频繁,有的列访问频率很低。
- 某些列的的字段文本过大,比如text类型和longtext类型的列。
什么情况下水平分表?
- 单表数量太大(通过索引无法解决问题,索引层级大于三层)
如何确定分表数量,就是要分多少个表呢?
根据1. 当前数据量,2. 未来5-10年数据增长量,3. 表的列宽度确定(单行数据大小会影响树的高度)。
- 假设当前数据10亿条,未来每年增长1亿。考虑10年所以总共20亿的数据,如果表比较宽一张表最多容纳2000w,如果表很窄可以容纳1亿(相同索引高度下,单行数据大小会影响总数据行数)。
- 所以需要20张或者100张表,可以适当取2的幂次方也就是16/32 或者 128张表(如果采用hash取模法的话,哈希槽的个数是2的幂次方,那么取模的时候直接 key%n == n-1&key )。
垂直分表后怎么查数据,如果我要查询副表的数据?
很简单,通过联表查询,根据主表id去联合查询,把所需要的列都查出来。
大宽表有什么优点呢?
- 结构简单啊,还有就是说不用去联表查询,如果我某个sql需要查询多个列,就不用去联表了。
- 适合频繁查询大部分列的场景。(注意是频繁查询,如果不是频繁查询大部分列,可以垂直分做冷热数据分离)
分片规则
分库分表,用什么规则分?
- 如果是垂直分库,按业务分(参考微服务)
- 如果是垂直分表,冷热数据分离
- 如果是水平分库或者水平分表,有一些分片规则
水平分库分表的分片规则是什么?
水平分库其实建立在水平分表的基础上。例如水平分库时,选择user_id作为分片键,那么可能user_id=1的数据在db1,user_id=2的数据在db2。
- hash取模(对表/库 的总数进行hash取模)
-
- 优点:数据分布均匀,不会存在热点问题
- 缺点:扩容麻烦
- 按范围分
-
- 缺点:可能存在热点问题
- 一致性哈希
-
- 这个有点麻烦
解决带来的问题(重要)
分库分表有什么缺点?引入了什么问题?
- 不通过分片键查询(上述有解决方案)
- 表联合查询。
在水平分表的情况下,假如分片键是id,我想通过另一个字段,比如update_time查询出修改时间最近的十条记录,怎么解决?(雪花算法)
用A字段水平分表,查询字段用B字段,怎么做?
三种方法
- 基因法(b字段里包含a字段(分片字段作为b字段的基因),对b做解析之后,得到分片键就可以定位具体的表)
- 建立中间表。维护a字段和b字段的映射表,首先,查中间表通过b字段查询对应的a字段,然后再使用A字段查目标记录(两次查询,维护两个表)。
- ES + Hbase:
- 建立a、b字段的索引在ES中。也是从b映射到a字段,带着a去Hbase查。
- Hbase大数据量下根据rowKey查询非常快,然后去Hbase查。
什么是基因法,有什么方案?(复合分片算法)
基因法是将分片键的信息,融入到另一个分片字段B中。这样如果通过字段B查询,可以通过字段B解析出分片键,得到分片键就能定位具体的分表。(shardingsphere如何操作,待操作)
- 淘宝订单号,把用户的后六位数据冗余到订单号里。这样的话,我们就可以按照用户 ID 后六位进行分库分表,并且将分片键定义为用户 ID 和订单号。(用户ID和订单号都算分片键了)
- 雪花算法基因法:
建立中间表,有什么缺点?
- 查询的时候比较麻烦。
- 维护的时候要维护两个表。
分库分表后,join联表查询怎么办?
首先要避免join查询,解决方案 都是避免联合查询的方案。
- 字段冗余,为了避免join,那就多存一些字段信息。(例:订单表保存userId时候,也将userName冗余保存一份,这样查询订单详情时就不需要再去查询"买家user表"了)
- 查两次表,而不是联表查。例如:第一次查询的结果集中找出关联数据id,然后根据id发起第二次请求得到关联数据。最后将获得到的数据进行字段拼装。
使用框架
shardingsphere是什么,说一下(重要)
JDBC就是Java操作各种数据库的中间层,要用Java语言操作不同厂商的数据库,当然需要一个中间层。将Java的api根据不同数据库厂商的驱动,翻译成对应sql语句,并调用数据库执行。
同时JDBC还提供池化概念,构建数据库连接池,避免重复创建关闭连接。
09-ShardingSphere介绍_哔哩哔哩_bilibili
shardingsphere-jdbc是增强版的jdbc,
shardingsphere 和 MyCat框架有什么区别?
shardingsphere是jdbc直接连MySQL,myCat是一个代理层处于MySQL和JVM应用之间。
概念
分库分表的中心思想都是将数据分散存储,使得单一数据库/表的数据量变小来缓解单一数据库的性能问题,从而达到提升数据库性能的目的
什么是分库分表?水平?垂直?
什么是分库,如何分?
垂直分库
按业务进行拆分,以表为依据,将不同的表放到不同的库中(有点像微服务),比如订单相关的表放到一个库,用户相关的表放到一个数据库。
水平分库
类似于redis的分片集群。将一个数据库中的表,拆分到多个数据库中的表中,表的字段都是相同的。
为了解决单个数据库QPS过高的问题。
在水平分库之前可以考虑读写分离,但是读写分离智能解决高并发读,不能解决高并发写的问题。(redis分片集群也是解决这个缺点)
一般mysql单机也就1000左右的QPS,如果超过1000就要考虑分库。
垂直分表
把一个表的多个字段分别拆成多个表,一般按字段的冷热拆分,热字段一个表,冷字段一个表。从而提升了数据库性能。两个表通过主键外键关联。
一开始商品表中包含商品的所有字段,但是我们发现:
1.商品详情和商品属性字段较长。2.商品列表的时候我们是不需要显示商品详情和商品属性信息,只有在点进商品商品的时候才会展示商品详情信息。
所以可以考虑把商品详情和商品属性单独切分一张表,提高查询效率。
水平分表
- 单表数据量过大。例如一张1亿记录的表,拆成10张1千万数据的表。
- 例如如下的user表。
分片规则
1. hash取模( 选择一个字段也就算分片键,对表长度进行hash取模 )
优点:数据均匀,不容易出现热点问题。
缺点:固定hash的方式,后续集群扩容的时候比较麻烦和困难。
2. 范围分片
数据是均匀分的,但可能存在某些节点上热点数据的问题。
例如如果按时间范围分,那么可能存在某一时间段内热点数据的问题。