[アップデート] Amazon DocumentDBで部分インデックスがサポートされました
こんにちは。サービス開発室の武田です。
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
を作成します。
[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で部分インデックスがサポートされました。現在稼働している環境があれば、ぜひインデックスの見直しなどしてみてください。