Azure SDKのfeed range query fixを解説:Cosmos DB Python SDKで確認すべき変更点

結論から言うと、今回の「Azure SDK documentation update: feed range query fix(new)」で最初に確認すべきなのは、Azure Cosmos DB Python SDK の query_items(feed_range=...) を使い、ページングや継続トークンを保存して再開している処理です。公開APIの追加・変更はないため、通常はメソッド呼び出しを書き換える必要はありません。ただし、物理パーティション分割後に feed range が複数の物理パーティション範囲へまたがるケースでは、再開位置、重複処理、旧トークンの扱いを必ず確認すべき変更です。(GitHub)

このPRは、Azure SDK for Python リポジトリの Azure Cosmos DB 向け修正として提示されており、hotfix/azure-cosmos_4.14.6 ブランチへのバックポート、Changelog上では 4.14.7 (Unreleased) の修正として扱われています。2026年5月5日時点ではテスト修正やレビューコメント対応のコミットも含まれているため、実際の導入前には利用している azure-cosmos の配布バージョンとPRの取り込み状況を確認してください。(GitHub)

目次

Azure SDK documentation update: feed range query fix(new) の要点

今回の変更は、Azure SDK全体の大規模な仕様変更というより、Azure Cosmos DB Python SDK のクエリページング処理、とくに continuation token の扱いを安全にする修正です。PRの説明では、公開API変更なしで2つの継続トークン関連の変更を同じリリースに含めるとされています。(GitHub)

確認項目内容実務上の影響
対象になりやすい処理query_items(feed_range=...) でページングする処理分割後の再開、重複、欠落を重点確認
公開API変更なし呼び出しコードの大幅な書き換えは基本不要
継続トークンfeed range 用に構造化された状態管理を追加旧トークンからの再開時に再読込が起こり得る
partition_key= クエリ内部の継続トークン処理を統一構造化トークンの発行は環境変数で段階導入
移行の注意点mixed-version 環境に注意先に全プロセスを新SDKへ更新し、その後に設定を有効化

特に重要なのは、「APIが変わらない=影響がない」ではない点です。クエリ結果をページ単位で取得し、途中再開のために continuation token を保存しているバッチ、ETL、インデックス作成、並列スキャン処理では、挙動確認が必要です。

何が修正されたのか

query_items(feed_range=...) のページング正確性が改善される

Azure Cosmos DB Python SDK の query_items には、クエリ範囲を指定する feed_range と、1回の列挙で返す最大件数を指定する max_item_count があります。公式APIリファレンスでも、feed_range はスコープを定義するための引数、max_item_count は列挙操作で返す最大アイテム数として説明されています。(Microsoft Learn)

問題になっていたのは、もともと1つの物理パーティション範囲だった feed range が、Azure Cosmos DB 側の分割後に複数の物理パーティション範囲へ重なるケースです。この状態で query_items(feed_range=..., max_item_count=N) を実行すると、内部的に複数範囲へ問い合わせが発生し、継続トークンの扱いを誤ると重複、欠落、または終わらない反復につながる可能性がありました。(GitHub)

今回のPRでは、分割や複数範囲への重なりを意識して、feed range の継続状態をより構造化して扱う方向に修正されています。PR本文では、コレクションID、クエリ、feed range、サブ範囲ごとのバックエンド継続トークンを概念的に保持するモデルが示されています。(GitHub)

旧feed rangeトークンは「安全側」に倒して扱われる

旧形式の opaque token は、feed range パスでは無理に解釈せず、開始し直しとして扱われます。これは危険なトークン解釈で誤った位置から再開するより、正確性を優先するための判断です。結果として、旧トークンから再開した場合は以前の位置から読み直す可能性があり、まれな移行時の再試行・再起動パスでは重複行が発生する可能性があります。(GitHub)

この点は、データ処理ジョブにとって重要です。たとえば「一度処理したIDは二度処理しない」設計になっていないバッチでは、SDK更新後に旧トークンを使って再開した際、同じアイテムを再処理する可能性があります。

