T-CREATOR

MongoDB が遅い原因を一発特定:`explain()`・プロファイラ・統計の使い方

MongoDB が遅い原因を一発特定:`explain()`・プロファイラ・統計の使い方

MongoDB のクエリが突然遅くなったとき、どこから手をつければいいのか悩んだことはありませんか?

本番環境で急にレスポンスが遅延し始めると、焦りますよね。しかし、MongoDB には強力な診断ツールが標準で備わっています。explain() メソッド、プロファイラ、そして統計情報を活用すれば、パフォーマンスのボトルネックを素早く特定できるんです。

この記事では、MongoDB のパフォーマンス問題を効率的にトラブルシュートする方法を、実践的な例とともに解説していきます。初めて診断ツールに触れる方でも、すぐに実務で使える知識が身につきますよ。

背景

MongoDB のパフォーマンス診断が重要な理由

MongoDB は柔軟なドキュメント指向データベースですが、データ量が増えたりクエリが複雑になったりすると、パフォーマンスが低下することがあります。

特に以下のような場面で、パフォーマンス問題が顕在化しやすいです。

  • データ件数が数百万件を超えた段階
  • 複雑な集約パイプラインを実行するとき
  • インデックスが適切に設定されていない場合
  • メモリが不足してディスク I/O が増加したとき

MongoDB が提供する診断ツールを理解しておけば、これらの問題を早期に発見し、適切な対策を講じることができます。

以下の図は、MongoDB のパフォーマンス診断の全体像を示しています。

mermaidflowchart TB
    problem["パフォーマンス低下<br/>検知"] --> analyze["診断ツールで<br/>原因分析"]
    analyze --> explain["explain()で<br/>クエリ実行計画確認"]
    analyze --> profiler["プロファイラで<br/>遅いクエリ特定"]
    analyze --> stats["統計情報で<br/>リソース状況確認"]
    explain --> solution["解決策<br/>実施"]
    profiler --> solution
    stats --> solution
    solution --> index["インデックス<br/>追加・最適化"]
    solution --> query["クエリ<br/>改善"]
    solution --> resource["リソース<br/>増強"]

図で理解できる要点:

  • パフォーマンス診断は 3 つの主要ツールで構成される
  • 各ツールは異なる視点から問題を分析する
  • 診断結果から適切な解決策を選択できる

MongoDB の診断ツール概要

MongoDB には主に 3 つの診断ツールがあります。

#ツール名主な用途使用タイミング
1explain()クエリ実行計画の確認特定クエリの最適化時
2プロファイラ遅いクエリの自動記録全体的な問題調査時
3統計情報データベース・コレクション状態の把握リソース状況確認時

それぞれのツールは補完的な関係にあり、組み合わせて使うことで、より正確な診断が可能になります。

課題

パフォーマンス問題の典型的な症状

MongoDB のパフォーマンス問題は、以下のような症状として現れることが多いでしょう。

アプリケーション側の症状:

  • API のレスポンスタイムが突然長くなった
  • タイムアウトエラーが頻発するようになった
  • 特定の時間帯だけ処理が遅延する

データベース側の症状:

  • クエリの実行時間が数秒以上かかる
  • CPU 使用率が常に高い状態が続く
  • ディスク I/O が異常に多い

これらの症状が出たとき、「どのクエリが遅いのか」「なぜ遅いのか」を特定しなければ、適切な対策が打てません。

よくある原因パターン

MongoDB のパフォーマンス低下には、いくつかの典型的なパターンがあります。

以下の図は、パフォーマンス問題の主な原因と、その診断方法の関係を示しています。

mermaidflowchart LR
    cause1["インデックス未設定"] --> explain1["explain()で<br/>COLLSCAN 検出"]
    cause2["インデックス非効率"] --> explain2["explain()で<br/>高い keysExamined"]
    cause3["クエリ設計問題"] --> profiler1["プロファイラで<br/>遅延クエリ特定"]
    cause4["リソース不足"] --> stats1["統計情報で<br/>メモリ・ディスク確認"]

    explain1 --> fix1["インデックス作成"]
    explain2 --> fix2["インデックス再設計"]
    profiler1 --> fix3["クエリ最適化"]
    stats1 --> fix4["リソース増強"]

図で理解できる要点:

  • 原因ごとに適切な診断ツールが異なる
  • 診断結果から具体的な解決策が導ける
  • 複数の原因が重なっている場合もある

