書き込み負荷の高いワークロードに対してMongoDBを最適化するには:

  • 書き込みを均等に分散するシャードキーを選ぶ
  • チャンクのバランスを監視し管理する
  • 書き込み効率のためにインデックスを微調整する
  • 書き込みの確認を慎重に使用する
  • WiredTigerストレージエンジンの使用を検討する

書き込みの重要性: ワークロードを理解する

最適化技術に入る前に、まず何を扱っているのかを理解しましょう。MongoDBでの書き込み負荷の高いワークロードには通常、以下が含まれます:

  • 高頻度の挿入操作
  • 既存のドキュメントへの頻繁な更新
  • 一括書き込み操作
  • 時間に敏感なデータの取り込み

これがあなたのユースケースに当てはまるなら、あなたは正しい場所にいます。それでは、腕まくりをして作業に取り掛かりましょう!

シャードキーの選択: 書き込み分散の基盤

適切なシャードキーを選ぶことは、高層ビルの完璧な基礎を選ぶようなものです。間違えると、他のすべてが大変な作業になります。書き込み負荷の高いワークロードでは、シャードキーは次のようにするべきです:

  • シャード全体に書き込みを均等に分散する
  • ホットスポットを避ける
  • データの増加に伴い水平にスケールする

以下は、時系列データコレクションの良いシャードキーの例です:


db.createCollection("sensor_data", {
    shardKey: { device_id: 1, timestamp: 1 }
})

この複合シャードキーは、高カーディナリティのフィールド(device_id)と単調増加フィールド(timestamp)を組み合わせています。この組み合わせにより、書き込みがシャード全体に分散され、新しいデータが単一のシャードに集中しないようにします。

注意点!

単調増加フィールドを単独でシャードキーとして使用することは避けてください。論理的に思えるかもしれませんが、最新の値を担当するシャードに書き込みホットスポットを作成してしまいます。

バランスの取れた行動: チャンクを管理する

適切に選ばれたシャードキーがあっても、チャンクの分布を監視する必要があります。MongoDBのバランサーはここでの友人ですが、いくつかのガイダンスが必要です:

  • 定期的にチャンクの分布を監視する
  • 必要に応じてチャンクサイズを調整する
  • オフピーク時にバランスを取るようにスケジュールする

チャンクの分布を確認する方法は次のとおりです:


sh.status()

チャンクを手動で移動する必要がある場合:


sh.moveChunk("mydb.mycollection", { device_id: "XYZ123" }, "shard3")

インデックスの調整: 書き込みに優しいアプローチ

インデックスは読み取りには優れていますが、書き込みには両刃の剣となることがあります。追加のインデックスごとに、MongoDBは書き込み操作中により多くの作業を行う必要があります。バランスを取る方法は次のとおりです:

  • 絶対に必要なインデックスに限定する
  • 複合インデックスを賢く使用する
  • 書き込み負荷の高いコレクションには部分インデックスを検討する

たとえば、ユーザーのアクティビティのコレクションがあり、特定のユーザーの最近のアクティビティを頻繁にクエリする場合、別々のインデックスの代わりに複合インデックスを検討してください:


db.user_activities.createIndex({ user_id: 1, timestamp: -1 })

このインデックスは、user_idのみのクエリと、user_idtimestampの両方を含むクエリをサポートし、インデックスの総数を減らします。

プロのヒント

explain()メソッドを使用してクエリを分析し、インデックスが効果的に使用されていることを確認してください:


db.user_activities.find({ user_id: "123", timestamp: { $gt: ISODate("2023-01-01") } }).explain("executionStats")

書き込みの確認: 最適なポイントを見つける

MongoDBの書き込み確認は、書き込み速度とデータの耐久性の間でトレードオフを可能にします。書き込み負荷の高いワークロードでは、可能な限り低い書き込み確認を使用したくなるかもしれませんが、リスクに注意してください:

  • { w: 0 }: ファイア・アンド・フォーゲット(最速だがリスクあり)
  • { w: 1 }: プライマリに書き込む(デフォルト)
  • { w: "majority" }: ノードの過半数に書き込む(遅いが安全)

一括操作の書き込み確認を設定する方法は次のとおりです:


const bulk = db.items.initializeUnorderedBulkOp();
// 操作をバルクオブジェクトに追加
bulk.execute({ writeConcern: { w: 1, j: false } });

考えるべきこと

異なるデータタイプに対して異なる書き込み確認を使用することを検討してください。重要な金融取引?{ w: "majority" }を選びましょう。一時的なキャッシュデータ?{ w: 1 }で十分かもしれません。

ストレージエンジン: WiredTigerが救いに

まだWiredTiger(MongoDB 3.2以降のデフォルト)を使用していない場合は、切り替える時です。WiredTigerは書き込み負荷の高いワークロードに対していくつかの利点を提供します:

  • ドキュメントレベルの同時実行制御
  • 圧縮(データとインデックスの両方)
  • インプレース更新なし(書き込み増幅を減少)

現在のストレージエンジンを確認するには:


db.serverStatus().storageEngine

監視と調整: 警戒を怠らない

書き込み負荷の高いワークロードの最適化は一度きりの作業ではなく、継続的なプロセスです。次のツールを手元に置いておきましょう:

  • MongoDB Compass: データとインデックスの視覚的分析のために
  • mongotopとmongostat: リアルタイムのパフォーマンス監視のために
  • MongoDB Atlas: クラウドを利用する場合、優れた監視と自動化機能を提供します

書き込み操作を監視するための簡単なmongostatコマンドは次のとおりです:


mongostat --rowcount 0 --discover

まとめ: 書き込みの道を進む

書き込み負荷の高いワークロードに対するMongoDBの最適化は、高性能エンジンの調整に似ています。それには理解、慎重な調整、そして継続的な監視が必要です。シャードキーの選択、バランスの取り方、インデックスの調整、MongoDBの書き込みに優しい機能を活用することで、大量の書き込み負荷を問題なく処理できるシステムを構築できます。

すべてのアプリケーションはユニークですので、実験を恐れず、特定のユースケースに最適な方法を見つけてください。そして、すべてがうまくいかない場合は、ハードウェアを追加するオプションもありますが、それは最後の手段としましょう。

出発前に

現在のMongoDBの設定について考えてみてください。ここで話したことに基づいて、すぐに適用できる最適化はありますか?シャードキーの選択を見直す時かもしれませんし、インデックス戦略を詳しく見る時かもしれません。将来の自分(と運用チーム)が感謝するでしょう!

最適化を楽しんでください。書き込み操作が常に迅速で、シャードが常にバランスが取れていることを願っています!