いつ、なぜデータベースの結合は高価なのですか?


354

私はデータベースの調査を行っており、リレーショナルDBのいくつかの制限を見ています。

大きなテーブルの結合は非常にコストがかかると感じていますが、その理由は完全にはわかりません。結合操作を実行するためにDBMSは何をする必要がありますか?ボトルネックはどこですか?
非正規化はこの費用を克服するのにどのように役立ちますか?他の最適化手法(インデックス作成など)はどのように役立ちますか?

個人的な体験は大歓迎です!リソースへのリンクを投稿する場合は、ウィキペディアを避けてください。すでにどこにあるかは知っています。

これに関連して、BigTableやSimpleDBなどのクラウドサービスデータベースで使用される非正規化アプローチについて疑問に思っています。この質問を参照してください。


3
メリットも調べていますか?;)
David Aldridge、

私は客観的な(もしあれば)比較を検討しています。プロ、コン、何を持っていますか。
のRik

事前にレンダリングされたクラウドコンピューティングのアプローチは、「間違った結合」の問題を回避し、あらゆる方法で賭けることができることを前提としています。Googleは独自のシステムに関するいくつかのホワイトペーパーを持っています。かなり興味深い-特別なケースの適用性を拡張する方法。
Peter Wone 08年

@PeterWone-それらの論文のいくつかへの参照を提供することに気を付けていますか?あなたのプロフィールの質問に答えるためにpsは、Androidはオープンソースです-まあ、少なくとも部分的には、オタクはその流行に飛びついた。洗われていない偉大な人たちによって技術的に進んでいると見られ、彼らはGoogleのタイトで汗ばんだ抱擁にレミングのように続いた!ベータマックス誰か?MySQL(FOREGIN KEYs FFSなし)がPostgreSQL(ネイティブWindowsバージョンなし)やFirebird(Opensourcing fiasco)と競合した場合、どのようにしてMySQL(s FFS なし)が世界で最も人気のある「R」DBMSになった(そして残った)か、それともSQLite?
Vérace

言うまでもなく、私はPostgreSQLとFirebird はマルチユーザーシステムのMySQLよりもはるかに優れており、SQLiteはシングルユーザーの領域では優れていると考えています。SQLiteはsqlite.orgサイトを処理します(1日あたり400,00ヒット!)。
Vérace

回答:


470

パフォーマンスを改善するために非正規化しますか?説得力がありますが、水を保持しません。

テッドコッド博士と協力してリレーショナルデータモデルの最初の支持者であったクリスデイは、正規化に対する誤った情報に基づく議論に我慢できず、科学的手法を使用して体系的に破壊しました:彼は大規模なデータベースを取得し、これらの主張をテストしました

私は彼がそれを書いたと思うのリレーショナル・データベース・著作1988年から1991年が、この本は、後の版6に圧延したデータベースシステムに導入され、私が書くと可能性を維持するように、データベースの理論と設計上の決定的なテキストは第8版では、今後数十年間印刷されます。私たちのほとんどがまだ裸足で走り回っていたとき、クリス・デートはこの分野の専門家でした。

彼はそれを発見しました:

  • それらのいくつかは特別なケースを保持します
  • それらのすべては一般的な使用のために報われることに失敗します
  • それらすべては他の特別な場合には著しく悪い

それはすべて、ワーキングセットのサイズを軽減することに戻ります。適切に選択されたキーと適切に設定されたインデックスを含む結合は、ローがマテリアライズされるに結果を大幅にプルーニングできるため、安価で高価ではありません。

結果の具体化には、大量のディスクの読み取りが含まれます。これは、1桁の規模で最も費用のかかる作業です。対照的に、結合を実行するには、論理的にはキーのみの取得が必要です。実際には、キー値さえフェッチされません。キーハッシュ値は結合の比較に使用され、複数列の結合のコストを軽減し、文字列の比較を伴う結合のコストを大幅に削減します。キャッシュの適合性が大幅に向上するだけでなく、実行するディスクの読み取りが大幅に少なくなります。