主な原因とその特徴:

#原因特徴診断方法
1インデックス未設定全件スキャンが発生explain() で COLLSCAN 確認
2インデックスの選択ミス不適切なインデックスを使用explain() の実行計画確認
3クエリ設計の問題不必要なデータ取得プロファイラで取得件数確認
4メモリ不足ディスクへのスワップ発生統計情報でメモリ使用量確認
5データの肥大化インデックスサイズ増大統計情報でサイズ確認

これらの問題を効率的に特定し、対策するために、3 つの診断ツールを使い分けることが重要なんです。

解決策

explain() でクエリ実行計画を確認する

explain() は、MongoDB がクエリをどのように実行するかの詳細な計画を表示してくれます。これを見れば、インデックスが使われているか、何件のドキュメントをスキャンしたかが一目瞭然です。

explain() の基本的な使い方

explain() には 3 つのモードがあり、それぞれ異なるレベルの情報を提供します。

javascript// モード 1: queryPlanner(デフォルト)
// 実行計画のみを表示、実際には実行しない
db.users.find({ age: { $gt: 25 } }).explain();

// モード 2: executionStats
// 実際に実行して統計情報も表示
db.users
  .find({ age: { $gt: 25 } })
  .explain('executionStats');

実際の診断では、executionStats モードが最も有用です。これにより、実行時間やスキャンしたドキュメント数などの重要な情報が得られますよ。

javascript// モード 3: allPlansExecution
// すべての候補プランの実行結果を表示
db.users
  .find({ age: { $gt: 25 } })
  .explain('allPlansExecution');

allPlansExecution は、複数のインデックスがある場合に、どのインデックスが選ばれたかを詳しく知りたいときに使います。

explain() の出力を読み解く

explain() の出力で特に注目すべきポイントを見ていきましょう。

javascript// 実行統計の確認例
const result = db.users
  .find({ email: 'user@example.com' })
  .explain('executionStats');

// 出力される主要な情報:
// {
//   executionStats: {
//     executionTimeMillis: 150,    // 実行時間(ミリ秒)
//     totalKeysExamined: 1,        // スキャンしたインデックスキー数
//     totalDocsExamined: 1,        // スキャンしたドキュメント数
//     nReturned: 1                 // 返されたドキュメント数
//   }
// }

理想的には、totalDocsExaminednReturned が同じ値になります。これは、必要なドキュメントだけを効率的に取得できている証拠です。

以下は、explain() の出力から問題を判断する基準をまとめたものです。

#指標良好な値要改善の値意味
1executionTimeMillis100ms 以下1000ms 以上クエリ実行時間
2totalDocsExamined ​/​ nReturned1 に近い10 以上スキャン効率
3stageIXSCANCOLLSCANインデックス使用有無
4totalKeysExamined ​/​ nReturned1 に近い100 以上インデックス効率

COLLSCAN の検出と対処

最も避けるべきなのが、COLLSCAN(コレクション全体スキャン)です。

javascript// COLLSCAN が発生している悪い例
db.products
  .find({ category: 'electronics' })
  .explain('executionStats');

// 出力例:
// {
//   winningPlan: {
//     stage: "COLLSCAN",  // ← 全件スキャン発生中
//     filter: { category: { $eq: "electronics" } }
//   },
//   executionStats: {
//     totalDocsExamined: 1000000,  // 100万件スキャン
//     nReturned: 5000               // 5000件返却
//   }
// }

この場合、100 万件のドキュメントをスキャンして、わずか 5000 件を返しています。これは非常に非効率ですね。

javascript// 解決策:インデックスを作成
db.products.createIndex({ category: 1 });

// インデックス作成後の確認
db.products
  .find({ category: 'electronics' })
  .explain('executionStats');

// 改善後の出力:
// {
//   winningPlan: {
//     stage: "FETCH",
//     inputStage: {
//       stage: "IXSCAN",  // ← インデックススキャンに改善
//       keyPattern: { category: 1 }
//     }
//   },
//   executionStats: {
//     totalDocsExamined: 5000,  // 必要な件数だけスキャン
//     nReturned: 5000
//   }
// }

インデックスを追加することで、スキャン数が 200 分の 1 に削減されました。

プロファイラで遅いクエリを自動収集する

プロファイラは、実行されたすべてのクエリを監視し、遅いものを自動的に記録してくれる機能です。

