シャーディングを行わない場合、コレクション内のすべてのデータは単一のシャードに格納され、他のシャードはアイドル状態のままになります。シャーディングは、すべてのシャードにデータを分散させることで、各シャードがワークロードの一部を処理するようにします。
以下の例は、シャーディングが構成される前の db.stats() の出力を示しています。1つのシャード (mgset-xxx65) にはデータがなく、1,000,021個のオブジェクトすべてがもう一方のシャード (mgset-xxx67) に存在します。
mongos> db.stats()
{
"raw" : {
"mgset-xxx65/xxx" : {
"db" : "mongodbtest",
"collections" : 0,
"views" : 0,
"objects" : 0,
"avgObjSize" : 0,
"dataSize" : 0,
"storageSize" : 0,
"numExtents" : 0,
"indexes" : 0,
"indexSize" : 0,
"fileSize" : 0,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000001")
}
},
"mgset-xxx67/xxx" : {
"db" : "mongodbtest",
"collections" : 2,
"views" : 0,
"objects" : 1000021,
"avgObjSize" : 352.4417477232978,
"dataSize" : 352449149,
"storageSize" : 209125376,
"numExtents" : 0,
"indexes" : 1,
"indexSize" : 10141696,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000001")
}
}
}
}前提条件
インスタンスはシャードクラスターインスタンスである必要があります。
シャードキーの選択
シャードキーは、MongoDB がシャード間でデータをどのように分散させるかを決定します。シャードキーはクエリのパフォーマンスとデータ分散に直接影響するため、慎重に選択する必要があります。シャードキーの詳細については、シャードキーおよびシャードキーの選択方法をご参照ください。
優れたシャードキーには、次の 3つの特性があります。
高いカーディナリティ:キーが多くの異なる値を持ち、きめ細かいデータ分散を可能にします。
低い頻度:単一のキー値が支配的になることはありません。頻繁に出現する値は、移動不可能な大きなチャンクを作成します。
非単調な変化:キーは着実に増加または減少しません。単調なキーは、すべての書き込みを 1つのシャードに集中させます。
シャードキーの可変性は MongoDB のバージョンによって異なります。
4.4 より前:シャードキーは作成後に変更または削除できません。
4.4 以降:refineCollectionShardKey は、既存のシャードキーにサフィックスフィールドを追加します。
5.0 以降:reshardCollection は、シャードキーを完全に変更します。
シャーディング戦略
MongoDB は、範囲シャーディング、ハッシュシャーディング、および複合シャードキーをサポートしています。
| 特性 | 範囲シャーディング | ハッシュシャーディング |
|---|---|---|
| 仕組み | シャードキーの値の範囲に基づいてデータをチャンクに分割します | 単一のフィールド値をハッシュ化し、ハッシュ範囲によってデータを分散します |
| 分散 | 不均一になる可能性があり、書き込みが分散されずにホットスポットが作成されることがあります | すべてのシャードノードに均等に分散され、書き込みが分散されます |
| 範囲クエリ | 効率的です。mongos ルーターがターゲットシャードを直接特定します。 | 非効率的です。クエリはすべてのシャードノードにブロードキャストされます。 |
| 最適な用途 | カーディナリティが高く、頻度が低く、非単調なキー。範囲クエリに依存するワークロード | カーディナリティが高く、単調に増加または減少するキー。ランダムな読み取りと書き込みを必要とするワークロード |
| シャードキーの値 | 1 (昇順) または -1 (降順) | "hashed" |
複合シャードキーは、複数のフィールドを組み合わせます。単一のフィールドでは十分なカーディナリティが得られない場合や、クエリが複数のフィールドでフィルター処理する場合に複合キーを使用します。例えば、カーディナリティの低いキーと単調に増加するキーを組み合わせます。
戦略の選択
クエリがシャードキーの値の範囲を頻繁にスキャンする場合は、範囲シャーディングを使用します。ホットスポットを避けるために、キーが非単調であることを確認してください。
書き込み量が多く、データを均等に分散させる必要がある場合は、ハッシュシャーディングを使用します。範囲クエリがすべてのシャードノードにヒットするというトレードオフを受け入れる必要があります。
コレクションのシャーディング
以下の手順では、mongodbtest データベースと customer コレクションを例として使用します。
ステップ 1:シャードクラスターへの接続
mongo シェルを介してシャードクラスターインスタンスに接続します。接続方法については、シャードクラスターインスタンスへのログオンをご参照ください。
ステップ 2:データベースのシャーディング有効化
インスタンスが MongoDB 6.0 以降を実行している場合は、このステップをスキップしてください。MongoDB 6.0 から、sh.enableSharding() は不要になりました。
次のコマンドを実行して、ターゲットデータベースでシャーディングを有効にします。
sh.enableSharding("mongodbtest")ステップ 3:シャードキーへのインデックス作成
コレクションをシャーディングする前に、シャードキーをサポートするインデックスを作成します。
構文:
db.<collection>.createIndex(<keyPatterns>, <options>)詳細については、db.collection.createIndex() をご参照ください。
範囲シャーディングの例 (name フィールドの昇順インデックス):
db.customer.createIndex({ name: 1 })ハッシュシャーディングの例 (name フィールドのハッシュインデックス):
db.customer.createIndex({ name: "hashed" })インデックスタイプの値:
| 値 | タイプ |
|---|---|
1 | 昇順 |
-1 | 降順 |
"hashed" | ハッシュ |
ステップ 4:コレクションのシャーディング
sh.shardCollection() を実行して、コレクションをシャーディングします。
構文:
sh.shardCollection("<database>.<collection>", { "<key>": <value> })範囲シャーディングの例:
sh.shardCollection("mongodbtest.customer", { "name": 1 })ハッシュシャーディングの例:
sh.shardCollection("mongodbtest.customer", { "name": "hashed" })<value> パラメーターはシャーディング戦略を決定します。
| 値 | 戦略 |
|---|---|
1 | 範囲シャーディング |
"hashed" | ハッシュシャーディング |
ステップ 5:バランサーによるデータ分散の待機
シャーディングを構成すると、バランサーは基準を満たすデータを自動的に分割し、シャードノード間でチャンクを移行します。
バランサーはデータ移行中にインスタンスのリソースを消費します。初期シャーディングはオフピーク時に実行してください。バランサーのアクティブウィンドウを設定して、バランサーのアクティビティを特定の期間に制限し、ピーク時のパフォーマンスへの影響を防ぎます。
シャーディング構成の確認
データ分散の確認
sh.status() を実行して、シャーディングのステータスとシャードノード間のデータ分散を表示します。
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("5xxx")
}
shards:
{ "_id" : "d-bpxxx3c4", "host" : "mgset-xxx29/xxx", "state" : 1 }
{ "_id" : "d-bpxxx834", "host" : "mgset-xxx27/xxx", "state" : 1 }
active mongoses:
"3.4.6" : 2
autosplit:
Currently enabled: yes
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
51 : Success
databases:
{ "_id" : "mongodbtest", "primary" : "d-bpxxx834", "partitioned" : true }
mongodbtest.customer
shard key: { "name" : 1 }
unique: false
balancing: true
chunks:
d-bpxxx3c4 51
d-bpxxx834 52
too many chunks to print, use verbose if you want to force print
{ "_id" : "test", "primary" : "d-bpxxx834", "partitioned" : false }シャードごとのストレージ確認
db.stats() を実行して、各シャードノードのストレージ統計を表示します。
mongos> db.stats()
{
"raw" : {
"mgset-xxx" : {
"db" : "mongodbtest",
"collections" : 2,
"views" : 0,
"objects" : 496075,
"avgObjSize" : 353.0421932167515,
"dataSize" : 175135406,
"storageSize" : 434943968,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 17107270,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000001")
}
},
"mgset-xxx" : {
"db" : "mongodbtest",
"collections" : 2,
"views" : 0,
"objects" : 505423,
"avgObjSize" : 352.9883444164591,
"dataSize" : 178408428,
"storageSize" : 501801512,
"numExtents" : 0,
"indexes" : 2,
"indexSize" : 17493372,
"ok" : 1,
"$gleStats" : {
"lastOpTime" : Timestamp(0, 0),
"electionId" : ObjectId("7fffffff0000000000000001")
}
}
}
}シャーディング後、両方のシャードノードにはほぼ同量のデータ (それぞれ約 496,075個と 505,423個のオブジェクト) が格納されます。