さらに、優れたオプティマイザは、最も制限の多い条件を選択し、それを結合を実行する前に適用します。これにより、カーディナリティの高いインデックスでの結合の高い選択性が非常に効果的に活用されます。

確かに、この種の最適化は非正規化データベースにも適用できますが、スキーマを非正規化したい人は、通常、インデックスを設定するとき(ある場合)のカーディナリティについては考えません。

テーブルスキャン(結合を作成する過程でのテーブル内のすべての行の検査)は実際にはまれであることを理解することが重要です。クエリオプティマイザーは、次の1つ以上が成立する場合にのみテーブルスキャンを選択します。

  • リレーションの行数が200未満です(この場合、スキャンのほうが安くなります)
  • 結合列に適切なインデックスがありません(これらの列で結合することが意味がある場合、なぜインデックス付けされないのですか?修正してください)
  • 列を比較する前に型強制が必要です(WTF ?!修正するか、帰宅します)ADO.NETの問題に関するエンドノートを参照してください
  • 比較の引数の1つは式(インデックスなし)です

操作を実行することは、実行しないことよりもコストがかかります。ただし、誤った操作を実行し、無意味なディスクI / Oを強制し、本当に必要な結合を実行する前にドロスを破棄すると、はるかにコストがかかります。「間違った」操作が事前に計算され、インデックスが適切に適用されている場合でも、重大なペナルティが残ります。結合を事前計算するための非正規化は、更新の異常が伴うにもかかわらず、特定の結合への取り組みです。あなたが必要な場合は異なるが参加し、そのコミットメントは、あなたがコストに起こっている

世界が変わりつつあることを誰かに思い出させたいのであれば、グランティアハードウェア上のより大きなデータセットは、Dateの調査結果の広がりを誇張しているだけだと思います。

課金システムまたはジャンクメールジェネレーター(あなたに恥)に取り組んでいて、非正規化の方が速いという申し訳ありませんが、特別なものの1つに住んでいますケース-具体的には、すべてのデータを順番に処理するケース。これは、一般的なケースではありません、あなたがしているあなたの戦略に正当化。

あなたはされていない誤って、それを一般化して正当化。データウェアハウジングシナリオでの非正規化の適切な使用の詳細については、「メモ」セクションの最後を参照してください。

私も対応したいと思います

結合は、リップグロスを含む単なるデカルト製品です

なんと大量のボロック。制限はできるだけ早く適用され、最も制限が最初に適用されます。あなたは理論を読みましたが、あなたはそれを理解していません。結合は、クエリオプティマイザによってのみ「述語が適用れるデカルト積」として扱われます。これはシンボリック表現(実際は正規化)であり、シンボリック分解を容易にするため、オプティマイザは同等の変換をすべて生成し、コストと選択性によってランク付けして、最適なクエリプランを選択できます。

オプティマイザにデカルト積を生成させる唯一の方法は、述語を提供しないことです。 SELECT * FROM A,B


ノート


David Aldridgeがいくつかの重要な追加情報を提供します。

実際、インデックスとテーブルスキャン以外にもさまざまな戦略があり、最新のオプティマイザは実行プランを作成する前にそれらすべてにコストをかけます。

実用的なアドバイス:外部キーとして使用できる場合は、インデックスを作成して、オプティマイザがインデックス戦略を利用できるようにします。

以前は、MSSQLオプティマイザーよりも賢いものでした。これは2つのバージョン前に変更されました。今、それは一般的にに教えます。非常に現実的な意味では、エキスパートシステムであり、ルールベースのシステムが効果的であるほど十分に閉じているドメイン内の多くの非常に賢い人々のすべての知恵を成文化しています。


「Bollocks」は無傷だったのかもしれません。私は傲慢さが少なくなるように求められ、数学は嘘をつかないことを思い出します。これは真実ですが、数学モデルのすべての影響が必ずしも文字どおりに解釈されるべきではありません。負の数の平方根は、それらの不条理を慎重に調べることを避け(そこに駄目)、方程式を解釈する前にそれらをすべてキャンセルすることを確認する場合に非常に便利です。

私がひどく対応した理由は、言葉のとおり、

結合デカルト積です...

