クラスター化されたコレクション
バージョン 5.3 で追加。
Overview
MongoDB 5.3以降では、 のクラスター インデックスを持つコレクションを作成できます。 クラスター化されたインデックスを使用して作成されたコレクションは、クラスター化されたコレクションと呼ばれます。
メリット
クラスター化されたコレクションでは、クラスター化されたインデックスのキー値順のドキュメントが保存されるため、クラスター化されていないコレクションと比較して次の利点があります。
クラスター化されたインデックス キーで範囲スキャンや等価比較を行うクエリなど、セカンダリインデックスを必要としないクラスター化されたコレクションのクエリを高速化します。
クラスター化されたコレクションはストレージ サイズが小さいため、クエリと一括挿入のパフォーマンスが向上します。
コレクションをクラスター化すると、セカンダリ TTL(Time To Live)インデックスを作成する必要がなくなります。
expireAfterSeconds フィールドを指定する場合、クラスター化されたインデックスは TTL インデックスでもあります。
TTL インデックスとして使用するには、
_id
フィールドがサポートされている日付型である必要があります。「TTL インデックス」を参照してください。クラスター化されたインデックスを TTL インデックスとして使用すると、ドキュメント削除のパフォーマンスが向上し、クラスター化されたコレクションのストレージ サイズが小さくなります。
クラスター化されたコレクションでは、挿入、更新、削除、クエリのパフォーマンスがさらに向上しています。
すべてのコレクションには _id インデックスがあります。
クラスター化されていないコレクションには、
_id
インデックスがドキュメントとは別にストアされます。これには、挿入、更新、削除の場合は 2 回の書き込みと、クエリの場合は 2 回の読み取りが必要です。クラスター化されたコレクションは、インデックスとドキュメントを
_id
値の順序でまとめてストアします。このため、挿入、更新、削除には 1 回の書き込みが必要で、クエリには 1 回の読み取りが必要です。
動作
クラスター化されたコレクションには、クラスター化されたインデックスのキー値順にドキュメントが保存されます。 クラスター化されたインデックス キーは{ _id: 1 }
である必要があります。
ドキュメントは 1 つの順序でしかストアできないため、1 つのコレクションには 1 つだけのクラスター化されたインデックスを含められます。クラスター化されたインデックスを持つコレクションのみがデータをソート順でストアします。
クラスター化されたインデックス作成し、クラスター化されたコレクションにセカンダリインデックスを追加できます。クラスター化されたインデックスはセカンダリインデックスと異なります。
クラスター化されたインデックスは、コレクションを作成するときにのみ作成できます。
クラスター化されたインデックス キーはコレクションとともにストアされます。
collStats
コマンドによって返されたコレクション サイズには、クラスター化されたインデックス サイズが含まれています。
MongoDB 6.0.7以降では、使用可能なクラスター化されたインデックスが存在する場合、MongoDB クエリ プランナーはクエリ プランニング プロセスでクラスター化されたインデックスをセカンダリ インデックスに対して評価します。 クエリがクラスター化インデックスを使用する場合、MongoDB は有界コレクションスキャン を実行します。
MongoDB 6.0.7より前では、クラスター化されたコレクションにセカンダリインデックスが存在し、そのセカンダリインデックスがクエリで使用できた場合、クエリ プランナーはデフォルトでクラスター化されたインデックスではなくセカンダリインデックスを選択していました。 MongoDB 6.1以前では、クラスター化インデックスを使用するには、クエリオプティマイザがクラスター化インデックスを自動的に選択しないため、ヒントを提供する必要があります。
重要
下位互換性のない機能
MongoDB 5.3 より前のバージョンにダウングレードする前に、クラスター化されたコレクションを削除する必要があります。
制限
クラスター化されたコレクションの制限事項:
クラスター化されたインデックス キーは
{ _id: 1 }
である必要があります。クラスター化されていないコレクションをクラスター化されたコレクションに、またはその逆に変換することはできません。代わりに、次のことができます。
$out
ステージまたは$merge
ステージで1 つの集計パイプラインを使用して、1 つのコレクションからドキュメントを読み取り、別のコレクションに書き込みます。mongodump
を使用してコレクション データをエクスポートし、mongorestore
を使用してそのデータを別のコレクションにインポートします。
デフォルトでは、クラスター化されたコレクションにセカンダリインデックスが存在し、そのセカンダリインデックスがクエリで使用できる場合、クラスター化されたインデックスではなくセカンダリインデックスが選択されます。
クラスター化されたインデックスはクエリオプティマイザ によって自動的に選択されないため、ヒントを提供する必要があります。
使用可能なセカンダリインデックスが存在する場合、クラスター化されたインデックスは クエリオプティマイザ によって自動的に使用されることはありません。
クエリがクラスター化インデックスを使用する場合、限界のあるコレクションスキャンが実行されます。
クラスター化されたインデックスを隠すことはできません。「非表示のインデックス」を参照してください。
クラスター化されたコレクションにセカンダリインデックスがある場合、コレクションのストレージ サイズは大きくなります。これは、大きなクラスター化されたインデックス キーを持つクラスター化されたコレクションのセカンダリインデックスは、クラスター化されていないコレクションのセカンダリインデックスよりもストレージサイズが大きい可能性があるためです。
クラスター化されたコレクションは、上限付きコレクションであってはなりません。
独自のクラスター化されたインデックスのキー値の設定
デフォルトでは、クラスター化されたインデックスのキー値はユニークなドキュメント オブジェクト識別子です。
独自のクラスター化されたインデックスのキー値を設定できます。あなたのキー:
ユニークな値を含める必要があります。
不変である必要があります。
順番に増加する値を含める必要があります。これは必須ではありませんが、挿入のパフォーマンスが向上します。
サイズはできるだけ小さくする必要があります。
クラスター化されたインデックスは最大 8 MB のサイズのキーをサポートしますが、それよりはるかに小さいクラスター化されたインデックスのキーの方が最適です。
クラスター化されたインデックスのキーが大きいと、クラスター化されたコレクションのサイズが大きくなり、セカンダリインデックスも大きくなります。これにより、クラスター化されたコレクションのパフォーマンスとストレージの利点が低下します。
大きなクラスター化されたインデックスのキーを持つクラスター化されたコレクションのセカンダリインデックスは、クラスター化されていないコレクションのセカンダリインデックスと比較してより多くの領域を使用する場合があります。
警告
ランダムに生成されたキー値により、クラスター化されたコレクションのパフォーマンスが低下する可能性があります。
例
このセクションでは、クラスター化されたコレクションの例を示します。
Create
例
次の create
の例では、products
という名前のクラスター化されたコレクションを追加します。
db.runCommand( { create: "products", clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "products clustered key" } } )
この例では、clusteredIndexは以下を指定しています。
"key": { _id: 1 }
は、_id
フィールドにクラスター化されたインデックス キーを設定します。"unique": true
は、クラスター化されたインデックス キーの値が一意でなければならないことを示しています。"name": "products clustered key"
は、クラスター化されたインデックス名を設定します。
db.createCollection
例
次の db.createCollection()
の例では、stocks
という名前のクラスター化されたコレクションを追加します。
db.createCollection( "stocks", { clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "stocks clustered key" } } )
この例では、clusteredIndexは以下を指定しています。
"key": { _id: 1 }
は、_id
フィールドにクラスター化されたインデックス キーを設定します。"unique": true
は、クラスター化されたインデックス キーの値が一意でなければならないことを示しています。"name": "stocks clustered key"
は、クラスター化されたインデックス名を設定します。
日付のクラスター化されたインデックス キーの例
次の create
の例では、orders
という名前のクラスター化されたコレクションを追加します。
db.createCollection( "orders", { clusteredIndex: { "key": { _id: 1 }, "unique": true, "name": "orders clustered key" } } )
この例では、clusteredIndexは以下を指定しています。
"key": { _id: 1 }
は、_id
フィールドにクラスター化されたインデックス キーを設定します。"unique": true
は、クラスター化されたインデックス キーの値が一意でなければならないことを示しています。"name": "orders clustered key"
は、クラスター化されたインデックス名を設定します。
次の例では、orders
コレクションにドキュメントを追加します。
db.orders.insertMany( [ { _id: ISODate( "2022-03-18T12:45:20Z" ), "quantity": 50, "totalOrderPrice": 500 }, { _id: ISODate( "2022-03-18T12:47:00Z" ), "quantity": 5, "totalOrderPrice": 50 }, { _id: ISODate( "2022-03-18T12:50:00Z" ), "quantity": 1, "totalOrderPrice": 10 } ] )
_id
の clusteredIndex キーには注文日がストアされています。
範囲クエリで _id
フィールドを使用すると、パフォーマンスが向上します。たとえば、次のクエリは _id
と$gt
を使用して、注文日が指定された日付よりも後の注文を返します。
db.orders.find( { _id: { $gt: ISODate( "2022-03-18T12:47:00.000Z" ) } } )
出力例:
[ { _id: ISODate( "2022-03-18T12:50:00.000Z" ), quantity: 1, totalOrderPrice: 10 } ]
コレクションがクラスター化されているかどうかの確認
コレクションがクラスター化されているかどうかを確認するには、listCollections
コマンドを使用します。
db.runCommand( { listCollections: 1 } )
クラスター化されたコレクションの場合、出力に clusteredIndex の詳細が表示されます。たとえば、次の出力では、orders
のクラスター化されたコレクションの詳細を示しています。
... name: 'orders', type: 'collection', options: { clusteredIndex: { v: 2, key: { _id: 1 }, name: 'orders clustered key', unique: true } }, ...
v
は、インデックス バージョンです。