讨论区

如何实现 mysql 分表,分表后的逻...
 

如何实现 mysql 分表,分表后的逻辑代码如何实现?  

 

爱学习的孩子
(@947dc045e...)
已加入: 3年前
帖子: 2
21/12/2019 9:47 上午  

你好,目前有一个用户订单表 user_dingdan 里面有 2015 - 2019 的数据,共有 8 百多万的数据。
每年数据平均下来有两百万,需求是按照年份为日期进行水平分表。
那我查询时,我的控制器代码逻辑如何实现,模型逻辑,还有修改时?

3年前 由 helloWorld 修改了此主题

引用
主题标签
helloWorld
(@helloworl...)
已加入: 3年前
帖子: 3
21/12/2019 9:56 上午  

你好,简单的来说,你现在 mysql 一张表的数据太多,在查询和插入更新的时候速度下降,影响体验,想要分表。
解决如下:

1. 首先分析业务情况,如果确实不需要老的数据,可以直接干掉。
2. 讲道理你的数据也不是很多,建好索引就行。
3. 接下就是分表方案,我会根据 id 分表,你要根据业务需求,到底如何分表。

业务场景:我有一个消息表,保留了用户发送的消息。很多,我要开始分表了。
我要打十个!
不对,是分十张表。
假设原来的表叫做:original_messages


CREATE TABLE original_messages (
id int(10) UNSIGNED NOT NULL,
message text NOT NULL
) ENGINE = MyISAM CHARSET = utf8mb4 COLLATE utf8mb4_unicode_520_ci;

现在我们要创建 11 张表。


CREATE TABLE messages (
	id int(10) UNSIGNED NOT NULL,
	message text NOT NULL
) ENGINE=MERGE union=(message1s,message2s,message3s,message4s,message5s,message6s,message7s,message8s,message9s,message10s) INSERT_METHOD=LAST DEFAULT CHARSET=utf8;

这个是主表,用来查询的!!!请注意表的引擎:ENGINE=MERGE。

然后是十张分表:


CREATE TABLE message1s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message2s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message3s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message4s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message5s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message6s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message7s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message8s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message9s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;
CREATE TABLE message10s ( id int(10) UNSIGNED NOT NULL,  message text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

这十张表才是做增删改操作的。

接下来你会遇到这几个问题:
1. 我插哪张表?
很简单啦,你自己逻辑决定,一般的表里面会有一个类似 user_id 的外键,又或者是你问题中的 order_id,我们可以把这个外键除以 10 取余数得到 $n。那么我们就插入表 message.$n.s。

2. 我插入表1和表2的时候,id 一样冲突了
很简单的啦,每种语言都可以生成 uuid,这种生成的 id 全世界独一无二。可以用它作为主键!

该帖子已被 3年前 修改了 helloWorld

回复引用
爱学习的孩子
(@947dc045e...)
已加入: 3年前
帖子: 2
21/12/2019 9:58 上午  

@helloworld

目前还有一个问题
我要统计 2019-01 - 2019-08 的数据,响应还是慢
如果我要跨表查询 2018-2019 的统计数据呢?我是直接拿取总表数据,还是写个for循环分别执行,拿取两张表的数据,然后进行逻辑合并数据

该帖子已被 3年前 修改了 helloWorld

回复引用
helloWorld
(@helloworl...)
已加入: 3年前
帖子: 3
21/12/2019 9:59 上午  

@947dc045ec0583d6e242d78c6c589dbc

您好,查询的话,你直接拿总表的数据就可以了。
慢是正常的。正因为慢你才分表的。
这边有个注意点。你处理数据不要一下子取出来。
你封装个方法,每10000个取出来处理下。
现在的 Laravel 版本有个 chunkById 方法,可以用来处理你的需求。

该帖子已被 3年前 修改了 helloWorld

回复引用

登录注册