2017-03-02 98 views
2

我有兩個巨大的表:Postgresql - 如何加快更新巨大的表(1億行)?

Table "public.tx_input1_new" (100,000,000 rows) 

    Column  |   Type    | Modifiers 
----------------|-----------------------------|---------- 
blk_hash  | character varying(500)  | 
blk_time  | timestamp without time zone | 
tx_hash  | character varying(500)  | 
input_tx_hash | character varying(100)  | 
input_tx_index | smallint     | 
input_addr  | character varying(500)  | 
input_val  | numeric      | 

Indexes: 
    "tx_input1_new_h" btree (input_tx_hash, input_tx_index) 

Table "public.tx_output1_new" (100,000,000 rows) 

    Column |   Type   | Modifiers 
--------------+------------------------+----------- 
tx_hash  | character varying(100) | 
output_addr | character varying(500) | 
output_index | smallint    | 
input_val | numeric    | 

Indexes: 
    "tx_output1_new_h" btree (tx_hash, output_index) 

我想通過其他表更新表1:

UPDATE tx_input1 as i 
SET 
    input_addr = o.output_addr, 
    input_val = o.output_val 
FROM tx_output1 as o 
WHERE 
    i.input_tx_hash = o.tx_hash 
    AND i.input_tx_index = o.output_index; 

之前,我執行SQL命令,我已經創建的索引對於這兩個表:

CREATE INDEX tx_input1_new_h ON tx_input1_new (input_tx_hash, input_tx_index); 

CREATE INDEX tx_output1_new_h ON tx_output1_new (tx_hash, output_index); 

我使用EXPLAIN命令查看查詢計劃,但它沒有使用我創建的索引。

完成UPDATE需要大約14-15個小時。

其中的問題是什麼?

如何縮短執行時間或調整我的數據庫/表?

謝謝。

+1

請** [編輯] **您的問題,並添加執行計劃(再次:[**格式化文本**](http://stackoverflow.com/help/formatting)請 –

+0

好吧,我很抱歉。 – user3383856

+0

你的問題更多關於:[爲什麼postgres不使用索引?](http://stackoverflow.com/search?q=postgres+why+not+using+index) – McNets

回答

5

由於您加入了兩個大表,並且沒有可能會過濾出行的條件,唯一有效的連接策略將是散列連接,並且沒有索引可以幫助實現這一點。

首先會對其中一個表格進行順序掃描,從中構建一個散列結構,然後將對另一個表格進行順序掃描,並且將對每個找到的行進行散列檢測。任何索引怎麼可以幫助?

你可以期待這樣的操作需要很長的時間,但也有一些方法,使您可以加快操作:上tx_input1在開始之前

  • 刪除所有的索引和約束。您的查詢是其中索引完全沒有幫助的示例之一,但實際上會損害的性能,因爲索引必須隨表一起更新。在完成UPDATE後重新創建索引和約束。根據表格中索引的數量,您可以期待體面的巨大性能提升。

  • 使用SET命令儘可能提高此一操作的work_mem參數。散列操作可以使用的內存越多,速度就越快。有了這麼大的表格,你可能最終還是會得到臨時文件,但你仍然可以期待體面的增長。

  • checkpoint_segments(或max_wal_size從版本9.6起)增加到較高的值,以便在UPDATE操作期間檢查點更少。

  • 確保兩個表上的表統計信息都準確無誤,以便PostgreSQL能夠對創建的散列桶的數量進行很好的估計。

UPDATE後,如果它影響行的大數目,你可能會考慮對tx_input1運行VACUUM (FULL)擺脫結果表膨脹的。這會鎖定表格更長的時間,所以在維護窗口中進行。這將減少表格的大小,並因此加快順序掃描。

+0

請問您如何建立一個散列結構表並做散列連接? – user3383856

+0

您不必這樣做,數據庫就可以爲您做到這一點。我剛剛向你解釋了數據庫如何執行你的加入,以便你瞭解如何加速它。 –

+0

100M中有多少行會被更新? – BobC