对于SQL INSERT Python代码优化

问题描述 投票:1回答:3

我有以下的代码,我运行它的一些大数据(处理时间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()

@@@@@@@@@@@@@@ EDIT @@@@@@@@@@@@@

代码更新:

   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)))

插入代码去一次在这里我找出语法

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

从亚历克斯了很多帮助解决方案

   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工作的唯一途径?

python sql python-3.x
3个回答
1
投票

好。让我们从积累所有的意见建议。

Suggesion 1. commit as rare as possible, don't print at all

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

您将能够打开/关闭登录信息,当您需要。

Suggestion 2. executemany for rescue

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()

Suggestion 3. Don't use psycopg2 at all. Use BULK operations

相反cur.execute的,conn.commitcsv文件。然后用COPY从创建的文件。

BULK解决方案必须提供极致的性能,但需要努力,使其工作。

选择你自己什么是适合你 - 多快,你所需要的。

祝好运


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
投票

尝试在循环结束而不是每一次迭代犯

© www.soinside.com 2019 - 2024. All rights reserved.