The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
sjmcefc2

请教 go 和 Python 逐行读文件,然后 insert 到数据库,哪个更快?

  •  
  •   sjmcefc2 · Jul 22, 2018 · 5681 views
    This topic created in 3031 days ago, the information mentioned may be changed or developed.

    用 python 的 mmap 来读文件,insert 到数据库,总感觉速度特别慢? pgadmin4 显示每秒 600transaction,cpu 使用率也非常低,iostat 貌似才几十 k/s。 是语言问题? go 能更高效吗? 或者是数据库设置问题? 或者是 insert 方式问题? 如何才能机器性能完全释放,把 postgres 发挥到最大? 很多配置已经参考了德哥 blog。

    32 replies  •  2018-07-23 14:27:37 +08:00
    ksupertu
    ksupertu
    Jul 22, 2018 via iPhone
    1
    组批量插入,例如 5000 条一起插入,跟语言性能关联度不高
    daigouspy
    daigouspy
    Jul 22, 2018 via Android
    2
    慢是因为数据库吧?
    F281M6Dh8DXpD1g2
    F281M6Dh8DXpD1g2
    Jul 22, 2018 via iPhone
    3
    不要一条一条的插入,主流数据库都有批量导入的方法
    iwiki
    iwiki
    Jul 22, 2018
    4
    如果可以的话开启事务,一次性提交
    reus
    reus
    Jul 22, 2018
    5
    和语言关系不大,和你的数据库配置、插入方式关系大些
    你又不说具体的,没法判断是哪里有瓶颈
    est
    est
    Jul 22, 2018 via Android
    6
    pg 导入最快的是 py 输出 csv 然后用 COPY
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    7
    @reus 具体还需要哪些信息判断 /

    @daigouspy 是啊,也是觉得是数据库。但是具体哪里呢?
    @ksupertu 组批量?主要是不知道哪条有问题,这些数据有些是有问题的,一下 copy 批量的话,不知道怎么把有问题的数据跳出来。

    @liprais 使用了批量,这些余下的数据是有问题的数据,不知道哪条哪个字段就有问题了。这样的如何批量导入,还能把有问题的数据挑出来呢?
    @liprais
    @iwiki 这个开启事务倒是还没有试过。
    目前我是用 python 一条一条的 insert,遇到不能 insert 的就写在新文件里面。因为有些字段有问题,copy 会中断,我想知道哪些数据没有被插入,所以想了这么弱智的办法。
    n2ex2
    n2ex2
    Jul 22, 2018 via Android
    8
    应该先把合格的数据筛选出来
    daigouspy
    daigouspy
    Jul 22, 2018 via Android
    9
    @sjmcefc2 先把写入数据库的代码注释掉再运行就知道啦
    MonoLogueChi
    MonoLogueChi
    Jul 22, 2018 via Android
    10
    你现在的瓶颈不是读取问题,和语言无关,要优化方法,一条一条 insert 用啥语言都不快
    zhs227
    zhs227
    Jul 22, 2018
    11
    开事务,一次多 insert 一点,然后再提交事务。 一条一条提交的话每次都要重建索引这些。
    语言层面的速度差异应该不大,影响大的是数据库插入速度。
    xjmroot
    xjmroot
    Jul 22, 2018
    12
    你这相当于是阻塞式的,一个 insert 完在处理下一个,没有用到并发呢。
    调整下程序逻辑,可以考虑下并发 insert
    limbo0
    limbo0
    Jul 22, 2018 via Android
    13
    我是用 python 拼出 sql,然后批量导入 sql 就行了
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    14
    @n2ex2 如何筛选呢?这个帅选的过程如何才能快?

    @MonoLogueChi 瓶颈不是读取,不是语言;不能一条一条 insert,具体要怎么优化方法呢?

    @zhs227 我现在是用 python 拼出 sql,但是我不知道这些拼出的 sql 哪些能够导入。如果分组( 5000 个一组)的话,倒是某些可能导入不了,但也能提高速度。问题我要知道哪些没有被导入。不知道是不是描述清楚了。

    @xjmroot 并发 insert ?能提供一个模版参考吗

    @limbo0 目前我用的就是 python 拼 sql,为了知道哪一条是坏数据,后面用的是逐条 insert。
    q2683252
    q2683252
    Jul 22, 2018
    15
    用 python 拼出 sql,用 Copy 语法,然后 psql 导入,亲测单机 50w/s 以上 挤爆你带宽
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    16
    @q2683252 假如 10w 条数据里面,中间一条或者 10 几条字段数据有问题,copy 出错,怎么处理?如何找到这几个错条?
    q2683252
    q2683252
    Jul 22, 2018
    17
    @sjmcefc2 那为什么字段数据会有问题呢 你的意思是数据格式不对还是说数据内容需要和数据库中的内容交互验证?
    q2683252
    q2683252
    Jul 22, 2018
    18
    @sjmcefc2 只有几条数据出错的话 可以等导入失败我就知道哪条数据有问题 然后用 vim 直接处理就可以了
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    19
    @q2683252 部分是编码问题;比如数据库要求所有数据是 gbk,而某条数据的几个字段是其他乱七八糟的编码拼凑的;或者是数据库设计时候类型是 int,在数据这边就变成了其他的;总之,就是体现为 insert 失败,copy 失败等等;错误条目数量不确定,有的吧可能也就一条,有的可能整个文件都乱了。

    现在纠结在于如何快速导入,如何还能挑出(最好自动)不能导入的数据。
    现在采取的就是 python 拼 insert sql,然后逐条 insert,失败了就另写文件。
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    20
    我用的是 psycopg2 这个包,copy,但是没有返回任何信息让我比较苦恼。不知道哪里 copy 错了。不知道大家都怎么处理这种情况。
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    21
    @q2683252 另外这个单机 50w/s 是从哪里得出的数据?一直不知道怎么衡量性能。
    q2683252
    q2683252
    Jul 22, 2018
    22
    @sjmcefc2 之前我自己导入过一些数据 50w 条我记得 几秒就好了 。
    有一个方法 ,你不需要知道哪条 copy 错了,因为每一个 copy 是一个事务,
    比如你批量 copy 5000 条 ,中间一条错了是吧,肯定是某一条开始出现问题,
    那么就试一下 copy2500 条,如果出现错误,那么错的数据肯定在 2500 条内。
    依次类推, 就是二分的思想
    limbo0
    limbo0
    Jul 22, 2018 via Android
    23
    用 begin commit 事务,中间出错会 rollback,然后根据报错信息调整
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    24
    @limbo0 貌似这样的话,很难用 python 程序自动处理啊,数据可能只有一条错,也可能整个文件都错了。
    FenGuWu
    FenGuWu
    Jul 22, 2018
    25
    跟语言没有关系。我也遇到了一样的问题。我用 java。一个事务提交 1w 条。开始 iostat 只有 16k。后来用 12 个线程往里怼,io 提高到 176k,server cpu 吃满。
    hustlibraco
    hustlibraco
    Jul 22, 2018
    26
    这种情况应该校验数据,使用数据库的批量导入方法,跟语言关系不大
    sjmcefc2
    sjmcefc2
    OP
    Jul 22, 2018
    27
    @hustlibraco 很棒的思路啊。就是不知道如何校验数据,如何把能批量导入的弄出来,把不能批量的有错误数据弄出来。一个文件分成两个?
    bbbai
    bbbai
    Jul 23, 2018
    28
    分组插入 一组 5000 条,然后多开几个线程就会快些,1000w 八线程我跑了 30 分钟
    sjmcefc2
    sjmcefc2
    OP
    Jul 23, 2018
    29
    @bbbai 能分享一下代码吗?机器配置如何?
    YumeMichi
    YumeMichi
    Jul 23, 2018
    30
    mysql 的话逐条 insert 肯定是很慢的 我以前的做法是每 5000 条 insert 合并成一条 这样能快很多 如果再加上多线程应该还能更快 但是因为 py 多线程这块当时没研究过 就只是用单线程跑的
    bbbai
    bbbai
    Jul 23, 2018
    31
    ···
    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
    Siglud
    Siglud
    Jul 23, 2018
    32
    你这么写铁定慢,快速的写法是
    INSERT INTO a_b_v("name","num") VALUES (%s,%s),(%s,%s),(%s,%s)....
    后面拼 1000 条
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1584 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 57ms · UTC 13:46 · PVG 21:46 · LAX 05:46 · JFK 08:46
    ♥ Do have faith in what you're doing.