データベース設計:新しいテーブルと新しい列


38

(これはStackOverflowからここに再投稿することが提案されました)

現在、テーブルがあり、新しいデータ列の追加を開始する必要があります。すべてのレコードに(新しいデータ列を追加した後に新しいデータを使用する場合でも)データがあるわけではありません。だから、これは実際にはいくつかのデータ行の拡張であり、すべての行に適用できないため、これが新しいテーブルに適しているのだろうかと思っています。

言い換えると、これらの新しいデータ要素には多くの未使用の列があるため、新しいテーブルにより適しているようです。

最初の表はページビューの記録です(現在200万件の記録)

-id
- IPアドレス
-視聴回数
-created_atタイムスタンプ
-日付

すべてのIPアドレスについて、1日ごとに記録が作成され、1日あたりの時間ビューに連続したページビューが追加されます

追加のフィールドは、起点の追跡用です(つまり、google analytics source / medium / campaign)

すべての訪問がその情報を持っているわけではありません。Imは、行の約10%にデータがあると想定します(通常は最初の訪問時にのみ属性付けされるため)

データの主な用途は、人々の出身地を特定することです。これは、より頻繁に使用される可能性があります(それは、単一のテーブルに役立つようです)

フィードバックに感謝-必要に応じてさらに追加できます

回答:


29

取り組んでいるのは、垂直分割です。これは、パフォーマンスを向上させるための物理的なデータベース設計手法です。物理データベースの設計手法と同様に、その適用可能性は、最適化しようとしている特定のクエリと、この技術によって最適化されるかどうかによって異なります。論理的な観点から見ると、これらの新しいフィールドがエンティティの候補キーに依存している場合、それらはエンティティに属する事実です。最初に、これらの新しいフィールドが候補キーに機能的に依存していることを完全に理解し、実際に毎日のページビューに関する事実であることを確認する必要があります。もしそうであれば、それらを別のテーブルに分割することはパフォーマンスの最適化であり、パフォーマンスの目標を達成する場合にのみ行うべきです。

一般に、元のテーブルの他の列と頻繁に区別せずにこれらの新しい列をクエリする場合、垂直分割は便利です。既存のテーブルと同じPKを共有する別のテーブルにそれらの列を配置することにより、それらの新しい列が必要なときに直接クエリを実行し、この新しいテーブルのディスクごとにページごとにより多くの行があるため、スループットが大幅に向上します元のテーブルのすべての列がそれらの行に置かれないためです。ただし、元のテーブルの列と一緒にこれらの列を常にクエリする場合、それらを取得するには常に外部結合が必要になるため、垂直パーティションはあまり意味がありません。ディスク上のテーブルのページは、DBMSのバッファプールに個別に入力されますが、事前に結合されることはありません。そのため、データがバッファプールに固定されている場合でも、クエリの実行ごとにその結合が発生する必要があります。このシナリオでは、元のテーブルのNULLABLE列を作成すると、NULLの場合にDBMSストレージエンジンがそれらを効率的に格納し、取得時に結合する必要がなくなります。

あなたのユースケースは後者であり、元のテーブルにNULLABLEとして追加するのが道であるように思えます。ただし、データベース設計の他のすべてと同様に、それは依存します。正しい判断を下すには、予想されるワークロードと適切な選択が何に依存するかを知る必要があります。垂直分割の適切なユースケースの良い例の1つは、人の検索パネルです。この場合、アプリケーションには、検索したい人はめったに入力しない人に関する非常にまれなデータが入力されます。その情報を別のテーブルに入れると、パフォーマンスの良いオプションがいくつかあります。検索を記述して、2つのクエリを作成できます。1つは、メインの常に入力された情報(姓やssnなど)のみを使用して、そして、外部からは、検索が要求されたときにのみ、非常にまれにしか入力されない情報を結合します。または、外部結合が不要で実行されないことを特定のホスト変数セットに対して十分に認識できるため、DBMSオプティマイザーを利用できます。したがって、クエリを1つ作成するだけで済みます。

どのDBMSプラットフォームを使用していますか?プラットフォームがNULL列ストレージを処理し、クエリを最適化する方法、およびスパース列サポートの可用性(SQL Serverにはこれがあります)は、決定に影響します。最終的には、実稼働サイズのデータ​​とワークロードを備えたテスト環境で両方の設計を試して、どちらがパフォーマンス目標をよりよく達成しているかを確認することをお勧めします。


「ただし、元のテーブルの列と一緒にこれらの列を常にクエリする場合、それらを取得するために常に外部結合が必要になるため、垂直パーティションはあまり意味がありません」という意味がわかりません。 、セカンダリカラムが使用可能かどうかにかかわらずプライマリカラムが必要な場合にのみ外部結合を行う必要があります。そうでない場合は、INNER JOINを使用します。 )。
jmoreno

ここでのすべての助けに感謝します..私は実際にフィールドを追加していきましたが、これを熟考した後、私はすべてをよりよく識別するために他のテーブルをいくつか持つ必要があることを見ました。最終的に訪問者visitor_visits(visitor_idを持ち、ソースを含む)page_views(vistor_idとvisitor_visit_idを含む)になりました。どのpage_viewが訪問に起因するかを正確に知りたいので、そのリンクを追加しました。私は少しそれと
格闘しました

10

個人的には、既存のテーブルに列を追加することに傾注しています。新しいテーブルは実際には何も買わない:

  • 元のテーブルのNULL値はスペースを占有しないため、実際には多くのスペースを節約しません。新しいテーブルには何らかの節約を相殺する何らかの種類の識別子が必要です
  • あなたのクエリは、より複雑になって... where newcolumn is not nullとなりleft outer join

単一のテーブルでは、行サイズがページごとに異なる可能性があることを意味しますが、特にクラスター化インデックスが単調に増加する列(IDまたは日付/時刻)にある場合、これは既存のページの多くに影響しないはずです。


現在、テーブルは(説明に基づいて)幅が広くなく、このデータが幅を広げすぎないため、同意します。
HLGEM

4

あなたが提供した情報を与え、一般的な正規化だけを目標とすると、おそらくヌル値を許可する列を追加しますが、データをモデル化する最善の方法を知るためにデータがどのように使用されるかについて十分な情報を与えていませんです。

このデータの実際の使用方法に応じて、異なるデータモデルを検討することをお勧めします。このデータをレポート用に配置する場合は、特定のタイプのレポートでより効率的なディメンションモデルを検討する必要があります。たとえば、時刻分析は、日付と時間のディメンションが分割されている場合にうまく機能します。

「Xなどのキャンペーンからの訪問で最も人気のある時間帯」や「1時間あたりの訪問数が最も多いキャンペーンの日」などの分析的な質問に答える場合、単一のデータ時間列は機能しません。非常にうまく(ただし、これはリレーショナルモデルで分割することもできます)、IPアドレスをディメンションとして扱う場合が多くあります(おそらく、スノーフレークのある種の地理データ)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.