拜託,在資料庫中執行計算

unblock發表於2014-04-01

如果一個計算應該在資料庫端執行,而卻沒有這麼做,那將是大錯特錯。

我們並非提倡將所有業務邏輯盲目地移到資料庫,但當我在 StackOverflow 看到一個這樣的問題時,就有種衝動想讓你看下這篇熱文——  10 Common Mistakes Java Developers Make When Writing SQL ——中的第二點。

那個 stack overflow 上的問題,本質上來說是這樣的:

在如下的中型表中,我想統計每個 App ID 中 status 為 0 或 1 的 doc 數

我該使用 Hibernate 嗎?

答案是:不!別用 hibernate 來做(除非是寫 native query),應該用 SQL 來做 。S——Q——L !使用SQL Server的話,有很多簡單的做法來實現這個查詢,而且時間會比將全部資料不作聚集就裝到 java 記憶體少很多。

以 SQL Server 來舉個例:

使用 GROUP BY

這是最簡單的做法,但它不一定完全符合你的要求。即是,子集合不在同一行。

如 SQLFiddle 的例子,會查出這樣的東西:

使用 nested select

這可能就是那個特殊使用者所要的效果。他們可能想每個集合分別一列,而nest select就是最通用的實現手法之一。記住這種做法在某些資料庫上是有點慢的,需要花些時間制定執行計劃。

例如 SQLFiddle ,跑出這樣的東西:

使用 sum()

這可能是最佳的作法。它跟前面那個nest select一樣,但只能用於簡單的查詢,而前者更靈活。

例如 SQLFiddle ,結果如上。

使用 PIVOT

這種方案是為 SQL 迷而準備的。它使用了 T-SQL 的 PIVOT 子句!

SQL 迷就該用 PIVOT !

例如 SQLFiddle ,結果亦如上。

結論

以上建議任君選擇,而且我也相信還有更多方案。它們都比基於java的聚合好幾個數量級,即使是在少量資料的情況下。我們將多次重申這個觀點。

正如 Gavin King 所說的:

你在使用 Hibernate,並不就意味著你把它套到所有事情上。這是我說了十幾年的話了。

轉為我們的說法就是:

該用 SQL 的時候就用 SQL ,它的適應性超乎你想象

相關文章