4.10亿数据如何插入Mysql
10亿数据如何插入Mysql
- 背景
- 10亿条数据,每条数据1Kb;
- 数据内容是非结构化的用户访问日志,需要解析后写入到数据库;
- 数据存放在
Hdfs
或S3
分布式文件存储里 - 10亿条数据并不是1个大文件,而是被近似切分为100个文件,后缀标记顺序;
- 要求有序导入,尽量不重复;数据库是
MySQL
;
- 数据库单表能支持10亿吗?
- 不能,单表推荐值是2000W,但是阿里规约建议500W就开始分表
- 如何高效的写入数据库?
- 单条写入数据库性能比较差,可以考虑批量写入数据库,批量数值动态可调整。每条1K,默认可先调整为100条批量写入
- 写入时按照主键id顺序顺序写入可以达到最快的性能,而非主键索引的插入则不一定是顺序的,频繁地索引结构调整会导致插入性能下降。最好不创建非主键索引,或者在表创建完成后再创建索引,以保证最快的插入性能。
- 是否需要并发写一个表
- 不能,必须分库分表
- 并发写同一个表无法保证数据写入时是有序的;
- 提高批量插入的阈值,在一定程度上增加了插入并发度无需再并发写入单表;
- 要不要进行分库
- mysql 单库的并发写入是有性能瓶颈的,一般情况5K TPS写入就很高了
- 读文件并发度等于分表数量,有利于简化模型设计。即100个读取任务,100个写入任务,对应100张表
- 如何保证写入数据库有序?
- 既然文件被切分为100个10G的小文件,可以按照文件后缀+ 在文件行号 作为记录的唯一键,同时保证同一个文件的内容被写入同一个表
- 如何更快的读取文件?
- JavaNIO FileChannnel更快,但是是读取固定大小的缓存区,不支持按行读取,也无法保证缓冲区正好包括整数行数据,而 BufferedReader JavaIO性能也不错,并且方式读取可以天然支持按行截断
- 如何协调文件任务和写数据任务
- 读取任务读一批数据,写入一批。即任务既负责读文件、又负责插入数据库。
- 如何保证任务的可靠性
- Redis记录task的进度,批量写入数据库成功后,更新 task进度,如果还不放心Redis进度和数据库更新的一致性,可以考虑 消费 数据库binlog,每一条记录新增则redis +1
参考文章
4.10亿数据如何插入Mysql
https://x-leonidas.github.io/2023/10/24/05数据库/05-1关系型数据库/4.10亿数据如何插入Mysql/