2017-09-02 133 views
1

我有一個PostgreSQL表sku_comparison看起來像這樣1.3十億行:如何更有效地更新此表中的13億行?

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

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

id1id2列在一個表中引用所謂sku,其中包含約300,000行,並在具有相關varchar(25)值來自列的每一行,code

有建立在id1id2一個B樹索引,以及id1id2sku_comparison一個複合索引。在idsku也有一個btree索引。

我的目標是從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'中的* all *行。所有行的值*會改變嗎? – 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外的長度,那麼在評估每一行的長度時不會浪費CPU週期。 –