プロファイラの有効化

プロファイラには 3 つのレベルがあります。

javascript// レベル 0: プロファイラ無効(デフォルト)
db.setProfilingLevel(0);

// レベル 1: 遅いクエリのみ記録(推奨)
// 100ms を超えるクエリを記録する例
db.setProfilingLevel(1, { slowms: 100 });

本番環境では、レベル 1 を使用するのが一般的です。閾値は環境に応じて調整しましょう。

javascript// レベル 2: すべてのクエリを記録(開発環境のみ推奨)
db.setProfilingLevel(2);

// 現在の設定確認
db.getProfilingStatus();
// 出力例:
// { was: 1, slowms: 100, sampleRate: 1.0 }

レベル 2 は大量のログを生成するため、本番環境では使わないように注意してください。

プロファイラのログを分析する

プロファイラのログは、system.profile コレクションに保存されます。

javascript// 遅いクエリの上位 5 件を取得
db.system.profile
  .find()
  .sort({ millis: -1 }) // 実行時間の降順
  .limit(5)
  .pretty();

// 出力例の主要フィールド:
// {
//   op: "query",              // 操作タイプ
//   ns: "mydb.users",         // 名前空間
//   millis: 2543,             // 実行時間(ミリ秒)
//   ts: ISODate("..."),       // タイムスタンプ
//   execStats: { ... }        // 実行統計
// }

実行時間が長いクエリを特定したら、そのクエリに対して explain() を実行して、詳細を調査します。

javascript// 特定のコレクションの遅いクエリだけを抽出
db.system.profile
  .find({
    ns: 'mydb.orders',
    millis: { $gt: 1000 }, // 1秒以上のクエリ
  })
  .sort({ ts: -1 });

// 集約パイプラインが遅い場合の確認
db.system.profile
  .find({
    op: 'command',
    'command.aggregate': { $exists: true },
  })
  .sort({ millis: -1 });

集約パイプラインは複雑になりがちなので、特に注意が必要です。

プロファイラデータの集計と可視化

どのクエリパターンが最も遅いかを把握するために、集計を活用します。

javascript// クエリパターンごとの平均実行時間を集計
db.system.profile.aggregate([
  {
    $match: {
      op: 'query',
      millis: { $gt: 100 },
    },
  },
  {
    $group: {
      _id: '$ns', // コレクションごと
      avgMillis: { $avg: '$millis' }, // 平均実行時間
      maxMillis: { $max: '$millis' }, // 最大実行時間
      count: { $sum: 1 }, // 実行回数
    },
  },
  {
    $sort: { avgMillis: -1 },
  },
]);

この集計により、どのコレクションのクエリが全体的に遅いかが分かります。

javascript// 実行回数が多い遅いクエリを特定
db.system.profile.aggregate([
  {
    $match: { millis: { $gt: 500 } },
  },
  {
    $group: {
      _id: {
        ns: '$ns',
        op: '$op',
      },
      count: { $sum: 1 },
      avgTime: { $avg: '$millis' },
    },
  },
  {
    $match: { count: { $gt: 10 } }, // 10回以上実行されたもの
  },
  {
    $sort: { avgTime: -1 },
  },
]);

頻繁に実行される遅いクエリは、優先的に最適化すべき対象です。

統計情報でリソース状態を把握する

統計情報は、データベースやコレクションの全体的な健康状態を確認するのに役立ちます。

データベース全体の統計

データベースレベルの統計情報を取得してみましょう。

javascript// データベース全体の統計情報
db.stats();

// 主な出力項目:
// {
//   db: "mydb",
//   collections: 15,           // コレクション数
//   views: 2,                  // ビュー数
//   objects: 5000000,          // ドキュメント総数
//   dataSize: 2147483648,      // データサイズ(バイト)
//   storageSize: 3221225472,   // ストレージサイズ
//   indexes: 25,               // インデックス総数
//   indexSize: 536870912,      // インデックスサイズ
//   totalSize: 3758096384      // 合計サイズ
// }

indexSizedataSize に対して異常に大きい場合、不要なインデックスがある可能性があります。

javascript// より詳細な統計(サーバー全体)
db.serverStatus();

// メモリ使用状況の確認
db.serverStatus().mem;
// {
//   resident: 2048,    // 物理メモリ使用量(MB)
//   virtual: 4096,     // 仮想メモリ使用量(MB)
//   mapped: 3072       // マップされたメモリ
// }

