4

次の構造のテーブルがあります。

create table MyTable (
   ID int identity,
   Whatever varchar(100),
   MyTime time(2) not null,
   MyDate date not null,
   MyDateTime AS (DATEADD(DAY, DATEDIFF(DAY, '19000101', [MyDate]), 
                          CAST([MyDate] AS DATETIME2(2))))
)

計算列は、日付と時刻を 1 つの datetime2 フィールドに追加します。テーブルに対するほとんどのクエリには、次の句が 1 つ以上含まれています。

... WHERE MyDate < @filter1 and MyDate > @filter2
... ORDER BY MyDate, MyTime
... ORDER BY MyDateTime

簡単に言えば、通常、日付はフィルタリングに使用され、完全な日時はソートに使用されます。質問は次のとおりです。

  1. これらの3つの日時列にインデックスを設定する最良の方法は? 日付と時刻で2つ、または日付で1つ、複合日時で1つ、または何か他のものですか? このテーブルでは非常に多くの挿入と更新が行われるため、過剰なインデックス作成は避けたいと考えています。
  2. この質問を書いているときに、長くてちょっと醜い計算列の定義に気づきました。少し前にどこかから拾いましたが、もっと簡単な方法があるかどうかを調べるのを忘れていました。date と time2 を datetime2 に結合する簡単な方法はありますか? 単純な追加は機能しません。また、varchar へのキャスト、結合、キャストバックを避けるべきかどうかわかりません。
4

3 に答える 3

4

残念ながら、使用しているSQLServerのバージョンについては言及していませんでした...。

ただし、SQL Server 2008以降を使用している場合は、次のことを確認する必要があります。

あなたのテーブルは持っている必要があります

MyDateTime DATETIME

次に、「唯一の日付」列を次のように定義します。

MyDate AS CAST(MyDateTime AS DATE) PERSISTED

永続化するため、テーブルデータと一緒に保存され(クエリを実行するたびに計算されるようになります)、簡単にインデックスを作成できるようになりました。

同じことがMyTimeカラムにも当てはまります。

于 2012-10-13T14:39:47.633 に答える
2

日付と時刻が 2 つの別々の列にあるのは奇妙に思えるかもしれませんが、日付のみ (および/または特に時刻部分のみ) を使用するクエリがある場合、それは有効な決定だと思います。日付のみ、時間、または(日付など)などでインデックスを作成できます。

私が理解していないのは、計算された日時列もある理由です。この値を保存する理由もありません。必要なときに簡単に計算できます。

また、日時で注文する必要がある場合は、を使用できますORDER BY MyDate, MyTime。これにインデックスを(MyDate, MyTime)付ければ問題ありません。範囲日時クエリもそのインデックスを使用します。

于 2012-10-13T14:48:41.720 に答える
1

答えはインデックスではなく、クエリにあります。

単一のフィールドを使用する必要があります。アプリケーションで必要な日付と時間の範囲が提供されている場合DateTimeでも使用する必要があります。SmallDateTime

その列にインデックスを付けてから、次のようなクエリを使用します。

 SELECT * FROM MyTable WHERE
    MyDate >= @startfilterdate
    AND MyDate < DATEADD(d, 1, @endfilterdate);

終了フィルターを使用<することにより、ユーザーが選択した「終了日」の翌日である、その日付の午前 0 時より前の結果のみが含まれます。これは、23:59:59 と 00:00:00 の間のマイクロ秒が格納された時間に含まれる可能性があるため、23:59:59 を追加するよりも簡単で正確です。

それらに対して永続化された列とインデックスを使用すると、サーバー リソースが浪費されます。

于 2012-10-13T14:48:53.383 に答える