の代わりに使用して、サーバー側の一時テーブルにデータをアップロードするために、あなたが可能性、クライアント側からの行でテーブルの行を更新すると、このコードをプロファイルすることができますcopy_from()
メソッドを呼び出して、単一のSQLでテーブルを更新します。あなたは第二の方法は、約20倍高速で見ることができるように
Prepare playground...
Done.
Test update row by row...
Done in 62.1189928055 s.
Test batch update...
Done in 3.95668387413 s.
:
#!/usr/bin/env python
import time, psycopg2
from random import random
from cStringIO import StringIO
CRowCount = 100000
conn = psycopg2.connect('')
conn.autocommit = False
print('Prepare playground...')
cur = conn.cursor()
cur.execute("""
drop table if exists foo;
create table foo(i int primary key, x float);
insert into foo select i, 0 from generate_series(1,%s) as i;
""", (CRowCount,))
print('Done.')
cur.close();
conn.commit();
print('\nTest update row by row...')
tstart = time.time()
cur = conn.cursor()
for i in xrange(1,CRowCount+1):
cur.execute('update foo set x = %s where i = %s', (random(), i));
conn.commit()
cur.close()
print('Done in %s s.' % (time.time() - tstart))
print('\nTest batch update...')
tstart = time.time()
cur = conn.cursor()
# Create temporary table to hold our data
cur.execute('create temp table t(i int, x float) on commit drop')
# Create and fill the buffer from which data will be uploaded
buf = StringIO()
for i in xrange(1,CRowCount+1):
buf.write('%s\t%s\n' % (i, random()))
buf.seek(0)
# Upload data from the buffer to the temporary table
cur.copy_from(buf, 't')
# Update test table using data previously uploaded
cur.execute('update foo set x = t.x from t where foo.i = t.i')
cur.close();
conn.commit();
print('Done in %s s.' % (time.time() - tstart))
が出力:ここ
は人工的な例です。
1回のトランザクションの通常の安全性を持たないことを前提としている場合、 'conn.commit()'を数回(2500?)クエリごとに実行すると、トランザクションが大きすぎる(クエリが遅くなります) – Ryan
高速化の方法:['copy_to()'](http://initd.org/psycopg/docs/usage.html#using-copy-to-and-copy-from)を使用してデータを一時テーブルにアップロードしてください。たとえば、[UPDATE ... FROM ...](https://www.postgresql.org/docs/current/static/sql-update.html)を使用して、単一のSQL文でテーブルを更新します。 – Abelisto
@Abelisto興味深い。あなたはこれをどうやって行うのかと答えることができますか? – dopatraman