MongoDB Academy · レッスン

レンジシャーディングとハッシュシャーディングの戦略

範囲クエリにはレンジシャーディングを、均一な書き込み分散にはハッシュシャーディングを使うようコレクションを構成し、それぞれのトレードオフを比較します。

レッスン 3/413 ステップ

「レンジシャーディングとハッシュシャーディングの戦略」はCoddyKit上の無料MongoDB Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはMongoDB Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 MongoDB Academyコースには全4レッスンが含まれています。

2つのシャーディング戦略の比較

MongoDBには、組み込みのシャーディング戦略として範囲シャーディングとハッシュシャーディングの2つがあります。範囲シャーディングは、シャードキー値の連続した範囲を特定のシャードに割り当てます。ハッシュシャーディングは、まずキーにハッシュ関数を適用し、そのハッシュに基づいて分散します。どちらにも異なる強みがあり、適切な選択はデータアクセスパターンによって決まります。

範囲シャーディング:仕組み

範囲シャーディングでは、MongoDBがシャードキーの値域を連続した範囲に分割し、各範囲(チャンク)をシャードに割り当てます。たとえば、userIdが1~10,000のユーザーをシャードAに、10,001~20,000のユーザーをシャードBに割り当てるといった具合です。シャードキーの値が近いドキュメントは同じシャードに配置されるため、範囲クエリに適しています。

// Enable ranged sharding on a field
sh.shardCollection('mydb.products', { category: 1, price: 1 })

// Range query is now targeted to the shard(s) holding that range
db.products.find({ category: 'electronics', price: { $lt: 100 } })

範囲シャーディング:強み

範囲シャーディングは、アプリケーションが値の範囲を頻繁にクエリする場合に優れています。たとえば、日付範囲、価格範囲、アルファベット順の名前の範囲、数値IDで並べ替えたページネーション結果などです。隣接する値が同じ場所に配置されるため、範囲クエリは1つまたは少数のシャードだけにアクセスするターゲットクエリとなり、レイテンシーを低く保てます。

// With ranged sharding on { orderId: 1 }, this is targeted:
db.orders.find({
  orderId: { $gte: 50000, $lte: 60000 }
})
// mongos knows exactly which shard owns this range

範囲シャーディング:弱点 — ホットスポット

範囲シャーディングの重大な弱点は、シャードキーが単調増加する場合(タイムスタンプ、自動インクリメントID、ObjectIdなど)に書き込みホットスポットが発生することです。新しいドキュメントはすべて範囲の上限側に集中し、1つのシャードに配置されます。バランサーがチャンクを移行するまで、そのシャードがすべての書き込みトラフィックを処理し、他のシャードはアイドル状態になります。

// Problematic: all new events go to the max-range shard
sh.shardCollection('mydb.events', { createdAt: 1 }) // ranged, monotonic = hot spot

// Production symptom: one shard has 90%+ of recent data
// and absorbs all write IOPS

ハッシュシャーディング:仕組み

ハッシュシャーディングでは、MongoDBがシャードキーの値をハッシュ化し、そのハッシュを使ってチャンクを決定します。元のキーが単調増加していても、ハッシュ値はランダムに見えるため、ドキュメントはハッシュ値に基づいて分散されます。これにより、初期書き込みがすべてのシャードにほぼ均等に分散されます。

// Hashed sharding on _id (neutralizes ObjectId monotonicity)
sh.shardCollection('mydb.events', { _id: 'hashed' })

// Hashed sharding on userId
sh.shardCollection('mydb.sessions', { userId: 'hashed' })

ハッシュシャーディングの長所

ハッシュシャーディングは、シャード間で書き込みを均等に分散することが主な目的で、シャードキーに対する範囲クエリが不要な場合に最適です。単調なキーを使用する高頻度の挿入ワークロード(イベントログ、IoTセンサーデータ、メッセージングなど)で、すべてのシャードに書き込み負荷を均等に分担させたい場合に適しています。

// With hashed sharding, inserts are spread uniformly:
// doc1 (hash: 2345...) -> shard A
// doc2 (hash: 8901...) -> shard C
// doc3 (hash: 4567...) -> shard B
// No hot spot regardless of insert order

ハッシュシャーディングの弱点:範囲クエリの効率が低い

ハッシュシャーディングのトレードオフは、シャードキーに対する範囲クエリがscatter-gatherになることです。隣接するハッシュ値が複数のシャードに分散するため、{ createdAt: { $gte: t1, $lte: t2 } }のようなクエリは、すべてのシャードに処理を分散させる必要があります。範囲クエリを頻繁に実行し、レイテンシーが重要な場合、ハッシュシャーディングによってシャーディングの性能向上が相殺される可能性があります。

