2014-11-05 38 views
4

我有一個表IDname。我想通過這張表的每一行。 IDprimary keyauto_incrementMySQL遍歷每一行(大表)

我不能使用(?)單個查詢來獲取所有行,因爲表很大。 我正在做每件事的結果。我希望有可能停止這項任務,並在稍後繼續。

我想我可以做這樣的事情:

for (int i = 0; i < 90238529; i++) { 
    System.out.println("Current ID :" + i); 
    query = "SELECT name FROM table_name WHERE id = " + i; 
    ... 
} 

但是,這並不工作,因爲auto_increment跳過一些數字。

如上所述,我需要一個選項來阻止這項任務,讓我可以在離開的地方重新開始。與上面的示例代碼一樣,我知道當前條目的ID,如果我想再次啓動它,我只需設置int i = X

回答

5

使用單一查詢來獲取所有的記錄:

query = "SELECT name FROM table_name WHERE id > ? ORDER BY id"; 

然後在ResultSet迭代和閱讀多少條記錄希望(你不必讀取ResultSet中返回的所有行)。

下次運行查詢時,傳遞您在上次執行中獲取的最後一個ID。

4

你提到這是一張大桌子。需要注意的則是非常重要的是,MySQL Connector/J API Implementation Notes

ResultSet

默認情況下,結果集是完全檢索和存儲在內存中。在大多數情況下,這是最有效的操作方式,並且由於MySQL網絡協議的設計更容易實現。如果您正在使用具有大量行或大值的ResultSets,並且無法在您的JVM中爲需要的內存分配堆空間,那麼您可以告訴驅動程序一次將結果串流回一行。

要啓用此功能,通過以下方式創建Statement實例:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, 
       java.sql.ResultSet.CONCUR_READ_ONLY); 
stmt.setFetchSize(Integer.MIN_VALUE); 

所以,我認爲你需要做到這一點,我會用a try-with-resources Statement。接下來,我建議你讓數據庫幫你迭代行

String query = "SELECT id, name FROM table_name ORDER BY id"; 
try (PreparedStatement ps = conn.prepareStatement(query, 
     ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); 
     ResultSet rs = ps.executeQuery();) { 
    while (rs.next()) { 
     int id = rs.getInt("id"); 
     String name = rs.getString("name"); 
     System.out.printf("id=%d, name=%s%n", id, name); 
    } 
} catch (SQLException e) { 
    e.printStackTrace(); 
} 
+0

表面上看起來並不那麼大(還)。但是,謝謝,這可能會在稍後有用。 – Josh 2014-11-05 15:55:06

0

我不能用一個單一的查詢來獲取所有行,因爲該表是巨大的,我做的每結果的東西。此外,我希望有可能停止此任務並在稍後繼續。

這些原因都不會消除使用單個查詢。它只會影響性能(使一個連接長時間處於活動狀態,而不斷打開和關閉連接,可以使用連接緩衝池緩解連接)。

如前所述,我需要一個選項來停止這項任務,但我可以從我離開的地方重新開始。與上面的示例代碼一樣,我知道當前條目的ID,如果我想再次啓動它,我只需設置int i = X

如果您考慮此問題,則這也不起作用,因爲你說你自己

但是,這是行不通的,因爲auto_increment跳過了一些數字。

更重要的是,自上次查詢數據庫以來,行可能已被插入或刪除。

首先,這聽起來像一個經典的XY問題,(您正在描述問題的解決方案問題,而不是實際問題)。其次,似乎使用RDBM來處理一些從未真正設計過的東西(一個隊列)。

如果你真的想這樣做,而不是使用更適合的數據庫有很多方法可以使用。您的第一個問題是您想要從某個點/狀態恢復,但這並不存儲在數據庫中,因此在有多個數據庫連接的情況下無法使用。解決這個問題的第一種方法是在表中引入一個「已處理」字段(如果要從任意點繼續,可以使用UPDATE語句清除),現在取決於您實際嘗試解決哪個問題,這可以是簡單的真/假字段,當前處理線程的唯一標識符或關係表。取決於要求。

然後你可以回到使用SQL來獲取你想要的數據。