看不到程序進度,機器在嘗試導入 5 億條記錄時變慢
工作環境:PostgreSQL 12.0,Ubuntu 18.10,4GB記憶體,i5-3230M CPU@2.60GHz×4,Os 64位
我正在嘗試使用我的 PC 將包含超過 5 億條記錄的 .csv 文件導入 PostgreSQL 數據庫表。(我們正在我的 PC 上進行測試,直到它可以工作,之後我們將在伺服器上進行)
我的公司正在從 Firebird 遷移到 Postgres,所以這應該是一次性的任務。之後,我們預計每天插入約 20 萬條記錄。
使用(從原始 firebird 數據庫生成的 SQL)創建表
CREATE TABLE REGDATA ( CODIGO integer NOT NULL, DTAREG timestamp NOT NULL, PERIOD integer NOT NULL, FLDCODIGO integer, REGVALUE double precision, CLICODIGO integer, SITCODIGO integer, CONSTRAINT PK_REGDATA PRIMARY KEY (CODIGO) );
.csv 是使用FBExport 1.9生成的
./fbexport -Sc -D /opt/firebird/bin/measures.fdb -H localhost -U user -P password -F /home/dani/Documents/raw_regdata.out -Q "SELECT * FROM REGDATA"
我將 raw_regdata.out 轉換為 utf8 以使用 postgres 編碼。去掉一些字元(ã、º等)
iconv -c -t utf8 /home/dani/Documents/raw_regdata.out > /home/dani/Documents/utf8_regdata.out
我已遵循Postgres關於如何導入大數據的指南,例如:
- 刪除所有索引;
- 增加maintenance_work_mem (maintenance_work_mem = 512MB)
- 增加 max_wal_size (max_wal_size = 4GB)
- 設置 wal_level = 最小
- 設置 max_wal_senders = 0
連接到 Postgres 集群後,我使用 COPY 導入數據
COPY REGDATA(CODIGO,DTAREG,PERIOD,FLDCODIGO,REGVALUE,CLICODIGO,SITCODIGO) from '/home/dani/Documents/utf8_regdata.out' DELIMITER ',' CSV HEADER;
問題來了,我看不到命令是否正在執行,一段時間後我的電腦變得非常慢,它只是****凍結了。
第一次嘗試:讓它執行 2-3 小時,然後終止程序(終端上的 Ctrl+c),從日誌中我看到它正在進行(第 131158327 行):
2019-10-16 10:28:05.657 -03 [9258] postgres@measures ERROR: canceling statement due to user request 2019-10-16 10:28:05.657 -03 [9258] postgres@measures CONTEXT: COPY regdata, line 131158327: ""178865944","13.03.2015 12:10:00","600","22439","358.60000000000002","9","37"" 2019-10-16 10:28:05.657 -03 [9258] postgres@measures STATEMENT: COPY REGDATA(CODIGO,DTAREG,PERIOD,FLDCODIGO,REGVALUE,CLICODIGO,SITCODIGO) from '/home/dani/Documents/utf8_regdata.out' DELIMITER ',' CSV HEADER;
但是我嘗試選擇一些東西卻什麼也得不到,我認為由於 Copy 僅在整個過程完成後送出,它只是撤消所有內容,我最終得到一個空表
第二次嘗試:讓它執行 24 小時(即使我的 PC 完全鎖定),然後再次終止該程序,希望在日誌上看到更多進展,但令我驚訝的是,我沒有看到任何類似的日誌,只有相同的 3 個警告結束和再次:
2019-10-16 17:42:31.061 -03 [5646] LOG: using stale statistics instead of current ones because stats collector is not responding . . . 2019-10-17 06:10:31.423 -03 [2734] WARNING: worker took too long to start; canceled 2019-10-17 06:57:19.150 -03 [5964] WARNING: autovacuum worker started without a worker entry 2019-10-17 08:04:47.445 -03 [2327] LOG: starting PostgreSQL 12.0 (Ubuntu 12.0-1.pgdg18.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit 2019-10-17 08:04:47.622 -03 [2327] LOG: listening on IPv4 address "127.0.0.1", port 5412 2019-10-17 08:04:48.048 -03 [2327] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5412" 2019-10-17 08:04:53.879 -03 [2546] LOG: database system was interrupted; last known up at 2019-10-16 15:47:25 -03 2019-10-17 08:05:10.887 -03 [2546] LOG: database system was not properly shut down; automatic recovery in progress 2019-10-17 08:05:11.534 -03 [2546] LOG: redo starts at 14/B8254908 2019-10-17 08:05:11.847 -03 [2546] LOG: invalid record length at 14/B8260848: wanted 24, got 0 2019-10-17 08:05:11.847 -03 [2546] LOG: redo done at 14/B82607D0 2019-10-17 08:05:16.417 -03 [2327] LOG: database system is ready to accept connections
有一種方法可以監控進度(它目前正在處理哪條線),並且在程序處於活動狀態時出現當機是正常的嗎?
沒有內置的方法來監控進度。v12 為某些操作添加了進度監控,但不針對 COPY。
我在這種情況下所做的就是用來
strace -s 1024 -y -p <backend pid>
跟踪載入過程。這將顯示它從“/home/dani/Documents/utf8_regdata.out”文件中讀取的數據(以及一堆其他內容)。然後,您可以從該流中獲取最近的主鍵,然後fgrep -n ,<primarykey> /home/dani/Documents/utf8_regdata.out
查看它所在的行號。這不是最優雅的過程,但比完全在黑暗中要好。如果你沒有刪除主鍵,並且載入時數據沒有按主鍵順序排序,那麼一旦主鍵索引的大小超過某個門檻值,就會出現嚴重的 IO 擁塞。這可以解釋“陳舊的統計數據”和“工人啟動時間太長”,並且系統也可能變得如此緩慢以至於它似乎已經死了(特別是如果您使用的是 GUI)。
索引大小的性能崩潰門檻值通常介於
shared_buffer
和之間greatest(shared_buffers,RAM - shared_buffers)
,但具體位置取決於核心版本和設置。