こんにちは。サービス開発室の武田です。
Amazon DocumentDBで部分インデックスがサポートされました。エンジンバージョンが5.0以降、インスタンスベースクラスターのみとなっています!
ちなみにMongoDBでは3.2からサポートされていました。もともとオンプレなどの環境で使用していた方は待望のアップデートでしょうか。
検証環境の構築
検証環境としてDocumentDBクラスター、接続するためのサーバーが必要となります。今回はDocumentDBへ接続する環境としてCloud9を利用します。
DocumentDBはインスタンスベースであること、エンジンバージョンが5.0.0であることに注意しましょう。インスタンスクラスなどは検証なので低いものにしておきます。
Cloud9は同じVPC内に構築します。設定はすべてデフォルトで問題ありません。
Cloud9の環境作成後、DocumentDBへ接続できるようにセキュリティグループの設定を変更する必要があります。Cloud9構築時にアタッチされたセキュリティグループがありますので、DocumentDBクラスターに紐づいているセキュリティグループのインバウンドに許可設定を追加します。
以上の設定が完了したらCloud9 IDEを開きましょう。
Cloud9からDocumentDBに接続する
それではさっそくDocumentDBに接続し、部分インデックスを試してみましょう。
DocumentDBはMongoDB互換のため、各種エコシステムを利用できます。MongoDBにはREPL環境であるMongoDB Shell(mongosh)がありますのでこれを使用しましょう。mongoshはいくつかの提供形態がありますが、今回はyum
を使用します。次の内容で/etc/yum.repos.d/mongodb-org-7.0.repo
を作成します。
/etc/yum.repos.d/mongodb-org-7.0.repo
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2023/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-7.0.asc
ファイルが準備できたら、次のコマンドでmongoshをインストールします。
sudo yum install -y mongodb-mongosh-shared-openssl3
続いてDocumentDBに接続していきます。まず次のコマンドを実行して証明書をダウンロードします。
wget https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
ダウンロードできたらmongoshを起動しましょう。USERNAME
とPASSWORD
は自分の環境に合わせてください(もちろんホスト名も)。
mongosh --tls --host docdb-2024-02-27-01-48-01.cjjms3a2tkhy.ap-northeast-1.docdb.amazonaws.com:27017 --tlsCAFile global-bundle.pem --retryWrites=false --username USERNAME --password PASSWORD
部分インデックス試してみた
接続できたらいくつかクエリを実行して動作を確認しましょう。まずはデータの準備です。次のようなワンライナーで100件のサンプルデータを投入しました。
> db.users.insertMany([...Array(100).keys()].map((n) => {return { userid: n * 1000, name: `hoge${n}`, age: Math.floor(Math.random() * 60) + 15 }}));
このようなデータが作成されます。
> db.users.find().limit(3)
[
{
_id: ObjectId('65dd7d669fdeb2000428c539'),
userid: 0,
name: 'hoge0',
age: 43
},
{
_id: ObjectId('65dd7d669fdeb2000428c53a'),
userid: 1000,
name: 'hoge1',
age: 31
},
{
_id: ObjectId('65dd7d669fdeb2000428c53b'),
userid: 2000,
name: 'hoge2',
age: 56
}
]
投入できたらクエリおよび実行計画を確認します。
> db.users.find({ userid: 30000 }).explain();
{
queryPlanner: {
plannerVersion: 1,
namespace: 'test.users',
winningPlan: { stage: 'COLLSCAN' }
},
serverInfo: { host: 'docdb-2024-02-27-01-48-01', port: 27017, version: '5.0.0' },
ok: 1,
operationTime: Timestamp({ t: 1709013613, i: 1 })
}
> db.users.find({ userid:{ $gte: 30000 }, age: { $gt: 40 } }).explain();
{
queryPlanner: {
plannerVersion: 1,
namespace: 'test.users',
winningPlan: { stage: 'COLLSCAN' }
},
serverInfo: { host: 'docdb-2024-02-27-01-48-01', port: 27017, version: '5.0.0' },
ok: 1,
operationTime: Timestamp({ t: 1709013676, i: 1 })
}
注目は winningPlan: { stage: 'COLLSCAN' } の部分です。これはいわゆるフルテーブルスキャンに相当するもので、コレクションすべてを走査します。
次に部分インデックスを作成します。今回はage
が40より大きいドキュメントに対してインデックスを張ります。
> db.users.createIndex({ userid: 1 }, { partialFilterExpression: { age: { $gt: 40 } } });
それでは先ほどと同じクエリを実行してみます。
> db.users.find({ userid: 30000 }).explain();
{
queryPlanner: {
plannerVersion: 1,
namespace: 'test.users',
winningPlan: { stage: 'COLLSCAN' }
},
serverInfo: { host: 'docdb-2024-02-27-01-48-01', port: 27017, version: '5.0.0' },
ok: 1,
operationTime: Timestamp({ t: 1709013708, i: 1 })
}
> db.users.find({ userid:{ $gte: 30000 }, age: { $gt: 40 } }).explain();
{
queryPlanner: {
plannerVersion: 1,
namespace: 'test.users',
winningPlan: { stage: 'IXSCAN', indexName: 'userid_1', direction: 'forward' }
},
serverInfo: { host: 'docdb-2024-02-27-01-48-01', port: 27017, version: '5.0.0' },
ok: 1,
operationTime: Timestamp({ t: 1709014383, i: 1 })
}
find({ userid: 30000 })
は COLLSCAN のままです。一方でfind({ userid:{ $gte: 30000 }, age: { $gt: 40 } })
のクエリは IXSCAN に変わっています。これはインデックスが正しく使用されていることを示しています。
まとめ
DocumentDBで部分インデックスがサポートされました。現在稼働している環境があれば、ぜひインデックスの見直しなどしてみてください。