close

POSTGRESQL資料庫COPY用法

 

壹:前言

因NABRO推播系統中postgresql資料庫的playback_log table歷史資料過多未清(兩千多萬筆),對資料庫運作效能及報表產生程式皆有不利影響,因此必須清除此table歷史資料。

貳:目標

一、將playback_log的2008及2009年資料撈出存檔後刪除記錄。

二、2008及2009年資料如果有需要,仍能正確倒回資料庫使用。

参:作法過程

一、要達成第一個目標很簡單,下個delete from playback_log where start_time like '2008%'即可,但無法做到第二個目標將刪除資料再倒回資料庫使用。所以需要將刪除資料先select出來到檔案,這也不難辦到。

二、接下來的困難點在於如何將select出來的檔案,再倒回資料庫。其實要在資料庫新增資料語法也很簡單--「INSERT INTO `playback_log` (`column name`, …) VALUES (…);」,以前有利用EXCEL將資料檔案先匯入,再將INSERT INTO的SQL語法快速複製進去,再將此加工過的SQL語法複製貼上GUI介面的SQL視窗執行,但這只適合資料量不大的情況(EXCEL只能吃6萬多筆而已)。但是當挑出來的檔案有幾百萬筆,甚至幾千萬筆的狀況該怎麼做呢?

