web-dev-qa-db-ja.com

データベース設計:1つの巨大なテーブルまたは個別のテーブル?

現在、当社で使用するデータベースを設計しています。 SQL Server 2008を使用しています。データベースには、複数の顧客から収集されたデータが保持されます。データベースの目標は、複数の顧客の集計ベンチマーク数を取得することです。

最近、特に1つのテーブルが非常に大きくなるのではないかと心配になりました。各顧客には約20.000.000行のデータがあり、データベースにはまもなく30人の顧客が含まれます(それ以上ではない場合)。このテーブルでは多くのクエリが実行されます。私はすでにパフォーマンスの問題とユーザーが一時的にロックアウトされていることに気づいています。

私の質問ですが、将来このテーブルを処理できるようになるのでしょうか、それともこのテーブルを顧客ごとに小さなテーブルに分割する方がよいのでしょうか。


更新:最初にテーブルを作成してから約半年が経ちました。以下のアドバイスに従って、私はいくつかの巨大なテーブルを作成しました。それ以来、私は インデックスを使用して実験 であり、Enterprise Editionがあれば、テーブルをパーティション分割する最初の2つの列(病院コードと部門コード)のクラスター化インデックスを決定しました。ガルウェジアンが予測したように、この設定は最近まで問題なく機能し、パフォーマンスの問題が発生しています。インデックスの再構築には時間がかかり、ユーザーはお互いをロックアウトし、クエリは必要以上に時間がかかることがよくあります。ほとんどのクエリでは、最初にデータの関連部分を一時テーブルにコピーし、一時テーブルにインデックスを作成して実行することで成果が得られます。クエリ。これはあるべき姿ではありません。そのため、パーティションテーブルを使用するためにEnterpriseEditionの購入を検討しています。購入が完了できない場合は、 Standard Editionでパーティション分割を実行するための回避策 を使用する予定です。

25
thomaspaulb

1つの大きなテーブルから始めて、2008年のテーブルのパーティション分割機能を必要に応じて適用しますパフォーマンスが問題になる場合

17
Galwegian

データウェアハウスは大きいはずです(手がかりは名前にあります)。倉庫保管基準では、2,000万行はほぼ中程度ですが、6億行は大きいと見なすことができます。

覚えておくべきことは、そのような大きなテーブルはブラックホールのような異なる物理学を持っているということです。したがって、それらを調整するには、さまざまな手法が必要です。もう1つは、データウェアハウスのユーザーは、大量のデータを処理していることを理解する必要があるため、すべてのクエリに対して1秒未満(または実際には1分未満)の応答を期待してはなりません。

パーティショニングは、特にCUSTOMERのように明確な境界がある場合に役立ちます。パーティショニングは、パーティショニングキーの粒度を横切るクエリのパフォーマンスを低下させる可能性があることに注意する必要があります。したがって、それは特効薬ではありません。

7
APC

パフォーマンス上の理由でテーブルを分割することをシャーディングと呼びます。また、データベーススキーマは多かれ少なかれ正規化することができます。正規化されたスキーマには、それらの間の関係を持つ個別のテーブルがあり、データは複製されません。

6
Sjoerd

データベースが適切に正規化されていることを前提としています。 SQLServerの単一のテーブルで参照するデータ量を処理することは問題ではありません。私があなたがする必要があると思うのはあなたのインデックスを見直すことです。

3
Otávio Décio

質問に「データウェアハウス」のタグを付けたので、この件についていくつか知っていると思います。目標に応じて、スタースキーマ(ファクトとディメンションテーブルを備えた多次元モデル)を選択できます。変化の速いすべてのデータを1つのテーブル(サブジェクトごと)に保存し、変化の遅いデータを別のディメンション/「スノーフレーク」テーブルに保存します。

他のオプションは、DanLindstedtによるDataVaultメソッドです。これはもう少し複雑ですが、完全な柔軟性を提供します。

http://danlinstedt.com/category/datavault/

3
Ben Fransen

適切に設計されたデータベースでは、それは大量のレコードではなく、SQlサーバーは簡単に処理できるはずです。

通常、分割された単一のテーブルが最善の方法です。個別の顧客テーブルを維持しようとすると、時間と労力の点で非常にコストがかかり、エラーが発生しやすくなります。

