2012-10-02 35 views
4

我一直在分析我的應用程序的某些部分,我發現 在執行完全相同的腳本時,PgAdmin3比psql快得多。 我使用unix套接字,Ubuntu 12.04和Postgresql 9.1和pgadmin3 v1.14。我有類似下面的簡單腳本:PSQL比PgAdmin III慢

BEGIN 
INSERT INTO key_value(section,key,value) VALUES('section','key1','value'); 
.... 
INSERT INTO key_value(section,key,value) VALUES('section','key10000','value'); 
COMMIT; 

下面是表:

CREATE TABLE key_value 
(
    key text NOT NULL, 
    value text, 
    CONSTRAINT key_value_pkey PRIMARY KEY (section , key) 
) 
WITH (
    OIDS=FALSE 
); 

有10000個插入這個腳本。在pgadmin3中執行它大約需要0.5秒,在psql中執行它需要2.5到3.5秒。兩者都包含在一個事務中,所以應該沒有什麼區別。結果是一致的,重新創建表格,完全真空等。記錄Postgresql服務器顯示postgres在psql中執行時爲每個插入語句執行日誌,但從pgadmin3執行時只有一個日誌。

psql的執行與完成以下事項:

psql -n -t -f p.sql -o/dev/null 

,並與

psql -n -t -1 -f p.sql -o/dev/null 

我的問題是測試爲什麼psql的這麼慢得多,爲什麼我們的PostgreSQL在一個記錄每一個發言客戶端,但只有在另一個整個事務,並有一個簡單的修復psql。

編輯只是爲了澄清,我記錄持續時間不聲明:

在服務器中,我發現了用psql執行時以下

2012-10-02 12:20:32 CEST LOG: duration: 0.283 ms 
.... 
2012-10-02 12:20:35 CEST LOG: duration: 0.285 ms 
2012-10-02 12:20:35 CEST LOG: duration: 0.291 ms 
2012-10-02 12:20:35 CEST LOG: duration: 0.279 ms 
2012-10-02 12:20:35 CEST LOG: duration: 0.284 ms 
2012-10-02 12:20:35 CEST LOG: duration: 0.279 ms 
2012-10-02 12:20:35 CEST LOG: duration: 0.299 ms 
.... 
2012-10-02 12:20:36 CEST LOG: duration: 5.779 ms 

當pgadmin3執行:

2012-10-02 12:23:21 CEST LOG: duration: 532.695 ms 

用戶和數據庫是在PSQL和pgadmin3

相同
+1

雖然沒有答案,但您的問題是「在此腳本中插入10000個」。使用['COPY'](http://www.postgresql.org/docs/current/static/sql-copy.html),或至少使用多值插入。至於不同的日誌記錄 - 也許你使用過'ALTER USER ... SET log_statement ='all'',你用psql和PgAdmin使用不同的用戶?或者,也許你在'psqlrc'中有'set'? –

+0

是的,我意識到(並且還有其他解決方案,如multrow插件等),但是應用程序現在正在使用舊版商店,因此需要重新構建應用程序。 – vseguip

+0

剛剛檢查並且沒有psqlrc或ALTER USER語句。 – vseguip

回答

3

我的提示:pgAdmin將腳本作爲一個多語句執行 - 因此網絡(協議)開銷較少。

+0

你好,謝謝你的回覆。有沒有一種方法可以讓psql將其作爲多語言執行? – vseguip

+0

這是否也可以解釋日誌差異? –

+0

psql可以執行從命令行以-c參數輸入的多條語句,但它是有限的。所以你可以只使用multiinsert - 你應該只使用一個分號,即語句分隔符。 –

1

psql有一個集成的解析器,它將分號識別爲語句分隔符。它使用它將SQL腳本分解爲多個語句,與pgadmin相反,如Pavel's answer中所述。

沒有選擇可以關閉此行爲。但是,使用DO匿名代碼塊應該可以獲得類似的結果,而且幾乎沒有變化。如果你寫這樣的劇本:

DO $$ 
BEGIN 
INSERT INTO key_value(section,key,value) VALUES('section','key1','value'); 
.... 
INSERT INTO key_value(section,key,value) VALUES('section','key10000','value'); 
END $$; 

這將一氣呵成被髮送到服務器作爲pgAdmin的(儘管它在技術上是完全不同),並在可比的時間大概是執行。

編輯:根據@vseguip評論,這是不高效的,因爲plpgsql解釋器花在這些10k語句上的時間。

替代IDEA:將腳本更改爲只有一個INSERT與多個INSERT,而不是多個INSERT,沒有DO塊。

BEGIN; 
INSERT INTO key_value(section,key,value) VALUES('section','key1','value'), 
     ('section','key2','value'), 
     ('section','key3','value'), 
     .... 
     ('section','key10000','value'); 
END; 
+0

出於某種原因(我想必須「編譯」匿名函數),這比普通的psql 10s vs 3.5s慢。 – vseguip

+0

@vseguip:太糟糕了。我已經用另一種方式更新了答案。 –

+0

謝謝,但使用多值插入將需要重新構建應用程序。因爲它的立場,我最好的辦法是將事務中的查詢分組在一個大字符串中,並將它們發送到一個查詢中。 – vseguip

相關問題