0

私のデータ セットは、整数の配列を持つフィールドを含むドキュメントで構成されています。フィールドにある範囲の要素が含まれるオブジェクトを当てにしている場合、indexBounds の値が高いほどインデックス スキャンのパフォーマンスが低下するようです (ただし、範囲によってスキャンされる値の量は同じです)。

テストデータ:

for (var i = 0; i < 100000; i++) db.foo.insert({tts:(function(){var val = [];for(var j = 0; j < 100; j++) {val[j] = j} return val;})()});
db.foo.ensureIndex({tts:1});

クエリ:

> db.foo.find({tts:{$elemMatch:{$gte:10, $lte:10}}}).explain()
{
    "cursor" : "BtreeCursor tts_1",
    "isMultiKey" : true,
    "n" : 100000,
    "nscannedObjects" : 100000,
    "nscanned" : 100000,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 1,
    "nChunkSkips" : 0,
    "millis" : 313,
    "indexBounds" : {
        "tts" : [
            [
                10,
                10
            ]
        ]
    },
    "server" : "localhost:27017"
}
> db.foo.find({tts:{$elemMatch:{$gte:90, $lte:90}}}).explain()
{
    "cursor" : "BtreeCursor tts_1",
    "isMultiKey" : true,
    "n" : 100000,
    "nscannedObjects" : 100000,
    "nscanned" : 100000,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 1,
    "nChunkSkips" : 0,
    "millis" : 1286,
    "indexBounds" : {
        "tts" : [
            [
                90,
                90
            ]
        ]
    },
    "server" : "localhost:27017"
}

実際、このフィールドには 200 近くの値があり、要求された範囲が最高の境界を持つ場合、クエリは最大 10 倍遅くなります。(フィールドの各値は一意の範囲に属し、すべての範囲で同じ量のオブジェクト (100000) が選択され、クエリはこの範囲の部分範囲に対してのみ実行されます)

コレクション統計:

> db.foo.stats()
{
    "ns" : "test.foo",
    "count" : 100000,
    "size" : 122400128,
    "avgObjSize" : 1224.00128,
    "storageSize" : 140763136,
    "numExtents" : 12,
    "nindexes" : 2,
    "lastExtentSize" : 40071168,
    "paddingFactor" : 1,
    "systemFlags" : 1,
    "userFlags" : 0,
    "totalIndexSize" : 254845920,
    "indexSizes" : {
        "_id_" : 3262224,
        "tts_1" : 251583696
    },
    "ok" : 1
}

この問題の回避策はありますか?

ありがとう。

4

1 に答える 1

0

Mongo はインデックスを使用して、各ドキュメントに $lte および $gte 条件に一致する要素があることを判断できます。$elemmatch では、単一の要素が両方の条件に一致する必要があるため、mongo は各ドキュメント (およびサブ配列) をスキャンして、そのような要素が存在するかどうかを判断します。より大きな値の場合、mongo は一致する要素を見つけるために、最初の 10 個だけではなく、90 個の要素を各配列にスキャンする必要があります。したがって、長い配列の末尾にある要素に一致するクエリは、より時間がかかります。

配列を逆にすると、動作が逆になることに注意してください。

for (var i = 0; i < 100000; i++) db.foo.insert({tts:(function(){var val = [];for(var j = 100; j >= 0; j--) {val[j] = j} return val;})()});

これはhttps://jira.mongodb.org/browse/SERVER-6002に関連しているようです。最新の開発リリースを使用すると、安定性を犠牲にして問題を解決できる場合があります。

于 2012-07-11T05:39:03.477 に答える