これは意図したものではないかもしれませんが、書かれたものであり、断固として真実でありません。デカルト積は関係です。結合は関数です。より具体的には、結合は関係値関数です。空の述語を使用すると、デカルト積が生成されます。生成されることをチェックすることは、データベースクエリエンジンの正当性チェックの1つですが、実際には制約のない結合は、教室の外には実用的でないため、誰も書き込みません。

モデルをモデル化されたものと混同するという古代の罠に読者が陥りたくないので、私はこれを呼び出しました。モデルは近似であり、操作を簡単にするために意図的に簡略化されています。


テーブルスキャン結合戦略の選択のカットオフは、データベースエンジン間で異なる場合があります。これは、ツリーノードのフィルファクター、キー値のサイズ、アルゴリズムの微妙さなど、実装に関する多くの決定の影響を受けますが、大まかに言えば、高性能インデックス付けの実行時間はk log n + cです。C項は、主にセットアップ時間で構成される固定オーバーヘッドであり、曲線の形状は、nが数百になるまで(線形探索と比較して)利益を得られないことを意味します。


時々非正規化は良い考えです

非正規化は、特定の結合戦略への取り組みです。前述のように、これは他の結合戦略に干渉します。しかし、ディスクスペースのバケット、予測可能なアクセスパターン、およびそのほとんどまたはすべてを処理する傾向がある場合、結合の事前計算は非常に価値があります。

操作で通常使用するアクセスパスを把握し、それらのアクセスパスのすべての結合を事前計算することもできます。これは、データウェアハウスの背後にある前提です。または、少なくとも、流行語のコンプライアンスのためだけでなく、自分たちがしていることをしている理由を知っている人々によって構築されている場合です。

適切に設計されたデータウェアハウスは、正規化されたトランザクション処理システムからの一括変換によって定期的に生成されます。このように操作データベースとレポートデータベースを分離すると、OLTPとOLAP(オンライントランザクション処理、つまりデータ入力、およびオンライン分析処理、つまりレポート)の衝突をなくすという非常に望ましい効果があります。

ここで重要な点は、定期的な更新とは別に、データウェアハウスは読み取り専用であることです。これは、更新異常の問題を疑わしくします。

OLTPデータベース(データ入力が行われるデータベース)を非正規化するミスを犯さないでください。課金実行の方が高速かもしれませんが、そうすると更新の異常が発生します。Reader's Digestに送信を停止させようとしたことがありますか?

最近のディスク容量は安いので、気を付けてください。しかし、非正規化はデータウェアハウスの話の一部にすぎません。はるかに大きなパフォーマンスの向上は、事前に計算された積み上げ値から得られます。月次の合計などです。それは常にワーキングセットを削減することです。


型の不一致に関するADO.NETの問題

varchar型のインデックス付き列を含むSQL Serverテーブルがあり、AddWithValueを使用して、この列に対するクエリを制約するパラメーターを渡すとします。C#文字列はUnicodeであるため、推定されるパラメーターの型はNVARCHARとなり、VARCHARと一致しません。

VARCHARからNVARCHARへの変換は拡大変換であるため、暗黙的に行われますが、インデックス付けに別れを告げ、その理由をうまく調べてください。


「ディスクヒットをカウントする」(Rick James)

すべてがRAMにキャッシュされている場合は、JOINsかなり安価です。つまり、正規化によるパフォーマンスの低下はそれほどありません。

「正規化された」スキーマがJOINsディスクを頻繁にヒットするが、同等の「非正規化された」スキーマがディスクをヒットする必要がない場合、非正規化はパフォーマンスの競争に勝ちます。

元の作者からのコメント:現代のデータベースエンジンは、アクセスシーケンスの編成に非常に優れており、結合操作中のキャッシュミスを最小限に抑えます。上記は真実ではありますが、大規模なデータでは結合が必然的に問題としてコストがかかることを意味すると誤解される可能性があります。これは、経験の浅い開発者の意思決定を悪化させることになります。


7
これらのステートメントのソンメは、特定のDBMSに固有のものではありませんか。例えば。「関係の行数は200未満です」
David Aldridge

