用 python 的 mmap 来读文件,insert 到数据库,总感觉速度特别慢? pgadmin4 显示每秒 600transaction,cpu 使用率也非常低,iostat 貌似才几十 k/s。 是语言问题? go 能更高效吗? 或者是数据库设置问题? 或者是 insert 方式问题? 如何才能机器性能完全释放,把 postgres 发挥到最大? 很多配置已经参考了德哥 blog。
1
ksupertu 2018-07-22 11:18:47 +08:00 via iPhone
组批量插入,例如 5000 条一起插入,跟语言性能关联度不高
|
2
daigouspy 2018-07-22 11:35:59 +08:00 via Android
慢是因为数据库吧?
|
3
liprais 2018-07-22 11:38:15 +08:00 via iPhone
不要一条一条的插入,主流数据库都有批量导入的方法
|
4
iwiki 2018-07-22 11:41:19 +08:00
如果可以的话开启事务,一次性提交
|
5
reus 2018-07-22 12:05:07 +08:00
和语言关系不大,和你的数据库配置、插入方式关系大些
你又不说具体的,没法判断是哪里有瓶颈 |
6
est 2018-07-22 12:06:33 +08:00 via Android
pg 导入最快的是 py 输出 csv 然后用 COPY
|
7
sjmcefc2 OP @reus 具体还需要哪些信息判断 /
@daigouspy 是啊,也是觉得是数据库。但是具体哪里呢? @ksupertu 组批量?主要是不知道哪条有问题,这些数据有些是有问题的,一下 copy 批量的话,不知道怎么把有问题的数据跳出来。 @liprais 使用了批量,这些余下的数据是有问题的数据,不知道哪条哪个字段就有问题了。这样的如何批量导入,还能把有问题的数据挑出来呢? @liprais @iwiki 这个开启事务倒是还没有试过。 目前我是用 python 一条一条的 insert,遇到不能 insert 的就写在新文件里面。因为有些字段有问题,copy 会中断,我想知道哪些数据没有被插入,所以想了这么弱智的办法。 |
8
n2ex2 2018-07-22 12:37:54 +08:00 via Android
应该先把合格的数据筛选出来
|
10
MonoLogueChi 2018-07-22 13:12:43 +08:00 via Android
你现在的瓶颈不是读取问题,和语言无关,要优化方法,一条一条 insert 用啥语言都不快
|
11
zhs227 2018-07-22 14:01:45 +08:00
开事务,一次多 insert 一点,然后再提交事务。 一条一条提交的话每次都要重建索引这些。
语言层面的速度差异应该不大,影响大的是数据库插入速度。 |
12
xjmroot 2018-07-22 14:32:42 +08:00
你这相当于是阻塞式的,一个 insert 完在处理下一个,没有用到并发呢。
调整下程序逻辑,可以考虑下并发 insert |
13
limbo0 2018-07-22 14:48:10 +08:00 via Android
我是用 python 拼出 sql,然后批量导入 sql 就行了
|
14
sjmcefc2 OP @n2ex2 如何筛选呢?这个帅选的过程如何才能快?
@MonoLogueChi 瓶颈不是读取,不是语言;不能一条一条 insert,具体要怎么优化方法呢? @zhs227 我现在是用 python 拼出 sql,但是我不知道这些拼出的 sql 哪些能够导入。如果分组( 5000 个一组)的话,倒是某些可能导入不了,但也能提高速度。问题我要知道哪些没有被导入。不知道是不是描述清楚了。 @xjmroot 并发 insert ?能提供一个模版参考吗 @limbo0 目前我用的就是 python 拼 sql,为了知道哪一条是坏数据,后面用的是逐条 insert。 |
15
q2683252 2018-07-22 14:57:09 +08:00
用 python 拼出 sql,用 Copy 语法,然后 psql 导入,亲测单机 50w/s 以上 挤爆你带宽
|
16
sjmcefc2 OP @q2683252 假如 10w 条数据里面,中间一条或者 10 几条字段数据有问题,copy 出错,怎么处理?如何找到这几个错条?
|
19
sjmcefc2 OP @q2683252 部分是编码问题;比如数据库要求所有数据是 gbk,而某条数据的几个字段是其他乱七八糟的编码拼凑的;或者是数据库设计时候类型是 int,在数据这边就变成了其他的;总之,就是体现为 insert 失败,copy 失败等等;错误条目数量不确定,有的吧可能也就一条,有的可能整个文件都乱了。
现在纠结在于如何快速导入,如何还能挑出(最好自动)不能导入的数据。 现在采取的就是 python 拼 insert sql,然后逐条 insert,失败了就另写文件。 |
20
sjmcefc2 OP 我用的是 psycopg2 这个包,copy,但是没有返回任何信息让我比较苦恼。不知道哪里 copy 错了。不知道大家都怎么处理这种情况。
|
22
q2683252 2018-07-22 15:24:06 +08:00
@sjmcefc2 之前我自己导入过一些数据 50w 条我记得 几秒就好了 。
有一个方法 ,你不需要知道哪条 copy 错了,因为每一个 copy 是一个事务, 比如你批量 copy 5000 条 ,中间一条错了是吧,肯定是某一条开始出现问题, 那么就试一下 copy2500 条,如果出现错误,那么错的数据肯定在 2500 条内。 依次类推, 就是二分的思想 |
23
limbo0 2018-07-22 16:34:01 +08:00 via Android
用 begin commit 事务,中间出错会 rollback,然后根据报错信息调整
|
25
FenGuWu 2018-07-22 20:04:51 +08:00
跟语言没有关系。我也遇到了一样的问题。我用 java。一个事务提交 1w 条。开始 iostat 只有 16k。后来用 12 个线程往里怼,io 提高到 176k,server cpu 吃满。
|
26
hustlibraco 2018-07-22 22:55:18 +08:00
这种情况应该校验数据,使用数据库的批量导入方法,跟语言关系不大
|
27
sjmcefc2 OP @hustlibraco 很棒的思路啊。就是不知道如何校验数据,如何把能批量导入的弄出来,把不能批量的有错误数据弄出来。一个文件分成两个?
|
28
bbbai 2018-07-23 10:33:19 +08:00
分组插入 一组 5000 条,然后多开几个线程就会快些,1000w 八线程我跑了 30 分钟
|
30
YumeMichi 2018-07-23 11:35:52 +08:00
mysql 的话逐条 insert 肯定是很慢的 我以前的做法是每 5000 条 insert 合并成一条 这样能快很多 如果再加上多线程应该还能更快 但是因为 py 多线程这块当时没研究过 就只是用单线程跑的
|
31
bbbai 2018-07-23 12:04:13 +08:00
···
insert_p = ("INSERT INTO a_b_v("name","num")" "VALUES(%s,%s)") for j in range(0,5000): data_p = ("admin","0001") data_p_list.append(data_cp) cursor.executemany(insert_p,data_p_list) db.commit()··· @sjmcefc2 核心就是这样,数据表多,行列多可能会很繁琐,可以考虑在数据结构进行优化。python2 |
32
Siglud 2018-07-23 14:27:37 +08:00
你这么写铁定慢,快速的写法是
INSERT INTO a_b_v("name","num") VALUES (%s,%s),(%s,%s),(%s,%s).... 后面拼 1000 条 |