如何使用 Python / psycopg2 高效更新大型 PostgreSQL 表中的列?

n10*_*000 5 python postgresql psycopg2 sql-update

我有一张大桌子,上面有大约。PostgreSQL 9.4 数据库中有 1000 万行。它看起来有点像这样:

\n\n
gid | number1 | random |\xc2\xa0result |\xc2\xa0...\n 1  |    2    |  NULL  |  NULL  |\xc2\xa0...\n 2  |   15    |  NULL  |  NULL  | ...\n... |   ...   |   ...  |  ...   | ...\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我想更新列randomresult作为 的函数number1。这意味着至少random需要在数据库外部的脚本中生成。由于我的 RAM 有限,我想知道如何使用psycopg2. 我相信我面临两个问题:如何在不使用太多 RAM 的情况下获取数据以及如何将其放回原处。简单方法看起来像这样:

\n\n
curs.execute("""SELECT gid1, number1 FROM my_table;""")\ndata = curs.fetchall()\n\nresult = []\nfor i in data:\n    result.append((create_random(i[1]), i[0]))\ncurs.executemany("""UPDATE my_table\n                    SET random = %s\n                    WHERE gid = %s;""",\n                 results)\ncurs.execute("""UPDATE my_table\n                SET result = number1 * random;""")\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,这肯定会很快耗尽我所有的记忆,并永远持续下去UPDATE my_table

\n\n

什么是更明智的策略?数据库正在被独占访问并且可以被锁定。不幸的是,PostgreSQL 随机函数不适合我的情况。

\n

Clo*_*eto 5

unnest一次性完成所有数据:

def create_random(i):
    return random() * i

curs.execute("select gid, number from t;")
data = curs.fetchall()

results = []
for i in data:
    results.append((create_random(i[1]), i[0]))

curs.execute("""
    update t
    set
        rnd = s.rnd,
        result = number * s.rnd
    from unnest(%s) s(rnd numeric, gid integer)
    where t.gid = s.gid;
""", (results,))

con.commit()
Run Code Online (Sandbox Code Playgroud)

药片:

create table t (
    gid integer,
    number integer,
    rnd float,
    result float
);
Run Code Online (Sandbox Code Playgroud)