2
代理キーの使用は、これらすべてに大きく影響しますか(または影響しませんか)?
David Plumpton、

3
優れたEF Coddは、リレーショナルモデルの責任者です。CJデートと最近ではHダーウェンはどちらも馬鹿であり、RMを理解しておらず、RMを「改善する方法」に関する大量の情報を提供しています。 。それらは、「欠けている」何かがあることを示唆することによって、RMの関連性を損なうことにのみ役立ちます。
PerformanceDBA

7
また、多くのNoSQLデータベースは、基本的に 40年前に破棄したデータベースと同じであることを忘れないでください。若い人たちはいつも何か新しいものを発見したと思っています。Fabian Pascal:dbdebunk.com/2014/02/thinking-logically-sql-nosql-and.html
N West

3
積極的。それは良い説明でしたが、攻撃性とマイクロ攻撃性はコンテンツやコンテンツの価値に追加されません。
MrMesees

46

ほとんどのコメンテーターが注意を怠っているのは、複雑なRDBMSで利用できる幅広い結合方法論であり、非正規化者は、非正規化データを維持するためのより高いコストを常に意識しています。すべての結合がインデックスに基づいているわけではなく、データベースには、結合コストを削減することを目的とした、結合のための最適化されたアルゴリズムと方法論がたくさんあります。

いずれにせよ、結合のコストはそのタイプと他のいくつかの要因に依存します。それはまったく高価である必要はありません-いくつかの例。

  • バルクデータが等結合されるハッシュ結合は、実際には非常に安価であり、ハッシュテーブルをメモリにキャッシュできない場合にのみコストが大きくなります。インデックスは必要ありません。結合されたデータセット間の等分割は、非常に役立ちます。
  • ソートとマージの結合のコストは、マージではなくソートのコストによって決まります。インデックスベースのアクセス方法では、ソートのコストを実質的に排除できます。
  • インデックスのネストされたループ結合のコストは、Bツリーインデックスの高さとテーブルブロック自体のアクセスによって決まります。高速ですが、バルク結合には適していません。
  • クラスターに基づくネストされたループ結合は、結合行ごとに必要な論理IOが少ないため、はるかに安価です。結合されたテーブルが両方とも同じクラスターにある場合、結合は結合された行のコロケーションによって非常に安価になります。

データベースは結合するように設計されており、結合方法に非常に柔軟性があり、結合メカニズムを間違えない限り、一般的に非常に高いパフォーマンスを発揮します。


「疑わしい場合は、DBAにお尋ねください」と思います。最新のデータベースは複雑な獣であり、理解するには研究が必要です。私は1996年以来Oracleを使用していますが、これは新機能に対応するフルタイムの仕事です。SQLserverも2005年以降、大きな進歩を遂げています。これはブラックボックスではありません。
ガイ

2
うーん、私の謙虚な経験では、ハッシュ結合について聞いたことがない、または普遍的に悪いことだと思っているDBAが多すぎます。
David Aldridge、

28

質問全体は誤った前提に基づいていると思います。大きなテーブルでの結合必ずしも高価ではありません。実際、効率的に結合を行うことが、リレーショナルデータベースが存在する主な理由の1つです。多くの場合、大きなセットの結合にはコストがかかりますが、大きなテーブルAのコンテンツ全体を大きなテーブルBのコンテンツ全体と結合することはめったにありません。代わりに、各テーブルの重要な行のみが使用されるようにクエリを記述し、結合によって保持される実際のセットは小さくなります。

さらに、Peter Woneによって言及された効率があり、最終的な結果セットが具体化されるまで、各レコードの重要な部分のみをメモリに格納する必要があります。また、多くの結合を持つ大規模なクエリでは、通常、小さいテーブルセットから始めて、大きいテーブルセットまで作業を進め、メモリに保持されるセットをできるだけ長く保つようにします。

結合が適切に行われると、結合は通常、大量のデータを比較、結合、またはフィルタリングするための最良の方法です。


