针对 sql 插入的 Python 代码优化



我有以下代码,我正在一些大数据上运行它(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)))

一旦我弄清楚语法,插入代码就转到此处

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

@@@

在亚历克斯的大力帮助下的解决方案

   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 工作?

有 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. 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。使用批量操作

conn.commitcsv文件代替cur.execute。然后使用从创建的文件复制。

BULK 解决方案必须提供终极性能,但需要努力使其发挥作用。

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

祝你好运

尝试在循环完成时提交,而不是每次迭代

最新更新