Mongodbプレミアム編-パフォーマンス最適化

6399 ワード

1、監視
mongodbはprofileでデータを監視し、最適化することができます.
現在profile機能用コマンドがオンになっているかどうかを確認します:db.getProfilingLevel()はlevelレベルを返し、値は0|1|2で、それぞれ意味を表します:0はオフを表し、1は記録スローコマンドを表し、2はすべてを表します.
開始プロファイル機能はdb.setProfilingLevel(level);levelが1の場合、スローコマンドのデフォルト値は100 ms、dbに変更されます.setProfilingLevel(level,slowms)例えばdb.setProfilingLevel(1,50)これで50ミリ秒に変更
dbを通過する.system.profile.find()現在のモニタリングログを表示します.db.system.profile.find({millis:{$gt:500}})を実行することによって、クエリ時間が500ミリ秒以上のクエリコマンドを返すことができる.
ここで値の意味は
ts:コマンド実行時間info:コマンドの内容query:クエリーorderを表す.order:クエリーを表すライブラリとコレクションreslen:返される結果セットサイズ、byte数nscanned:スキャンレコード数nquery:クエリー条件nreturned:レコード数と使用時間millisを返す
発見時間が長い場合は最適化が必要です.
たとえばnscannedの数が大きいか、レコードの総数に近い場合は、インデックスクエリが使用されない可能性があります.
reslenは大きく、不要なフィールドを返す可能性があります.
nreturnedは大きいので、クエリー時に制限がない可能性があります.
mongoはdbを通ることができます.serverStatus()mongodの運転状態の表示
2、索引
クエリ時間が比較的長い場合は、最適化が必要です.クエリー対象のフィールドにインデックスを作成することが優先されますが、インデックスは万能霊薬ではありません.コレクションデータの半分以上をクエリーする必要がある場合は、インデックスは従来のものに直接適用するほうがいいです.
インデックスの原理は、指定されたフィールドのBツリーを作成し、Bツリーを検索することで対応するdocumentのアドレスを検索することです.これは,集合データの半分以上をクエリーする必要がある場合,Bツリーを検索する過程を直接遍歴する必要がなく,かえって効率が高いことを説明している.
インデックスについては、インデックス列の粒子が小さいほど良いです.粒子が小さいほど良いとは何ですか.インデックス列内の各データの重複数は、パーティクルと呼ばれ、インデックスの基数と呼ばれます.データの粒子が大きすぎると、インデックスのパフォーマンスが発揮されません.たとえば、「age」列のインデックスがあります.「age」列で20歳が50%を占めている場合、「Tom」という20歳の人をクエリーする場合は、テーブルの50%のデータでクエリーする必要があります.インデックスの役割は大幅に低下します.したがって、インデックスを作成するときは、インデックスの左側にデータ粒子の小さい列をできるだけ配置して、インデックスが最大の役割を果たすことを保証します.
3、exlpainクエリーの実行状況
コマンドの実行:
> db.order.find({ "status": 1.0, "user.uid": { $gt: 2663199.0 } }).explain()
{
    "cursor" : "BasicCursor",#    
    "nscanned" : 2010000,#    
    "nscannedObjects" : 2010000,#    
    "n" : 337800,#    
    "millis" : 2838,#  
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {#    (    )
        
    }
}

これらの情報でクエリがどのように実行されるかを判断できます
4、データベース設計の最適化
プロジェクト設計の段階で、集合の用途を明確にすることは、パフォーマンスの最適化にとって非常に重要な一歩です.
パフォーマンスの最適化の観点から、セットの設計は、セット内のデータの一般的な操作を考慮する必要があります.たとえば、ログ(log)のセットを設計する必要があります.ログの表示頻度は高くありませんが、書き込み頻度は高いので、このセットでよく使われる操作は更新(削除)です.もし私たちが保存するのが都市リストだったら?このコレクションは、表示頻度が高いが、書き込み頻度が低いコレクションであることが明らかになり、クエリが一般的に使用されます.
頻繁に更新され、頻繁に検索される集合について、私たちが最も注目しなければならないポイントは、彼らのモデル化の程度です.現在、図書とその著者を保存する必要があると仮定すると、MongoDBでの関連は以下のいくつかの形式に反映されます.
1.完全分離(様式化設計)
例1:
View Code
{
     "_id" : ObjectId("5124b5d86041c7dca81917"),
     "title" : "    MongoDB", 
      "author" : [ 
               ObjectId("144b5d83041c7dca84416"),
              ObjectId("144b5d83041c7dca84418"),
              ObjectId("144b5d83041c7dca84420"),
     ]
 } 