1
@joel。逆もまた真実です。大規模なデータセットの結合はコストがかかる場合があり、場合によっては必要になることもありますが、a)必要なIOとRAMを処理できること、およびb)あまり頻繁に実行しないことを除いて、あまり頻繁に実行する必要はありません。マテリアライズドビュー、レポートシステム、リアルタイムvs CoBレポートを検討してください。
ガイ

11

ボトルネックは、ほとんどの場合ディスクI / Oであり、さらに具体的には-ランダムディスクI / Oです(比較すると、シーケンシャルリードはかなり高速で、先読み戦略でキャッシュできます)。

結合により、ランダムなシーク増加する可能性があります-大きなテーブルの小さな部分を読んでいる場合 しかし、クエリオプティマイザーはそれを探し、それがより適切であると考える場合、それを順次テーブルスキャン(不要な行を破棄)に変換します。

単一の非正規化テーブルにも同様の問題があります-行が大きいため、単一のデータページに収まりません。別の行から遠くにある行が必要な場合(および行のサイズが大きいと行がさらに離れる)、ランダムI / Oが多くなります。繰り返しになりますが、これを回避するためにテーブルスキャンが強制される場合があります。ただし、今回は行サイズが大きいため、テーブルスキャンでより多くのデータを読み取る必要があります。さらに、1つの場所から複数の場所にデータコピーしていること、およびRDBMSにはそれだけ多くの読み取り(およびキャッシュ)機能があることを付け加えます。

2つのテーブルを使用すると、2つのクラスター化インデックスも取得します-通常、(挿入/更新のオーバーヘッドが少ないため)より多くのインデックスを作成でき、これによりパフォーマンスが大幅に向上します(インデックスが(比較的)小さいため、ディスクからすばやく読み取ることができるため) (またはキャッシュするのが安い)、そしてディスクから読み取る必要があるテーブル行の量を減らします)。

結合のオーバーヘッドは、一致する行を特定することによってのみ発生します。SQL Serverは、主にデータセットのサイズに基づいて、3つの異なるタイプの結合を使用して、一致する行を検索します。オプティマイザーが誤った結合タイプを選択した場合(不正確な統計、不十分なインデックス、または単にオプティマイザーのバグまたはエッジケースのため)、クエリ時間に劇的な影響を与える可能性があります。

  • ループ結合は、(少なくとも1つの)小さなデータセットに対してはかなり安価です。
  • マージ結合では、最初に両方のデータセットの一種が必要です。ただし、インデックス付きの列で結合する場合、インデックスは既にソートされているため、これ以上の作業は必要ありません。そうしないと、ソート時にCPUとメモリのオーバーヘッドが発生します。
  • ハッシュ結合には、メモリ(ハッシュテーブルを格納するため)とCPU(ハッシュを構築するため)の両方が必要です。繰り返しますが、これはディスクI / Oに関してはかなり高速です。ただし、ハッシュテーブルを保存するのに十分なRAMがない場合、SQL Serverはtempdbを使用してハッシュテーブルの一部と見つかった行を保存し、一度にハッシュテーブルの一部のみを処理します。すべてのものディスクと同様に、これはかなり遅いです。

最適なケースでは、これらはディスクI / Oを引き起こさないため、パフォーマンスの観点からは無視できます。

全体として、最悪の場合、x結合されたテーブルから同じ量の論理データを読み取る方が実際には高速です。同じ量の物理データを読み取るために、若干のオーバーヘッドが発生する可能性があります。

通常、クエリ時間はI / Oコストによって支配され、データのサイズは非正規化によって変更されないため(行のオーバーヘッドが非常にわずかです)、テーブルをマージするだけで得られるメリットはそれほど大きくありません。パフォーマンスを向上させる傾向がある非正規化のタイプ、IMEは、計算に必要な10,000行を読み取るのではなく、計算された値をキャッシュします。


ランダムシークの削減:良い点ですが、大きなキャッシュを備えた優れたRAIDコントローラーはエレベーターの読み取り/書き込みを実行します。
Peter Wone 2009年

3

テーブルを結合する順序は非常に重要です。データのセットが2つある場合は、クエリを作成して、クエリで処理する必要のあるデータの量を減らすために、最小のものが最初に使用されるようにします。

