2

エンティティのセットがあり、それぞれの状態がフリー、ビジー、または壊れていると想像してください。状態は1日指定されます。たとえば、今日の2011-05-17にはエンティティE1が空いていて、明日の2011-05-18には忙しいです。

1000日間で最大10^5のエンティティを保存する必要があります。そうするための最良の方法はどれですか?

私は2つのオプションについて考えています:

  • 毎日を文字「0」、「1」、または「2」として表し、すべてのエンティティに対して1000文字の文字列を格納します
  • エンティティの状態を1行に、つまりエンティティの場合は1000行で毎日保存します

このようなデータの最も重要なクエリは次のとおりです。指定された開始日と終了日は、どのエンティティが空いているかを識別します。

パフォーマンスはストレージよりも優先されます。

すべての提案やコメントを歓迎します。

4

6 に答える 6

3

最善の方法は、最初に単純で柔軟なオプションを試して(つまり、毎日独自の行に格納する)、パフォーマンスが不十分な場合にのみ高度な代替方法を考案することです。時期尚早の最適化は避けてください。

最近のコモディティサーバー上の平均的なデータベースでは、10^8行はそれほど大きな問題ではありません。日付にインデックスを付けると、範囲クエリ(「指定された開始日と終了日...」)が問題なく機能することは間違いありません。

これが1000文字の文字列を格納するという考えよりも単純で柔軟性があると私が主張する理由は、次のとおりです。

  • これをコードで処理する必要があります。そのコードは、日付とステータスを含むDBレコードをクエリするコードほど簡単に理解することはできません。
  • データベースエンジンによっては、1000文字の文字列がレコードの外部に格納されているblobである場合があります。そのため、効率が低下します。
  • 突然1,000日ではなく2,000日が必要になった場合はどうなりますか?すべての行とそれらを処理するコードの更新を開始しますか?これは、クエリを変更するだけではありません。
  • 次に、日次レコードごとに追加情報を保存するように求められた場合、または粒度を変更する必要がある場合(たとえば、日数から時間数に移動)はどうなりますか?
于 2011-05-17T13:22:27.687 に答える
2

データを保持する単一のテーブルを作成します。ID、日付、エンティティ名、および8つのブールフィールドを使用してテーブルを作成します。SQL Server 2008から、次のテーブルのコードが提供されました。

CREATE TABLE [dbo].[EntityAvailability](
[EA_Id] [int] IDENTITY(1,1) NOT NULL,
[EA_Date] [date] NOT NULL,
[EA_Entity] [nchar](10) NOT NULL,
[EA_IsAvailable] [bit] NOT NULL,
[EA_IsUnAvailable] [bit] NOT NULL,
[EA_IsBroken] [bit] NOT NULL,
[EA_IsLost] [bit] NOT NULL,
[EA_IsSpare1] [bit] NOT NULL,
[EA_IsSpare2] [bit] NOT NULL,
[EA_IsSpare3] [bit] NOT NULL,
[EA_IsActive] [bit] NOT NULL,
 CONSTRAINT [IX_EntityAvailability_Id] UNIQUE NONCLUSTERED 
(
    [EA_Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[EntityAvailability]') AND name = N'IXC_EntityAvailability_Date')
CREATE CLUSTERED INDEX [IXC_EntityAvailability_Date] ON [dbo].[EntityAvailability] 
(
    [EA_Date] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

日付のクラスター化されたインデックスは、範囲検索に最適です。日付範囲のない検索は絶対に許可しないでください。クラスター化されたインデックス以外のインデックスは必要ありません。ブールフィールドでは、1バイトのみを使用して8つの状況が可能です。このテーブルの行サイズは35バイトです。230行が1ページに収まります。10 ^ 5のエンティティを1000日間保存する必要があるとおっしゃいましたが、これは1億です。1億行は、434,7828Kページまたは約3ギガを占有します。

SSDにテーブルをインストールすると、準備が整います。

于 2011-05-18T16:27:57.503 に答える
1

エンティティがより頻繁に無料であるかどうかに応じて、エンティティが無料であるかどうかの日付を保存するだけです。

エンティティが空いていない日付を保存すると仮定すると、検索は開始日<=日付および終了日> =日付であり、エンティティがその期間中空ではないことを意味する行の一致です。

于 2011-05-17T13:00:35.517 に答える
0

あなたは正しい方向に進んでいるように思われます。レコードの数が非常に多く、パフォーマンスを重視しているため、スキーマを可能な限り非正規化しておくことをお勧めします。空きエンティティまたはビジーエンティティを判別するために必要な結合が少ないほど、優れています。

于 2011-05-17T13:04:42.483 に答える
0

私は広く、3つのテーブルを持つKimballスタースキーマ(http://en.wikipedia.org/wiki/Star_schema)タイプの構造を選びます(最初は)

  • FactEntity(FK kStatus、kDate)
  • DimStatus(PK kStatus)
  • DimDate(PK kDate)

これは非常に簡単にロードでき(最初にDims、次にFact(s))、非常に簡単に照会することもできます。適切なインデックス付けにより、パフォーマンスを最適化できます。

この設計の大きな利点は、非常に拡張性があることです。日付範囲を増やしたい場合、または有効な状態の数を増やしたい場合は、拡張するのは簡単です。

他のディメンションを適切に追加することもできます。たとえば、DimEntityは、エンティティをスライス/ダイスするのに興味深いカテゴリ情報を提供する、より豊富な情報を持つことができます。

DimDateは通常、DayNo、MonthNo、YearNo、DayOfWeek、WeekendFlag、WeekdayFlag、PublicHolidayFlagを追加することで強化されます。これらにより、いくつかの非常に興味深い分析を実行できます。

@Eladが尋ねているように、時間ベースの情報を追加した場合、これは1時間または1分に1つのレコードを持つDimTimeディメンションによって情報を提供することもできます。

私はあなたのデータをよく理解していないので、私の命名についてお詫び申し上げます。もっと時間があれば、もっと良いものを思いつくことができました!

于 2011-05-17T13:58:32.570 に答える
0

ここに画像の説明を入力してください

日付に無料のエンティティを取得するには、次のことを試してください。

select
      e.EntityName
    , s.StateName
    , x.ValidFrom
from EntityState as x
join Entity      as e on e.EntityId = x.EntityId
join State       as s on s.StateID  = x.StateID
where StateName = 'free'
  and x.ValidFrom = ( select max(z.ValidFrom)
                      from EntityState as z
                      where z.EntityID   = x.EntityID
                        and z.ValidFrom <= your_date_here )
;

注:状態の変更のみをEntityStateテーブルに保存するようにしてください。

于 2011-05-17T14:45:06.887 に答える