2012-04-11 11 views
2

私は非常に普通のMongoDBクエリを実行していますが、実際には複雑で特別なものは何もありません。MongoDBのクエリまたはインデックスを最適化する

この特定のクエリのインデックスを提供しました。explain()も使用されていますが、そのたびにコレクションのフルスキャンを行い、Webページ全体を1秒以上遅くします。

クエリ:

db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"}) 

を説明:

> db.tog_artikel.find({"art_filter":{"$exists":false},"$where":"this._id == this.art_hauptartikelnr"}).explain() 
{ 
    "cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1", 
    "nscanned" : 21306, 
    "nscannedObjects" : 21306, 
    "n" : 21306, 
    "millis" : 1180, 
    "nYields" : 0, 
    "nChunkSkips" : 0, 
    "isMultiKey" : false, 
    "indexOnly" : false, 
    "indexBounds" : { 
     "art_filter" : [ 
      [ 
       null, 
       null 
      ] 
     ], 
     "art_hauptartikelnr" : [ 
      [ 
       { 
        "$minElement" : 1 
       }, 
       { 
        "$maxElement" : 1 
       } 
      ] 
     ] 
    } 
} 

ランキング:

{ 
    "v": 1, 
    "key": { 
    "art_filter": 1, 
    "art_hauptartikelnr": 1 
    }, 
    "ns": "togshop.tog_artikel", 
    "background": true, 
    "name": "art_filter_1_art_hauptartikelnr_1" 
} 

フルコレクションがするたびにスキャンされ、なぜ? isMultiKeyがなぜfalseで、なぜこのクエリ/インデックスを最適化できますか?

環境がスタンドアロンサーバーであるフルコレクションがするたびにスキャンされ、なぜ、MongoDBの2.0.1、64ビットLinuxは、PHP-モンゴ/ wのPHPから1.2.6

答えて

7

にアクセスしましたか?

これはありません。インデックスを通過している:

"cursor" : "BtreeCursor art_filter_1_art_hauptartikelnr_1", 

これは、インデックス「art_filter_1_art_hauptartikelnr_1は」$は条件が存在する満たすために使用されることを意味します。

フィルタがあまり選択的でない場合(つまり、それを満たすレコードが多数ある場合)、クエリにはまだ多くの時間がかかります。

はなぜ

何のマルチキーインデックスが使用されなかったので、それが偽の偽isMultiKeyです。マルチキーインデックスは、配列を値として持つフィールドを含むインデックスです。複合インデックス(つまり、複数のフィールドを持つ)とは何の関係もありません。

$where":"this._id == this.art_hauptartikelnr" 

あなたの第2の条件は、Javascriptの式であり、(クエリアナライザは、あなたが何をしているかを理解していないので)インデックスは、ここで使用することはできません。 それがあっても、_idも含むインデックスが必要になります。

どのようにこのクエリ/インデックスを最適化できますか?

データを正規化して、値がtrueまたはfalseの新しいフィールド「idIsHauptArtikelNr」を持つようにします。 (art_filter、idIsHauptArtikelNr)にインデックスを作成し、とあなたのクエリを置き換える

{ art_filter :{ $exists :false}, idIsHauptArtikelNr : true } 
私はそれに追加します
+2

その$が、それはまだにBツリーのほとんどを歩く必要があり、これらの日のインデックスを使用しない存在するがそれを満足させる。言い換えると、1つのクエリで2つの最悪操作($ existsと$ where)をパフォーマンスの面で使用することができました。 –

+2

@RemonvanVliet:私はそれについて言及しようとしていましたが、$が存在すると考えました。偽でないインデックスでは効率的でなければなりません($が存在しますが、ツリーのほとんどは真でなければなりません)。 YMMVはデータスキューに依存する。 – Thilo

+1

非常に真です。 $ exists:falseは、ツリーウォークの早期終了による効率的なアプローチです。それにかかわらず、一般的には$が存在するのを避けるほうが良いと思いますが、どこでも可能です。) –

関連する問題