簡體   English   中英

為什么 hibernate PersistentSet.contains() 這么慢? (與 java.util.HashSet 相比)

[英]Why hibernate PersistentSet.contains() is so slow? (compared to java.util.HashSet)

我正在開發一個用例,其中給了我一個 ID 集合(名為group ),並且需要驗證這些 ID 中的哪些在另一個集合(名為projectDevicesIds )中,哪些不在。 請注意,最后一個集合是從數據庫獲得的 PersistentSet。 代碼非常簡單,如下:

Collection<String> inside = new HashSet<>();
Collection<String> notInside = new HashSet<>();
group.forEach(id -> {
        if (projectDevicesIds.contains(id)) inside.add(id);
        else notInside.add(id);
    });

到目前為止一切順利,問題是當projectDevicesIds (hibernate PersistentSet) 的大小為 100 000 並且group包含 1000 個 id 時,此代碼平均需要 200 毫秒才能運行。 當我進行相同的測試但不使用 PersistentSet 而使用 HashSet 時,它只需要 1 毫秒,即使測試在專業上並不准確。 這種差異很瘋狂,會損害我的用例性能。 在 hibernate 官方文檔中,他們說 PersistentSet 在內部使用 HashSet,所以我期待相同的性能。

有人可以向我解釋為什么 PersistentSet.contains() 與 HashSet 相比需要這么長時間嗎? 並以某種方式幫助我提高這個用例的性能?

PersistentSet 表示數據庫上的關聯。 這意味着當您調用contains時,Hibernate ORM 需要首先刷新可能影響關聯的先前操作,並最終從數據庫中重新加載它。 或者,如果關聯已被延遲加載,它可能只需要重新加載它。

首次加載集合后,性能差異不應該那么高,但這實際上取決於您如何獲取projectDevicesIds

如果啟用日志,您應該查看在調用contains方法時 Hibernate ORM 是否需要運行額外的查詢。

@Davide 的回答解決了forEach時間問題(從 200 毫秒到 1 毫秒),但結果是eager獲取速度較慢,並且總時間( eager fetch + forEach )更高(> 250 毫秒)。

所以我想出了一個解決方法來強制使用HashSet (而不是PersistentSet )。 我沒有通過Project POJO獲取設備,而是在ProjectJpaRepositoty中添加了一個自定義 SQL 查詢以從特定項目獲取設備 ID,但返回 class 是一個HashSet

public interface ProjectRepository extends JpaRepository<Project, String> {
            @Query(
                    value = "SELECT id FROM device WHERE project_id = :projectId",
                    nativeQuery = true
            )
            HashSet<String> getDevicesId(String projectId);
}

現在總時間是我能得到的最低時間(~75ms),這是可以接受的。

暫無
暫無

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

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