三、會寫程式的應該就會說寫個程式就可以解決阿!的確是很好的解決方法,但除了寫程式外沒有其他方法?上網查詢又找不到相關資料,好吧,山不轉路轉,只好從書裡去找答案,後來在網路上找到這本電子書「Practical PostgreSQL」網址如後:(http://www.faqs.org/docs/ppbook/book1.htm)。

四、這本書寫的相當不錯,但為原文書,所以讀起來會比較辛苦,中間看的過程就略過,最後看的結果是書裡還是沒有直接答案!感覺洩氣了。先看學到什麼新的東西吧!

1.Copying Values (to/from) External Files with COPY

就是說在pgsql命令列模式可以用COPY指令將table內的全部資料拷貝到外部檔案,或從外部檔案將資料拷貝回table,但這是用在table整個資料,無法下條件子句拷貝部分資料出去。(就差那麼一步,如果可以下條件子句拷貝部分資料,那問題早就解決了)

2.Restructuring with CREATE TABLE AS

意思是可以在pgsql命令列模式下,用CREATE TABLE AS指令,從一個已存在的table複製成另一個新的table,語法如下:

CREATE TABLE new_table [ ( column_name [, ...] ) ] AS query

五、現在整理我們會的指令有哪些:

1.select * from playback_log where start_time like '2008%'

2.delete from playback_log where start_time like '2008%'

3.INSERT INTO `playback_log` (`column name`, …) VALUES (…)

4.Copying Values (to/from) External Files with COPY

5.Restructuring with CREATE TABLE AS

這些指令跟我們想要解決方案的指令似乎無關又有關,難道真的只能靠寫程式嗎?公司人事又已經精簡到不行,只好自力救濟啦,這次,路不轉人轉,其實原理說明了,似乎根本也是很簡單的,程序如後:

a.先用第1、5指令從playback_log CREATE 2008年資料到playback_log_2008

b.用第4指令將playback_log_2008整個COPY到外部檔案。

c.用第2指令將playback_log的2008年資料刪除。

d.用第4指令從2008年外部檔案COPY到playback_log測試是否可正確倒回。

以上程序指令在243備份資料庫測試過可行,完整執行指令如附錄。

肆:結論

書本上教的是基本的,但運用之妙存乎一心,就看是否能融會貫通。這次也是經過多次try & error後得出來的經驗。其實用postgresql內建指令執行的速度還算不錯,以2009年資料量6165910筆來看,CREATE TABLE playback_log_2009花78秒,再將playback_log_2009拷貝到外部檔案約45秒,從playback_log刪除2009年資料約94秒,最後測試從2009年外部檔案拷貝回playback_log要2003秒(33分鐘左右)。最後記得請先在備份資料庫做過ㄧ遍沒問題後,再到正式資料庫執行。

 

伍:附錄

以下紅色粗體字為指令部份,黑色細體字為執行結果,duration為執行時間。

先用自己帳號ssh登入到243主機。

$ sudo su –           --切換到superuser

# su – postgres      --切換到postgres user

$ psql                  --使用postgresql的命令列模式

Postgres=# \c NabroRepository --切換到NabroRepository資料庫

NabroRepository=# CREATE TABLE playback_log_2008 as select * from playback_log where start_time like '2008%';

LOG:  statement: CREATE TABLE playback_log_2008 as select * from playback_log where start_time like '2008%';

LOG:  duration: 53686.562 ms

SELECT

NabroRepository=# SELECT count (*) from playback_log_2008;

LOG:  statement: SELECT count (*) from playback_log_2008;

LOG:  duration: 4.777 ms

 count

-------

 20528

(1 row)

 

NabroRepository=# COPY playback_log_2008 TO '/var/lib/pgsql/playback_log_2008.txt';

LOG:  statement: COPY playback_log_2008 TO '/var/lib/pgsql/playback_log_2008.txt';

LOG:  duration: 144.384 ms

COPY 20528

NabroRepository=# DELETE FROM playback_log where start_time like '2008%';

LOG:  statement: DELETE FROM playback_log where start_time like '2008%';

LOG:  duration: 53470.131 ms

DELETE 20528

NabroRepository=# SELECT count (*) from playback_log;

LOG:  statement: SELECT count (*) from playback_log;

LOG:  duration: 7210.239 ms

  count  

----------

 21347214

(1 row)

 

NabroRepository=# COPY playback_log FROM '/var/lib/pgsql/playback_log_2008.txt';

LOG:  statement: COPY playback_log FROM '/var/lib/pgsql/playback_log_2008.txt';

LOG:  duration: 1958.721 ms

COPY 20528

 

NabroRepository=# SELECT count (*) from playback_log;

LOG:  statement: SELECT count (*) from playback_log;

LOG:  duration: 7232.225 ms

  count  

----------

 21367742

(1 row)

 

 

NabroRepository=# CREATE TABLE playback_log_2009 as select * from playback_log where start_time like '2009%';

LOG:  statement: CREATE TABLE playback_log_2009 as select * from playback_log where start_time like '2009%';

LOG:  duration: 78194.930 ms

SELECT

NabroRepository=# SELECT count (*) from playback_log_2009;

LOG:  statement: SELECT count (*) from playback_log_2009;

LOG:  duration: 2285.198 ms

  count 

---------

 6165910

(1 row)

 

NabroRepository=# COPY playback_log_2009 TO '/var/lib/pgsql/playback_log_2009.txt';

LOG:  statement: COPY playback_log_2009 TO '/var/lib/pgsql/playback_log_2009.txt';

LOG:  duration: 45813.709 ms

COPY 6165910

 

NabroRepository=# DELETE FROM playback_log where start_time like '2009%';

LOG:  statement: DELETE FROM playback_log where start_time like '2009%';

LOG:  duration: 94604.313 ms

DELETE 6165910

NabroRepository=# SELECT count (*) from playback_log;

LOG:  statement: SELECT count (*) from playback_log;

LOG:  duration: 8023.077 ms

  count  

----------

 15201832

(1 row)

 

NabroRepository=# COPY playback_log FROM '/var/lib/pgsql/playback_log_2009.txt';

LOG:  statement: COPY playback_log FROM '/var/lib/pgsql/playback_log_2009.txt';

LOG:  duration: 2003791.433 ms

COPY 6165910

 

NabroRepository=# SELECT count (*) from playback_log;LOG:  statement: SELECT count (*) from playback_log;

LOG:  duration: 16176.402 ms

  count  

----------

 21367742

(1 row)

 

NabroRepository=# SELECT count (*) from playback_log where start_time like '2010%';;

LOG:  statement: SELECT count (*) from playback_log where start_time like '2010%';

LOG:  duration: 60504.378 ms

  count  

----------

 15181304

(1 row)

 

NabroRepository=# DELETE FROM playback_log where start_time like '2008%';

LOG:  statement: DELETE FROM playback_log where start_time like '2008%';

LOG:  duration: 54676.813 ms

DELETE 20528

NabroRepository=# DELETE FROM playback_log where start_time like '2009%';

LOG:  statement: DELETE FROM playback_log where start_time like '2009%';

LOG:  duration: 93285.418 ms

DELETE 6165910

 

NabroRepository=# SELECT count (*) from playback_log;

LOG:  statement: SELECT count (*) from playback_log;

LOG:  duration: 8600.796 ms

  count  

----------

 15181304

(1 row)

 

arrow
arrow
    創作者介紹
    創作者 Johnson峰 的頭像
    Johnson峰

    Johnson峰的部落格

    Johnson峰 發表在 痞客邦 留言(1) 人氣()