postgresql 的gui用戶端比較多,有開源的,也有商業的。
用得比較多的可能是pgadmin了,有些人可能會用edb的pem。
但實際上這兩個gui都有一個小問題,在傳回較大的結果集時,會非常的慢。
例如 :
資料庫端建立一個表,插入約30mb資料。
使用edb的pem或者pgadmin連接配接到資料庫 :
在gui中執行 :
耗時20秒。
換個執行語句:
3秒傳回。
copy與select * 查詢的資料量一樣多,而且都是全表掃描,但是時間卻相差10幾秒。
原因排查
在pgadmin用戶端的機器上,觀察到一個現象 :
執行select * from test;時,網絡使用率不高,持續時間長。
網絡傳輸結束後,cpu馬上飙高,估計pgadmin在處理資料,很長一段時間後,才開始展示結果。

而更換為
後,執行非常迅速,而且展示也非常快,可以看到網絡使用率很高,出現了一個尖峰。
将gui用戶端更換為heidisql後,執行 select * from test; 執行速度很快,與copy相當。
從網絡使用率來看,也出現了一個尖峰,資料很快就傳完了。
使用 postgresql 用戶端 psql 指令執行select * from test,速度也和heidisql一樣,很快。
對比以上幾種情況,說明pgadmin和pem在處理 select 時,效果并不理想,如果要傳回大量的結果集,請慎用。
如果使用pem或者pgadmin要傳回大量結果集,建議使用遊标來傳回:
例子:
網絡流量對比圖 :
從左往右數
第1個尖峰,heidisql中執行select * from test;
第2個尖峰,pgadmin中執行copy (select * from test) to stdout;
第3個尖峰,pgadmin中執行copy test to stdout;
第4個尖峰,psql中執行select * from test;
說明 select * from test 的網絡傳輸流量确實比copy的更大一些。
heidisql不支援 copy指令.
如果你用的是windows平台,并且遇到了與之類似的問題,建議排查一下用戶端程式的代碼,從程式層面來解決這個問題。
這個問題我也會回報給pgadmin和edb,看看他們怎麼解決。
最後要給應用開發人員的一個小建議 :
查詢大結果集,給使用者展示資料的sql,建議修改為用遊标打開,一次fetch少量資料, 拿到資料馬上就可以向使用者展示,背景可以根據政策選擇是否再繼續fetch剩餘的資料。
這樣做的好處是使用者體驗更好,同時有可能可以大大減少資料庫的網絡開銷和cpu開銷(因為使用者并不一定要查詢所有資料)如果使用者關閉視窗,可以不再fetch其他資料。
大多數類似的應用場景,都是這樣來設計的。