簡體   English   中英

基准測試 spring 數據與來自 postgres 數據庫的 select 中的 JDBI

[英]Benchmarking spring data vs JDBI in select from postgres Database

我想比較 Spring 數據與 JDBI 的性能我使用了以下版本

Spring Boot 2.2.4.RELEASE

對比

JDBI 3.13.0

測試相當簡單 select * 從 admin 表並轉換為 Admin object 列表

這是相關的細節

帶 spring 啟動

public interface AdminService extends JpaRepository<Admin, Integer> {


}

對於 JDBI

public List<Admin> getAdmins() {
    String sql = "Select admin_id as adminId, username from admins";
    Handle handle = null;
    try {
        handle = Sql2oConnection.getInstance().getJdbi().open();
        return handle.createQuery(sql).mapToBean(Admin.class).list();
    }catch(Exception ex) {
        log.error("Could not select admins from admins: {}", ex.getMessage(), ex );
        return null;
    } finally {
        handle.close();
    }
}

使用 junit 5 執行測試 class

@Test
@DisplayName("How long does it take to run 1000 queries")
public void loadAdminTable() {
    System.out.println("Running load test");
    Instant start = Instant.now();
    for(int  i= 0;i<1000;i++) {
        adminService.getAdmins(); // for spring its findAll()
    for(Admin admin: admins) {
                if(admin.getAdminId() == 654) {
                    System.out.println("just to simulate work with the data");
                }
            }
    }
    Instant end = Instant.now();
    Duration duration = Duration.between(start, end);
    System.out.println("Total duration: " + duration.getSeconds());

}

我很震驚得到以下結果

Spring 數據:2 秒 JDBI:59 秒

知道為什么我得到這些結果嗎? 我期待 JDBI 更快

問題是 spring 為我們管理連接生命周期,並且在閱讀 JDBI 文檔后有充分的理由

每次分配和釋放連接時都會有性能損失。 在上面的示例中,兩個 insertFullContact 操作從數據庫連接池中獲取單獨的 Connection 對象。

我將JDBI測試的測試代碼更改為以下

@Test
@DisplayName("How long does it take to run 1000 queries")
public void loadAdminTable() {
    System.out.println("Running load test");
    String sql = "Select admin_id as adminId, username from admins";
    Handle handle = null;
    handle = Sql2oConnection.getInstance().getJdbi().open();
    Instant start = Instant.now();
    for(int  i= 0;i<1000;i++) {
        
        List<Admin> admins = handle.createQuery(sql).mapToBean(Admin.class).list();
        if(!admins.isEmpty()) {
            for(Admin admin: admins) {
                System.out.println(admin.getUsername());
            }
        }
    }
    handle.close();
    Instant end = Instant.now();
    Duration duration = Duration.between(start, end);
    System.out.println("Total duration: " + duration.getSeconds());
    
}

這樣連接打開一次,查詢運行 1000 次

最終結果是 1 秒

速度是 spring 的兩倍

一方面,您似乎在基准測試中犯了一些基本錯誤:

  • 您沒有預熱 JVM。
  • 您沒有以任何方式使用結果。

因此,您所看到的可能只是虛擬機不同優化的效果。 查看JMH以改進您的基准。

使用外部資源進行基准測試非常困難,因為您要控制的參數太多了。 一個大問題是,例如,與數據庫的連接是否真的很慢,因為在大多數生產系統中,數據庫至少虛擬地位於不同的機器上,很可能在不同的硬件上。 在你的測試中也是這樣嗎?

假設你的結果是真實的,下一步是調查額外的時間花在了哪里。 我預計大部分時間都花在執行 SQL 語句並通過網絡獲取結果上。 因此,您應該檢查實際執行了哪些 SQL 語句。

這可能會為您指出一個可能的答案,即 JPA 正在執行大量延遲加載,甚至還沒有加載您真正需要的大多數人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM