すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB for MongoDB:過剰なデータベースとコレクションによるパフォーマンスの問題

最終更新日:Jun 23, 2026

MongoDB インスタンスにデータベースとコレクションが多すぎると、データベースのパフォーマンスが低下し、他の問題を引き起こす可能性があります。

従来のデータベースで使用されるデータベーステーブルという用語は、それぞれ MongoDB のデータベースコレクションに対応します。

MongoDB では、WiredTiger ストレージエンジンが各コレクションに対応するディスクファイルを作成します。各インデックスも新しいディスクファイルを作成します。ファイルシステムオブジェクトなどの開いているリソースごとに、WiredTiger エンジンは dhandle データ構造を維持します。この構造には、チェックポイントの詳細、セッションの参照カウント、メモリ内の B+ ツリー構造へのポインター、統計データなどの情報が格納されます。

したがって、MongoDB インスタンスが持つデータベースとコレクションが多いほど、WiredTiger エンジンが開いたままにしておく必要のあるファイルシステムオブジェクトが多くなります。これにより、メモリ内の dhandle データ構造の数が増加します。これらの dhandle 構造が多数メモリに保持されると、ロック競合が発生し、インスタンスのパフォーマンスが低下する可能性があります。

潜在的な問題

  • handleLock または schemaLock によるクエリの低速化とリクエストレイテンシの増加

    データベースとコレクションが多すぎると、クエリが遅くなり、次の例のようなログが生成されることがあります。

    2024-03-07T15:59:16.856+0800 I  COMMAND  [conn4175155] command db.collections command: count { count: "xxxxxx", query: { A: 1, B: 1 }, 
    $readPreference: { mode: "secondaryPreferred" }, $db: "db" } planSummary: COLLSCAN keysExamined:0 keysExaminedBySizeInBytes:0 
    docsExamined:1 docsExaminedBySizeInBytes:208 numYields:1 queryHash:916BD9E3 planCacheKey:916BD9E3 reslen:185 
    locks:{ ReplicationStateTransition: { acquireCount: { w: 2 } }, Global: { acquireCount: { r: 2 } }, Database: { acquireCount: { r: 2 } }, 
    Collection: { acquireCount: { r: 2 } }, Mutex: { acquireCount: { r: 1 } } } storage:{ data: { bytesRead: 304, timeReadingMicros: 4 }, 
    timeWaitingMicros: { handleLock: 40, schemaLock: 134101710 } } protocol:op_query 134268ms

    上記のスロークエリログは、ドキュメントが 1 つしかないコレクションでの単純な count 操作が、長い実行時間を要したことを示しています。ログの timeWaitingMicros: { handleLock: 40, schemaLock: 134101710 } } protocol:op_query 134268ms の部分は、多数のコレクションが原因で、読み取りリクエストが基盤となるストレージエンジンの handleLockschemaLock を取得するために待機する時間が長すぎたことを示しています。

  • 新しいノードを追加する際の初期同期フェーズでのメモリ不足 (OOM) エラー。

  • インスタンスの起動時間の増加。

  • データ同期時間の増加。

  • データのバックアップと復元にかかる時間の増加。

  • 物理バックアップの失敗率の増加。

  • 障害回復にかかる時間の増加。

説明

多数のデータベースとコレクションが必ずしも問題を引き起こすわけではありません。実際のインパクトは、アプリケーションのデータモデルやワークロードなどの要因に依存します。例えば、同じ仕様のデータベースがそれぞれ 10,000 のコレクションと合計 100,000 のファイルを持つ 2 つのシナリオを考えてみましょう。彼らが直面する課題は全く異なります。

  • 会計ソフトウェアシステム:アクセスパターンは非常に集中しています。ほとんどのコレクションはコールドデータのストレージに使用され、最近の少数のコレクションのみが頻繁にアクセスされます。

  • マルチテナント管理システム:テナントは別々のコレクションを使用して隔離されており、ほとんどすべてのコレクションがアクティブにアクセスまたは使用されています。

最適化の方法

不要なコレクションの削除

データベース内で削除できるコレクション (期限切れや使用されなくなったものなど) を特定します。dropCollection コマンドを使用してそれらを削除します。詳細については、「dropCollection()」をご参照ください。

警告

削除操作を実行する前に、利用可能な完全バックアップがあることを確認してください。

