MongoDB学習報告(二)

8864 ワード

概要
MongoDBインデックス管理MongoDBクエリー最適化
MongoDBインデックス管理
  • 単一キーインデックスの各項目は、インデックスされたドキュメントの値
  • に対応する必要があります.
  • 複合インデックスは、各項目が複数のキーで結合されたインデックスである.複合インデックスのキーの順序が重要です.
  • 各インデックスはメンテナンスにコストをもたらし、1つのセットに10個のインデックスがある場合、書き込み操作のたびに10個のインデックスを更新するので、余分なインデックスがないことを保証します.
  • インデックスを使用するには、少なくともインデックスがメモリに格納されることを保証します.理想的な状態は、インデックスと使用中のセットがメモリに格納されることです.
  • の1つのセットで複数のインデックスを作成できますが、最も適切な1つのみが使用されます.$or例外(明確にする)
  • インデックス管理
    ≪索引の作成|Create Index|oem_src≫:索引の作成方法3.0の前にensureInde()メソッドを使用し、3.0の後にcreateIndex()を使用します.1昇順に指定する索引を作成します.降順に索引を作成する場合は-1を指定します.ドキュメントにネストされている場合は、サブドキュメントのインデックスを作成できます.大きなデータセットに対応して、インデックスの構築に数時間または数日かかる場合があります.background項目では、インデックスの作成をバックグラウンドで実行できます.
    #    ,     。
    db.user.createIndex({name: 1});
    #    
    db.user.createIndex({name: 1,age: -1});
    #    ,      
    {
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
    }
    #     ,       address     ,   address city     
    db.user.createIndex({address.city: 1});
    #        
    db.user.createIndex({name: 1,age: -1},{background: true});
    

    検索インデックス:
     db.user.getIndexes();
    #  
    [
        {
            "v" : 1,
            "key" : {
                "_id" : 1
            },
            "name" : "_id_",
            "ns" : "test.user"
        },
        {
            "v" : 1,
            "unique" : true,
            "key" : {
                "name" : 1
            },
            "name" : "name_1",
            "ns" : "test.user"
        }
    ]
    

    索引の削除:dropIndex()指定された索引の削除、dropIndexes()すべての索引の削除、idを除く.
    #      name_1   
    db.user.dropIndex("name_1");
    #      
    db.user.dropIndexes();
    

    ユニークインデックス:作成方法、uniqueを設定します.ユニークインデックスは通常、データを挿入する前に作成されます.事前に作成すると、データの重複を回避してユニークインデックスの作成に失敗します.データが重要でない場合は、dropDupsオプションを使用して、データベースに自動的に重複ドキュメントを削除するように伝えます.
    #  name     ,
    db.user.createIndex({name: 1},{unique: true});
    #                     
    WriteResult({
        "nInserted" : 0,
        "writeError" : {
            "code" : 11000,
            "errmsg" : "E11000 duplicate key error collection: test.user index: name_1 dup key: { : \"lance\" }"
        }
    })
    #             
    db.user.createIndex({name: 1},{unique: true,dropDups: true});
    

    疎インデックス:インデックスはデフォルトで密集しています.つまり、インデックスのあるセットには、各ドキュメントに対応するインデックス項目があり、ドキュメントにインデックスキーがない場合、対応するインデックスにもnullの値があります.例えば、上記のユーザテーブルでは、ageのキーがないユーザがいる、ageのインデックスを作成すると、*db.user.find({age:null})*クエリーも、インデックスを使用して対応するユーザーにナビゲートできます.しかし、密なインデックスが適切でない場合があります.たとえば、次のような場合があります.
  • 商城の製品集合にはskuの一意コードがあり、skuキーに一意インデックスがあれば、skuのない製品を複数挿入すると、初めて成功し、その後は失敗します.一意インデックスにはskuがnullの項目を持っているからです.この場合、疎インデックスが必要です.
  • db.product.createIndex({sku: 1},{unique: true, sparse: true})
    
  • コメント機能user_idキーはインデックスを作成しますが、匿名のコメントは許可されます.この場合、集合内の大量のドキュメントuser_idのキーが存在しない場合、インデックスは大量のnullを持つアイテムがnullになり、インデックスのサイズが増加します.さらに重要なのはuser_です.idがnullのドキュメント書き込み操作の場合もインデックスが更新されます.匿名のユーザーをクエリーしない場合は、疎インデックスを使用する必要があります.
  • db.commons.createIndex({user_id}: 1},{sparse: true})
    

    マルチキーインデックス:MongoDBでは、インデックス内の複数のエントリが同じドキュメントを指すことができます.マルチキーインデックスはデフォルトでアクティブになります.インデックスキーが配列の各配列値であれば、インデックスに独自の位置があります.たとえば、記事セット内の各記事には複数のラベルがあり、配列tagsで記録されます.tagsキーにインデックスが確立されている場合、tagsの各配列値はインデックスに含まれます.
    {
        "title":    ,
        "tags":["mysql", "nosql", "nginx"]    
    }
    

    MongoDBクエリーの最適化
    ≪遅いクエリー|Low Query|emdw≫:オンにすると、文の消費量が予想を上回るかどうかを効果的に識別できます.Mongodbオープンスロークエリーでは、実行されたインスタンスでMongoDBに関する書き込み操作、カーソル、データベースコマンドなどを収集するProfilingツール、またはインスタンスレベルで開くことができます.このツールは収集したすべてをsystemに書き込む.profileはコレクションを固定し、コレクションサイズは固定され、最大デフォルト値を超えると古いレコードが上書きされます.
  • プロファイルのデフォルトオープンスロークエリー
  • を変更できます.
    #      ,       。profile      ,0   ;1        ,     ;2        。slowms     ,    ,  100ms
    profile=1
    slowms=200
    
  • 対応するデータベースでオープンコマンド
  • を直接実行する.
    #     ,        200ms     。       100ms。
    db.setProfilingLeve(1,200);
    #    
    { "was" : 0, "slowms" : 200, "ok" : 1 } 
    #           profile
    db.getProfilingLeve();
    
  • レコードを参照してください.詳細は、公式ドキュメント
  • を参照してください.
    #     
    db.user.find();
    #   system.profile  ,pretty     
    db.system.profile.find().pretty()
    {
        "op" : "query", #    , insert、query、update、remove、getmore、command   
        "ns" : "test.user", #     
        "query" : {  #    
            "find" : "user",
            "filter" : {
                
            }
        },
        "keysExamined" : 0,#      ,  3.2     nscanned
        "docsExamined" : 2, #      ,  3.2     nscannedObjects
        "cursorExhausted" : true,
        "keyUpdates" : 0,#          index    。              ,                   B-tree   。
        "writeConflicts" : 0,
        "numYield" : 0,
        "locks" : {  #   ,R:    ;W:    ;r:        ;w:        
            ......
        },
        "nreturned" : 2,  #      。   limit(n)     n   ,ntoreturn  n
        "responseLength" : 314,  #      ,     responseLength     .
        "protocol" : "op_command",
        "millis" : 106,    #     (  )
        "execStats" : {
            ......
        },
        "ts" : ISODate("2016-07-22T07:32:46.289Z"),#       
        "client" : "127.0.0.1",#  ip    
        "allUsers" : [
            {
                "user" : "lance",
                "db" : "admin"
            }
        ],
        "user" : "lance@admin" #  
    }
    
    #        ,"millis" : 13,keysExamined docsExamined   1。
    db.user.find({name:"lance"})
    

    遅いクエリーの分析:**EXPLAIN()の使用と理解**
  • 3.0以降は、explain()関数
  • を直接使用できます.
  • 3.0以降explainが変更され、3つのモードに分けられ、デフォルトqueryPlanner、executionStats、allPlansExecution
  • queryPlannerクエリー計画のセレクタは、まずクエリー分析を行い、最終的にwinningPlanを選択し、explainが返すデフォルトレベルです.
  • executionStatsは実行統計レベルでwinningPlanの統計結果
  • を返します.
  • allPlansExecutionは、rejectedPlan
  • を含むすべての実行計画の統計を返すために使用されます.
    db.test.find({name:'lance'}).explain()
    #  
    {
        "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "test.test", #       query     
            "indexFilterSet" : false, # query   indexfilter
            "parsedQuery" : {
                "name" : {
                    "$eq" : "lance"
                }
            },
            "winningPlan" : {  #        query               
                "stage" : "FETCH",#       stage,     FETCH,          index          (          )
                "inputStage" : { #     stage,     stage          。
                    "stage" : "IXSCAN", 
                    "keyPattern" : {
                        "name" : 1  #    index  
                    },
                    "indexName" : "name_1",
                    "isMultiKey" : false, #   Multikey,     false,       array ,    true
                    ......
                    "direction" : "forward", # query     ,   forward,    .sort({modify_time:-1})   backward
                    "indexBounds" : { #        ,          [MaxKey, MinKey],         mongodb chunck      ,      。
                        "name" : [
                            "[\"lance\", \"lance\"]"
                        ]
                    }
                }
            },
            "rejectedPlans" : [ ] #      (          reject )     
        },
        ......
    }
    
    db.test.find({name:'lance'}).explain('executionStats')
    {
        "queryPlanner" : {
            ...... 
        },
        "executionStats" : {
            "executionSuccess" : true, #      
            "nReturned" : 1, #           ,        
            "executionTimeMillis" : 0, #      
            "totalKeysExamined" : 1, #           
            "totalDocsExamined" : 1,#document    
            "executionStages" : {
                ......
            }
        },
        ......
    }
    

    **ステージのタイプの意味**
  • COLLSCAN:全表スキャン
  • IXSCAN:インデックススキャン
  • FETCH::指定document
  • をインデックスに基づいて取得する.
  • SHARD_MERGE:各スライス戻りデータによるmerge
  • SORT:メモリ内のソートが行われていることを示す(前期バージョンのscanAndOrder:trueと一致する)
  • SORT_MERGE:メモリに並べ替えてから
  • をマージすることを示します.
  • LIMIT:limit制限を使用した戻り数
  • SKIP:skipでスキップ
  • IDHACK:対象_idクエリー
  • SHARDING_FILTER:mongosによるスライスデータの照会
  • COUNT:dbを利用する.coll.count()などはcount演算
  • を行う.
  • COUNTSCAN:count Indexでcountを行わない場合のstageは
  • を返す.
  • COUNT_SCAN:count Indexを使用してcountを行う場合のstageは
  • を返します.
  • SUBPLA:インデックスに使用されていない$orクエリのステージは
  • を返します.
  • TEXT:全文インデックスを使用してクエリーを行う場合のステージは
  • を返します.