如何 10 分钟内插入 13 亿条记录?

2020-10-10 09:16:50 +08:00
 hooopo

之前的一个帖子 单表 13 亿记录创建索引需要多长时间? 测试了在一台 8C32G 服务器给一列加索引大概需要 24 分钟,由于插入脚本没有优化,花费了大概 2 个小时左右。

最近研究了一下,还是 8C32G 服务器,最快的插入大概多久?先上结论:10 分钟。

步骤:

建表:

CREATE unlogged TABLE  "test" (
  "id" SERIAL PRIMARY KEY NOT NULL,
  "ip" integer NOT NULL,
  "domain" varchar DEFAULT 'drawerd.com'
);

再生成一个 12.8 亿条记录的 csv,大概 41G

f = File.open("ii.csv", "w")
(1..1280000000).each do |x|
  f.puts [x, Random.random_number(1000000000), "#{x}.com"].join(",")
end
f.close

csv 概览:

tail -fn20 ii.csv
1279999981,379768240,1279999981.com
1279999982,440776589,1279999982.com
1279999983,194045965,1279999983.com
1279999984,643339201,1279999984.com
1279999985,397295532,1279999985.com
1279999986,308045177,1279999986.com
1279999987,860093304,1279999987.com
1279999988,557636470,1279999988.com
1279999989,882497774,1279999989.com
1279999990,987416658,1279999990.com
1279999991,728315013,1279999991.com
1279999992,163951092,1279999992.com
1279999993,524652,1279999993.com
1279999994,871673632,1279999994.com
1279999995,833545894,1279999995.com
1279999996,635775438,1279999996.com
1279999997,19686670,1279999997.com
1279999998,243310061,1279999998.com
1279999999,706814112,1279999999.com
1280000000,701386384,1280000000.com

使用timesccaledb-parallel-copy,开 8 个进程,batch-size 设置为 10w,并发 copy 。之前以为 timesccaledb-parallel-copy 只能 timescaledb 用,现在测试了一下,纯 pg 也可以用。

timescaledb-parallel-copy --db-name postgres --table test --file ./ii.csv --workers 8 --reporting-period 30s -connection "host=localhost user=postgres password=helloworld sslmode=disable" -truncate -batch-size 100000

如果单纯使用 PG 的 copy 的话,只是利用单进程,使用 imescaledb-parallel-copy 会多进程同时 copy,从图上可以看到 CPU 几乎被跑满。可以达到每秒 200w 的写入。如果是 64 核的机器,只要不到两分钟,神不神奇...

timescaledb-parallel-copy --db-name postgres --table test --file ./ii.csv --workers 8 --reporting-period 30s -connection "host=localhost user=postgres password=helloworld sslmode=disable" -truncate -batch-size 100000
at 30s, row rate 2049993.13/sec (period), row rate 2049993.13/sec (overall), 6.150000E+07 total rows
at 1m0s, row rate 1913075.25/sec (period), row rate 1981529.69/sec (overall), 1.189000E+08 total rows
at 1m30s, row rate 1930261.28/sec (period), row rate 1964442.55/sec (overall), 1.768000E+08 total rows
at 2m0s, row rate 1943332.35/sec (period), row rate 1959165.00/sec (overall), 2.351000E+08 total rows
at 2m30s, row rate 1966667.61/sec (period), row rate 1960665.52/sec (overall), 2.941000E+08 total rows
at 3m0s, row rate 1919998.29/sec (period), row rate 1953887.65/sec (overall), 3.517000E+08 total rows
at 3m30s, row rate 1950001.96/sec (period), row rate 1953332.55/sec (overall), 4.102000E+08 total rows
at 4m0s, row rate 1949999.02/sec (period), row rate 1952915.86/sec (overall), 4.687000E+08 total rows
at 4m30s, row rate 1929999.19/sec (period), row rate 1950369.56/sec (overall), 5.266000E+08 total rows
at 5m0s, row rate 1873333.69/sec (period), row rate 1942665.98/sec (overall), 5.828000E+08 total rows
at 5m30s, row rate 1913172.63/sec (period), row rate 1939984.56/sec (overall), 6.402000E+08 total rows
at 6m0s, row rate 1843488.31/sec (period), row rate 1931943.89/sec (overall), 6.955000E+08 total rows
at 6m30s, row rate 1816666.49/sec (period), row rate 1923076.40/sec (overall), 7.500000E+08 total rows
at 7m0s, row rate 1962938.14/sec (period), row rate 1925924.19/sec (overall), 8.089000E+08 total rows
at 7m30s, row rate 1950394.13/sec (period), row rate 1927555.19/sec (overall), 8.674000E+08 total rows
at 8m0s, row rate 1963333.08/sec (period), row rate 1929791.31/sec (overall), 9.263000E+08 total rows
at 8m30s, row rate 1963333.49/sec (period), row rate 1931764.38/sec (overall), 9.852000E+08 total rows
at 9m0s, row rate 1966666.04/sec (period), row rate 1933703.36/sec (overall), 1.044200E+09 total rows
at 9m30s, row rate 1963333.35/sec (period), row rate 1935262.83/sec (overall), 1.103100E+09 total rows
at 10m0s, row rate 1949999.36/sec (period), row rate 1935999.66/sec (overall), 1.161600E+09 total rows
at 10m30s, row rate 1966667.45/sec (period), row rate 1937460.03/sec (overall), 1.220600E+09 total rows
at 11m0s, row rate 1933333.38/sec (period), row rate 1937272.46/sec (overall), 1.278600E+09 total rows
COPY 1280000000

