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


12

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

  1. 私は列の車両データを格納する65個の列を持つテーブルを持っている:used_vehiclecolordoorsmileagepriceなど、合計65インチ
  2. 今、私はそれを分割して持つことができるVehicleテーブル、VehicleInteriorVehicleExteriorVehicleTechnicalVehicleExtra(すべての一対一のメインとVehicleテーブル)。

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

SELECTでのWHERE句:パフォーマンスが(どちらの場合は、上の少なくともインデックスを付けて検索するほうが良いでしょうIDs):

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

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

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


1
あなたは、クエリを持っている場合は、1つの理由は、この(垂直分割)を行うことから、カラムとの契約VehicleInterior、他のクエリ、それだけの列との契約VehicleTechnicalなど、それとも多くの行/について全く情報を持っていない車がある場合(例えば)VehicleExtraので、代わりに、1テーブル内のヌルのたくさんの多くの行の、あなたは内のテーブルの残りの行と行が持っているVehicleExtra
ypercubeᵀᴹ

回答:


14

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

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

NULLストレージは非常に安価であるため、ほとんどの行で多くの列がNULLである場合も同様です。

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

垂直分割 により、特定のクエリのパフォーマンスが向上する場合があります。たとえば、クエリの90%が65の利用可能な列から同じ5つの列を取得する場合、これらの5つの列を保持しているテーブルの方が高速です。

OTOH、インデックスのみのスキャンを可能にする「カバーリング」インデックスを使用して、選択したいくつかの列でこのようなクエリに対応できる場合があります

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

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


何も選択しないと更新がほとんど行われず、検索結果リストのすべての列(車両の詳細ページ)とメイン情報(いくつかの列)が更新されます。実際、おそらく最良の解決策は2つのテーブルです。 )と残りの列を含む他のテーブル。したがって、この場合、SQL結合での500万行とは何ですか-パフォーマンスに関してはどうでしょうか。BTWあなたの詳細な努力に感謝します
Urim Kurtishi 2015

1
@octavius:結果リストのインデックスのみのスキャンを可能にするために、いくつかの列に複数列のインデックスを持つ単一のテーブルが最適なルートである可能性があります。(btreeインデックスでは列の順序が重要であることに注意してください。)結合はそれほど高価ではありませんが、結合を使用しなくても高速です。複数のテーブルの追加のストレージサイズとデータの分散により、速度が大幅に低下する場合があります(クエリごとに読み取るデータページが多くなります)。
Erwin Brandstetter、2015

1
Erwinsのコメントに同意しますが、その答えは実際には完全な状況または実際の使用法に依存します。クエリの90%がデータの小さなサブセットであり、パフォーマンスが絶対的に最優先であることがわかった場合、追加の労力を多くのテーブルに分割することを正当化する場合があるかもしれません。個人的には、データモデルをシンプルに維持しようとしています。また、どれくらいの速さで十分な速度ですか?最後のミリ秒を節約するためにどれだけの努力をしますか?データのモックアップとテストを試しましたか?
Swears-a-lot卿

@ErwinBrandstetterは、関係が1:1であると回答で述べました。1:Nリレーションシップはどうですか?
スリム

1:Nリレーションの場合は、とにかく2つの別々のテーブルが必要です。複数の行を配列またはドキュメントタイプに詰め込む場合を除きます。その後、状況によって異なります。ここで概説する原則は関係なく適用されます。アクセスパターンとインデックス戦略によって違いが生まれます。より具体的にしたい場合は、新しい質問をします。
Erwin Brandstetter 2018

0

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

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

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

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


2
「単一のテーブルでの選択は常により速くなるはずです。」どうして?
ypercubeᵀᴹ

VehiclemakeとVehicleModelは異なるテーブルであるため、VehicleテーブルにはVehiclemakeとVehicleModelの外部キーがあります。ここでは正規化が問題だとは思わない。私は、単一のテーブルの上に選択を理解するより速くなり、しかし、我々は多くの列と行が少ない列(ただし、いくつかのテーブル- 5彼らの加入で)を持つテーブルに対してなど、パフォーマンスに影響を与えるだろうか、異なる状況がある
ウリムKurtishi

申し訳ありませんが、メーカーとモデルがすでに分離されているという点を逃してしまいました。短いバージョンでは、データベースエンジンの結合に労力がかかります。単一のテーブル/行を使用する場合、すべてを単一の選択で取得するため、dbエンジンのI / Oとオーバーヘッドが少なくなります。
Swears-a-lot卿2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.