質問

次の2つのPythonコードの例を考えてみましょう。これは、同じですが、驚くべき驚くべきパフォーマンスの違いがあります。

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
cur.execute("SELECT * FROM test for update;")
print ("Finished: SELECT * FROM test for update;: " + str(time.clock() - startTime));
for i in range (100000):
    cur.fetchone()
    cur2.execute("update test set num = num + 1 where current of cursor_unique_name;")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

と:

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
for i in range (100000):
    cur2.execute("update test set num = num + 1 where id = " + str(i) + ";")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()

テーブルテストの作成ステートメントは次のとおりです。

CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);

そして、そのテーブルには100000行と真空分析テストが含まれています。実行されました。

いくつかの試行で一貫して次の結果を得ました。

最初のコード例:

Finished: SELECT * FROM test for update;: 0.00609304950429
Finished: update starting commit: 37.3272754429
Finished: update : 37.4449708474

2番目のコード例:

Finished: update starting commit: 24.574401185
Finished committing: 24.7331461431

これは私にとって非常に驚くべきことです。つまり、正反対であるべきだと思います。つまり、カーソルを使用した更新は、 これ 答え。

役に立ちましたか?

解決

テストのバランスが取れているとは思いません。最初のコードはカーソルからデータを取得し、更新しますが、2番目のコードはデータを取得せずにIDで盲目的に更新しています。最初のコードシーケンスは、Fetchコマンドに続いて更新されるため、1つではなく2つのクライアント/サーバーコマンドのターンアラウンドに変換されます。

(また、最初のコードはテーブル内の各行をロックすることから始まります。これにより、テーブル全体がバッファキャッシュに引き込まれます。

また、TBH私は単純なテーブルの場合、CTIDによる更新の間でそれほど違いはないと思います(これはどのようにしていると思いますか where current of... 動作)およびプライマリキーを介して更新 - Pkeyアップデートは追加のインデックスルックアップですが、インデックスがそうでない限り 巨大 それはあまり劣化していません。

このような100,000行を更新するために、ほとんどの場合、余分なタプルを生成し、それらをテーブルに挿入したり、削除したりするのではなく、テーブルに挿入したり、削除したりするのではなく、それらをテーブルに挿入したりすると思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top