5

だから私は次のシャードキーを持つ私のデータベースにコレクションを持っています: {cl:"yyyy-mm", user_id:N}

次のクエリを実行すると

db.collection.find({ cl:"2012-03", user_id:{$in:users}, _id:{"$lt":new ObjectId('4f788b54204cfa4946000044')} }).sort({_id:-1}).limit(5).explain(true)

それは私にこの結果を与えます:

"clusteredType" : "ParallelSort",
"shards" : {
    "set1/hostname.com:27018" : [
        {
            "cursor" : "BtreeCursor cl_1_user_id_1 multi",
            "nscanned" : 21294,
            "nscannedObjects" : 21288,
            "n" : 5,
            "scanAndOrder" : true,
            "millis" : 1258,
            "nYields" : 69,
            "nChunkSkips" : 0,
            "isMultiKey" : false,
            "indexOnly" : false,
            "indexBounds" : { ...

では、インデックスを使用するように並べ替えるにはどうすればよいでしょうか。最後の 5 を返すためだけに、21288 個のドキュメントすべてをスキャンする必要はありません。

4

4 に答える 4

4

Dex をご利用いただきありがとうございます。

2013 年になっても遅くなければ、ここで scanAndOrder を回避するために推奨するインデックスは { _id: -1, cl: 1, user_id: 1 } です。

その理由は、_id の $lt と user_id の $in が複数のインデックス「バケット」にわたる範囲を構成するためです。上記以外の順序のインデックスは、_id の並べ替えを満たすために、それらのバケットをまとめて並べ替える必要があることを意味します。_id を最初に置くことで、インデックス内でアクセスされたすべてのドキュメントが事前に適切に並べ替えられます。

これは Andre の提案 ({ _id: -1, user_id: 1, cl: 1 }, これも scanAndOrder を回避する必要があります) よりもわずかに改善されていることに注意してください。これにより、cl に対する直接の等価性チェックで結果を切り捨てることができるからです。

詳細については、 http://blog.mongolab.com/2012/06/cardinal-ins/をご覧ください。

于 2013-08-07T21:15:30.530 に答える
3

を使用しているため、クエリから操作$ltを削除できるかどうかわかりません。scanAndOrder通常の公理は、インデックスの最後のメンバーとして並べ替えフィールドがあるということですが、これは、範囲クエリが行われている場所を壊します。これは通常、インデックスの順序を逆にして、並べ替えフィールドを最初のメンバーとして挿入することで解決できます。コレクションがシャードされているため、「逆順インデックス」よりも少なくともシャードキーインデックスを常に選択する可能性が高いため、あなたの場合には追加の問題があります。

データの分布を知らなければ、特定の行動方針を推奨することは困難です。私が行った簡単なテストから、インデックスを追加すると、 andが{cl:1,user_id:1,_id:-1}約半分になりました。これは、並べ替えフィールドをインデックスの最後のメンバーとして使用することになりますが、上記で説明した落とし穴があります。これの逆を試すこともできますが、シャード キーがそのインデックスより優先される場合があります。さらに、ヒントを使用して逆インデックスを強制することもできますが、これは私のテストではパフォーマンスの向上にはつながりませんでした。nscannednscannedobjects{_id:1,user_id:1,cl:-1}

于 2012-08-10T07:12:59.323 に答える
2

Dexを試して、インデックスが期待どおりに機能していることを確認してください:https ://github.com/mongolab/dex

于 2012-08-08T19:36:35.697 に答える
1

AFAIK、条件演算子 $gt、$lt など (mongo クエリの比較関数) により、mongo は(クエリのその部分に対して)インデックスをまったく使用しなくなります。そのようなクエリを実行するには、 Mongo はコレクション内のすべてのドキュメントをスキャンする必要があります。

したがって、この部分:

find({ cl:"2012-03", user_id:{$in:users}, _id:{"$lt":new ObjectId('4f788b54204cfa4946000044')} })

インデックスが存在しても使用しません。それはそれを遅くします。

クエリ内のUPDATE 条件演算子 $gt、$lt などはインデックスを使用できますが、インデックスを使用しない場合ほど効率的ではありません。それでも、mongodb は、結果として返されるドキュメントをさらにスキャンする必要があります。

于 2012-11-23T16:13:26.133 に答える