著者(comment)のid配列をフィールドとして図書に追加した.このような設計方式は,非関係型データベースでよく用いられる,すなわち,我々が言うモデル化設計である.MongoDBでは、プライマリ・キーと直接関係のない図書を別のセットに個別に抽出し、プライマリ・キーを格納する方法で関連クエリーを行います.文章とコメントを検索するには、まず必要な文章を検索し、文章からコメントidを取得し、最後に完全な文章とそのコメントを使用する必要があります.この場合、クエリのパフォーマンスは明らかに理想的ではありません.しかし、ある著者の情報を修正する必要がある場合、モデル化されたメンテナンスの優位性が明らかになり、著者に関連する図書を考慮する必要がなく、著者のフィールドを直接修正すればよい.
2.完全インサート(逆パターン化設計)
例2:
View Code
{
       "_id" : ObjectId("5124b5d86041c7dca81917"),
       "title" : "    MongoDB",
       "author" : [
                {
                         "name" : "  "
                         "age" : 40,
                         "nationality" : "china",
                },
                {
                         "name" : "  "
                         "age" : 49,
                         "nationality" : "china",
                },
                {
                         "name" : "   "
                         "age" : 59,
                         "nationality" : "china",
                },
      ]
  }

この例では、著者のフィールドを完全に図書に埋め込み、検索時に直接図書を検索すると対応する著者のすべての情報を得ることができますが、1人の著者が複数の著作を持っている可能性があるため、ある著者の情報を修正する場合は、すべての図書を遍歴してその著者を見つけ、修正する必要があります.
3.部分インサート(折衷案)
例3:
View Code
{
       "_id" : ObjectId("5124b5d86041c7dca81917"),
       "title" : "    MongoDB",
       "author" : [ 
               {
                         "_id" : ObjectId("144b5d83041c7dca84416"),
                         "name" : "  "
                },
                {
                         "_id" : ObjectId("144b5d83041c7dca84418"),
                         "name" : "  "
                },
                {
                         "_id" : ObjectId("144b5d83041c7dca84420"),
                         "name" : "   "
                },
      ]
  }

今回は著者フィールドで最もよく使われる部分を抽出します.図書と著者名を取得するだけで、再び著者の集合に入って検索する必要はありません.図書の集合検索だけで取得できます.
この方法は、クエリーの効率と更新の効率を保証する相対的な折衷方法です.しかし、このような方法は明らかに前の2つよりも把握しにくい.難点は、実際のビジネスと結合して適切な抽出フィールドを探す必要があることだ.例3で説明したように、名前は明らかに頻繁に変更されるフィールドではありません.このようなフィールドは抽出すれば問題ありませんが、抽出されたフィールドが頻繁に変更されるフィールド(ageなど)であれば、このフィールドを更新する際には、広範囲に探して更新する必要があります.
上記の3つの例では、最初の例の更新効率が最も高かったが、クエリー効率が最も低く、2番目の例のクエリー効率が最も高く、更新効率が最も低かった.したがって、実際の作業では、テーブル内のフィールドを実際のニーズに合わせて設計し、最高の効率を得る必要があります.
5、その他の方法
ねつデータほう
データセットは非常に大きいかもしれませんが、これはそれほど重要ではありません.重要なのは、ホットデータセットがどれだけ大きいか、頻繁にアクセスするデータがどれだけ大きいか(頻繁にアクセスするデータとすべてのインデックスデータを含む)です.MongoDBを使用すると、あなたのホットデータがあなたのマシンのメモリサイズの下にあることを保証し、メモリがすべてのホットデータを収容できることを保証したほうがいいです.
ファイルシステムほう
MongoDBのデータファイルはプリアサイメントモードを採用しており、ReplicationではMasterとReplica Setsの非Arbiterノードが操作ログを格納するのに十分な空きファイルを事前に作成しています.これらのファイル割り当て操作は、一部のファイルシステムで非常に遅く、プロセスがBlockされる可能性があります.そのため、スペース割り当てが迅速なファイルシステムを選択する必要があります.ここでの結論は、できるだけext 3、ext 4またはxfsを使わないことです.
ハードウェアほう
ここでの選択にはディスクRAIDの選択が含まれ、ディスクとSSDの比較選択も含まれている.
その他
データファイルがシステムメモリより大きい場合、mongodbはメモリデータベースであるため、クエリー速度は数桁低下します.以前テストしたことがありますが、1000万のデータがインデックスされていない場合、クエリは数秒以上かかる可能性があります.
この場合、よくクエリーするアイテムにインデックスを作成したほうがいいです.インデックスがあると、クエリーの速度が非常に速くなります.
もう1つは、データインデックスがメモリより大きいと、速度が大幅に低下することです.また、マルチ条件クエリーの場合、クエリーの順序とインデックスの順序が異なる場合は、インデックスも使用できません.これは手探りで
replica setを使用すると、これは書き込み速度に影響し、3つのreplica setで、速度は3分の1に低下します.