22

私の単純化された不自然な例は次のとおりです:-

世界中のすべての町の気温 (およびその他の値) を毎日測定して保存したいとしましょう。1 つの町のすべての気温を歴史的に取得するのと同じくらい簡単に、すべての町の現在の気温を取得できるように、データを保存する最適な方法を探しています。

解決するのは簡単な問題ですが、最善の解決策を探しています。

私が考えることができる2つの主なオプションは次のとおりです。

オプション 1 - 同じテーブルに現在のレコードと過去のレコードを格納

現在のレコードとアーカイブ レコードをすべて同じテーブルに格納します。

すなわち

CREATE TABLE [dbo].[WeatherMeasurement](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

これによりすべてがシンプルになりますが、町のリストと現在の気温を取得するための最も効率的なクエリは何でしょうか? テーブルに何百万行もあると、これはスケーリングされますか? テーブルに何らかの IsCurrent フラグを設定することで得られるものはありますか?

オプション 2 - すべてのアーカイブ レコードを別のテーブルに保存する

現在のライブ測定値を保存するテーブルがあります

CREATE TABLE [dbo].[WeatherMeasurement](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

そして、過去のアーカイブ日付を格納するテーブル (おそらくトリガーによって挿入されます)

CREATE TABLE [dbo].[WeatherMeasurementHistory](
  MeasurementID [int] Identity(1,1) NOT Null,
  TownID [int] Not Null,
  Temp [int] NOT Null,
  Date [datetime] NOT Null,
)

これには、スキーマがより複雑になり、データの挿入にかかるコストが高くなるという犠牲を払って、メインの現在のデータをスリムに保ち、クエリを非常に効率的に行うという利点があります。

最良の選択肢はどれですか? 私が言及していないより良いオプションはありますか?

注: 質問に的を絞るためにスキーマを単純化しましたが、毎日大量のデータ (100,000 レコード) が挿入され、データは 1 日分最新のものであると想定しています。現在のデータは、過去のデータと同じようにクエリされる可能性があります。

4

8 に答える 8

13

それはアプリケーションの使用パターンに依存します...使用パターンが履歴データが現在の値よりも頻繁にクエリされることを示している場合は、それらすべてを1つのテーブルに入れます...しかし、履歴クエリが例外である場合(またはそれより少ない場合)クエリの 10%)、より一般的な現在の値のクエリのパフォーマンスは、すべてのデータを 1 つのテーブルに配置すると低下します。その場合、そのデータを独自のテーブルに分離することは理にかなっています...

于 2008-11-17T16:23:54.390 に答える
5

現在のデータ (使用状況) または履歴データ (量) に非常に深刻なバイアスがない限り、データを 1 つのテーブルに保持します。DATE + TOWNID を (この順序で) 含む複合インデックスを使用すると、ほとんどの場合、パフォーマンスの問題が解消されます (ただし、現時点でこれを確認できるデータがないことは明らかです)。

私が疑問に思っていることの 1 つは、誰かが町の現在のデータと履歴データの両方からのデータを必要とするかどうかということです。もしそうなら、少なくとも 1 つの新しいビューを作成しただけであり、その方向でパフォーマンスの問題が発生する可能性があります。

残念ながら、これは現実世界のデータに対してソリューションをプロファイリングする必要がある場合の 1 つです。私は個人的に上記のような複合インデックスを多くの場合に使用してきましたが、履歴を別のテーブルに分割することを選択したエッジケースがいくつかあります。実際には別のデータ ファイルです。問題は、履歴が非常に密集していたため、プライマリ データ ファイル セット全体が肥大化するのを避けるために、その履歴専用の新しいデータ ファイルを作成したことです。パフォーマンスの問題が理論によって解決されることはめったにありません。

インデックスの使用についてはクエリのヒントを読んで、パフォーマンスの問題の詳細については「インデックスをカバーする」ことをお勧めします。

于 2008-11-17T16:30:11.507 に答える
3

あなたのテーブルは非常に狭く、適切にインデックスが作成された単一のテーブルでおそらくパフォーマンスが向上し、従来の正規化された OLTP モデルでは、数百万行であっても SQL Server の容量を超えることはありません。デュアル テーブル モデルの場合でも、SQL Server でテーブル パーティション分割を使用することで利点を軽減できます。そのため、単一テーブル モデルよりも推奨することはあまりありません。これは、Inmon スタイルまたは「エンタープライズ データ ウェアハウス」のシナリオです。

はるかに大きなシナリオでは、データをデータ ウェアハウス (Kimball スタイルの次元モデルでモデル化) に定期的に転送し、ライブ データを単純に消去します。あなたのようないくつかの単純なシナリオでは、実質的にライブ データがない可能性があります。それはすべて倉庫に直行します。次元モデルには、データをさまざまな方法でスライスし、さまざまな次元で膨大な数のファクトを格納する場合に多くの利点があります。データ ウェアハウスのシナリオでも、多くの場合、ファクト テーブルは日付によって分割されます。

データにこれが含まれているようには見えないかもしれません (Town と Date が唯一の明示的なディメンションです)。ただし、ほとんどのデータ ウェアハウスでは、ディメンションがスノーフレークまたは冗長性を持つ可能性があるため、ロード時に格納された事実に関する他のディメンションが存在します。 State、Zip Code、WasItRaining、IsStationUrban (不自然) など、より効率的なスノーフレークの代わりに。

これはばかげているように思えるかもしれませんが、データ ウェアハウスで結果を得るためにデータをマイニングし始めると、たとえば都市環境で雨が降った日のメイン州の平均気温は何度だったでしょうか? - たくさんのテーブルを結合しなくても、少し簡単に取得できます (つまり、正規化されたモデルについて多くの専門知識を必要とせず、非常に迅速に実行されます)。野球の役に立たない統計のようなものですが、明らかに有用であることが判明したものもあります.

于 2008-11-17T16:37:54.223 に答える
1

履歴データは同じ頻度でクエリされるため、同じテーブルに保持することをお勧めします。テーブルにさらに多くの列を追加しない限り。

サイズが問題になる場合は、10 年ごとにパーティション分割し、要求された行をストアド プロシージャ ユニオンに結合させることができます。

于 2008-11-17T16:20:29.563 に答える
1

もう 1 つの方法は、すべてのデータに対して 1 つのテーブルを使用し、現在の温度を表示することです。これはパフォーマンスには役立ちませんが、可読性/保守性を向上させる可能性があります。適切なバージョンの sql がある場合は、インデックス付きビューを使用してパフォーマンスを向上させることもできます。

于 2008-11-17T16:26:37.350 に答える
0

インデックス ビューを持つ単一のテーブルを使用して、最新の情報を提供します。SQL 2005 および 2008 サーバーはデータ ウェアハウジング用に設計されているため、この条件下でも適切に機能するはずです。

データベースに頻繁に書き込む必要があるデータ パターンがある場合、最適な選択は、一定の間隔でバッチ更新するアクティブなテーブルとアーカイブ テーブルを用意することです。

于 2008-11-17T16:37:27.717 に答える