また、パフォーマンスの問題が発生している場合は、現在のクエリを調べてください。適切なインデックス付けがない場合(たとえば、外部キーフィールドにインデックスを付けましたか?)、クエリは遅くなります。sargeableクエリがない場合は、相関サブクエリまたはカーソルを使用すると遅くなります。厳密に必要とされるよりも多くのデータを返していますか?プロダクションコードのどこかに*を選択した場合は、それを取り除き、必要なフィールドのみを返します。ビューを呼び出すビューを呼び出すビューを使用した場合、またはEAVテーブルを使用した場合は、このレベルでパフォーマンスが向上します。フレームワークにSQlコードの自動生成を許可した場合、クエリのパフォーマンスが低下する可能性があります。プロファイラーはあなたの友達であることを忘れないでください。もちろん、ハードウェアの問題も発生する可能性があります。その数のレコードには、かなり適切なサイズの専用サーバーが必要です。これをWebサーバーまたは小さなボックスで実行することはできません。

パフォーマンスチューニングの経験を持つプロのdbaを雇う必要があることをお勧めします。それはかなり複雑なものです。アプリケーションプログラマーが設計したデータベースは、実際の数のユーザーとレコードを取得すると、パフォーマンスが低下することがよくあります。データベースは、データの整合性、パフォーマンス、およびセキュリティを念頭に置いて設計する必要があります。あなたがそれをしなかったならば、それらを持っていることの変化は確かにスリムです。

3
HLGEM

パーティショニングは間違いなく調査すべきものです。 2つのテーブルがシャーディングされたデータベースがありました。各テーブルには、約3,000万から3,500万のレコードが含まれていました。それ以来、これを1つの大きなテーブルにマージし、いくつかの適切なインデックスを割り当てました。これまでのところ、このテーブルは扱いやすいのでパーティション化する必要はありませんでしたが、パーティション化を念頭に置いています。データがシャーディングされたときと比較して、私が気づいたことの1つは、データのインポートです。今は遅くなっていますが、インポートツールを書き直すことができるので、私はそれで生きることができます; o)

2
Neil Knight

1つのテーブルとテーブルパーティションを使用します。

与えられた情報に基づいて、NOLOCKを使用するというアドバイスは不当だと思います。 NOLOCKは、クエリから不正確で信頼性の低い結果を取得することを意味します(ダーティおよびファントム読み取り)。 NOLOCKを使用する前に、それが顧客にとって問題にならないことを確認する必要があります。

1
nvogel

これは単一のフラットテーブルですか(特定のモデルはありません)?通常、データウェアハウスでは、正規化されたデータモデル(少なくとも3番目の正規形-通常はエンティティリレーションシップモデル)またはディメンションデータ(キンボールメソッドまたはバリエーション-通常、一連のディメンションテーブルに関連付けられたファクトテーブル)があります。出演者)。

どちらの場合も、インデックスは大きな役割を果たし、パーティション化は、非常に大きなデータセットに対してクエリを実行する役割も果たします(ただし、パーティション化は通常、パフォーマンスではなく、メンテナンスによってパーティションをすばやく追加および削除できることです)。実際には、集計の順序とクエリの種類によって異なります。

1
Cade Roux

1つのテーブル、次にパフォーマンスについて心配します。つまり、顧客ごとにまったく同じ情報を収集していると仮定します。そうすれば、列を追加/削除/変更する必要がある場合、それを1か所で行うだけです。

0
brien

MS SQLサーバーを使用していて、単一のテーブルを保持したい場合は、テーブルのパーティション分割が1つの解決策になる可能性があります。

0
kragan

1つのテーブルを保持する-20M行は巨大ではなく、顧客は簡単に「アーカイブオフ」できる種類のテーブルではなく、複数のテーブルを検索して顧客を見つけるという略語は努力する価値がありません(SQLはあなた自身の発明よりもBTree検索ではるかに効率的である可能性が高い)

ただし、パフォーマンスとロックの問題を調べる必要があります。これにより、データベースのスケーリングが妨げられます。

0
StuartLC

一般的なクエリがある場合は、履歴情報についてすでに計算された詳細を保持する補足テーブルを作成することもできます。

0
Jacob G