可能我的python代码有问题,从昨天到现在只跑了3亿条数据,用threadpool创建的线程一直没回收,任务管理器里面可以看到python.exe的线程在持续上涨,而且导入的速度会越来越慢,已经将进程结束掉了。 目前准备采用@coolmenu 的方案,正在将json文件过滤并处理成csv格式,处理速度比插入数据库快很多大概每100万行40秒的样子。
1
strahe 2017-12-14 10:19:46 +08:00
之前将几千万条股票数据插入 mongo 大概也是这个思路, 一台办公的笔记本执行程序, mongo 在内网的服务器上, 基本都能达到你这速度.
|
2
mhycy 2017-12-14 10:22:59 +08:00
压力应该在 IO,看看磁盘延迟,8400 条 /秒这个速度可以了
|
3
billion 2017-12-14 10:41:26 +08:00
不太了解 Postgresql,但是我之前导入 40G 的 JSON 到 MongoDB,使用了 gevent 的 monkey_patch(),它可以让 pymongo 支持异步,性能比多线程高很多。
|
4
likuku 2017-12-14 11:10:06 +08:00 1
[服务器板载 RAID 无法使用,用 windows 的带区卷将两块硬盘组成一个卷,极限 io 也就 170MB/s]
这算软件 RAID0 ?胆子够壮... 这要是纯玩耍环境,无所谓,正式环境...老板知道了,肯定打死你。 机械硬盘 IOPS 很低的,极大限制 DB 操作。 |
6
lianz 2017-12-14 11:30:02 +08:00
@likuku 机械硬盘的顺序写速度还是可以的,楼主这种情况基本上就是顺序写。好点的硬盘可以达到几百 M/s,不过随机 IOPS 确实低,这个没办法。
|
7
togodo 2017-12-14 11:33:54 +08:00 1
两块盘单独用是非常正确的做法
|
8
HowardMei 2017-12-14 11:36:17 +08:00 1
最起码有 3 种:
1. 用 COPY https://stackoverflow.com/questions/8144002/use-binary-copy-table-from-with-psycopg2/8150329#8150329 2. 多值插入 + 异步 调整参数 synchronous_commit=off 和 commit_delay 降低 fsync 消耗 3. 用 TRANSACTION 把批量插入动作包含在内,一次性提交,跟 2 差不多 |
9
oyosc 2017-12-14 11:37:11 +08:00
copy_from 你值得拥有
|
10
bkmi 2017-12-14 11:38:10 +08:00 via Android
python 弱弱的问一句,不是讲 python 的多线程并没有真的并行吗
|
11
exch4nge 2017-12-14 11:47:33 +08:00
以下纯靠 Google 搜索跟已有知识猜的,本人没试过。
搜索以下发现 postgres 有叫 COPY 的命令,感觉会比 insert 快一些…… 大概方案是,先用 python 处理 json 生成适用于 COPY 命令的文件 A,然后为了速度,最好把这个文件放在内存盘中,然后调用 postgres 的 COPY 倒入进去。循环。根据内存大小决定每次处理多少个。 |
12
min 2017-12-14 12:11:08 +08:00 1
github 上有个项目是帮助导入 csv 和 json 的
另外就是用 postgresql 的 copy 命令 |
13
shepherd OP @min pgfutter 这个工具导入 json 时需要先将 json 整行作为一个单元格导入,然后利用 postgres 对 json 类型的支持,重新插入到一个新表里面。不过这个工具真的挺快的。但因为我们要对 json 做一些简单的过滤,所以流程上还是感觉复杂了点。
|
14
coolmenu 2017-12-14 12:30:00 +08:00 1
先根据条件过滤,分成几个文件,然后用 copy,尽量利用数据库提供的工具,他会绕过一些数据库的转换等,如 oracle 的 sqlldr 就比批量 insert 要快
|
15
catcn 2017-12-14 12:30:55 +08:00
不会 python 的吧,PIL 的存在,首先就应该考虑多进程。
|
16
shepherd OP @coolmenu copy 果然强悍,拿 10G 数据做测试,硬盘 io 平均可以到 60M/s,峰值有 110M/s。
|
20
kuwater 2017-12-16 18:30:31 +08:00
pg 的话,大规模导入也是用 copy 的接口吧,
另外可以考虑 pg_loader,看看能用不。 |