1

オンライン カレンダー アプリ (Google カレンダーや MS Outlook など)を作成していますが、基本的なビュー (日単位、週単位、月単位) をすばやくクエリできるようにデータを保存する方法がわかりません。

これを重複としてマークする前に、ここでいくつかのスレッドを読んだことを覚えておいてください。ほとんどの場合、「一般的な目的のために最適化するのは難しい」と言われています。私の場合、これはまだ質問されていない非常に具体的な目的であり、多くの開発者が [願わくば] 経験したことがある非常に具体的なタイプのデータです。

ビュー (日、週、月) 内にある行をすばやく取得する必要があるため、次のようになります。

[end date of row] >= [start date of query]
AND
[start date of row] <= [end date of query]

通常の b ツリー インデックスがこれに対してうまく機能しているとは思えませんが、誰かが SQL Server 2005 (およびおそらくそれよりも古いバージョン) で動作する巧妙なものを考え出したのではないかと思います。それらの数百。

また、繰り返し発生するイベント、それらを保存する方法にも興味がありますが、現在の計画では、常にそれらすべてを読み取り (「Is Recurring」によるインデックス)、SQL ではなくコードで最適化することです。時間の経過とともに非常に大きくなる可能性がある通常のイベントとは異なり、それらの数は膨大であってはなりません。

更新:これもこの質問に固有のものです。これはカレンダー アプリ用であるため、日付をタイムゾーン情報と共に保存する必要がありますが、クエリをタイムゾーン固有にすることはできません。カレンダー アプリを使用した経験がある場合は、私の言いたいことがわかるでしょう (そうでない場合は、ストアを UTC と言うだけです)。

4

2 に答える 2

1

しばらく前に、これに似たものを使用する必要がありました。それは緊急治療室のソフトウェアであり、多くの日付範囲とシフトの計算を行う必要があり、タイム ゾーンの問題に影響を受けることはありませんでした。最終的にやらなければならないことは、日付ごとに 6 つの列を格納することです。3 つの列 (Date、Date as int、time as int) を 1 回入力し、1 回は UTC として設定します。タイムゾーンの問題を回避するために、すべての計算は UTC を使用して行われます。必要に応じてタイムゾーン列を追加することもできます。

Date as datetime -- in the time zone entered - Used for display
UDate as a datetime -- The UTC version of the date.
            -- Used for display and some calculations
IntDate as int -- Date as an int YYYYMMDD so 20130417
IntUDate as int -- UTC date as an int.   
IntTime as int -- Time as an int HHMMSS.  
              -- So for 1:12:40 PM it would be 131240 and for 1:12:40 AM 
              -- it would be 11240.  Note only 5 places.
              -- May need to be decimal if you need more precision)
IntUTime as int -- Sames as IntTime but for the UTC datetime

時間列は必要ない場合があります。シフト計算のため、そうしました。必要に応じて列にインデックスを作成します。少なくとも IntDate 列と IntUDate 列。これらは整数であるため、インデックスは非常に高速になります。タイムゾーンの問題を回避するために、すべての計算は UTC 列を使用して行う必要があることに注意してください。表示は通常、Date 列で行われます。

次に日付テーブルを作成します。ここで認識しなければならないのは、この表はかなり狭く、数百年分の日付を入力できても、それほど大きな表にはならないということです。100 年あたり約 36525 行。インデックスを追加すると、非常に高速になります。

うちはこんな感じでした。

CREATE TABLE DateTable (
    [Date] Int PRIMARY KEY,
    [DayOfYear] smallint,
    [Month] tinyint,
    [Quarter] tinyint,
    [Year] smallint,
    [LeapYear] bit,
    [DaylightSavings] bit
    )

(Year、DayOfYear)、(Year、Month、Day)などのインデックスを使用します。必要なものは何でも。また、必要な他の列を追加することもできます。うるう年、休日、月の最初の日、月の最後の日などを言います。

特定の年/四半期のすべてをプルする必要がある場合は、日付テーブルに結合を追加すると、すべてが適切にインデックス化されます。

上記の例を使用すると、次のようなことができます。

SELECT *
FROM MyTable
WHERE EXISTS
    (SELECT 1 FROM DateTable
    WHERE DateTable.[Date] BETWEEN MyTable.UTCStartDate AND MyTable.UTCEndDate
    AND DateTable.[Date] BETWEEN @StartDate AND @EndDate)
于 2013-04-17T21:50:18.333 に答える