一部のデータベースではそれは重要ではありません。たとえば、MS SQLはほとんどの場合、適切な結合順序を認識しています。一部のユーザー(IBM Informixなど)では、順序によってすべての違いが生じます。


1
一般的に、まともなクエリオプティマイザーは、結合またはテーブルがリストされる順序の影響を受けず、結合を実行する最も効率的な方法を独自に決定します。
David Aldridge、

5
MySQL、Oracle、SQL Server、Sybase、postgreSQLなど。結合の順序は重要ではありません。私はDB2を使用してきましたが、私の知る限り、それらをどのような順序で配置してもかまいません。これは一般的なケースでは役に立ちません
Matt Rogish

NDBエンジンを使用したMySQLクラスタリング(確かにエッジケースであり、高度な開発者のみがNDBに近づく予定です)は結合順序を正しく推測しないため、結合されたほとんどのクエリに「USE INDEX」ステートメントを追加する必要があります。ひどく非効率的です。MySQLのドキュメントがそれをカバーしています。
joelhardi 2008年

@iiya、オプティマイザが何を選択するかを理解することは、テーブルの順序に関する一般化されたステートメントまたは「神話」よりも重要です。SQLの特定の癖に依存しないでください。RDBMSがアップグレードされると、動作が頻繁に変わるためです。Oracleはv7以降、動作を何度か変更しています。
ガイ

1
@マット私は、Oracle 9iが結合の順序を調整するだけで非常に異なる最適化とクエリプランを実行するのを見てきました。多分これはバージョン10i以降から変更されましたか?
カミロ・ディアス・レプカ、2009

0

結合の複雑性クラスを検討する場合、非正規化するか正規化するかを決定することは、かなり単純なプロセスです。たとえば、クエリがO(k log n)である場合、正規化を使用してデータベースを設計する傾向があります。ここで、kは目的の出力の大きさに相対的です。

パフォーマンスを非正規化して最適化する簡単な方法は、正規化構造への変更が非正規化構造にどのように影響するかを考えることです。ただし、非正規化された構造で処理するためにトランザクションロジックが必要になる場合があるため、問題が発生する可能性があります。

問題が広大であるため、正規化と非正規化の議論は終わりません。自然な解決策が両方のアプローチを必要とする多くの問題があります。

一般的なルールとして、私は常に再構築可能な正規化された構造と非正規化されたキャッシュを保存してきました。最終的に、これらのキャッシュは私の将来の正規化問題を解決するために私のお尻を保存します。


-8

他の人が言ったことを詳しく説明し、

結合は、リップグロスを含む単なるデカルト製品です。{1,2,3,4} X {1,2,3}は12の組み合わせを提供します(nXn = n ^ 2)。この計算されたセットは、条件が適用される基準として機能します。DBMSは、条件(左と右の両方が2または3の場合など)を適用して、一致する条件を提供します。実際にはより最適化されていますが、問題は同じです。セットのサイズを変更すると、結果のサイズが指数関数的に増加します。消費されるメモリとCPUサイクルの量はすべて指数関数的に影響を受けます。

非正規化するときは、この計算を完全に回避し、本のすべてのページに色付きの付箋を付けることを考えます。参照を使用せずに情報を推測できます。私たちが支払うペナルティは、DBMS(データの最適な構成)の本質を損なうことです。


3
-1:この投稿は、DBMSに結合を実行させる良い例です。DBMS設計者はこれらの問題を常に考え、compsci 101メソッドよりも効果的な方法を考え出すためです。
David Aldridge、

2
@David:そうですね。DBMSオプティマイザープログラマーは、いくつかのスマートCookieです
Matt Rogish

この答えは間違っています。クエリが正規化されたインデックス付きデータベースに対して実行され、あらゆる種類のフィルターまたは結合条件がある場合、オプティマイザはデカルト積を回避し、メモリ使用量とCPUサイクルを最小限に抑える方法を見つけます。実際にデカルト積を選択する場合は、正規化または非正規化されたデータベースで同じメモリを使用します。
rileymcdowell
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.