resident が利用可能な物理メモリに近い場合、メモリ不足の可能性があります。

コレクション単位の統計

特定のコレクションの詳細な統計を確認します。

javascript// コレクションの統計情報
db.users.stats();

// 主な出力項目:
// {
//   ns: "mydb.users",
//   size: 104857600,           // データサイズ
//   count: 100000,             // ドキュメント数
//   avgObjSize: 1048,          // 平均ドキュメントサイズ
//   storageSize: 125829120,    // ストレージサイズ
//   nindexes: 5,               // インデックス数
//   totalIndexSize: 20971520,  // インデックス合計サイズ
//   indexSizes: {              // 各インデックスのサイズ
//     _id_: 2097152,
//     email_1: 5242880,
//     age_1: 3145728
//   }
// }

avgObjSize が大きい場合、不要なフィールドを削除するか、スキーマ設計を見直すことを検討しましょう。

javascript// インデックスの詳細確認
db.users.getIndexes();

// 出力例:
// [
//   {
//     v: 2,
//     key: { _id: 1 },
//     name: "_id_"
//   },
//   {
//     v: 2,
//     key: { email: 1 },
//     name: "email_1",
//     unique: true
//   }
// ]

インデックスの一覧を確認することで、重複や不要なインデックスを発見できます。

インデックス使用状況の確認

作成したインデックスが実際に使われているかを確認することも重要です。

javascript// インデックスの使用統計
db.users.aggregate([{ $indexStats: {} }]);

// 出力例:
// {
//   name: "email_1",
//   key: { email: 1 },
//   host: "localhost:27017",
//   accesses: {
//     ops: 15234,              // 使用回数
//     since: ISODate("...")    // 統計開始時刻
//   }
// }

ops が 0 のインデックスは、使われていないため削除を検討すべきです。

javascript// 使用されていないインデックスの特定
db.users.aggregate([
  { $indexStats: {} },
  {
    $match: {
      'accesses.ops': { $eq: 0 },
    },
  },
]);

不要なインデックスは、書き込みパフォーマンスを低下させ、ストレージを無駄に消費します。

具体例

ケース 1:検索クエリが遅い問題の診断と解決

実際のトラブルシューティングの流れを見ていきましょう。

症状: ユーザー検索 API のレスポンスが 3 秒以上かかる

ステップ 1:問題のクエリを特定

まず、プロファイラで遅いクエリを特定します。

javascript// プロファイラを有効化(100ms以上のクエリを記録)
db.setProfilingLevel(1, { slowms: 100 });

// しばらく待ってから遅いクエリを確認
db.system.profile
  .find({ millis: { $gt: 1000 } })
  .sort({ millis: -1 })
  .limit(3);

// 検出されたクエリ例:
// {
//   op: "query",
//   ns: "mydb.users",
//   command: {
//     find: "users",
//     filter: {
//       status: "active",
//       createdAt: { $gte: ISODate("2024-01-01") }
//     }
//   },
//   millis: 3245
// }

users コレクションの検索クエリが 3.2 秒かかっていることが判明しました。

ステップ 2:explain() で実行計画を確認

次に、なぜ遅いのかを explain() で調査します。

javascript// 問題のクエリの実行計画を確認
db.users
  .find({
    status: 'active',
    createdAt: { $gte: ISODate('2024-01-01') },
  })
  .explain('executionStats');

// 出力結果:
// {
//   executionStats: {
//     executionTimeMillis: 3189,
//     totalKeysExamined: 0,      // インデックス未使用
//     totalDocsExamined: 500000, // 全件スキャン
//     nReturned: 12000
//   },
//   winningPlan: {
//     stage: "COLLSCAN",          // 全件スキャン発生
//     filter: { ... }
//   }
// }

50 万件のドキュメントをスキャンして 1.2 万件を返している、非効率な状態です。

ステップ 3:適切なインデックスを作成

問題が判明したので、複合インデックスを作成します。

javascript// status と createdAt の複合インデックスを作成
db.users.createIndex(
  { status: 1, createdAt: 1 },
  { name: 'status_createdAt_idx' }
);

// インデックス作成確認
db.users.getIndexes();

複合インデックスの順序は、等値条件(status)を先に、範囲条件(createdAt)を後にするのが基本です。

ステップ 4:改善を確認

