web-dev-qa-db-ja.com

年、月、週、日、時間ごとのSQLグループとSQLのパフォーマンスの比較

年から時間までの期間ごとに多数のレコードをグループ化するクエリを作成する必要があります。

私の最初のアプローチは、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)

私の懸念は、datebyフィールドのインデックスを効率的に使用できないため、group byでdatepartを使用すると、一定期間クエリを複数回実行するよりもパフォーマンスが低下することです。これが真実かどうかについての考えは?

ありがとう。

22
RSlaughter

パフォーマンスに関連するものと同様にMeasure

2番目のアプローチのクエリプランを確認すると、明らかな問題(事前に必要ではないことがわかっている場合の完全なテーブルスキャン)が事前にわかりますが、測定に代わるものはありません。 SQLパフォーマンステストでは、適切なサイズのテストデータを使用して測定を行う必要があります。

これは複雑なケースであるため、単一のクエリを実行する2つの異なる方法を単に比較するのではなく、反復クエリに対して単一のクエリアプローチを比較しているため、実際のパフォーマンスに環境の側面が大きな役割を果たす可能性があります。

具体的には

  1. 各呼び出しの待ち時間が1つの大きなクエリアプローチと比較して無駄になるため、アプリケーションとデータベース間の「距離」
  2. 準備済みステートメントを使用しているかどうか(各クエリでデータベースエンジンに追加の解析作業が発生する)
  3. 範囲クエリ自体の構築にコストがかかるかどうか(2の影響が大きいかどうか)
9
ShuggyCoUk

比較のフィールド部分に式を入力すると、テーブルスキャンが得られます

インデックスはdatepart(field)ではなくフィールドにあります。したがって、すべてのフィールドを計算する必要があります

6
Galwegian

さらにもう1つのテーブルに参加することによるパフォーマンスヒットに耐えることができる場合、奇妙に思えるかもしれませんが、うまく機能する提案があります。

平日、月、年などの列を持つALMANACを呼び出すテーブルを作成します。日付が会社の休日かどうかなど、日付の会社固有の機能の列を追加することもできます。以下で参照するように、開始タイムスタンプと終了タイムスタンプを追加することができます。

1日1行でうまくいくかもしれませんが、私がこれをしたとき、1日3シフトのシフトごとに1行で行くのが便利だとわかりました。そのレートでさえ、10年の期間は10,000行をわずかに超えていました。

このテーブルにデータを入力するSQLを作成すると、すべての日付指向の組み込み関数を使用して、作業を簡単にすることができます。クエリを実行する場合、日付列を結合条件として使用できます。または、範囲内のタイムスタンプを取得するための範囲を提供するために2つのタイムスタンプが必要な場合があります。残りは、他の種類のデータを扱うのと同じくらい簡単です。

5
Walter Mitty

これに似たことができます:

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
5
Mladen Prajdic

レポート作成の目的で同様のソリューションを探していたところ、 Group by Month(and other time periods) と呼ばれるこの記事に出会いました。日時フィールドでグループ化するためのさまざまな方法(良い方法と悪い方法)を示しています。間違いなく見る価値があります。

2
alextansc

信頼できる結果を得るためにベンチマークを行う必要があると思いますが、私見と私の最初の考えは、クライアントコードで行うよりもDBがそれを処理すること(2番目のアプローチ)がはるかに高速になることです。最初のアプローチでは、DBへの複数の往復がありますが、これははるかに高価になると思います。 :)

1

各行に日付および/または時間ディメンションへの外部キーがある次元アプローチ(これはWalter Mittyが提案したものに似ています)を見ることができます。これにより、これらの部分が事前計算されるこのテーブルへの結合により、非常に柔軟な集計が可能になります。これらの場合、キーは通常、YYYYMMDDおよびHHMMSSという形式の自然な整数キーであり、比較的パフォーマンスが高く、人間が読める形式です。

別の選択肢として、日付部分ごとに個別の式があるインデックス付きビューがあります。

または計算列。

しかし、パフォーマンスをテストし、実行計画を検討する必要があります...

1
Cade Roux