千万级单表数据水平拆分实战

花了几天时间,做了一次生产数据迁移,记录下来

概述:

大背景:单表数据太大,导致查询特别慢,经讨论,要进行水平拆分

数据库:Mysql;mysql版本:测试环境5.65;生产环境5.7.22(这两个版本经多次测试,迁移数据速度几乎一样)

表:单表数据1300万,导出的文件有4.3G,主键自增;引擎:InnoDB;有三个索引(索引类型:Normal,索引方法:BTREE);有两个外键约束

目的:根据表中一个字段的值将该表数据分散到19个表中(迁移后老表废弃,用n个新表,代码已经做了修改)

要求:10分钟分散完毕;不能修改引擎;不能删除索引

具体过程:

经过多次尝试,发现一次性迁移数据是不能满足10分钟迁移完的,就转换一下思路,先迁移绝大多数数据,然后部署项目;然后再迁移剩余极少数据(在用户最不活跃的时间段迁移,我选择凌晨三点)

1.删除外键

删除所有的外键

2.迁移数据

经过不断尝试,发现每次插入50万条速率是最快的

2.1迁移绝大多数数据,具体limit后面start和end需要根据实际数据条数来确定,略大于实际数据即可(若数据产生特别迅速,适当改大)

# 分散到表1

insert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件1 limit 0,500000);

insert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件1 limit 500000,500000);

...

nsert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件1 limit 5000000,500000);

# 分散到表2

insert into 新表2(select * from 老表 old where old.type_id=2 and 主键约束条件1 limit 0,500000);

insert into 新表1(select * from 老表 old where old.type_id=2 and 主键约束条件1 limit 500000,500000);

...

# 分散到表n

insert into 新表n(select * from 老表 old where old.type_id=n and 主键约束条件1 limit 0,500000);

执行完需要40分钟左右

2.2.部署迁移后的应用

2.3.迁移少量数据

# 分散到表1

insert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件2 limit 0,500000);

insert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件2 limit 500000,500000);

...

nsert into 新表1(select * from 老表 old where old.type_id=1 and 主键约束条件2 limit 5000000,500000);

# 分散到表2

insert into 新表2(select * from 老表 old where old.type_id=2 and 主键约束条件2 limit 0,500000);

insert into 新表1(select * from 老表 old where old.type_id=2 and 主键约束条件2 limit 500000,500000);

...

# 分散到表n

insert into 新表n(select * from 老表 old where old.type_id=n and 主键约束条件2 limit 0,500000);

执行完需要4分钟左右

3.校验数据是否完整,不完整的手动迁移

4.完成

ps1:如果允许修改引擎,将引擎修改为MyISAM可以在十分钟三十秒完成数据分散,但是修改引擎后再次修改引擎非常耗时(因为测试环境配置太差,这个时间没测出来,每次修改都是卡死,使用的是navicat客户端,估计是10分钟+,生产数据又不敢随便动,怕万一把数据库搞挂,无权操作数据库所在服务器)

 

ps2:不修改引擎,直接将全部索引干掉,也是十分钟三十秒左右迁移完全部数据,但是重建索引老卡死,也没采用这种方案,数据库服务器性能强悍的话可以试试这种方式,之前就这样干过

你可能感兴趣的:(数据库)