0

私のSCHEMAは次のとおりで、更新が必要なDBに約4mの既存の投稿があります。テキストの場所を指す整数を追加しています。

CREATE TABLE app_post (
id integer NOT NULL,
text_location integer,
title character varying(140)
);

(id、text_location)を表すタプルの長い(1000-5000)リストで既存のレコードを更新したい:

[(1, 123), (2,3), (9, 10)....]

これを行う最も効率的な方法は何ですか?

4

1 に答える 1

1

phyton を使用してオンザフライで値を生成している場合は、次のことができます。

  1. INSERT単一のステートメントを含むバッファーを作成する
  2. 取引を開始する
  3. 一時テーブルを作成INSERTし、バッファでステートメントを実行します
  4. 実行するUPDATE ... FROM
  5. トランザクションをコミットし、一時テーブルを破棄します。

ステートメントは次のUPDATEようになります (new_values更新する必要がある新しい値を含むテーブルがあると仮定します)。

UPDATE app_post AS a SET text_location = n.text_location 
    FROM new_values AS n WHERE a.id = n.id

id列をPRIMARY KEYとして定義するか、列にインデックスを作成することを忘れないでください。


編集:パフォーマンスが非常に遅いため、別の回避策として、テーブル全体を再作成することができます。次のアイデアは、最初の投稿で示したように、テーブルにFOREIGN KEY適用される制約がないことを前提としています。app_post

-- Begin the Transaction
BEGIN;

-- Create a temporary table to hold the new values
CREATE TEMPORARY TABLE temp_update_values (
    id integer PRIMARY KEY,
    text_location integer
) ON COMMIT DROP;

-- Populate it
INSERT INTO temp_update_values (id, text_location) VALUES (1, 123), (2, 456) /* ... #5000 total */ ;

-- Create a temporary table merging the existing "app_post" and "temp_update_values"
CREATE TEMPORARY TABLE temp_new_app_post ON COMMIT DROP AS 
    SELECT a.id, COALESCE(n.text_location, a.text_location) AS text_location, a.title 
    FROM app_post AS a LEFT JOIN temp_update_values AS n ON a.id = n.id;

-- Empty the existing "app_post"
TRUNCATE TABLE app_post;

-- Repopulate "app_post" table 
INSERT INTO app_post (id, text_location, title) 
    SELECT id, text_location, title FROM temp_new_app_post;

-- Commit the Transaction
COMMIT;

制約がある場合は、テーブルをFOREIGN KEYTRUNCATING する前にそれらを削除しapp_post、再作成された後にそれらを再作成して、それらを処理する必要があります。

于 2013-09-12T14:59:14.307 に答える