2017-05-05 84 views
0

我在PostgreSQL 9.5數據庫表中有大約1,500,000條記錄,並且我得到一個CSV文件(通過http post請求),其中包含新的〜1,500,000行,其中一些沒有改變,有些不同,有些被刪除到原始行。截斷行並插入新行而不引入服務中斷?

我再

  1. 截斷舊錶
  2. 循環遍歷CSV文件的行
  3. 將每個行插入表

我需要的是一個辦法做到這一點沒有向我的客戶介紹服務中斷,即服務應該繼續使用舊數據,直到完成所有三個步驟。目前服務暫停將會持續1個小時,這就是讀取CSV並插入所有新行所需的時間。如果需要的話,我可以休息5分鐘。

我該如何實現這樣的行爲?

這裏是我的Python腳本的簡化版本:

cursor = conn.cursor(cursor_factory=DictCursor) 
cursor.execute('TRUNCATE TABLE rows CASCADE') 
with open(request.files.csv) as csv_file: 
    for line in csv_file: 
     row = parse_line(line) 
     cursor.execute(
      '''INSERT INTO rows (name, bla, blu) 
      VALUES (%(name)s, %(bla)s, %(blu)s)''', 
      row, 
     ) 
cursor.commit() 

回答

3
  1. 使用COPY代替with open(request.files.csv),因爲150萬行從CSV
  2. 複製到一個表在幾秒鐘內,如果這些秒(讓我們假設一個分鐘)太長,只是使用交易無濟於事,導致表格上的truncate requires lock,而不是行

TRUNCATE上

所以它的運作 每個表獲取到一個ACCESS EXCLUSIVE鎖,如果你可以重建在桌子上,興田最重要依賴對象很可能是:

create t_table as select * from "rows" where false; 
copy t_table from request.files.csv; 
--build all needed dependant objects (indexes, constraints,triggers); 
begin; 
    alter table "rows" rename to "some_name"; 
    alter table "t_table " rename to "rows"; 
end; 
--here is a miliseconds glitch to swith for users (if you use memcache or so - need to refresh it) 
drop table "some_name"; 

更新 to copy columns from csv to several table columns list columns

COPY table_name [(column_name [,...])]]

+0

截斷會在truncate命令出現問題之前影響其他正在處理快照的事務,所以它不適合'服務應該繼續使用舊數據,直到完成所有三個步驟完成要求。 –

+0

這看起來很棒,謝謝!只有一個跟進問題; CSV文件有20列,但我的表只需要其中的五個。我能否以某種方式只複製五個特定的列,或者我應該在將Python轉發到數據庫之前使用Python編輯CSV? –

+1

@MarkusMeskanen更新。使用request.files.csv中的'copy t_table(col1,col4,col5等);' –