partition_key= 指定クエリのトークン処理も内部的に統一される

もう1つの変更は、query_items(partition_key=..., ...) の内部継続トークン処理を feed range 側と同じ枠組みに寄せるものです。ただし、構造化された full-PK 継続トークンの発行は、AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK という環境変数で制御されます。未設定の場合は従来形式を発行し、新SDK側の読み取りは従来形式と構造化形式の両方をサポートする説明になっています。(GitHub)

ここで注意すべきなのは、環境変数の値が CosmosClientConnection の構築時に読まれる点です。実行中のプロセスで環境変数を変更しても、既存クライアントの挙動は変わりません。設定を変える場合は、アプリケーションやワーカーの再起動まで含めて計画してください。(GitHub)

影響を受ける可能性が高いケース

今回の Azure SDK documentation update は、すべての Azure SDK 利用者が緊急対応すべき内容ではありません。影響が大きいのは、Azure Cosmos DB Python SDK で feed range や継続トークンを明示的に使っている処理です。

利用状況対応優先度理由
query_items(feed_range=...) を使い、.by_page() でページングしている高分割後の複数範囲ページングが主な修正対象
continuation token をDB、Queue、Blob、Redisなどへ保存して再開している高旧トークンからの再開で再読込や重複が起こり得る
複数Pod・複数VM・複数ワーカーで同じチェックポイントを共有している高mixed-version 環境でトークン形式の混在リスクがある
query_items(partition_key=...) を使い、環境変数で構造化トークン発行を有効化したい中段階導入の順序を誤ると旧SDKプロセスが読めない可能性がある
point read、write、一般的なCRUD中心低今回の中心はクエリページングと継続トークン
Python以外のAzure SDKだけを利用している低指定PRは azure-sdk-for-python の Azure Cosmos DB 関連

判断に迷う場合は、まずコードベースで次の文字列を検索してください。

grep -R "query_items" .
grep -R "feed_range" .
grep -R "continuation" .
grep -R "by_page" .
grep -R "AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK" .

検索結果が出たら、「ページ途中で停止して、保存済みトークンから再開する処理か」「複数プロセスで同じトークンを共有しているか」「処理済みデータの重複を許容できるか」を確認します。

実務で確認すべき変更点

max_item_count の期待値をテストする

過去の関連PRでは、feed range が複数の物理パーティション範囲に重なると、max_item_count=N を指定していても最大で K×N 件が返る可能性が説明されていました。たとえば3つの範囲に重なり、max_item_count=5 の場合、1ページに15件返るようなケースです。(GitHub)

今回の修正は、単に件数を切るだけでなく、継続トークンの正確性まで含めた後続対応に位置づけられます。ステージング環境では、max_item_count を小さめにしてページ境界を増やし、ページごとの件数、最終件数、重複ID、途中再開後の結果を確認してください。

旧トークンを使い続けるか、破棄して取り直すか決める

移行時に最も失敗しやすいのは、旧SDKで保存した continuation token を新SDKでそのまま使い、重複を想定していない処理です。旧feed rangeトークンは安全のため開始し直しとして扱われる可能性があるため、再処理を許容できない業務では、トークンの移行方針を決めてからSDKを更新してください。(GitHub)

実務では、次のどれかを選ぶのが現実的です。

方針向いているケース注意点
旧トークンを破棄して最初から再スキャン重複排除が実装済み、データ量が許容範囲RU消費と処理時間が増える
旧トークンを維持して再開再読込を許容できる、処理が冪等重複検知ログを必ず見る
チェックポイントを別キーで作り直す本番影響を抑えながら段階移行したい新旧ジョブの二重実行に注意
データ側の処理済みマーカーで制御厳密な一度きり処理に近づけたい書き込み競合やコストを設計する必要がある

おすすめは、少なくとも移行期間中は「アイテムID」「パーティションキー」「_etag」「処理日時」などで重複を検知できるログを残すことです。継続トークンは位置情報であり、業務的な処理済み保証そのものではありません。

full-PK構造化トークンの環境変数は段階的に有効化する

AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK は、partition_key= 指定の full-PK クエリで構造化継続トークンを発行するための環境変数です。PRのロールアウト方針では、まず新SDKをすべての環境へ展開し、すべてのPodやプロセスが更新されたことを確認してから、構造化 full-PK トークンの発行を有効化する流れが示されています。(GitHub)

コンテナやKubernetesで設定する場合は、次の順序を守ると安全です。

| 手順 | 作業 | 確認ポイント |
| -: | ——————– | ————————– |
| 1 | すべてのアプリでSDKバージョンを確認 | 古い azure-cosmos が残っていないか |
| 2 | 環境変数は未設定のまま新SDKをデプロイ | 従来形式の発行を維持 |
| 3 | 全Pod・全ワーカーの更新完了を確認 | ローリング更新中の旧プロセスがないか |
| 4 | ステージングで環境変数を有効化 | 保存済みトークンを読み書きできるか |
| 5 | 本番で段階的に有効化 | エラー率、再試行、重複処理を監視 |

設定例は次のとおりです。

export AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK=1

Pythonコード内で設定する場合は、CosmosClient を作成する前に設定する必要があります。

import os
from azure.cosmos import CosmosClient

os.environ["AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK"] = "1"

client = CosmosClient(url, credential=key)

ただし、本番環境ではコード内で環境変数を切り替えるより、コンテナ環境変数、App Service のアプリケーション設定、VMのサービス設定など、プロセス起動前に確定する仕組みで管理するほうが安全です。

移行前に見るべきチェックリスト

SDK更新前に、次の項目を確認してください。

チェック確認方法問題があった場合の対応
現在のSDKバージョンpython -m pip show azure-cosmos対象バージョンとの差分を確認
PyPI配布状況リリース履歴を確認PR取り込み前なら本番適用を待つ
feed_range 利用箇所grep やIDE検索ページングと再開処理を重点レビュー
継続トークン保存先DB、Blob、Queue、Redis、ファイル旧トークンの扱いを決める
処理の冪等性同じアイテムを2回処理しても安全かID単位の重複排除を追加
mixed-version リスクPod、VM、ジョブの更新順序先に全ワーカーを新SDKへ統一
SELECT VALUE AVG(...) の利用クエリ文字列を検索エラー発生時の代替集計を用意

配布状況については、PyPI上の azure-cosmos は本稿確認時点で最新安定版が 4.15.0 と表示されており、リリース履歴には 4.14.6 までが見えています。PR側のChangelogでは 4.14.7 (Unreleased) とされているため、記事だけを根拠に本番適用せず、実際のパッケージに修正が含まれているかを確認してください。(PyPI)

SELECT VALUE AVG(...) を使っている場合の注意点

今回のPRのChangelogには、複数の物理パーティションにまたがる SELECT VALUE AVG(...) クエリで、クライアント側集計により数学的に誤った値が返る可能性があったため、該当クエリでは ValueError を発生させる修正も記載されています。(GitHub)

これは一見すると「エラーが増える」変更に見えますが、実務上は誤った平均値を返すより安全です。たとえばレポート、課金集計、在庫分析、スコア集計などで AVG を使っている場合、SDK更新後に突然 ValueError が出る可能性があります。

対策としては、次のような見直しを検討してください。

対策内容
SUM と COUNT に分けるアプリ側で sum / count を計算する
サーバー側で完結するクエリにするfeed range スコープをまたぐクライアント側マージを避ける
集計専用コンテナを使うバッチやChange Feedで集計済みデータを保持する
エラーハンドリングを追加するValueError を検知して代替処理へ切り替える

重要なのは、SDK更新後のテストで「件数が合うか」だけを見るのではなく、「集計値が業務上期待する値か」「エラーになった場合に再試行ループへ入らないか」まで確認することです。

本番適用の進め方

まず依存関係を固定して検証する

本番で pip install azure-cosmos のようにバージョン未指定のまま更新している場合、意図せずSDKが変わる可能性があります。検証環境では、まず現在バージョンを固定し、次に修正を含むバージョンへ上げる形にしてください。

