1

記事に関する情報を格納するコレクションがあります。コレクションはアーカイブ用であるため、読み取り専用です。現在、「title」と「page_length」の 2 つのフィールドのみが使用されています。最初に長い記事を取得することに常に関心があるため、次のインデックスを用意しています: { title: 1, page_length: -1}.

コレクションが非常に大きく、メモリに収まらないため、ソートがまだ遅いことがわかりました。

このコレクションで使用するほぼすべてのクエリで sort({page_length:-1}) が必要になると仮定すると、単純にレコードを page_length の降順でディスクに格納する方法はありますか? つまり、コレクション内の最初のレコードを最大の page_length 値にし、2 番目のレコードを 2 番目に大きい値にする簡単な方法はありますか?

そうすれば、並べ替えを実行することなく、 limit(n) を使用して最初の n レコードを取得できます。何か案は?


詳細情報の更新:

これを検索のオートコンプリート機能に使用しているため、速度が重要です。私が使用してきたクエリは次のようになります。

db.articles.find({"title": /^SomeKeyword/}).sort({page_length:-1})

挿入は問題ではないので、複数のインデックスを作成できてうれしいです。読み取り速度を最大化したいだけです。

編集:参考までに、私は実際に find().forEach() を使用してコレクション内のレコードを新しいコレクションに再編成することができました。次に、コレクションを検索し、並べ替えを必要とせずに最初の N 個の結果を取得しました。これは非常にうまく機能しました。私のデータセットは決して変更されないため、これはのみ機能することに注意してください。

4

2 に答える 2

1

インデックス{ title: 1, page_length: -1 }は、次のようなクエリには使用されません。

db.collection.find( {} ).sort( { page_length: -1 } );

MongoDB は左から右への複合インデックスのみを使用できるため、インデックスを使用するには、find または sort 引数として「タイトル」を指定する必要があります。

db.collection.find( { title: 'foo' } ).sort( { page_length: -1 } ); db.collection.find().sort( { title: 1, page_length: -1 } );

説明すると、次のことがわかります。

db.so.find( {} ).sort( { page_length: -1 } ).explain();

{
    "cursor" : "BasicCursor",
    …

インデックスを次のように変更した場合:

db.so.ensureIndex({ page_length: -1, title: 1 } );

次に、インデックスは並べ替えに使用されますが、ルックアップを実行するためだけにインデックスを使用することはできず、そのtitleために追加のインデックスが必要になります。本当にこれら 2 つのフィールドだけに関心があり、カバーされたインデックスを使用していることを確認する場合に役立ちます。複合インデックスを{ page_length: -1, title: 1 }使用する必要があり、射影を使用して使用することを確認できます。

db.collection.find( {}, { page_length: 1, title: 1, _id: 0 } ).sort( { page_length: -1 } );

しかし、MongoDB がディスクに物を格納する方法を決定したり、影響を与えたりすることはできません。

于 2013-08-01T16:52:43.653 に答える
0

2 つのクエリを使用するソリューションを考えることができます。

まず、カバーされたクエリを実行して、関心のあるドキュメントのリストを取得できます。次に、取得したドキュメントのリストと$in演算子を使用して、最終結果を取得できます。

対象となるクエリはメモリ内で (または少なくともディスク上で順次) 動作するため、高速である必要があり$in、インデックスを利用でき_id、妥当な数のドキュメントでかなり効率的である必要があります。

于 2013-08-01T16:29:33.523 に答える