簡體   English   中英

SQL組按年,月,周,日,小時SQL與程序性能

[英]SQL Group By Year, Month, Week, Day, Hour SQL vs Procedural Performance

我需要編寫一個查詢,按年度到小時的時間段對大量記錄進行分組。

我最初的方法是在C#中以程序方式決定周期,迭代每個周期並運行SQL以獲取該周期的數據,隨時構建數據集。

SELECT Sum(someValues)
FROM table1
WHERE deliveryDate BETWEEN @fromDate AND @ toDate

我后來發現我可以使用Year(),Month()Day()和datepart(week,date)和datepart(hh,date)對記錄進行分組。

SELECT Sum(someValues)
FROM table1
GROUP BY Year(deliveryDate), Month(deliveryDate), Day(deliveryDate)

我擔心的是,由於無法有效地使用datetime字段上的索引,因此在group by中使用datepart會導致比在一段時間內多次運行查詢更糟糕的性能; 有關這是否屬實的任何想法?

謝謝。

與任何與績效相關的措施一樣

檢查第二種方法的查詢計划將提前告訴您任何明顯的問題(當您不需要時可以進行全表掃描),但無法替代測量。 在SQL性能測試中,應使用適當大小的測試數據進行測量。

由於這是一個復雜的案例,您不是簡單地比較兩種不同的方式來執行單個查詢,而是將單個查詢方法與迭代方法進行比較,您的環境方面可能在實際性能中起主要作用。

特別

  1. 應用程序和數據庫之間的“距離”,因為與一個大查詢方法相比,每個調用的延遲將浪費時間
  2. 是否使用預准備語句(在每個查詢上導致數據庫引擎的額外解析工作)
  3. 范圍查詢本身的構造是否代價高昂(受2的影響很大)

如果將公式放入比較的字段部分, 則會進行表掃描

索引在字段上,而不是在datepart(字段)上, 因此必須計算所有字段 - 所以我認為你的預感是正確的。

你可以做類似的事情:

SELECT Sum(someValues)
FROM 
(
    SELECT *, Year(deliveryDate) as Y, Month(deliveryDate) as M, Day(deliveryDate) as D
    FROM table1
    WHERE deliveryDate BETWEEN @fromDate AND @ toDate
) t
GROUP BY Y, M, D

如果你能夠容忍加入另一張桌子的表現,我有一個看似奇怪的建議,但效果很好。

創建一個我稱之為ALMANAC的表,其中包含工作日,月,年等列。 您甚至可以為日期的公司特定功能添加列,例如日期是否為公司假日。 您可能希望添加開始和結束時間戳,如下所述。

雖然你可能每天都有一排,但是當我這樣做的時候,我覺得每班一排很方便,一天有三班。 即使按照這個速度,十年的時間也只有一萬多排。

當您編寫SQL來填充此表時,您可以使用所有面向日期的內置函數來使工作更輕松。 當您進行查詢時,可以使用日期列作為連接條件,或者您可能需要兩個時間戳來提供范圍以捕獲范圍內的時間戳。 其余部分與使用任何其他類型的數據一樣簡單。

我正在尋找用於報告目的的類似解決方案,並且遇到了這篇名為“ 按月分組”(以及其他時間段)的文章 它顯示了按日期時間字段分組的各種方式,無論好壞。 絕對值得一看。

我認為你應該對它進行基准測試以獲得可靠的結果,但是,恕我直言和我的第一個想法是讓DB處理它(你的第二種方法)會比你在客戶端代碼中做得快得多。 使用您的第一種方法,您可以多次往返數據庫,我認為這將更加昂貴。 :)

您可能希望查看維度方法(這與Walter Mitty建議的相似),其中每一行都有一個日期和/或時間維度的外鍵。 這允許通過連接到該表進行非常靈活的求和,其中這些部分是預先計算的。 在這些情況下,密鑰通常是YYYYMMDD和HHMMSS形式的自然整數密鑰,其相對高性能且人類可讀。

另一種替代方案可能是索引視圖,其中每個日期部分都有單獨的表達式。

或計算列。

但必須測試性能並檢查執行計划......

暫無
暫無

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

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