文章目录
一、前言
1-1、什么时候需要分表呢?
这个其实就很简单了,就是当表数据太大的时候,一个表里面存储不下,或者存储后影响使用(比如数据多的时候就影响查询效率)
1-2、分表的规则是什么呢?
一般来说我们都是根据数据量来分表的,数据存储是为了后面使用,所以我们表名也应该清楚明了。
我们可以根据数据量分为、天、月、年 (当然了,还可以细分,但是逻辑会相对复杂一些,原理都一样)
1-2-1、分表前后
这里以月和年进行举例
之前的表名 | 之后的表名 |
---|---|
pub_send_message | pub_send_message_2021_03 |
pub_send_message_batch | pub_send_message_batch_2021 |
其实也很简单,就是在之前的表名后面加上规则。
1-2-2、其它
这里有有趣的事情
- 我:你看看这样命名有没问没? pub_send_message_21_03
- 大佬:小了,格局小了,你们公司难道不能存活80年以上嘛?
二、举例场景
这里举例一个短信中台的业务场景。
短信的发送1V1和1VN,也就是一条短信发送给一个人,一条短信发送给多个人。
每一条短信都是要先存到数据库,为了后面追溯,所以需要一个短信明细表,一个短信批次表。
三、实现分表功能
3-1、数据的增删改
之前我们插入数据的时候只需要写下面的sql
INSERT INTO pub_send_message (id,mobile) VALUES(#{id},#{mobile});
而现在的话,因为我们的表是按照月份区分的,所以再插入的时候我们需要明确我们的表名。
我们获取到当前年、月的时候,传递过去就好了,所以我们的sql改成这样。
INSERT INTO pub_send_message_${year}_${month} (id,mobile) VALUES(#{id},#{mobile});
注:这里需要区分一下 $ 和#的区别,$是字符串拼接,#是带引号的拼接。
3-2、数据的查询
因为我们查询的数据可能存在多张表里面,这样就很难的查询了。
- 上面我们是按照月来区分的,所以我们可以规定一下,我们只查询本月数据
- 我们可以规定下只查询近3个月的数据,这样我们可以使用union连接查询
- 如果要以某个维度查询全部的数据,那么建议以这个维度建立一个报表(不可能全部的数据去union的)
3-3、自动创建表
比如上面的这个pub_send_message_2021_03表,每个月都会产生一张,我们不可能每个月自己去建,一来这样很麻烦,二来如果忘记了系统就会异常,所以我们要写一个定时任务或者脚本去自动生成表。
MySql查看表是否存在
- work_order 数据库名
- css_work_order_21表名
SELECT
count(*)
FROM
information_schema.TABLES t
WHERE
t.TABLE_SCHEMA = 'work_order'
AND t.TABLE_NAME = 'css_work_order_21'
建表语句就不说了,Java定时任务或脚本见表也不说了
3-4、其它
这里说一个小的设计思路
如果我们之前的代码是这样写的
void add(PubSendMessage pubSendMessage);
<select id="add" parameterType="com.koron.mgdevops.shortmessage.bean.PubSendMessage">
INSERT INTO pub_send_message (id,mobile) VALUES(#{id},#{mobile});
</select>
现在我们的操作都是要多传入year和month两个参数
方法一
void add(@Param("bean") PubSendMessage pubSendMessage,@Param("year") String year,@Param("month") String month);
<select id="add" parameterType="com.koron.mgdevops.shortmessage.bean.PubSendMessage">
INSERT INTO pub_send_message_${year}_${month} (id,mobile) VALUES(#{bean.id},#{bean.mobile});
</select>
方法二
先让我们的PubSendMessage去继承一个新的实体,这样我们其它的接口和xml都不需要改变了
public class PubSendMessage extends TestBean2{}
public class TestBean2 {
private String year;
private String month;
public String getYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String getMonth() {
return month;
}
public void setMonth(String month) {
this.month = month;
}
}