次のコマンドを使用して、データベースとコレクションの情報を表示します。

  • 次のコマンドを実行して、データベース内のコレクション数を表示します。

    db.getSiblingDB(<dbName>).getCollectionNames().length
  • 次のコマンドを実行して、コレクション、インデックス、ドキュメントの数、および合計データサイズを含むデータベースの詳細情報を表示します。

    // 特定のデータベースの統計情報を表示します。
    db.getSiblingDB(<dbName>).stats()
  • 次のコマンドを実行して、特定のコレクションの詳細情報を表示します。

    // 特定のコレクションの統計情報を表示します。
    db.getSiblingDB(<dbName>).<collectionName>.stats()

不要なインデックスの削除

インデックスの数を減らすと、ディスクファイルの数と、WiredTiger ストレージエンジンが維持する対応する dhandle 構造の数も減少します。これにより、この問題が緩和されます。

インデックス最適化のための基本的な原則は次のとおりです。

  • 未使用のインデックスを避ける

    クエリが特定のフィールドにアクセスしない場合、そのフィールド上のインデックスは使用されません。このようなインデックスは未使用と見なされ、削除できます。

  • インデックスのプレフィックスルールに従う

    例えば、{a:1}{a:1,b:1} の両方のインデックスがある場合、最初のインデックスは 2 番目のインデックスの冗長なプレフィックスであり、削除できます。

  • 等価性クエリのインデックスフィールドの順序を考慮する

    等価性マッチングの場合、複合インデックス内のフィールドの順序は重要ではありません。例えば、フィールド a と b に対するクエリでは、インデックス {a:1,b:1}{b:1,a:1} は機能的に同等です。使用頻度の低い方を削除できます。

  • 範囲クエリには ESR ルールを使用する

    クエリに最適な複合インデックスを構築するには、フィールドを Equality, Sort, Range (等価性、ソート、範囲) の順序で配置します。詳細については、「ESR (Equality, Sort, Range) ルール」をご参照ください。

  • ヒット数が低いインデックスをレビューする

    ヒット数が低いインデックスは、より効率的なインデックスと重複していることがよくあります。関連するすべてのクエリパターンを分析して、安全に削除できるかどうかを判断します。

MongoDB の $indexStats 集約ステージを使用して、コレクション内のすべてのインデックスの統計情報を表示できます。次のコマンドを実行する前に、必要な権限があることを確認してください。

// 特定のコレクションのインデックス統計情報を表示します。
db.getSiblingDB(<dbName>).<collectionName>.aggregate({"$indexStats":{}})

このコマンドは、次の例のような出力を返します。

{
   "name" : "item_1_quantity_1",
   "key" : { "item" : 1, "quantity" : 1 },
   "host" : "examplehost.local:27018",
   "accesses" : {
      "ops" : NumberLong(1),
      "since" : ISODate("2020-02-10T21:11:23.059Z")
   }
}

次の表は、返された情報内のパラメーターについて説明しています。

パラメーター

説明

name

インデックスの名前。

key

インデックスキーの詳細。

accesses.ops

このインデックスを使用した操作の数。インデックスのヒット数に相当します。

accesses.since

統計収集が開始された時刻。このフィールドと ops フィールドは、インスタンスが再起動されるか、インデックスが再構築されるとリセットされます。

インデックスのヒット数が非常に低い場合、例えば accesses.ops1 の場合、それは冗長または未使用のインデックスである可能性が高く、削除を検討できます。MongoDB インスタンスのバージョンが 4.4 以降の場合は、hideIndex コマンドを使用して、インデックスを削除する前に非表示にすることができます。これにより、一定期間アプリケーションに悪影響がないことを確認でき、インデックス削除のリスクを軽減できます。

ゲームプレイヤーのコレクションがあり、「プレイヤーが 20 coins を集めるごとに、1 star に変換される」というルールがあるとします。コレクション内のドキュメントは次のようになります。

// players コレクション
{
  "_id": "ObjectId(123)",
  "first_name": "John",
  "last_name": "Doe",
  "coins": 11,
  "stars": 2
}

現在、コレクションには次の 5 つのインデックスがあり、すべてのフィールドをカバーしています。

  • _id (デフォルトインデックス)

  • { last_name: 1 }

  • { last_name: 1, first_name: 1 }

  • { coins: -1 }

  • { stars: -1 }

インデックス最適化のロジックは次のとおりです。

  • アプリケーションのクエリは coins フィールドにアクセスしないため、{ coins: -1 } は未使用のインデックスです。

  • 前述のインデックスプレフィックスルールによれば、{ last_name: 1, first_name: 1 } インデックスは { last_name: 1 } インデックスをカバーします。したがって、{ last_name: 1 } インデックスを削除できます。

  • $indexStats コマンドを使用すると、{ stars: -1 } のヒット数が低いことがわかります。しかし、ゲームラウンドの終了時に、アプリケーションはリーダーボードのためにプレイヤーを stars の数で降順にソートする必要があります。したがって、頻繁に使用されなくても、完全なコレクションスキャンを避けるために { stars: -1 } インデックスは保持する必要があります。

最適化後、コレクションには 3 つのインデックスが残ります。

  • _id

  • { last_name: 1, first_name: 1 }

  • { stars: -1 }

この最適化の利点は次のとおりです。

  • ストレージスペースの削減。

  • 書き込みパフォーマンスの向上。

インデックスの最適化についてさらに質問がある場合は、チケットを送信して Alibaba Cloud のテクニカルサポートに連絡し、支援を求めてください。

複数のコレクションからのデータを統合

複数のコレクションからのデータを単一のコレクションに統合して、コレクションの総数を減らします。

例えば、temperatures という名前のデータベースがセンサーからの温度データを格納しているとします。センサーは午前 10:00 から午後 10:00 まで動作し、30 分ごとに温度データを読み取って保存します。各日の温度データは、日付にちなんで名付けられた別のコレクションに保存されます。

次のスニペットは、2 つのコレクション temperatures.march-09-2020temperatures.march-10-2020 の一部のデータを示しています。

  • コレクション temperatures.march-09-2020

    {
      "_id": 1,
      "timestamp": "2020-03-09T010:00:00Z",
      "temperature": 29
    }
    {
      "_id": 2,
      "timestamp": "2020-03-09T010:30:00Z",
      "temperature": 30
    }
    ...
    {
      "_id": 25,
      "timestamp": "2020-03-09T022:00:00Z",
      "temperature": 26
    }
  • コレクション temperatures.march-10-2020

    {
      "_id": 1,
      "timestamp": "2020-03-10T010:00:00Z",
      "temperature": 30
    }
    {
      "_id": 2,
      "timestamp": "2020-03-10T010:30:00Z",
      "temperature": 32
    }
    ...
    {
      "_id": 25,
      "timestamp": "2020-03-10T022:00:00Z",
      "temperature": 28
    }
    

時間が経つにつれて、データベース内のコレクションの数は増加します。MongoDB はコレクション数に厳密な制限を課しておらず、このモデルには明確なデータライフサイクルポリシーがないため、コレクションとその対応するインデックスの数は無期限に増え続けます。

コレクション数が無限に増え続けるという問題に加えて、このデータモデルでは複数日にわたるクエリを実行することが困難です。長期的な温度傾向を分析するために数日間のデータをクエリするには、$lookup クエリを使用する必要がありますが、これは単一のコレクション内でクエリするよりもパフォーマンスが劣ります。

より良いデータモデルは、すべての温度測定値を単一のコレクションに格納し、各日のデータを単一のドキュメントに格納することです。このアプローチは、バケットパターンの例です。次の例は、最適化されたモデルを示しています。

// temperatures.readings
{
  "_id": ISODate("2020-03-09"),
  "readings": [
    {
      "timestamp": "2020-03-09T010:00:00Z",
      "temperature": 29
    },
    {
      "timestamp": "2020-03-09T010:30:00Z",
      "temperature": 30
    },
    ...
    {
      "timestamp": "2020-03-09T022:00:00Z",
      "temperature": 26
    }
  ]
}
{
  "_id": ISODate("2020-03-10"),
  "readings": [
    {
      "timestamp": "2020-03-10T010:00:00Z",
      "temperature": 30
    },
    {
      "timestamp": "2020-03-10T010:30:00Z",
      "temperature": 32
    },
    ...
    {
      "timestamp": "2020-03-10T022:00:00Z",
      "temperature": 28
    }
  ]
}

最適化されたモデルは、元のモデルよりもはるかに少ないリソースを消費します。時刻に基づいてインデックスを作成する必要がなくなり、コレクションのデフォルトの _id インデックスが日付によるクエリを容易にします。これにより、無制限のコレクション数の問題も解決されます。

説明

時系列データについては、この問題に対処するために 時系列コレクション の使用も検討できます。

時系列コレクション機能は、MongoDB 5.0 以降のバージョンでのみサポートされています。

インスタンスの分割

単一の MongoDB インスタンス内でデータベースとコレクションの総数を減らせない場合は、データベースインスタンスの論理的な分割と、それに対応するアプリケーションの変更を検討してください。

これには 2 つのシナリオでアプローチできます。

シナリオ

分割ソリューション

考慮事項

コレクションが複数のデータベースに分散している

データベース間のビジネスロジックが密接に関連していない場合 (例えば、複数のアプリケーションやサービスが単一のデータベースインスタンスを共有している場合)、DTS (Data Transmission Service) を使用して、一部のデータベースを新しい ApsaraDB for MongoDB レプリカセットまたはシャードクラスターインスタンスに移行します。移行が完了する前に、アプリケーションロジックとアクセス方法もそれに応じて分割する必要があります。

データベース間のビジネスロジックが密接に関連している場合は、単一データベースシナリオの分割ソリューションを参照してください。

  • DTS タスクを作成する際は、適切なソースオブジェクトを選択してください。

  • 移行中に、元のデータベース名とコレクション名を維持することも、変更することもできます。

  • 移行が完了したら、dropDatabase コマンドを使用して、ソースインスタンスから対応するデータベースを削除します。

コレクションが単一のデータベースに集中している

まず、ビジネスチームが、リージョン、都市、優先度、その他の意味のあるビジネス属性など、特定のディメンションに基づいてすべてのコレクションを分割できるかどうかを判断する必要があります。

次に、DTS を使用して一部のコレクションを 1 つ以上の新しい MongoDB インスタンスに移行し、1 つのインスタンスを N 個のインスタンスに効果的に分割します。移行が完了する前に、アプリケーションロジックとアクセス方法もそれに応じて分割する必要があります。

  • DTS タスクを作成する際は、適切なソースオブジェクトを選択してください。

  • 移行中に、元のコレクション名を維持することも、変更することもできます。

  • 移行が完了したら、drop コマンドを使用して、ソースインスタンスから対応するコレクションを削除します。

  • 分割後、インスタンス間の集約クエリを処理するための追加のアプリケーションロジックが必要になります。

マルチテナント管理プラットフォームが MongoDB データベースを使用しています。初期のデータモデルでは、各テナントが個別のコレクションを持っていました。ビジネスの成長に伴い、テナント数は 10 万を超え、データベースの総サイズはテラバイトレベルに達しました。インスタンスでは、データベースアクセスの低速化と高レイテンシが頻繁に発生しました。

ビジネスチームは、地理的リージョンによってテナントを分割することを決定し、国内のテナントを華北、東北、華東、華中、華南、西南、西北に分けました。彼らは各リージョンに対応するアベイラビリティゾーンに新しい MongoDB インスタンスを作成し、DTS を使用して複数回の移行を実施しました。ビジネスの集約分析のニーズを満たすために、MongoDB インスタンスからデータウェアハウスへの同期も設定しました。

この分割により、各 MongoDB インスタンスのデータベースとコレクションの数が大幅に削減され、チームはそれに応じてインスタンスの仕様をスケールダウンしました。最近接リージョンアクセス原則を採用することで、アプリケーションはリクエストレイテンシをミリ秒レベルに短縮し、プロダクト体験を大幅に向上させました。その後のインスタンスのメンテナンスもはるかに簡単になりました。

シャードタグを使用してシャードクラスターに移行

すべてのコレクションが単一のデータベースにあり、それらを単一の論理インスタンスとして管理したい場合は、データをシャードクラスターアーキテクチャに移行し、管理にシャードタグを使用することを検討してください。シャードタグ管理方法はやや複雑で、追加の操作手順 (sh.addShardTagsh.addTagRange を使用) が必要です。しかし、単一の MongoDB インスタンスがすべてのコレクションを管理するため、アプリケーションへの変更は最小限で済みます。接続文字列を新しいシャードクラスターインスタンスのものに置き換えるだけで済みます。

例えば、インスタンスに 100,000 のアクティブなコレクションがある場合、新しい 10 シャードのシャードクラスターインスタンスを購入できます。以下のプロセスに従ってインスタンスを構成し、データを移行すると、シャードごとに 10,000 のアクティブなコレクションになります。手順は次のとおりです。

  1. 新しいシャードクラスターインスタンスを購入します。この例では 2 シャードのインスタンスを使用します。シャードクラスターの作成方法については、「シャードクラスターインスタンスの作成」をご参照ください。

  2. シャードクラスターインスタンスの mongos ノードに接続します。詳細については、「mongo シェルを使用して ApsaraDB for MongoDB シャードクラスターインスタンスに接続する」をご参照ください。

  3. 次のコマンドを実行して、各シャードにシャードタグを追加します。

    sh.addShardTag("d-xxxxxxxxx1", "shard_tag1")
    sh.addShardTag("d-xxxxxxxxx2", "shard_tag2")
    説明
    • これらのコマンドを実行する前に、使用しているアカウントが必要な権限を持っていることを確認してください。

    • DMS (Data Management) は現在、sh.addShardTag コマンドをサポートしていません。mongo シェルまたは mongosh でインスタンスに接続してこれらのコマンドを実行することを推奨します。

  4. すべてのシャードコレクションに対して、タグベースの範囲分散ルールを事前に構成します。

    use <dbName>
    sh.enableSharding("<dbName>")
    sh.addTagRange("<dbName>.test", {"_id":MinKey}, {"_id":MaxKey}, "shard_tag1")
    sh.addTagRange("<dbName>.test1", {"_id":MinKey}, {"_id":MaxKey}, "shard_tag2")

    この例では、シャードキーとして _id を使用しています。ワークロードに適したシャードキーを選択し、すべてのクエリ操作にシャードキーフィールドが含まれるようにしてください。シャードキーは、次のステップで使用するフィールドと一致している必要があります。また、単一のコレクションのすべてのデータが単一のシャードに存在するように、[MinKey,MaxKey] の境界を使用する必要があります。

  5. 移行するすべてのコレクションに対して shardCollection 操作を実行します。

    sh.shardCollection("<dbName>.test", {"_id":1})
    sh.shardCollection("<dbName>.test1", {"_id":1})
  6. sh.status() コマンドを実行して、ルールが有効であることを確認します。

    zhongli.test
            shard key: { "_id" : 1 }
            unique: false
            balancing: true
            chunks:
                    d-xxx	1
            { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : d-xxx Timestamp(1, 0)
             tag: shard_tag1  { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } }
    zhongli.test1
            shard key: { "_id" : 1 }
            unique: false
            balancing: true
            chunks:
                    d-xxx	1
            { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : d-xxx Timestamp(1, 0)
             tag: shard_tag2  { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } }
  7. レプリカセットインスタンスからシャードクラスターインスタンスへのデータ移行

    説明

    宛先インスタンスでコレクションを事前にシャーディングしているため、すべてのデータベースとコレクション情報はすでに存在します。したがって、DTS タスクで競合するテーブルの処理モードエラーを無視して続行に設定する必要があります。

  8. データ整合性を確認した後、アプリケーションを新しいシャードクラスターインスタンスにアクセスするように切り替えます。

説明
  • インスタンスにさらにシャードを追加する必要がある場合は、ステップ 3 を繰り返して、すべての新しいシャードにタグを追加する必要があります。

  • データベースに新しいコレクションが継続的に追加される場合は、それらに対してステップ 4 と 5 を繰り返す必要があります。これらのステップを実行しないと、新しいコレクションはプライマリシャードにのみ作成され、そのシャードのコレクション数が増加し、再びパフォーマンスの不安定性を引き起こす可能性があります。

ゾーンを使用してシャードクラスターに移行

この方法はシャードタグの使用に似ていますが、代わりに MongoDB の ゾーン 機能を使用します。これには追加の操作手順、具体的には sh.addShardToZone()sh.updateZoneKeyRange() が必要です。

手順は次のとおりです。

  1. 新しいシャードクラスターインスタンスを購入します。この例では 2 シャードのインスタンスを使用します。シャードクラスターの作成方法については、「シャードクラスターインスタンスの作成」をご参照ください。

  2. シャードクラスターインスタンスの mongos ノードに接続します。詳細については、「mongo シェルを使用して ApsaraDB for MongoDB シャードクラスターインスタンスに接続する」をご参照ください。

  3. 次のコマンドを実行して、各シャードをゾーンに割り当てます。

    sh.addShardToZone("d-xxxxxxxxx1", "ZoneA")
    sh.addShardToZone("d-xxxxxxxxx2", "ZoneB")
    説明
    • これらのコマンドを実行する前に、使用しているアカウントが必要な権限を持っていることを確認してください。

    • DMS は現在、sh.addShardToZone コマンドをサポートしていません。mongo シェルまたは mongosh でインスタンスに接続してこれらのコマンドを実行することを推奨します。

  4. すべてのコレクションに対して、ゾーンベースの範囲分散ルールを事前に構成します。

    use <dbName>
    sh.enableSharding("<dbName>")
    sh.updateZoneKeyRange("<dbName>.test", { "_id": MinKey }, { "_id": MaxKey }, "ZoneA")
    sh.updateZoneKeyRange("<dbName>.test1", { "_id": MinKey }, { "_id": MaxKey }, "ZoneB")

    この例では、シャードキーとして _id を使用しています。ワークロードに適したシャードキーを選択し、すべてのクエリ操作にシャードキーフィールドが含まれるようにしてください。シャードキーは、次のステップで使用するフィールドと一致している必要があります。また、単一のコレクションのすべてのデータが単一のシャードに存在するように、[MinKey,MaxKey] の境界を使用する必要があります。

  5. 移行するすべてのコレクションに対して shardCollection 操作を実行します。

    sh.shardCollection("<dbName>.test", { "_id": 1 })
    sh.shardCollection("<dbName>.test1", { "_id": 1 })
  6. sh.status() コマンドを実行してシャーディングの分散状況を表示し、ゾーン構成が有効であることを確認します。出力例は次のとおりです。

    {  "_id" : "shardDistributionDB",  "primary" : "d-xxx24",  "partitioned" : false,  "version" : {  "uuid" : UUID("1dc635xxx"),  "lastMod" : 1 } }
            shardDistributionDB.test
                    shard key: { "_id" : "hashed" }
                    unique: false
                    balancing: true
                    chunks:
                            d-2ze9797089ef3704      1
                    { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : d-xxx04 Timestamp(1, 0)
                     tag: ZoneA  { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } }
            shardDistributionDB.test1
                    shard key: { "_id" : "hashed" }
                    unique: false
                    balancing: true
                    chunks:
                            d-2zed2e752c35af24      1
                    { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : d-xxx24 Timestamp(1, 0)
                     tag: ZoneB  { "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } }
  7. レプリカセットインスタンスからシャードクラスターインスタンスへのデータ移行

    説明

    宛先インスタンスでコレクションを事前にシャーディングしているため、すべてのデータベースとコレクション情報はすでに存在します。したがって、DTS タスクで競合するテーブルの処理モードエラーを無視して続行に設定する必要があります。

  8. データ整合性を確認した後、アプリケーションを新しいシャードクラスターインスタンスにアクセスするように切り替えます。

説明
  • インスタンスにさらにシャードを追加する必要がある場合は、ステップ 3 を繰り返して、すべての新しいシャードにゾーンを割り当てる必要があります。

  • データベースに新しいコレクションが継続的に追加される場合は、それらに対してステップ 4 と 5 を繰り返す必要があります。これらのステップを実行しないと、新しいコレクションはプライマリシャードにのみ作成され、そのシャードのコレクション数が増加し、再びパフォーマンスの不安定性を引き起こす可能性があります。

リスク勧告

多数のコレクションを含むデータベースを直接削除するために dropDatabase コマンドを使用することは、強くお勧めしません

dropDatabase コマンドを実行した後、WiredTiger エンジンは非同期クリーンアップ操作を実行し、削除対象としてマークされたすべてのコレクションのメタデータと物理ファイルを順次削除します。この操作はセカンダリノードでのレプリケーションを妨害し、レプリケーションのレイテンシを増加させる可能性があります。これにより、フロー制御メカニズムがトリガーされたり、{writeConcern:majority} を使用するすべての書き込み操作に影響を与えたりする可能性があります。

このリスクを軽減するために、次のアプローチを検討してください。

  • バッチ間で適切な間隔を空けて、コレクションをバッチで削除します。すべてのコレクションが削除された後、最後の dropDatabase コマンドを実行します。

  • DTS または他の移行ツールを使用して、保持したいデータベースとコレクションを新しいインスタンスに移動します。移行と切り替えが完了した後、古いインスタンスを削除します。

すべての場合において、インスタンスに適切なレプリケーションレイテンシアラートを設定する必要があります。インスタンスでこの問題が発生した場合は、チケットを送信して技術的な支援を求めてください。

まとめ

  • 一般的なルールとして、単一のレプリカセット内のコレクションの総数を 10,000 未満に保つようにしてください。個々のコレクションに多数のインデックス (例えば 15 以上) がある場合は、この数をさらに低くする必要があります。

  • コレクションベースの分離を使用するマルチテナントシステムなど、アプリケーションの要件で多数のコレクションが必要な場合は、アプリケーションロジックを分割し、シャードクラスターインスタンスを使用することを検討してください。

  • データベースがすでにコレクションが多すぎる影響を受けており、アプリケーションのデータモデルをどのように変更すればよいかわからない場合は、チケットを送信してテクニカルサポートに連絡し、支援を求めてください。

関連ドキュメント