// With hashed sharding on createdAt:
// Range query CANNOT be targeted — fans out to all shards
db.events.find({ createdAt: { $gte: ISODate('2025-01-01'), $lte: ISODate('2025-02-01') } })
// Equivalent to a full collection scan across all shards

レンジシャーディングとハッシュシャーディングの選択

判断の目安:レンジシャーディング → シャードキーが自然に分散しており(単調増加ではなく)、主要なクエリがそのキーに対する範囲クエリである場合。ハッシュシャーディング → シャードキーが単調増加する場合、または主要なクエリがカーディナリティの高いフィールドに対するポイント検索(等価検索)である場合。迷ったときに挿入がボトルネックであれば、ハッシュシャーディングを優先してください。

ハイブリッド:ハッシュコンポーネントを含む複合キー

両方の方式を、先頭フィールドをレンジ方式にしてクエリの局所性を確保し、2番目のフィールドにハッシュ方式を追加する複合シャードキーで組み合わせることができます。例:{ tenantId: 1, _id: 'hashed' }では、テナントごとにデータを近接配置しながら、各テナント内でシャード間に書き込みを分散できます。

// Ranged tenantId + hashed _id within tenant
// Writes are distributed; per-tenant queries are targeted
sh.shardCollection('mydb.events', { tenantId: 1, _id: 'hashed' })

// Targeted: all tenantId queries go to the right shard(s)
db.events.find({ tenantId: 'acme', _id: ObjectId('...') })

使用中の方式を確認する

コレクションのシャーディング設定を調べることで、使用中の方式を確認できます。config serverのメタデータにはシャードキーと、'hashed'を使用しているかどうかが保存されています。sh.status()コマンドとdb.collection.stats()のどちらでも、この情報を確認できます。

// Check sharding info for a collection
use config
db.collections.findOne({ _id: 'mydb.events' })
// { key: { _id: 'hashed' }, unique: false, ... }

// Or via sh.status()
sh.status()

一括ロード用のチャンクの事前分割

新しくシャーディングしたコレクションにデータを一括ロードする場合、最初はすべてのチャンクが1つのシャードに存在し、balancerによる移行が必要になります。これは時間がかかる場合があります。事前分割では、ロード前に空のチャンクを作成し、すべてのシャードに分散させます。これにより、balancerの作業を最小限に抑え、最初の挿入から書き込みを分散できます。

// Pre-split chunks for ranged sharding
// Define desired split points and assign to shards
db.adminCommand({ split: 'mydb.events', middle: { userId: 500000 } })
db.adminCommand({ moveChunk: 'mydb.events',
  find: { userId: 500000 }, to: 'shard02' })

理解度チェック

このレッスンで学んだMongoDBとNoSQLデータベースの概念について、理解度を確認しましょう。

レッスンのまとめ

このレッスンでは、レンジシャーディングは類似したキー値を近接配置して範囲クエリを効率化する一方、単調なキーではホットスポットを発生させること、ハッシュシャーディングはシャード間に均等に分散する一方、範囲クエリをscatter-gatherにすること、そして複合キーによって両方の利点を組み合わせられることを学びました。次は、データを特定のリージョンに固定するゾーンシャーディングについて学びます。

無料で開始

AI チューターと学ぶ JavaScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
30
レッスン
120

よくある質問

「レンジシャーディングとハッシュシャーディングの戦略」レッスンは無料ですか?

はい。「レンジシャーディングとハッシュシャーディングの戦略」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、MongoDB Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 MongoDB Academyコースには全4レッスンが含まれています。

「レンジシャーディングとハッシュシャーディングの戦略」で何を学びますか?

範囲クエリにはレンジシャーディングを、均一な書き込み分散にはハッシュシャーディングを使うようコレクションを構成し、それぞれのトレードオフを比較します。 ブラウザで直接実行するハンズオンコードでMongoDB Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

MongoDB Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのMongoDB Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「レンジシャーディングとハッシュシャーディングの戦略」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このMongoDB Academyレッスンでコードを書いて実行できますか?

はい。すべてのMongoDB Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. シャーディングの概念:チャンク、バランサー、シャードキー
  2. シャードキーの選択:カーディナリティ、頻度、単調性
  3. レンジシャーディングとハッシュシャーディングの戦略
  4. ゾーンシャーディング:データのリージョン固定
← MongoDB Academyに戻る