46

パラメータがクエリされるのと同じ順序で複合インデックスを作成する必要があります。この順序は、パフォーマンスに関してまったく重要ですか?

sex(99.9% の確率で「男性」または「女性」ですが、文字列 (バイナリではない)) と のインデックスを持つ、地球上のすべての人間のコレクションがあるとしnameます。

sex特定のを持つ特定のすべての人、たとえば"John"nameという名前のすべての「男性」を選択できるようにしたい場合、 first またはfirstを使用して複合インデックスを使用する方がよいでしょうか? なぜだめですか)?sexname

4

3 に答える 3

2

これについて私自身が実験を行ったところ、識別性の低いインデックス キーを最初に使用してもパフォーマンスが低下しないように思われることがわかりました。(私は、mmapとは異なる可能性があるwiretigerでmongodb 3.4を使用しています)。という新しいコレクションに 2 億 5000 万のドキュメントを挿入しましたitems。各ドキュメントは次のようになります。

{
    field1:"bob",
    field2:i + "",
    field3:i + ""

"field1"は常に に等しかった"bob""field2"に等しかったiので、完全に一意でした。最初に field2 を検索しましたが、2 億 5000 万のドキュメントをスキャンするのに 1 分以上かかりました。次に、次のようなインデックスを作成しました。

`db.items.createIndex({field1:1,field2:1})`

もちろん、フィールド 1 はすべてのドキュメントで "bob" であるため、インデックスは目的のドキュメントを見つける前に多数のアイテムを検索する必要があります。しかし、これは私が得た結果ではありませんでした。

インデックスの作成が完了した後、コレクションで別の検索を行いました。今回は、以下にリストした結果が得られました。"totalKeysExamined"毎回 1であることがわかります。おそらく、ワイヤード タイガーか何かを使って、これをよりうまく行う方法を見つけたのでしょう。私は、wiredtiger が実際にインデックス プレフィックスを圧縮することを読んだので、それが関係している可能性があります。

db.items.find({field1:"bob",field2:"250888000"}).explain("executionStats")

{
    "executionSuccess" : true,
    "nReturned" : 1,
    "executionTimeMillis" : 4,
    "totalKeysExamined" : 1,
    "totalDocsExamined" : 1,
    "executionStages" : {
        "stage" : "FETCH",
        "nReturned" : 1,
        "executionTimeMillisEstimate" : 0,
        "works" : 2,
        "advanced" : 1,
        ...
        "docsExamined" : 1,
        "inputStage" : {
            "stage" : "IXSCAN",
            "nReturned" : 1,
            "executionTimeMillisEstimate" : 0,
            ...
            "indexName" : "field1_1_field2_1",
            "isMultiKey" : false,
            ...
            "indexBounds" : {
                "field1" : [
                    "[\"bob\", \"bob\"]"
                ],
                "field2" : [
                    "[\"250888000\", \"250888000\"]"
                ]
            },
            "keysExamined" : 1,
            "seeks" : 1
        }
    }

field3次に、 (フィールド 2 と同じ値を持つ) にインデックスを作成しました。それから私は検索しました:

db.items.find({field3:"250888000"});

複合インデックスの場合と同じ 4ms かかりました。field2 と field3 の値を変えてこれを何度も繰り返しましたが、毎回わずかな違いしかありませんでした。これは、wiretiger を使用すると、インデックスの最初のフィールドの微分が不十分であってもパフォーマンスが低下しないことを示唆しています。

于 2017-07-10T21:03:30.843 に答える