43

パフォーマンスの向上を念頭に置いて、結合テーブル(特にRails 3 has_and_belongs_to_manyコンテキストで使用される)でどのインデックスが役立つかどうか疑問に思いました。

モデルとテーブルの設定

私のモデルはFooでありBar、レールの規則に従って、と呼ばれる結合テーブルがありますbars_foos。このテーブルbar_id:integerとの古いフィールドを作成する主キーまたはタイムスタンプはありませんfoo_id:integer。次のインデックスのどれが最適で、重複がないかを知りたいです。

  1. 複合インデックス:add_index :bars_foos, [:bar_id, :foo_id]
    • 2つのインデックス
    • A。add_index :bars_foos, :bar_id
    • B。add_index :bars_foos, :foo_id
  2. 1と2-Bの両方の組み合わせ

基本的に、最初から役立つと仮定すると、複合インデックスで十分かどうかはわかりません。複合インデックスは最初の項目の単一のインデックスとして使用できると思います。そのため、3行すべてを使用すると、不必要な重複が発生することは間違いありません

使用の可能性

最も一般的な使用法はモデルのインスタンスを与えられますFoo、私はモデルのインスタンスのためbarsにのRoR構文を使用して関連付けられていることを求めます。foo.bars逆もまた同様bar.foosですBar

SELECT * FROM bars_foos WHERE foo_id = ?これらは、タイプとのクエリをSELECT * FROM bars_foos WHERE bar_id = ?それぞれ生成し、それらの結果のIDをSELECT * FROM bars WHERE ID in (?)とに使用しSELECT * FROM foos WHERE ID in (?)ます。

私が間違っている場合はコメントで訂正してください。ただし、Railsアプリケーションのコンテキストでは、のような両方のIDを指定するクエリを実行しようとすることはないと思いますSELECT * FROM bars_foos where bar_id = ? AND foo_id = ?

データベース

データベース固有の最適化手法がある場合は、PostgreSQLを使用する可能性があります。ただし、このコードを使用している他の人は、Railsの構成に応じてMySQLまたはSQLiteで使用したい場合があるため、すべての回答を歓迎します。

4

2 に答える 2

35

答え

よく繰り返される答えは、常にそうなる傾向がありますが、「状況によって異なります」です。より具体的には、それはあなたのデータが何であるか、そしてそれがどのように使われるかによります。

tl;dr説明

私の特定のケース(および将来のすべてのベースをカバーするため)の短いtl; drの答えは、私が疑ったものである選択肢#2です。ただし、データの使用法によっては、複合インデックスの作成に使用される余分な時間とスペースによって、将来のクエリルックアップが減少する可能性があるため、選択肢3は問題なく機能します。

完全な説明

この理由は、データベースは、プログラマーの入力に関係なく、スマートになり、可能な限り高速に処理しようとするためです。インデックスを追加するときに考慮すべき最も基本的な項目は、このオブジェクトがこのキーによって検索されるかどうかです。はいの場合、インデックスはそれをスピードアップするのに役立つ可能性があります。ただし、このインデックスが使用されるかどうかは、すべて選択性とフィールドのカーディナリティに依存します。

通常、外部キーは別のARクラスのIDであるため、カーディナリティは通常高くなります。しかし、繰り返しますが、これはデータによって異なります。私の例では、sが多くてもFoosが少ない場合Bar、結合テーブルのエントリの多くに同様のが含まれますbar_id。カーディナリティbar_idが低い場合、インデックスonは使用されない可能性があり、新しいエントリが作成さbar_idれるたびにデータベースにこのインデックスへの追加に時間とリソース*を費やさせることで邪魔になる可能性があります。bars_foos同じことが、多くBarのsと少数Fooのs、および両方の少数にも当てはまります。

一般的な教訓は、テーブルのインデックスを検討するときに、エントリがこのフィールドで検索されるかどうか、およびこのフィールドのカーディナリティが高いかどうかを判断することです。つまり、このフィールドには多くの異なる値がありますか?ほとんどの結合テーブルの場合、「依存する」ため、データが何を表しているのか、および関係自体についてより慎重に考える必要があります。私の場合、私は多くのsとsの両方を持ち、それらに関連付けられたsでsを検索し、その逆も同様です。FooBarFoobar

私がオフィスで得たもう1つの良い答えは、「なぜインデックスについて心配しているのですか?アプリを作成してください!」でした。

脚注

* STIのインデックスに関する同様の質問で、インデックスのコストが非常に低いことが指摘されたため、疑わしい場合は追加するだけです。

于 2012-07-01T23:59:14.703 に答える
6

データのクエリ方法によって異なります。

これらすべてを検索したいとします...

  • WHERE bar_id = ?
  • WHERE foo_id = ?
  • WHERE bar_id = ? AND foo_id = ?

...次に、インデックスをオンにし、インデックスをオンにする必要があり{bar_id, foo_id}ます{foo_id}

に3番目のインデックスを作成することもできますが、追加のインデックスを維持することの代償は、小さいインデックスでのより良いクラスタリング{bar_id}の利点をおそらく上回ります。


また、クエリをインデックスでどのようにカバーする予定ですか?いくつかの選択肢、例えば...

  • {foo_id, bar_id}{bar_id}
  • {foo_id, bar_id}{bar_id, foo_id}

...特定の種類のクエリをより適切にカバーする可能性があります。

カバーすることはバランスをとる行為です-カバーする目的のためだけにインデックスにフィールドを追加することが正当化される場合もあれば、そうでない場合もあります。現実的な量のデータを測定するまではわかりません。

(免責事項:私はRubyに精通していません。この答えは純粋にデータベースの観点からのものです。)

于 2012-05-29T16:11:40.940 に答える