Cosmos DB の offset limit

Cosmos DB (今回はNoSQLを想定)にはよくある指定件数までスキップして指定件数分のデータを取得するOffset Limit句があります。

ただドキュメントには

OFFSET LIMIT を使用するクエリの RU 料金は、オフセットされる用語の数が増えるにつれて増加します。 複数の結果ページがあるクエリの場合は、通常、継続トークンを使用することをお勧めします。 継続トークンとは、後でクエリを再開できる場所の “ブックマーク” です。 OFFSET LIMIT を使用する場合、”ブックマーク” はありません。 クエリの次のページを返す場合は、最初から開始する必要があります。

項目を完全にスキップしてクライアント リソースを節約したい場合は、OFFSET LIMIT を使用してください。 たとえば、1000 番目のクエリ結果にスキップし、1 から 999 の結果は表示する必要がない場合は、OFFSET LIMIT を使用します。 バックエンドでは、OFFSET LIMIT は引き続き、スキップされた項目を含めて各項目を読み込みます。 パフォーマンス上の利点は、不要な項目の処理を回避することによる、クライアント リソースの削減で測定されます。

とありOffset LimitしてるのにRUはOffsetが大きくなるとRUも増えてCosmos DBのバックグラウンド側はOffsetまで全部読み込む、とあります。
仕組み的にはまぁそうですね、という感じなのですが補足するとインデックスがない場合の話であってインデックスが効く場合はこの限りではありません。

よくあるクロスパーティションクエリーだと全体から取得してからでないと位置が定まらないのでドキュメント記載通りになります。

1パーティションに10万件あるコンテナーでクエリしてみましょう。

image
image
image
image

位置が10、100、1000、10000と10倍していくとだいたい件数に応じてRUも(取得時間も)増大します。
インデックスの利かない全パーティションのデータを取得するのでしょうがない。

次はインデックスが効く1パーティションに限定したクエリで同じように位置を10、100、1000、10000として投げてみます(Whereのところは諸事情でぼかし)

image
image
image
image

インデックスのおかげで全読み込みしなくても位置がわかるのでOffsetが増大してもRUに変化はありません。

パーティション設計とインデックスが大事ですね。

コメントを残す