数据分表分库的基本思路

简介: 当一个数据库被创建之后,随着时间的推移和业务量的增加,数据库中的表以及表中的数据量都会越来越多,就有可能会出现两种弊端: (1)数据库的存储资源是有限的,其负载能力也是有限的,数据的大量积累肯定会导致其处理数据的能力下降; (2)数据量越多,那么对数据的增删改查等操作的开销也会越来越大; 所以,当出现如上两种情况,分库分表势在必行。

什么情况需要切分?


当一个数据库被创建之后,随着时间的推移和业务量的增加,数据库中的表以及表中的数据量都会越来越多,就有可能会出现两种弊端: (1)数据库的存储资源是有限的,其负载能力也是有限的,数据的大量积累肯定会导致其处理数据的能力下降; (2)数据量越多,那么对数据的增删改查等操作的开销也会越来越大; 所以,当出现如上两种情况,分库分表势在必行。


两种切分方式


垂直切分


举例场景:表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。 学生答题表 t 结构如下


列名


注释


id


答题表id


name


学生名


fraction


得分


answer


答案




其中answer是以特定格式来储存的字符 如: ABCCCDDDABB填空一填空二其他算数题…. 对于常用的列表来说,一般只查看姓名和总分数,对于具体的答案等字段很少需要查看,所以可以考虑把答案拆分成一张独立的表。 通过id与t表建立一对一的关系,同样将回答单独放到一张表中。这样我们插叙t中的分数的时候就不会扫描回答等不常用字段了。 若有些场景需要所有字段都查询出,可以使用join或者分次查询再合并结果。 再以一个实例代码示范 将订单拆分成订单主要信息表、订单附加信息表,两种信息都需要的情况再join,如果是单条信息,则也可以单独用id查询附加信息等。


<?php
/**
 * 订单分库 - 垂直分割
 * 将一笔订单的数据拆分储存在多个表里,查询的时候使用join联查出来
 * User: Siam
 * Date: 2018/11/25 0025
 * Time: 下午 10:04
 */
// 开始结束时间
$beginTime = '2018-09-01 00:00:00';
$endTime   = '2018-11-25 23:52:24';
$tableName = 'order_vertical as o';
$joinTableName = 'order_vertical_attach as oa';
// 联查
$sql = "select o.*,oa.* from $tableName JOIN $joinTableName where o.id = oa.o_id AND o.order_time BETWEEN '$beginTime' AND '$endTime'";
echo $sql;
// select o.*,oa.* from order_vertical as o JOIN order_vertical_attach as oa where o.order_time BETWEEN '2018-09-01 00:00:00' AND '2018-11-25 21:52:24'


水平切分


当表的列并不复杂,数量却很多,如用户表。假设有一千万条用户信息,如果只有一张表,每个用户登录的时候数据库都要从这一千万中查找,会很慢很慢。哪怕你建立了索引。 但如果将表以一定规则分割成10个表,则每个表只有百万条数据,就小了很多了,表命名一般可以为table_1,table_2等等 水平切分的规则常见有:id取模、添加时间等 id取模:可以将用户的id%100(这个数是你想要分成多少个表),那么会得到0-99的数,查询表的时候,将表名qq跟取模的数连接起来,就构建了表名。比如123456789用户,取模的89,那么就到table_89表查询 添加时间:以下用一条代码实例示范


<?php
/**
 * 订单分库 - 水平分割
 * 将订单表按一定规则(一般是时间)拆分成多个表,根据不同筛选条件调用不同表查询
 * User: Siam
 * Date: 2018/11/25 0025
 * Time: 下午 9:51
 */
/**
 * 方案① 时间中线分割,以某个时间点为中线切割
 * 注意:
 * 筛选的时候以结束日期为条件判断该差哪个表,在页面上需要做提示:数据以每一年的数据为区间分割,无法跨区间查询
 * 或者在代码中判断日期区间,然后分别查询,结果合并
 */
// 开始结束时间
$beginTime = '2017-09-01 00:00:00';
$endTime   = '2018-11-25 23:59:24';
// 分割的时间中线
$limitTime_1 = '2018-01-01 00:00:00'; // 10月以前的数据
$limitTime_2 = '2019-01-01 00:00:00'; // 10月1号到11月1号的数据
switch ($endTime) {
    case ($endTime < $limitTime_1):
        $tableName = 'order_2017';
        break;
    case ($endTime < $limitTime_2):
        $tableName = 'order_2018';
        break;
    default:
        $tableName = 'order_2018';
        break;
}
$sql = "select * from $tableName where order_time BETWEEN '$beginTime' AND '$endTime'";
echo $sql;
目录
相关文章
|
4月前
|
Java Maven 数据库
【快速使用ShardingJDBC的哈希分片策略进行分表】
【快速使用ShardingJDBC的哈希分片策略进行分表】
|
5月前
|
存储 大数据 数据库
分库分表知识总结(三)之水平分表
分库分表知识总结(三)之水平分表
47 0
|
5月前
|
存储 监控 数据库
分库分表知识总结(二)之垂直分表
分库分表知识总结(二)之垂直分表
50 1
|
4月前
|
存储 缓存 算法
哈希表与一致性哈希的原理理解以及应用
哈希表与一致性哈希的原理理解以及应用
64 0
|
8月前
|
负载均衡 监控 定位技术
分库表数据倾斜的处理让我联想到了 AKF 模型
这里的特殊性可以是表中字段的某一个属性,比如订单编号、创建时间等等。这就需要我们根据实际情况,既要拆分的均匀又要拆分之后能满足未来几年的发展,同时还要满足现有业务的支持。
45 0
|
12月前
|
存储 数据处理 数据库
分表方案有哪些
分表方案有哪些
82 0
|
12月前
|
存储 数据库连接 数据库
分库方案有哪些
分库方案有哪些
75 0
|
12月前
|
存储 程序员 数据库
如何选择合适的分表分库方案
如何选择合适的分表分库方案
68 0
|
12月前
|
存储 算法 关系型数据库
一次数据库分表分库的真实场景应用
一次数据库分表分库的真实场景应用
72 0
作为5年开发的程序员你不懂分表分库的实现思路,我表示不理解
分表分库实现思路 技术选型这一难题解决后,具体如何落实分表分库方案呢?需要考虑5个要点。 1)使用什么字段作为分片主键? 2)分片的策略是什么? 3)业务代码如何修改? 4)历史数据如何迁移? 5)未来的扩容方案是什么?