インデックス作成後、再度 explain() で確認します。

javascript// 改善後の実行計画を確認
db.users
  .find({
    status: 'active',
    createdAt: { $gte: ISODate('2024-01-01') },
  })
  .explain('executionStats');

// 改善後の出力:
// {
//   executionStats: {
//     executionTimeMillis: 45,    // 3189ms → 45ms に改善
//     totalKeysExamined: 12000,
//     totalDocsExamined: 12000,   // 必要な件数のみスキャン
//     nReturned: 12000
//   },
//   winningPlan: {
//     stage: "FETCH",
//     inputStage: {
//       stage: "IXSCAN",          // インデックススキャン
//       keyPattern: { status: 1, createdAt: 1 }
//     }
//   }
// }

実行時間が約 70 分の 1 に改善されました。素晴らしい結果ですね。

ケース 2:集約パイプラインのパフォーマンス改善

集約パイプラインは複雑になりがちで、最適化が難しい場合があります。

症状: 売上集計レポートの生成に 10 秒以上かかる

ステップ 1:遅い集約パイプラインの特定

javascript// プロファイラから集約コマンドを検索
db.system.profile
  .find({
    op: 'command',
    'command.aggregate': { $exists: true },
    millis: { $gt: 5000 },
  })
  .sort({ millis: -1 });

// 検出された集約パイプライン:
// {
//   op: "command",
//   ns: "mydb.orders",
//   command: {
//     aggregate: "orders",
//     pipeline: [
//       { $match: { status: "completed" } },
//       { $group: { _id: "$productId", total: { $sum: "$amount" } } },
//       { $sort: { total: -1 } }
//     ]
//   },
//   millis: 12450
// }

orders コレクションの集約に 12 秒以上かかっています。

ステップ 2:集約パイプラインを explain() で分析

集約パイプラインにも explain() が使えます。

javascript// 集約パイプラインの実行計画を確認
db.orders
  .explain('executionStats')
  .aggregate([
    { $match: { status: 'completed' } },
    {
      $group: {
        _id: '$productId',
        total: { $sum: '$amount' },
      },
    },
    { $sort: { total: -1 } },
  ]);

// 各ステージの統計を確認
// stages: [
//   {
//     $cursor: {
//       queryPlanner: {
//         winningPlan: { stage: "COLLSCAN" }  // 問題発見
//       },
//       executionStats: {
//         totalDocsExamined: 800000
//       }
//     }
//   },
//   { $group: ... },
//   { $sort: ... }
// ]

$match ステージで全件スキャンが発生しているのが問題です。

ステップ 3:インデックスを活用するように改善

javascript// status フィールドにインデックスを作成
db.orders.createIndex({ status: 1 });

// さらに、よく使う集計パターンに合わせて複合インデックスを作成
db.orders.createIndex({
  status: 1,
  productId: 1,
  amount: 1,
});

複合インデックスにすることで、$group ステージでもインデックスを活用できる可能性があります。

ステップ 4:パイプラインの順序を最適化

javascript// 改善後の集約パイプライン
db.orders.aggregate([
  {
    $match: {
      status: 'completed',
      createdAt: { $gte: ISODate('2024-01-01') }, // 範囲を絞る
    },
  },
  {
    $group: {
      _id: '$productId',
      total: { $sum: '$amount' },
      count: { $sum: 1 },
    },
  },
  {
    $sort: { total: -1 },
  },
  {
    $limit: 100, // 上位100件のみ取得
  },
]);

$limit を追加して、不要なデータの処理を削減します。

ステップ 5:改善結果の確認

javascript// 改善後の実行時間を確認
db.orders.explain('executionStats').aggregate([
  // ... 改善後のパイプライン ...
]);

// 改善後の統計:
// {
//   executionStats: {
//     executionTimeMillis: 234,  // 12450ms → 234ms に改善
//     totalDocsExamined: 45000   // 必要な件数のみスキャン
//   }
// }

実行時間が約 50 分の 1 に改善されました。

以下は、最適化前後の比較をまとめた表です。

#項目最適化前最適化後改善率
1実行時間12,450 ms234 ms★ 53 倍高速化
2スキャンドキュメント数800,000 件45,000 件★ 18 分の 1 に削減
3インデックス使用なしIXSCAN★ 効率化

ケース 3:メモリ不足によるパフォーマンス低下

