2017-09-02 5 views
1

私はこのようになりますPostgreSQLのテーブルsku_comparisonに13億行を持っている:この表の13億行をより効率的に更新するにはどうすればよいですか?

id1 (INTEGER) | id2 (INTEGER) | (10 SMALLINT columns) | length1 (SMALLINT)... | 

... length2 (SMALLINT) | length_difference (SMALLINT) 

id1id2列がテーブルで参照されているが、30万行を含むskuと呼ばれる、とに関連するvarchar(25)値を持っています各列は列から、codeです。

id1id2上に構築されたBTREEインデックス、およびsku_comparisonid1id2の複合インデックスがあります。 id列のbtreeインデックスはskuです。

私の目標はskuテーブルから対応codeカラムの長さとlength1length2列を更新することです。しかし、私は20時間以上のために次のコードを実行し、それが更新を完了しませんでした:

UPDATE sku_comparison SET length1=length(sku.code) FROM sku 
WHERE sku_comparison.id1=sku.id; 

データのすべてがローカルコンピュータに単一のハードディスクに格納され、プロセッサはかなり近代的です。 Pythonではるかに複雑な文字列比較が必要なこのテーブルを作成するには約30時間かかりました。なぜなら、このようなものがなぜ長くかかるのかわかりません。

編集:ここでは、テーブル定義でフォーマットされています

         Table "public.sku" 
    Column |   Type   |     Modifiers      
------------+-----------------------+-------------------------------------------------- 
id   | integer    | not null default nextval('sku_id_seq'::regclass) 
sku  | character varying(25) | 
pattern | character varying(25) | 
pattern_an | character varying(25) | 
firsttwo | character(2)   | default ' '::bpchar 
reference | character varying(25) | 
Indexes: 
    "sku_pkey" PRIMARY KEY, btree (id) 
    "sku_sku_idx" UNIQUE, btree (sku) 
    "sku_firstwo_idx" btree (firsttwo) 
Referenced by: 
    TABLE "sku_comparison" CONSTRAINT "sku_comparison_id1_fkey" FOREIGN KEY (id1) REFERENCES sku(id) 
    TABLE "sku_comparison" CONSTRAINT "sku_comparison_id2_fkey" FOREIGN KEY (id2) REFERENCES sku(id) 


      Table "public.sku_comparison" 
      Column   | Type |  Modifiers   
---------------------------+----------+------------------------- 
id1      | integer | not null 
id2      | integer | not null 
consec_charmatch   | smallint | 
consec_groupmatch   | smallint | 
consec_fieldtypematch  | smallint | 
consec_groupmatch_an  | smallint | 
consec_fieldtypematch_an | smallint | 
general_charmatch   | smallint | 
general_groupmatch  | smallint | 
general_fieldtypematch | smallint | 
general_groupmatch_an  | smallint | 
general_fieldtypematch_an | smallint | 
length1     | smallint | default 0 
length2     | smallint | default 0 
length_difference   | smallint | default '-999'::integer 
Indexes: 
    "sku_comparison_pkey" PRIMARY KEY, btree (id1, id2) 
    "ssd_id1_idx" btree (id1) 
    "ssd_id2_idx" btree (id2) 
Foreign-key constraints: 
    "sku_comparison_id1_fkey" FOREIGN KEY (id1) REFERENCES sku(id) 
    "sku_comparison_id2_fkey" FOREIGN KEY (id2) REFERENCES sku(id) 
+0

テーブル定義はテキストではなく(DDL)コードで説明してください。 – wildplasser

+0

あなたの更新は 'sku_comparison_pkey'の*すべての*行に触れます。すべての行について値*が変更されますか? – wildplasser

+0

はい、すべての値が更新されます。私はPythonのpsycopg2を使用してテーブルを最初にバッチで作成しましたが、後見では、他のカラムと一緒に使用したいコードの長さを含めるのを忘れてしまいました。 –

答えて

0

は匿名コードブロックを使用することを検討しますか?擬似コードを使用して

...

FOREACH 'SELECT ski.id, 
       sku.code, 
       length(sku.code) 
     FROM sku 
     INTO v_skuid, v_skucode, v_skulength' 
DO 
UPDATE sku_comparison 
SET sku_comparison.length1 = v_skulength 
WHERE sku_comparison.id1=v_skuid; 
END DO 
END FOREACH 

この小さなトランザクションに全体を破ると、あなたがsku.codeの長さを毎回評価されることはありません。

+0

「毎回sku.codeの長さを評価する」とはどういう意味ですか? –

+0

また、私はデータの挿入が10個のスレッドと並行して行われたことを思い出しました。更新された行が重複しない場合、更新と同様のことを行うことはできますか? –

+0

@ user1362215、いつも評価していたのは、あなたのsku_comparisonに同じsku.codeの複数のインスタンスがあり、あなたの更新stmtで更新されたすべての行の長さを評価していたということです。しかし、ループを使用して更新stmt以外の長さを評価すると、すべての行の長さを評価する際にCPUサイクルを浪費することはありません。 –

関連する問題