聊聊项目中分表的实际应用-2022新项目

一、业务场景

  Web项目开发中,分表是时常会使用到的方式。分表的一个目的是为了缓解单表数据量过大,导致操作时

性能下降的问题。可是在实际开发中应该如何进行进行分表呢?那种分表方式更符合实际呢?

二、需求分析

  网上随便去搜索一下就会发现有很多的分表方式,比如常规的垂直拆分或者水平拆分。垂直拆分的方式就是将一个表中

的字段拆分到两张表中,可以将需要经常使用的字段放在一个表中,不经常使用的字段放在另一个表中,查询的时候需要两

张表同时进行取数据进行查询。操作比较麻烦,理论上可行,实际开发中自己从没遇到过这么分表的。第二种方式是进行

水平拆分,其中一种方式是可以按照时间段进行拆分,比如按照年份进行拆分,不同的年份查询不同的表。这种分法在实际

的项目开发中遇到过,比如一些统计表中使用的就是这种方式,按照年为单位来进行数据统计操作。示例为tabl_2022,taible_2023,

table_2024.

三、解决方案

  自己在真实开发中还遇到过其他的分表方案,也主要是应对数据量比较大的情况来进行处理的。以贵州省为例,分为各地州市,

在建表的时候,以各地州市的区号作为表的后缀进行分表。这样在查询的时候,就可以根据不同的表去查询需要的数据,由于数据

分散在各个地州市的表中,查询的效率也会高很多。这种方式有特定的应用场景,除了根据地州市进行分表外,也可以根据其他方式,

比如说省份编号,如果是全国性的项目。总之就是根据实际数据的特点来进行具体的分表操作。示例table_0851,table_0852,table_0853,

table_0854,table_0855,table_0856,table_0857,table_0858,table_0859.

自己还遇到过另外一种分表方式也比较实用,那就是先大致确定要创建多少张表,然后使用表中的一个具体的字段比如

用户id对表的总数取余,就可以知道将数据存储在哪一张表当中。举个简单的示例,如果需要分表总数为30,表的后缀

可以是029。如果用户ID130,就会均匀的散落在这张表当中。测试代码如下:

 

int uerId;
int tableTotal = 30;
int tableSuffix;
for(int i = 0; i < 30; i++) {
    uerId = i + 1;
    tableSuffix = uerId % tableTotal;

    System.out.println("用户IDuerId->" + uerId + ";表后缀tableSuffix->" + tableSuffix);
}

测试结果如下:

用户IDuerId->1;表后缀tableSuffix->1

用户IDuerId->2;表后缀tableSuffix->2

用户IDuerId->3;表后缀tableSuffix->3

用户IDuerId->4;表后缀tableSuffix->4

用户IDuerId->5;表后缀tableSuffix->5

用户IDuerId->6;表后缀tableSuffix->6

用户IDuerId->7;表后缀tableSuffix->7

用户IDuerId->8;表后缀tableSuffix->8

用户IDuerId->9;表后缀tableSuffix->9

用户IDuerId->10;表后缀tableSuffix->10

用户IDuerId->11;表后缀tableSuffix->11

用户IDuerId->12;表后缀tableSuffix->12

用户IDuerId->13;表后缀tableSuffix->13

用户IDuerId->14;表后缀tableSuffix->14

用户IDuerId->15;表后缀tableSuffix->15

用户IDuerId->16;表后缀tableSuffix->16

用户IDuerId->17;表后缀tableSuffix->17

用户IDuerId->18;表后缀tableSuffix->18

用户IDuerId->19;表后缀tableSuffix->19

用户IDuerId->20;表后缀tableSuffix->20

用户IDuerId->21;表后缀tableSuffix->21

用户IDuerId->22;表后缀tableSuffix->22

用户IDuerId->23;表后缀tableSuffix->23

用户IDuerId->24;表后缀tableSuffix->24

用户IDuerId->25;表后缀tableSuffix->25

用户IDuerId->26;表后缀tableSuffix->26

用户IDuerId->27;表后缀tableSuffix->27

用户IDuerId->28;表后缀tableSuffix->28

用户IDuerId->29;表后缀tableSuffix->29

用户IDuerId->30;表后缀tableSuffix->0

数据会均匀的分散在各个表当中。随机测试用户ID,代码如下,

public static void main(String[] args) {
    int uerId;
    int tableTotal = 30;
    int tableSuffix;
    for(int i = 0; i < 30; i++) {
        uerId = createUserId();
        tableSuffix = uerId % tableTotal;
        System.out.println("用户IDuerId->" + uerId + ";表后缀tableSuffix->" + tableSuffix);
    }
}

private static Random random = new Random();

public static int createUserId() {
    return random.nextInt(200000) + 1;
}

测试结果如何预期,数据也会按照一定的规律散落在不同的表当中,测试结果如下

用户IDuerId->54631;表后缀tableSuffix->1

用户IDuerId->128276;表后缀tableSuffix->26

用户IDuerId->83817;表后缀tableSuffix->27

用户IDuerId->68859;表后缀tableSuffix->9

用户IDuerId->182986;表后缀tableSuffix->16

用户IDuerId->103205;表后缀tableSuffix->5

用户IDuerId->70934;表后缀tableSuffix->14

用户IDuerId->146739;表后缀tableSuffix->9

用户IDuerId->118293;表后缀tableSuffix->3

用户IDuerId->149639;表后缀tableSuffix->29

用户IDuerId->141622;表后缀tableSuffix->22

用户IDuerId->159620;表后缀tableSuffix->20

用户IDuerId->167884;表后缀tableSuffix->4

用户IDuerId->115932;表后缀tableSuffix->12

用户IDuerId->68012;表后缀tableSuffix->2

用户IDuerId->143793;表后缀tableSuffix->3

用户IDuerId->159777;表后缀tableSuffix->27

用户IDuerId->138104;表后缀tableSuffix->14

用户IDuerId->85888;表后缀tableSuffix->28

用户IDuerId->5910;表后缀tableSuffix->0

用户IDuerId->138018;表后缀tableSuffix->18

用户IDuerId->152221;表后缀tableSuffix->1

用户IDuerId->117515;表后缀tableSuffix->5

用户IDuerId->22838;表后缀tableSuffix->8

用户IDuerId->183603;表后缀tableSuffix->3

用户IDuerId->99599;表后缀tableSuffix->29

用户IDuerId->158027;表后缀tableSuffix->17

用户IDuerId->111455;表后缀tableSuffix->5

用户IDuerId->39728;表后缀tableSuffix->8

用户IDuerId->61524;表后缀tableSuffix->24

这种分表方式很好的实现了对数据的分表存储和查询操作。在操作的时候传入表后缀,然后使用Mybatis中提供的

拦截器,在查询的时候进行统一的替换表名,可以查看之前写的博文 https://www.cnblogs.com/yilangcode/p/16482816.html

这样就可以很好的实现分表操作。这种方式也是项目中正在使用的一种方式。

具体的分表操作可以根据实际的需求进行选用,如果有其他方法进行分表,欢迎各位留言讨论。

posted @ 2022-08-21 13:09  一只爱阅读的程序员  阅读(116)  评论(0编辑  收藏  举报