2016-08-14 69 views
5

我有一個Dashboard視圖,它需要來自整個數據庫的表的少量數據集。我優化了數據庫查詢(例如,刪除的子查詢)。現在有〜20個查詢依次執行,並且從數據庫中獲取不同的數據集。大多數HQL查詢包含GROUP BYJOIN子句。使用Spring REST接口,結果返回到前端。Spring數據查詢執行優化:在JpaRepository中並行執行Hibernate @Query方法

如何優化自定義查詢的執行?我最初的想法是並行運行數據庫查詢。但我該如何實現這一目標?在做了一些研究之後,我發現了註釋@Async,它可以並行運行方法。但是這與Hibernate方法一起工作嗎?是否總會爲每個用JpaRepository中的@Query註解的方法創建一個新的數據庫會話?畢竟,運行數據庫查詢是否會影響總體執行時間?

並行運行數據庫調用的另一種方式是將Dashboard調用拆分爲幾個單獨的Ajax調用(每個關注點都會獲得自己的Ajax調用)。我不想這樣做,因爲每次打開儀表板(或者例如日期範圍發生變化)時,都會有20個Ajax調用來獲取新數據。同樣的問題仍然存在:並行運行SQL查詢是否會影響數據庫的執行時間?

我目前還沒有添加額外的索引到數據庫。這將是下一件事,我肯定會做。但是,我對並行運行查詢的性能影響以及如何用Spring編程實現這一點感興趣。

我的項目最初是由jHipster(春季啓動,MariaDB的,AngularJS等)產生

回答

6

首先,在並行運行這些SQLS不會影響數據庫,只會使頁面加載速度更快,這樣的設計應該專注於此。

我發佈這個答案,假設你已經確保你不能合併這20個SQL因爲數據是不相關的(沒有聯接,視圖等)。

我建議不要使用@Async有兩個原因。

原因1 - 當您想要激發一堆任務並忘記,或者知道所有任務何時完成時,異步任務非常棒。因此,您需要「等待」完成所有異步任務。你應該等多久?直到最慢的查詢完成?

檢查異步此示例代碼(來自@導遊spring.io - https://spring.io/guides/gs/async-method/

// Wait until they are all done 
while (!(page1.isDone() && page2.isDone() && page3.isDone())) { 
    Thread.sleep(10); //10-millisecond pause between each check 
} 

請問/應在20個異步DAO查詢您的服務組件的等待?

原因2 - 請記住,Async只是作爲一個線程產生任務。由於您要使用JPA,請記住實體管理器不是線程安全的。 DAO類將傳播事務。這裏是一個可能出現的問題的例子 - http://alexgaddie.blogspot.com/2011/04/spring-3-async-with-hibernate-and.html

恕我直言,最好是繼續進行多個Ajax調用,因爲這將使您的組件具有內聚性。是的,您將擁有20個端點,但它們將具有更簡單的DAO,更簡單的SQL,更容易進行單元測試,並且返回的數據結構將更易於由AngularJS小部件處理/分析。當用戶界面觸發所有20個Ajax調用時,儀表板將在它們準備好時加載單個小部件,而不是同時加載所有這些小部件。這將有助於您通過優化儀表板的較慢加載部分(可能是緩存,索引等)來擴展您的設計。

將您的DAO調用捆綁在一起將只會使數據結構變得複雜,單元測試更難。

+1

謝謝。不幸的是,我太遲不能給你完整的賞金。 –

3

通常,並行執行查詢會快得多。如果您使用Spring數據並且未配置任何特定的JPA提供程序(Hibernate)將創建一個連接池來存儲與您的數據庫的連接。我認爲默認情況下,Hibernate擁有10個連接,通過這樣做,它準備並行處理10個查詢。通過並行運行查詢的速度要快多少取決於數據庫和表/查詢的結構。 我認爲使用@Async並不是這裏的最佳做法。定義提供特定查詢結果的20個REST端點是一種更好的方法。通過這樣做,您可以爲每個查詢簡單地創建Entity,Repository和RestEndpoint類。通過這樣做,每個查詢都是孤立的,代碼也不那麼複雜。