鍍金池/ 問答/Java  Linux  數(shù)據(jù)庫/ JDBC數(shù)據(jù)庫操作解惑

JDBC數(shù)據(jù)庫操作解惑

目前在測試JDBC數(shù)據(jù)庫多線程操作,想要提高效率,無奈發(fā)現(xiàn)

每次運行的SQL執(zhí)行時間不太一樣,遍歷ResultSet的時間,也不太一樣

為了方便觀察,我采用單線程單Session會話模擬,核心代碼

try (Connection connection = DBUtils.openConnection()) {
    for (int i = 0; i < 6; i++) {
        long s = System.currentTimeMillis();
        System.out.println("準備執(zhí)行SQL... ... ... ... ...");
        try (PreparedStatement preparedStatement = connection.prepareStatement(PRE_SQL + i);
             ResultSet resultSet = preparedStatement.executeQuery()) {
            long cost1 = System.currentTimeMillis() - s;
            System.out.println("執(zhí)行SQL耗時:" + cost1 + "ms");
            s = System.currentTimeMillis();
            while (resultSet.next()) {
                names.add(resultSet.getString("name"));
            }
            long cost2 = System.currentTimeMillis() - s;
            System.out.println("遍歷結果耗時:" + cost2 + "ms");
            System.out.println("總耗時:" + (cost1 + cost2) + "ms");
            System.out.println();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    System.out.println("集合大小為:" + names.size());
} catch (ClassNotFoundException | SQLException e) {
    e.printStackTrace();
}

然后結果大同小異,如下:

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:2194ms
遍歷結果耗時:474ms
總耗時:2668ms

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:1934ms
遍歷結果耗時:407ms
總耗時:2341ms

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:793ms
遍歷結果耗時:536ms
總耗時:1329ms

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:1812ms
遍歷結果耗時:395ms
總耗時:2207ms

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:810ms
遍歷結果耗時:643ms
總耗時:1453ms

準備執(zhí)行SQL... ... ... ... ...
執(zhí)行SQL耗時:682ms
遍歷結果耗時:2207ms
總耗時:2889ms

集合大小為:6000000

補充一句,有6個測試表,test_0至test_5,每個有100w測試數(shù)據(jù)。

望了解其中一二的解答下,困擾很久這個問題了,感謝~

回答
編輯回答
兔寶寶

數(shù)據(jù)庫查詢時間粗略地可以分為:

  1. 建立網(wǎng)絡連接
  2. sql語句傳輸
  3. sql語句解析
  4. sql語句執(zhí)行
  5. 數(shù)據(jù)傳輸
  6. 客戶端數(shù)據(jù)處理等

這里(1)可能因使用連接池,使得時間不盡相同,取決于連接池的實現(xiàn)和參數(shù)設置, 可能某一次與其他次建立連接時間不一樣; (2)基本為定值, 但也有可能在客戶端進行PreparedStatement緩存而不一致; (3)同(2), 數(shù)據(jù)庫會對解析進行緩存, 第一次可能和第二次不一樣; (4)數(shù)據(jù)庫一會對執(zhí)行過的sql進行短時間緩存; (5)取決于數(shù)據(jù)量和網(wǎng)速, 對于同樣的數(shù)據(jù)量變化不大; (6)取決于客戶端代碼, 但一般會小于ms級.

這里還沒有考慮數(shù)據(jù)庫服務器端的配置和是否有主從及負載均衡的配置等等.

所以你測試的數(shù)據(jù)是變化的很正常不過了, 需要采集大量數(shù)據(jù),最好是與業(yè)務相似的使用場景才有價值.

2018年3月11日 07:06
編輯回答
假灑脫

沒sql、沒上下文,僅從表象上分析。

  1. 由于數(shù)據(jù)量不小,因此sql語句查詢時網(wǎng)絡傳輸是一個不小的開銷(你可以在mysql端查看是否有write data等行為占用一定時間)
  2. 遍歷結果耗時可以觀察下gc的記錄,另外不確定你用的集合類型,set和list的擴容方式不一樣對耗時影響也不一樣。6000W的集合不小了
2018年8月15日 19:15