python -m pip show azure-cosmos
python -c "import importlib.metadata as m; print(m.version('azure-cosmos'))"

requirements.txt や pyproject.toml では、少なくとも本番反映時点ではバージョンを明示しておくと、ロールバックもしやすくなります。

azure-cosmos==<検証済みバージョン>

ステージングで再開テストを行う

単にクエリが成功するかだけでは不十分です。次の順序で、途中停止と再開を再現してください。

テスト見るポイント
1ページだけ取得して停止continuation token が保存されるか
保存済みトークンから再開同じアイテムが再処理されないか
max_item_count を小さくするページ境界で欠落しないか
旧SDKトークンで新SDK再開再読込時の重複を許容できるか
複数ワーカーで同時処理同じfeed rangeを二重処理しないか

ログには、最低限次の情報を出すと調査が楽になります。

job_id
feed_range_id または feed_range hash
page_number
item_count
first_item_id
last_item_id
continuation_token_saved: true/false
sdk_version
worker_id

継続トークンそのものは長く、機密性や運用上の扱いに注意が必要です。ログへ全文を出すのではなく、ハッシュ化して追跡する程度に抑えるのが現実的です。

mixed-version を避ける

もっとも避けたいのは、旧SDKのワーカーと新SDKのワーカーが同じチェックポイントストアを読み書きする状態です。新SDKは従来形式と構造化形式の読み取りに対応する説明になっていますが、古いSDKが新しい形式を読めるとは限りません。PRのロールアウト方針どおり、まず全プロセスを新SDKへ更新し、その後に構造化 full-PK トークン発行を有効化するのが安全です。(GitHub)

Kubernetesなら、ローリング更新中に旧Podが残っていないかを確認します。

kubectl get pods
kubectl describe deployment <deployment-name>

App Service、VM、バッチジョブ、Data Factory経由のカスタム処理などでも、古い実行環境が残っていないかを棚卸ししてください。

よくある失敗と回避策

「公開API変更なし」だけを見てテストを省略する

公開APIが変わらなくても、継続トークンやページングの挙動は業務結果に直結します。とくにバッチ処理では、1件の重複がメール二重送信、外部API二重呼び出し、集計値のズレにつながることがあります。

回避策は、処理を冪等にすることです。たとえば、処理済みアイテムIDを保存する、外部送信に一意キーを付ける、結果テーブルでユニーク制約を使う、といった方法があります。

環境変数を変えたのに挙動が変わらない

AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK は、クライアント接続の構築時に読み込まれます。プロセス起動後に環境変数を変更しても、既存の CosmosClient には反映されません。(GitHub)

回避策は、環境変数をデプロイ設定として変更し、アプリケーションを再起動することです。コンテナ環境では、Podの再作成まで行われたか確認してください。

旧トークン再開時の重複を想定していない

旧feed rangeトークンは、安全のため開始し直しとして扱われる可能性があります。重複が業務上問題になる場合は、SDK更新前にチェックポイントをどう扱うか決めてください。(GitHub)

回避策は、移行タイミングで旧トークンを破棄するか、重複排除を入れてから再開することです。どちらを選ぶかは、処理量、RUコスト、業務上の重複許容度で判断します。

次に取るべき行動

今回の Azure SDK documentation update: feed range query fix(new) は、Azure Cosmos DB Python SDK の query_items(feed_range=...) を使っていない環境では影響が小さい可能性があります。一方で、feed range、ページング、continuation token、複数ワーカー処理を組み合わせている環境では、SDK更新前に必ず検証すべき変更です。

まずはコードベースで feed_range と continuation の利用箇所を洗い出し、保存済みトークンからの再開テストを行ってください。次に、旧SDKと新SDKが混在しないデプロイ順序を決め、AZURE_COSMOS_EMIT_STRUCTURED_CONTINUATION_PK を使う場合は全プロセス更新後に有効化します。最後に、重複処理・欠落・ValueError・RU消費を監視できるログを用意してから本番へ反映するのが、安全で実務的な進め方です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次