web-dev-qa-db-ja.com

多くの列といくつかのテーブル-パフォーマンスの面で

はい、私はデータの正規化が(現状のまま)私の優先事項であることを認識しています。

  1. 列を持つ車両データを格納する65列のテーブルがあります:used_vehiclecolordoorsmileagepriceなど、合計65です。
  2. これで、分割してVehicleテーブル、VehicleInteriorVehicleExteriorVehicleTechnicalVehicleExtra(すべて1対メインのVehicleテーブルを含むもの)。

約500万行(車両)があるとします。

SELECTWHERE句を指定した場合:パフォーマンスの検索が向上します(どちらの場合も、少なくともIDsでインデックスが作成されます):

  1. Vehicleテーブル、65列または
  2. Vehicleに関連するすべてのデータを返すために、他の4つのテーブル(すべて500万行)にJOINSを含むVehicleテーブル

(データベースエンジンごとに、PostgreSQLやMySQLを検討してください)。

以前の経験から得られた詳細な洞察を本当に感謝しますか?

12
Urim Kurtishi

すべてのテーブル間の1対1の関係について話していると仮定します。

全体的なstorageは、実際には常に(実質的に)1つの複数のテーブルではなく単一のテーブルを使用する方が安価です。 1つの関係。各行には28バイトのオーバーヘッドがあり、通常は追加の埋め込み用にさらに数バイト追加されます。そして、すべてのテーブルにPK列を格納する必要があります。また、これらの各列に個別の(冗長)インデックスを設定します。サイズはパフォーマンスにとって重要です。

NULLストレージはvery安いであるため、ほとんどの行で多くの列がNULLの場合でもこれは当てはまります。

すべての列を取得する一方で、単一のテーブルは、5つのテーブルを結合するよりも大幅に高速です。 simpler。すべてのテーブルにすべての行が存在するわけではない場合、5つのテーブルを結合するのは難しいかもしれません。単一のテーブルをターゲットとするWHERE条件により、他のテーブルにLEFT JOINを追加するのは簡単です。複数のテーブルに述語がある場合、それほど簡単ではありません...

Vertical partitioningmayは、特定のクエリのパフォーマンスを向上させます。たとえば、クエリの90%が65の利用可能な列から同じ5つの列を取得する場合、これらの5つの列を保持するテーブルの方が高速です。

OTOH、あなたは index-only scans を許可する「カバーする」インデックスを使用して、いくつかの選択された列でそのようなクエリに応えることができるかもしれません。

垂直分割のもう1つの候補:ほんの数列に大量の更新があり、残りはほとんど変更されない場合。 Postgresは更新ごとに新しい行バージョンを書き込むので、そのような場合に行を分割する方がかなり安価になる場合があります。行外に格納された( "TOASTed")大きな値には例外があります。詳細:

それは本当に完全な状況に依存します。疑わしい場合は、単一のテーブルを使用するという単純な解決策を使用してください。特に、それが現実をよく表している場合はそうです。例では、これらはすべて車の属性であり、一緒に意味をなしています。

14

単一のテーブルでの選択は常に高速である必要があります。あなたがあなたの車を見つけたらすぐにあなたはすでにすべての詳細を持っています。

ただし、正規化の効率は失われます。たとえば、1台の車にさまざまなオプションのモデルが多数ある場合。

これはすべての車の参照データベースですか?または中古車のリスト?同じオプション/オプションを持つ同じメーカー/モデルの多くの例がありますか?

編集:私の回答は、postgres固有ではなく、一般的なrdbmsであると見なす必要があります。 @Erwinのpostgresに固有の詳細な回答に従います

0