2016-09-28 20 views
1

執行查詢我有一個存儲過程,PostgreSQL的查詢,有一個參數(參數)執行使用JDBC採取更多的時間比在pgAdmin的

的讓我們把它叫做x

當我運行,

select * from x('myParameter') 

它完成了4分鐘。

現在,我嘗試在java中執行相同的存儲prcedure如下: -

PreparedStatement statement = connection.prepareStatement("Select * from x('myParameter')"); 
org.postgresql.PGStatement pgstmt = (org.postgresql.PGStatement)statement; 
pgstmt.setPrepareThreshold(1); 
boolean usingServerPrepare = pgstmt.isUseServerPrepare(); 
System.out.println(usingServerPrepare); 
statement.execute(); 

這需要大約26小時才能完成。

我最初嘗試不使用pgstmt.setPrepareThreshold(1);, 即prepareThreshold的默認值。 結果是一樣的。

然後我試圖java程序以「set ENABLE_NESTLOOP假」作爲存儲過程的第一行,並將其在4分鐘內完成。

我無法理解爲什麼查詢改變了執行計劃,當我明確地迫使服務器端prepared statement。

我使用的Postgres 9.4和Java 8.我還使用PGBouncer連接池。

我在這裏的查詢是 - 爲什麼JDBC會影響執行計劃?有沒有辦法強制服務器端執行計劃到我的查詢從Java程序觸發?

+1

它返回多少行?函數'x'到底是什麼?請編輯你的問題,爲所討論的表(包括所有索引)和函數'x'的代碼添加'create table'語句。 [_Formatted_](http://stackoverflow.com/editing-help#code)**文本**,請[無屏幕截圖](http://meta.stackoverflow.com/questions/285551/why-may-i -not-upload-images-code-on-so-when-asking-question-285557#285557) –

+0

它不返回任何東西。這是一個存儲過程,它執行一些連接並將數據加載到另一個表中。當我從存儲過程執行查詢並使用JDBC執行查詢時,條件相同。 –

+0

你確定你在同一個數據庫上執行它嗎? – talex

回答

2

得到的解決方案: - 在存儲過程中使用了一個表,如「tab1」。

當我們運行從pgAdmin的/ SQL窗口TAB1存儲過程已創建/修改小時回來。所存儲的過程的執行之前

在自動運行,用java,TAB1被創建並加載/改性幾秒鐘。
在第一種情況(從pgAdmin的/ SQL窗口運行存儲過程)上TAB1自動分析已經由我們運行在pgAdmin的存儲過程的時間在第二種情況下完成的,而(自動化用java運行)自動對tab1進行分析尚未開始或正在處理中,因爲tab1剛剛被修改。
這導致Postgres在運行PGAdmin查詢時選擇更好的計劃,與我們使用java運行時相比。

總結 - 不同的方案被選中,因爲在第二種情況下,自動分析並沒有完成,我們跑了存儲過程的時候,導致較差的查詢計劃的選擇。

相關問題