5649 次点击
所在节点    问与答
39 条回复
aec4d
2020-10-10 12:22:33 +08:00
插进去了查询也是个问题....... 我选择用 clickhouse
hooopo
2020-10-10 12:26:43 +08:00
@aec4d ch 能 oltp 吗
aec4d
2020-10-10 12:29:12 +08:00
@hooopo 当然不能
yushiro
2020-10-10 12:33:45 +08:00
这个……不就是对应 mssql 的 bcp 方式导入嘛,buck copy 肯定比单条 insert 快。
大概 10 多年前就这样来准备测试数据了。
当时的机器,单线程 insert 速度在 1000 条 /s
用 bcp 的方式导入,快 2 个数量级。
namelosw
2020-10-10 12:47:46 +08:00
这么大插入是不是可以考虑 Cassandra 或者 Kafka 风格的那种顺序读写,异步索引的方案了?
hooopo
2020-10-10 12:50:42 +08:00
@yushiro bcp 只是生成了批量 insert 语句吧,怎么都不如 pg 的 copy 快:https://programmer.help/blogs/data-migration-import-and-export-tests-between-postgresql-and-mssql-sql-server.html
hooopo
2020-10-10 12:54:24 +08:00
@namelosw 有什么好处
mazyi
2020-10-10 12:58:48 +08:00
@hooopo 跑不出就是跑不出,再强硬的姿态也改变不了事实。
hooopo
2020-10-10 13:00:07 +08:00
@mazyi 你在说什么 你是小学生吗
mazyi
2020-10-10 13:01:51 +08:00
@hooopo 没有呢,幼儿园学前班呢
hooopo
2020-10-10 13:37:02 +08:00
@mazyi 好的
yanfany
2020-10-10 13:43:18 +08:00
一个纯技术交流的帖都能吵起来。。。v 站的讨论氛围恶化
namelosw
2020-10-10 14:01:53 +08:00
@namelosw 比较简单把,可以比较容易达到硬盘理论极限,疯狂插入的场景用的。RDBMS 的设计导致了插入速度慢。
shyling
2020-10-10 14:29:13 +08:00
原问题是 mysql 吧,这都换了几个数据库了=。=

不知道换 rocksdb 这种基于 lsm 的写入是个什么速度
hooopo
2020-10-10 14:30:09 +08:00
@shyling 换了一个
yushiro
2020-10-10 19:05:01 +08:00
@hooopo 不,bcp 是导入导出 mssql 的 cli,数据需要事先生成的,跟你写的类似,先准备 csv 文件。
我觉得此题的要点就是,你所熟悉的 dbms 系统,有没有相应的 buck copy 实现,以及你是否熟悉这种用法。
kingsmalltwo
2020-10-10 20:01:37 +08:00
有一个思路,就是直接写数据库表对应的文件,然后重启服务加载。
yintianwen
2021-03-09 14:47:34 +08:00
PG 参数有什么需要优化的?
hooopo
2021-03-09 14:49:48 +08:00
@yintianwen 没有优化 这个要按实际应用类型来吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/713519

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX