大多數JDBC驅動程序將按需獲取行(基於獲取大小),因此通常maxRows
將非常高效。他們通常甚至優化,只能獲取不超過maxRows
。
A ROWS
或TOP
可能會爲數據庫服務器提供一些額外的提示以優化查詢,因此設置maxRows
可能不如在查詢本身中包含最大值。確切的行爲是依賴於驅動程序和數據庫的,因此很難概括行爲和性能特徵。
值得注意的例外是MySQL驅動程序(可能也MariaDB的),默認爲獲取所有行(除非獲取大小設置爲Integer.MIN_VALUE
)立即執行查詢。
如Jaybird(火鳥JDBC驅動程序)的示例中,following完成(用於TYPE_FORWARD_ONLY
):
public void fetch() throws SQLException {
synchronized (syncProvider.getSynchronizationObject()) {
checkClosed();
int maxRows = 0;
if (this.maxRows != 0) maxRows = this.maxRows - rowNum;
int fetchSize = this.fetchSize;
if (fetchSize == 0) fetchSize = MAX_FETCH_ROWS;
if (maxRows != 0 && fetchSize > maxRows) fetchSize = maxRows;
if (!allRowsFetched && (rows.isEmpty() || rows.size() == rowPosition)) {
rows.clear();
stmt.fetchRows(fetchSize);
rowPosition = 0;
}
if (rows.size() > rowPosition) {
setNextRow(rows.get(rowPosition));
// help the garbage collector
rows.set(rowPosition, null);
rowPosition++;
} else {
setNextRow(null);
}
}
}
由於服務器可以決定發送比請求,額外的檢查是在next()
由更多的行。
但即使所有的行被提取,MySQL不使用類似的方法嗎?在開始通過電線發送響應之前,它是否必須獲取數據庫內存中的所有行? –
默認的MySQL行爲是獲取所有行並將其緩存到客戶端,請參閱_ResultSet_:http://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html。您可以使用流式結果集,但這具有其他含義,因爲在所有行都被提取之前,它不可能使用相同的連接來執行其他語句。我不知道MySQL協議如何工作的確切細節,但據我瞭解,只要您執行了查詢,就需要讀取查詢生成的所有行;但我不是100%確定的。 –
根據文檔,這是它應該如何工作的,但是它必須對不限制結果集的查詢執行同樣的操作。在實踐中,性能更接近於使用LIMIT。所以,我想他們會做一些事情來優化它。 –