2016-04-29 8 views
1

私は10億レコードを持つMongoDBコレクションを持っています。その15日間のSMSCノードからのログは、SMSCを介して送信されたすべてのSMSの配信ステータスを基本的に保持します。私はDateTimeフィルタに基づいてデータを選択するのに苦労しています。本当に遅いです。このコレクションから2週間以上のログを削除するためにレコードのチャンクを削除しようとすると、非常に遅くなります。削除クエリは文字通り終了しません。このすべてを言って、私が使用しているPCは、4GBのRAMを搭載したCore i7プロセッサを搭載したかなり一般的なデスクトップDell PCです。なにか提案を ?10億レコードのMongoDBコレクションを最適化して維持する方法は?

答えて

2

これらは、キーです:

は、クエリ結果の数が

使用突起が必要なデータのみ

使用$ヒントを返すように需要のネットワークを削減するためにクエリ

リミットをサポートするためのインデックスを作成します。特定のインデックスを選択する

インクリメント演算子を使用して演算を実行するサーバー側

あなたはで説明を見つけることができます:あなたは、文書の構造を投稿することができますhttps://docs.mongodb.org/manual/tutorial/optimize-query-performance-with-indexes-and-projections/

2

私は2つのことを推測します。まず、10億レコードの場合、私はあなたが重度にRAMが枯渇していると思っています。 MongoDBのパフォーマンスは、作業セットをメモリに残さないと崖から落ちます。少なくとも、あなたのインデックスが含まれています。しかし、優れたパフォーマンスを得るには、作業セット(たとえば、クエリが一般にそのドキュメントの何百万ものドキュメントを対象としている場合など、DBが日常的にアクセスするドキュメントの数)にも十分に含める必要があります。 10億レコードの小さなインデックス(_idフィールドのプライマリインデックスなど)でも4GBをはるかに超えます。

第2に、適切なインデックスをお持ちですか?そしてあなたのクエリはあなたのインデックスを使用していますか?タイムスタンプフィールドにインデックスを追加するだけでなく、クエリに使用するフィールド(タイムスタンプ以外の検索クエリにも削除クエリが含まれている場合など)が必要なようです。

最初の手順では、インデックスのサイズを取得することをお勧めします。これは、db.collection.stats().indexSizesと入力してmongoシェルで行うことができます。あなたが必要とする最小のRAMはあなたのインデックスサイズ+あなたのワーキングセットのためのある量です。

十分なRAMを確保したら、クエリでインデックスを使用していることを確認してください。 Mongoのexplain()機能を使ってクエリのクエリプランを見ることができます。実際にインデックスにヒットしているかどうか、またはMongoがバイパスして完全なドキュメント検索を行っているかどうかを調べることができます。

適切なインデックスを定義し、作業セット(インデックスと通常はアクセスするドキュメントのセット)を保持するのに十分なメモリがあり、クエリでインデックスが使用されていることを確認したら、シャーディングのような他の戦略に移行する。しかし、あなたの現在のコンピュータの統計情報(特に4GBのRAM)があれば、上記の最初のステップでは長い道のりを行くだろうと思う。

+0

ありがとうございました。以下のサンプルデータを投稿してください。 –

0

ここにコレクションのサンプルデータがあります。

サンプルデータ:

{ "_id":のObjectId( "56eacd643f8621ca653d5bf3")、 "ノード": "torsmsc11"、 "MESSAGE_ID": "1264F954"、 "CDR_TYPE":「初期MO "、 " SUB_TIME ":" 2016-03-17 08:59:50 "、 " DEL_TIME ":" 2016-03-17 08:59:50 "、 " OA_ADDR ":NumberLong(" 16477392921 ")、 "PRE_TRANS_OA":NumberLong( "16477392921")、 "DA_ADDR":NumberLong( "16472202975")、 "PRE_TRANS_DA":NumberLong( "16472202975")、 "ORIG_L OCN」:NumberLong( "161350003000")、 "ORIG_IDNT":NumberLong( "3024902")、 "DEST_LOCN": ""、 "UNKNOWN DEST_IDNT": "UNKNOWN"、 "SEG_NUM": "1の" 、 "DLV_ATT":0、 "END_POINT": "STORAGE"、 "FINAL_STATE": "DELIVERED"、 "CDR_TYPE2": "MO"、 "DCS":私が作成した0 }

これらのフィールドを持つユニークな複合インデックス:

MESSAGE_ID、CDR_TYPE、SUB_TIME、DEL_TIME、END_POINT

(マイクロソフトのBIツール)SSRSからこのクエリを実行する:

セレクトTOP * mycollectionから '2016年3月17日午前8時59分50秒' と「の間DEL_TIME 2016年3月17日9時59分1000 :50 '

1

文書の構造とインデックスに基づいて、インデックスがメモリに保持されていないと思われます。

mongoシェルでは、db.collection.stats().indexSizesと入力します。これにより、そのコレクションのすべてのインデックスのサイズがバイト単位で表示されます。その数値がRAMよりも大きい場合(実際には2GBを超えていても、おそらくスワップしています)、最初のステップでは、索引をメモリに保存するのに十分なRAMを追加します。

第2に、複合インデックスが必要ですか?つまり、これらのフィールドをすべて使用するクエリをたくさん実行していますか?それとも、一意性を確保するために行うのですか?すべての照会がDEL_TIMEフィールドにある場合は、そのフィールドに単純な索引を置くだけで、索引スペース要件が削減されます。

第3に、explain()オプションを使用してクエリを実行しましたか?これをmongoシェルで直接行う必要があります。クエリが実際にインデックスを使用しているかどうかがわかります。ちょうどクエリを見て、私はそれがする必要がありますが、あなたがチェックするまでわからないと思う。

関連する問題