データ量が増えると、メモリ不足が原因でパフォーマンスが低下することがあります。

ステップ 1:メモリ使用状況の確認

javascript// サーバーのメモリ統計を確認
db.serverStatus().mem;

// 出力例:
// {
//   bits: 64,
//   resident: 4096,    // 物理メモリ使用量(MB)
//   virtual: 8192,     // 仮想メモリ使用量
//   mapped: 6144
// }

resident が利用可能な RAM に近い場合、メモリ不足の兆候です。

ステップ 2:ワーキングセットサイズの確認

javascript// WiredTiger のキャッシュ統計
db.serverStatus().wiredTiger.cache;

// 重要な指標:
// {
//   "maximum bytes configured": 2147483648,  // キャッシュ最大サイズ
//   "bytes currently in the cache": 2100000000,  // 現在の使用量
//   "pages evicted by application threads": 15234,  // ページ退避回数
//   "pages read into cache": 234567,
//   "pages written from cache": 123456
// }

pages evicted が多い場合、キャッシュサイズが不足している可能性があります。

ステップ 3:統計情報でデータサイズを確認

javascript// データベース全体のサイズ確認
db.stats(1024 * 1024); // MB単位で表示

// {
//   dataSize: 15360,      // データサイズ: 15GB
//   indexSize: 8192,      // インデックスサイズ: 8GB
//   totalSize: 23552      // 合計: 23GB
// }

// 大きなコレクションを特定
db.getCollectionNames().forEach(function (collection) {
  const stats = db[collection].stats(1024 * 1024);
  if (stats.size > 1000) {
    // 1GB以上
    print(collection + ': ' + stats.size + ' MB');
  }
});

ワーキングセット(頻繁にアクセスされるデータ+インデックス)が物理メモリに収まらない場合、ディスク I/O が増加します。

ステップ 4:対策の実施

メモリ不足の対策には、いくつかのアプローチがあります。

javascript// 対策 1: 不要なインデックスの削除
db.users.aggregate([
  { $indexStats: {} },
  { $match: { 'accesses.ops': { $eq: 0 } } },
]);

// 使われていないインデックスを削除
db.users.dropIndex('unused_index_name');

インデックスを削除することで、メモリとストレージを節約できます。

javascript// 対策 2: プロジェクションで必要なフィールドのみ取得
// 改善前(全フィールド取得)
db.users.find({ status: 'active' });

// 改善後(必要なフィールドのみ)
db.users.find(
  { status: 'active' },
  { _id: 1, name: 1, email: 1 } // 必要なフィールドのみ
);

不要なフィールドを取得しないことで、メモリ使用量を削減できます。

メモリ最適化の主な対策:

#対策効果実施難易度
1不要なインデックスの削除メモリ・ストレージ削減★ 低
2クエリのプロジェクション活用メモリ使用量削減★ 低
3古いデータのアーカイブデータサイズ削減★★ 中
4物理メモリの増設根本的解決★★★ 高
5シャーディング導入データ分散★★★ 高

まとめ

MongoDB のパフォーマンス問題を効率的に診断するには、3 つの主要ツールを適切に使い分けることが重要です。

診断ツールの使い分け:

  • explain() は、特定のクエリが遅い原因を詳しく調べるときに使います
  • プロファイラ は、どのクエリが遅いかを自動的に見つけるときに使います
  • 統計情報 は、データベース全体の健康状態やリソース使用状況を把握するときに使います

効果的なトラブルシューティングの流れ:

  1. プロファイラで遅いクエリを特定する
  2. explain() で実行計画を確認し、原因を分析する
  3. 統計情報でリソース状況を把握する
  4. インデックスの追加・最適化、クエリの改善を実施する
  5. 改善後、再度 explain() で効果を確認する

この流れを習慣化することで、パフォーマンス問題を早期に発見し、迅速に対処できるようになりますよ。

パフォーマンス最適化のベストプラクティス:

  • インデックスは必要なものだけ作成し、定期的に使用状況を確認する
  • クエリは常に explain() で実行計画を確認してから本番環境に投入する
  • プロファイラは本番環境でも継続的に稼働させ、異常を早期検出する
  • データの増加に応じて、定期的に統計情報をモニタリングする

MongoDB の診断ツールを使いこなせば、パフォーマンス問題の多くは解決できます。日々の運用の中で、これらのツールを活用する習慣をつけていきましょう。

関連リンク