sql插入的Python代码优化

时间:2019-02-07 11:33:11

标签: python sql python-3.x

我有以下代码,我正在一些大数据上运行它(2小时的处理时间),我正在研究CUDA来加速GPU,但与此同时任何人都可以提出优化以下代码的方法吗?

我正在从数据集“ T”中获取一个3D点,并找到与另一个点数据集“ B”具有最小距离的点

通过将结果首先发送到列表然后插入数据库表,可以节省任何时间吗?

欢迎所有建议

    conn = psycopg2.connect("<details>")
    cur = conn.cursor()

    for i in range(len(B)):
        i2 = i + 1
        # point=T[i]
        point = B[i:i2]
        # print(B[i])
        # print(B[i:i2])
        disti = scipy.spatial.distance.cdist(point, T, metric='euclidean').min()
        print("Base: ", end='')
        print(i, end='')
        print(" of ", end='')
        print(len(B), end='')
        print(" ", end='')
        print(disti)

        cur.execute("""INSERT INTO pc_processing.pc_dist_base_tmp (x,y,z,dist) values (%s, %s, %s, %s)""",
                    (xi[i], yi[i], zi[i], disti))
        conn.commit()

    cur.close()

@@@@@@@@@@@@@@@编辑@@@@@@@@@@@@@@

代码更新:

   conn = psycopg2.connect("dbname=kap_pointcloud host=localhost user=postgres password=Gnob2009")
    cur = conn.cursor()

    disti = []

    for i in range(len(T)):
        i2 = i + 1
        point = T[i:i2]
        disti.append(scipy.spatial.distance.cdist(point, B, metric='euclidean').min())
        print("Top: " + str(i) + " of " + str(len(T)))

弄清楚语法后,将代码插入此处

@@@@@@@@@@编辑@@@@@@@@@

Alex提供了大量帮助的解决方案

   cur = conn.cursor()
      # list for accumulating  insert-params
    from scipy.spatial.distance import cdist

    insert_params = []
    for i in range(len(T)):
        XA = [B[i]]
        disti = cdist(XA, XB, metric='euclidean').min()
        insert_params.append((xi[i], yi[i], zi[i], disti))
        print("Top: " + str(i) + " of " + str(len(T)))

    # Only one instruction to insert everything
    cur.executemany("INSERT INTO pc_processing.pc_dist_top_tmp (x,y,z,dist) values (%s, %s, %s, %s)",
                    insert_params)
    conn.commit()

要进行时间比较,请:

初始代码为:0:00:50.225644

没有多行打印:0:00:47.934012

将提交移出循环:0:00:25.411207

我假设要使其更快的唯一方法是使CUDA正常工作?

3 个答案:

答案 0 :(得分:3)

有2种解决方案

1)如果len(B)非常大,请尝试执行单次提交或分块提交。

2)您可以准备要插入的数据列表并进行批量插入。

例如:

insert into pc_processing.pc_dist_base_tmp (x, y, z, dist) select * from unnest(array[1, 2, 3, 4], array[1, 2, 3, 4]);

答案 1 :(得分:1)

尝试在循环结束时提交,而不是每次迭代都提交

答案 2 :(得分:1)

好。让我们从评论中收集所有建议。

建议1. commit尽可能少见,不要print

conn = psycopg2.connect("<details>")
cur = conn.cursor()
insert_params=[]

for i in range(len(B)):
    i2 = i + 1
    point = B[i:i2]
    disti = scipy.spatial.distance.cdist(point, T, metric='euclidean').min()        
    cur.execute("""INSERT INTO pc_processing.pc_dist_base_tmp (x,y,z,dist) values (%s, %s, %s, %s)""", (xi[i], yi[i], zi[i], disti))        

conn.commit() # Note that you commit only once. Be careful with **realy** big chunks of data
cur.close()

如果您确实需要在循环中使用调试信息,请使用logging

您将可以在需要时打开/关闭日志记录信息。

建议2。executemany进行救援

conn = psycopg2.connect("<details>")
cur = conn.cursor()
insert_params=[] # list for accumulating  insert-params 

for i in range(len(B)):
    i2 = i + 1
    point = B[i:i2]
    disti = scipy.spatial.distance.cdist(point, T, metric='euclidean').min()        
    insert_params.append((xi[i], yi[i], zi[i], disti))

# Only one instruction to insert everything
cur.executemany("INSERT INTO pc_processing.pc_dist_base_tmp (x,y,z,dist) values (%s, %s, %s, %s)", insert_params)                     
conn.commit()
cur.close()

建议3.完全不要使用psycopg2。使用批量操作

写入cur.execute文件而不是conn.commitcsv。 然后从创建的文件中使用COPY

批量解决方案必须提供最终的性能,但需要努力才能使其正常工作。

选择适合自己的人-您需要多少速度。

祝你好运