這不是網絡上的罕見問題,但我使用MySQL服務器做了一些優化工作來解決這個問題,但沒有得到結果。所以起初我使用maven的包mysql:mysql-connector-java:6.0.6。 我只是想運行這段代碼:SELECT連接上的JDBC連接器速度太慢
try {
mysqlConnection = DriverManager.getConnection(DatabaseUtils.mysqlUrl, DatabaseUtils.mysqlUser, DatabaseUtils.mysqlPassword);
PreparedStatement valuesStatement = "SELECT * FROM `test` ORDER BY `id`"
ResultSet cursor = valuesStatement.executeQuery();
double value = 0;
if (cursor.next())
value = cursor.getDouble("value");
} catch (SQLException sqlEx) {
sqlEx.printStackTrace();
} finally {
cursor.close();
pricesStatement.close();
}
我在表中有很多記錄。它約爲百萬,但每天增加約千條記錄。所以當這個簡單的例子執行了30秒時,我感到非常驚訝。我GOOGLE了我的問題,我發現只有「使用池」,「調整MySQL服務器」,「嘗試解釋選擇」。但我注意到執行時間與行數有關。所以,我看着司機的代碼,發現:
TextResultsetReader ::閱讀():
while(true) {
if(row == null) {
rows = new ResultsetRowsStatic(rowList, cdef);
break;
}
if(maxRows == -1 || rowList.size() < maxRows) {
rowList.add(row);
}
row = (ResultsetRow)this.protocol.read(ResultsetRow.class, trf);
}
這意味着,即使我想獲取只有一個行驅動器讀取所有查詢行,讓我首先它。手冊建議使用「setFetchSize」僅提取n條記錄。但它不起作用。無論如何,驅動程序代碼獲取所有數據。於是我發現有兩個記錄集:ResultRowsStatic和ResultSetStreaming。其次,似乎只在需要查詢時才提取數據。如何使用ResultRowsStreaming?我發現它只是代碼。參數「fetchSize」必須等於-2147483648。我確實嘗試過,它的工作!現在「executeQuery()」的執行時間約爲0.0007秒。這對我來說非常快。但是等等..我的腳本無論如何都需要30秒。爲什麼?我在執行查詢後調試了代碼。之後只有兩個「關閉」方法。什麼可能會出錯?這是真的,「cursor.close()」需要剩下的時間。我看着庫代碼再次達到ResultsetRowsStreaming :: close()方法:
boolean hadMore = false;
int howMuchMore = 0;
synchronized(mutex) {
while(this.next() != null) {
hadMore = true;
++howMuchMore;
if(howMuchMore % 100 == 0) {
Thread.yield();
}
}
if(conn != null) {
if(!((Boolean)this.protocol.getPropertySet().getBooleanReadableProperty("clobberStreamingResults").getValue()).booleanValue() && ((Integer)this.protocol.getPropertySet().getIntegerReadableProperty("netTimeoutForStreamingResults").getValue()).intValue() > 0) {
int oldValue = this.protocol.getServerSession().getServerVariable("net_write_timeout", 60);
this.protocol.clearInputStream();
try {
this.protocol.sqlQueryDirect((StatementImpl)null, "SET net_write_timeout=" + oldValue, (String)this.protocol.getPropertySet().getStringReadableProperty("characterEncoding").getValue(), (PacketPayload)null, -1, false, (String)null, (ColumnDefinition)null, (GetProfilerEventHandlerInstanceFunction)null, this.resultSetFactory);
} catch (Exception var9) {
throw ExceptionFactory.createException(var9.getMessage(), var9, this.exceptionInterceptor);
}
}
if(((Boolean)this.protocol.getPropertySet().getBooleanReadableProperty("useUsageAdvisor").getValue()).booleanValue() && hadMore) {
ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(conn.getSession());
eventSink.consumeEvent(new ProfilerEventImpl(0, "", this.owner.getCurrentCatalog(), this.owner.getConnectionId(), this.owner.getOwningStatementId(), -1, System.currentTimeMillis(), 0L, Constants.MILLIS_I18N, (String)null, (String)null, Messages.getString("RowDataDynamic.2") + howMuchMore + Messages.getString("RowDataDynamic.3") + Messages.getString("RowDataDynamic.4") + Messages.getString("RowDataDynamic.5") + Messages.getString("RowDataDynamic.6") + this.owner.getPointOfOrigin()));
}
}
}
此代碼無條件地獲取數據的所有剩下的只有對記錄有多少條記錄沒有牽強。真奇怪。如果連接了記錄器,這將是合理的。但在我的情況下,這個代碼統計未提取的行,並在30秒內...並沒有採取任何措施。而這個問題我無法修復,因爲沒有可以告訴代碼不能計算行的參數。
現在我不知道下一步該怎麼做。查詢時間對我來說非常慢。例如php的mysql驅動程序在0.0004-0.001秒內執行此查詢。
因此,使用mysql-connector for Java的人告訴我請你有這些問題嗎?如果沒有,你可以張貼任何例子,我應該怎麼做才能繞過上述問題?也許你使用另一個連接器。所以請告訴我,該怎麼辦?
如果我的理解正確 - 你會得到你想要的結果,但是聲明在結束之前繼續執行select?你嘗試過'valuesStatement.cancel()'嗎? [看到這裏](http://stackoverflow.com/questions/295920/how-can-i-abort-a-running-jdbc-transaction) – Michael
我試圖在close()之前添加cancel(),但它沒有也幫助。其餘所有數據都由驅動程序提取。我正在使用jar,所以我不能編輯驅動程序的代碼。 –
如果您只需要一行,請告訴服務器僅使用['LIMIT 1'](https://dev.mysql.com/doc/refman/5.7/en/select.html#idm140545627869536)發送一行。 – Andreas