回答
目前主流的分表策略有三种:
- Range 拆分
- Hash 取模拆分
- Rang 拆分 和 Hash 取模拆分的组合
Range 拆分
Range 拆分也叫做范围分表,即根据某个字段的范围来分表,比如我们将订单表的主键 order_id
,按照 0 ~ 500 万
,500 ~ 1000 万
的梯度来分表,如下:
有时候我们也会根据时间来排序,比把按年维度拆分工单表:
这种拆分的优点是它有利于扩容,比如我们按照时间来拆分,理论上是可以无限的扩容,而且不需要担心已经拆分好的数据。
但是它可能会有热点问题,比如 2024 年的工单表,在 2024 年内,几乎所有的请求都会打在 2024 年这张分表中,而2022、2023 的表几乎是已半归档的方式存在。同时,按照时间来拆分的话,也可能会出现数据倾斜的问题,比如随着业务的扩展,2024年的工单数据肯定比 2023 的数据多得多。
Hash 取模拆分
选定一个 Hash 算法对某个字段(例如 user_id
、order_id
、order_no
等等)进行进行哈希运算得到其 Hash 值,然后利用该 Hash 值取模分表的数量,得到的余数就是具体的分表。例如:假设有10 订单表,order_id
为 12345
的记录需要存储时,对 order_id
进行哈希,然后取模 10,结果为5,则存储在第 6 张表中,如下:
Hash 分表一份非常明显的优势就是他数据分布均匀,能够将数据均匀分布到各个表中,能够有效地避免热点问题,但是它有一个问题就是扩容非常麻烦,如果未来某天,表数据量增长到数据瓶颈了,需要进行扩容操作时,就会很麻烦。
所以,选择 Hash 分表测试时一般建议提前规划好,一次性分够,避免未来需要进行扩容操作。
当然,在实际生产场景中我们是可以灵活运用这两种分表策略,可以量量互相配合,比如 Hash 分表 + 时间,比如 Range 分表 + 时间,又或者 Hash 分表 + Range 分表,等等组合的策略,各位小伙伴们可以根据实际情况来进行组合。
大明哥举一个简单的例子,比如我们开发一个博客系统,用户基数非常大,则我们可以用 Hash 对用户表进行分表,然后对用户的博客按照时间来分表,如下:
扩展
分库分表可以从垂直(纵向)和水平(横向)两个维度进行拆分。
垂直拆分
垂直分库
垂直分裤一般来说都是按照业务维护来进行拆分,其核心理念就是专库专用,即将不同的业务数据分别放入到不同的数据库中。
由于业务刚刚开始,为了赶进度,能够尽快上线,我们一般将所有的业务、功能都冗余在一个单体应用中(如果你老板一上来,不管什么系统就是微服务,赶紧离开,因为他会害死你),但是随着业务的发展,我们需要按照业务类型对数据进行分离,比如将一个单体的电商服务拆分为订单、会员、支付、物流、商品、商家等等服务,不同的服务对应不同的数据库,且不同业务禁止跨库直连,统一采用 API 的方式来获取数据,其实就是微服务化!
垂直分表
垂直分表也垂直分库是存在区别的,它是指将一个表按照列来进行拆分为多个表,每个表包含原表中一部分的列,其主要目的是减少单表的宽度,提高查询效率。
比如,我们有一张 tb_user
表,他有 id
、name
、email
、phone
、address
五个字段,如下
在我们使用过程中发现 id
、name
、phone
使用很多,但是 email
、address
使用很少,这个时候我们就可以对 tb_user 表进行垂直分表,比将其拆分为 tb_user_base
和 tb_user_ext
两张表,如下:
当然垂直分表也不是瞎分的,一般都需要遵循几个原则:
- 高频字段和低频字段分离:将访问频率较高的字段和较低的字段分开存储,以提高高频字段的访问效率。
- 按照业务逻辑进行拆分:根据业务逻辑,将相关性强的字段放在一个表中,相关性弱的字段放在另一个表中。
虽然,垂直分表在一定程度上能够增加查询效率,但是由于一张表变成了多张表,所以会涉及到事务问题,同时,在某些查询的时候可能会涉及到关联表的查询,这样其实效率可能会更加低。
水平拆分
水平拆分是将一个很大的数据表按照某种规则拆分为多个小表,这些小表的表结构与大表一模一样,且每个小表中的数据只包含大表中的一部分数据。
比如,我们有一张 t_user
表中有 1000 万数据,我们按照某种规则将其拆分为 4 张小表 t_user_1
、t_user_2
、t_user_3
、t_user_4
,如下:
水平拆分后,减少了单表的数据量,在一定程度上提高了查询的性能,但是分表后,程序的处理会更加复杂,比如某个查询条件的数据位于多个表中,这就涉及到多个问题,比如分页、排序等问题。同时,如果水平分表的键选择不合适,则会导致数据分布不均匀。
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。