2

MongoDBのフィールドの一部、たとえば最初の10文字にのみインデックスを作成する方法はありますか?私はそれが文書化されているのを見つけることができませんでした(またはここで尋ねられました)。

MySQLに相当するものはですCREATE INDEX part_of_name ON customer (name(10));

理由:単一のフィールドの長さが数文字から1000文字を超え、平均50文字まで変化するコレクションがあります。1億ほどのドキュメントがあるため、完全なインデックスをメモリに収めるのは困難です(統計によると、データの8%でテストすると、インデックスはすでに400MBになっています)。フィールドの最初の部分だけにインデックスを付けると、インデックスサイズが約75%減少します。ほとんどの場合、検索語は非常に短く、全文検索ではありません。

回避策は、アイテムごとに10文字(小文字)の2番目のフィールドを追加し、それをインデックスに登録してから、検索語が10文字を超える場合に結果をフィルター処理するロジックを追加することです(大文字と小文字を区別する場合は、追加のフィールドが必要になる可能性があります)。 -誰かがより良い方法を持っていない限り、大文字と小文字を区別しない検索)。しかし、それを行うには醜い方法のようです。

[後で追加]

メインフィールドの最初の12文字を含む2番目のフィールドを小文字で追加してみました。それは大成功ではありませんでした。

以前は、オブジェクトの平均サイズは50バイトでしたが、_idやその他のオーバーヘッドを含めるのを忘れたため、メインフィールドの長さ(1つしかありませんでした)の平均は50バイトよりも30バイト近くになりました。次に、2番目のフィールドインデックスには_idとその他のオーバーヘッド。

最終的な結果(私の8%のサンプルの場合)は、メインフィールドのインデックスが415MBで、12バイトフィールドのインデックスが330MBです。スペースを20%節約するだけで、価値はありません。フィールド全体を複製することもできますが(大文字と小文字を区別しない検索の問題を回避するため)、現実的には、MongoDBがその仕事に適したツールであるかどうかを再検討する必要があるようです(または、より多くのメモリを購入して2倍のディスク容量を使用します)。

[後で追加]

これは典型的なドキュメントで、ソースフィールドと短い小文字のフィールドがあります。

{ "_id" : ObjectId("505d0e89f56588f20f000041"), "q" : "Continental Airlines", "f" : "continental " }

インデックス:

db.test.ensureIndex({q:1});

db.test.ensureIndex({f:1});

短いフィールドで機能する「f」インデックスは、「q」インデックスのサイズの80%です。インデックスに_idを含めたことを意味するのではなく、どこかでそれを使用して表示する必要があるということです。インデックスが指す場所なので、短いキーがほとんど違いをもたらさない理由を説明するのにおそらく役立つオーバーヘッドです。

インデックスへのアクセスは基本的にランダムであり、他のどの部分よりもアクセスされる可能性が高い部分はありません。フルファイルの合計インデックスサイズは5GBになる可能性が高いため、その1つのインデックスでは極端ではありません。他の検索ケース用に他のいくつかのフィールドとそれに関連するインデックス、および小文字用のデータのコピーを追加すると、合計が始まり、ページングとスワッピングの可能性が高くなります(8GBサーバーです)。簡潔なインデックス。

4

1 に答える 1

2

MongoDBには、フィールドの値の一部にインデックスを作成する方法がありません。提案したように、最善のアプローチは2番目のフィールドを作成することです。

とにかく大文字と小文字を区別しない効率的な検索には2番目のフィールドが必要になるため、作成しない理由は実際にはありません。

インデックスには、ドキュメントの「_id」フィールドは格納されません。インデックスには、はるかに低レベルの構造であるDiscLoc構造が格納されます。詳細については、こちらを参照してください。

また、「醜い」は実際には「関係的思考」の産物であることに注意してください。(私自身、長年のSQLユーザーとして、MongoDBの学習で最も難しいのは、リレーショナル思考を学習しないことです。)ドキュメント指向データベースでは、データの非正規化と複製は実際にはベストプラクティスです

于 2012-09-22T01:03:36.543 に答える