N
NextTech Insights
RAG取り込みの鮮度・更新・削除チェックリスト|差分同期を壊さない設計(2026)
airagdata-engineeringoperations

RAG取り込みの鮮度・更新・削除チェックリスト|差分同期を壊さない設計(2026)

21 min read

RAGの差分取り込みを運用するための実務チェックリスト。決定的ID、冪等upsert、tombstone、派生データ削除、ACL反映、freshness SLO、照合、replayを整理します。

目次

RAGの差分取り込みで、更新漏れと削除漏れをどう防ぐ?

1分要約

  • sourceとchunkに毎回同じ決定的IDを割り当て、同じイベントを再実行しても同じ状態へ収束する冪等upsertにする。
  • 削除とACL取り消しを独立したイベントとして扱う。tombstoneを残し、chunk・vector・cacheまで消して、検索できないことを確かめる。
  • 更新・削除・権限反映に別々のfreshness SLOを置く。end-to-endの遅延を測り、定期照合と安全なreplayでdriftを直す。

どんな人向けか

  • 初回投入後も更新・削除される文書をRAGで扱うチーム
  • 定期実行、イベント駆動、または両方を組み合わせた取り込み基盤を作るエンジニア
  • 削除、権限取り消し、監査証跡に責任を持つplatform・security担当者

結論

本番のRAG indexは一度だけ作る成果物ではなく、source of truthから再生成される派生storeである。作成、更新、削除、権限変更、retry、部分失敗の後にも、正しい状態へ収束できなければならない。

基本の流れは次の通り。

  1. source文書と派生chunkを決定的に識別する
  2. 観測したsource versionと、出力したchunk ID集合を保存する
  3. 新versionを冪等にupsertする
  4. source削除時は物理cleanupより先にtombstoneを記録する
  5. 古いchunk、vector、enrichment、semantic cacheを削除する
  6. ACL変更を本文更新とは別の経路・期限で反映する
  7. 変更が検索結果へ現れる、または消えるまでを計測する
  8. 定期的に全体を照合し、driftがあれば安全にreplayする

製品機能はこの一部を担うが、契約は製品ごとに異なる。Azure AI Search indexerにはsource別の変更・削除検出、schedule、status history、reset、index projectionがある。Pineconeはnamespaceを指定したupsertとdeleteを提供する。どちらを使っても、ID、manifest、SLO、検証をアプリケーション側で設計する責任は残る。

解説

差分取り込みは「状態を収束させる」処理

取り込みjobは文章を転送するだけではない。file抽出、section分割、metadata enrichment、embedding生成、keyword/vector recordの書き込み、cache更新など複数の段階を通る。途中のどこでも失敗し得る。

したがって「jobがsuccessだった」ことと、「検索結果が最新かつ現在の権限に合っている」ことは同義ではない。各source versionがすべての派生storeへ反映されたかを追跡する。

source単位で次のstateを持つとよい。

  • 不変の source_id
  • 観測済みの source_version または単調増加するchange token
  • content hashとACL version
  • 現在有効なchunk IDのmanifest
  • activetombstonedpurged などのlifecycle state
  • 最後に成功したstageと各timestamp

source側の契約が重要な理由はAzure AI Searchにも表れている。SQLのhigh-water-mark policyではinsertとupdateのたびに対象columnが進む必要があり、Microsoftは同時transaction下の同期には rowversion を推奨している。一方、high water markだけでは物理削除されたrowを推測できない。SQL削除にはintegrated change trackingか、設定済みのsoft-delete markerが必要になる。

安定したIDがretryとcleanupを簡単にする

通常の編集やrenameで変わらないsource IDを使う。chunk IDも、可能なら安定した構造から生成する。

chunk_id = hash(tenant_id + source_id + section_anchor + chunk_variant)

chunk配列の現在位置だけに依存すると、途中へ1段落追加しただけで後続IDがすべて変わる。chunk境界を変えた場合は、新旧manifestの差分を取り、消えたIDを明示的に削除する。

決定的IDならretryも同じrecordへ向かう。Pineconeでは、既存IDへのupsertはrecord全体をoverwriteし、一部だけを変える操作はupdateとして区別される。ただし、これはPineconeの契約であり、すべてのvector databaseに共通する保証ではない。利用製品のoverwrite、merge、順序、consistencyを確認する。

削除はすべての派生層へ伝える

source objectを消しても、RAG側には次が残り得る。

  • 抽出済みtextと一時artifact
  • chunk rowとkeyword search document
  • embeddingとvector record
  • enrichment cache
  • semantic cacheと生成済み回答
  • manifest、backup、export、評価fixture

物理cleanupの前にtombstoneを記録し、遅れて届いたupdateが削除済みデータを復活させないようにする。tombstoneにはsource ID、削除version、認可scope、retention判断を持たせる。各workerは派生物を冪等に消し、完了証跡を残す。

Azureの仕様は製品固有だが参考になる。reset後にrunしても、sourceに存在しないorphan documentは自動削除されない。Azure Blob indexerでは、削除検出policyを最初のindexer runから設定する必要があり、後から加えても過去の削除は遡って検出できない。native blob soft deleteの保持期間も、indexerが削除状態を観測できるよう、実行間隔より十分長くする必要がある。

ACLの鮮度は本文の鮮度と別物

本文が同じまま、閲覧可能なuserやgroupだけ変わることがある。acl_versioncontent_version を分け、sourceが対応していればpermission専用のupdateやresyncを実行する。

Azure AI Searchのpush APIでACLを扱うにはschemaにpermission-filter fieldを用意し、取り込み時にrepositoryの権限をidentity IDへ解決する。またADLS Gen2では、ACL変更でblobの LastModified が更新されない場合があり、通常のcontent change detectionでは拾えないとMicrosoftが説明している。製品を問わず、本文の更新時刻をpermission変更signalとして兼用しないことが重要である。

freshnessは期限と観測点を決める

source eventから検索上の結果まで、種類別にSLOを置く。

  • 更新freshness: source commitから新しい認可済みversionを検索できるまで
  • 削除freshness: 削除決定からlive retrievalとresponse cacheが何も返さなくなるまで
  • ACL freshness: 権限変更から、取り消された利用者が拒否され、新規許可された利用者が正しいversionを得るまで
  • 照合freshness: driftが存在できる最長時間と、全体照合が検出するまでの期限

平均job時間だけでなくpercentileと、未完了eventの最古時刻を見る。schedule間隔は遅延の一部にすぎない。Azure AI Search indexerのscheduleは5分から24時間まで設定できるが、queue待ち、処理、failure、後段cache invalidationもend-to-endの鮮度へ影響する。

実務ガイド

Step 1: source of truthの変更契約を決める

connectorごとに、作成、更新、削除、復元、権限変更をどう通知するか整理する。cursorが単調増加するか、eventが順不同で届くか、delete markerをどれだけ観測できるかも記録する。

delete eventを出せないconnectorには、定期的な全件listingかinventory exportを組み合わせる。現存rowしか見ないhigh water markでは、「消えたrowが削除された」と証明できない。

Step 2: 安定IDとsource manifestを作る

source versionごとにmanifestを保存する。

{
  "source_id": "tenant_7:policy_42",
  "source_version": "018f3d6a",
  "acl_version": "acl_109",
  "state": "active",
  "chunk_ids": ["c_31aa", "c_90bf", "c_a712"]
}

新しいchunk集合を作り、直前の確定manifestと比較する。現行IDをupsertし、差分で消えたIDを削除する。Azureのindex projectionもparent keyを保持しながら1つのsourceをchild search documentへ展開する。利用する場合は、一般的なparent-child動作を想定せず、同機能のmapping ruleに従う。

Step 3: handlerを冪等かつversion-awareにする

次は製品非依存のpseudocodeである。

async function applySourceEvent(event: SourceEvent) {
  const current = await manifests.get(event.sourceId);

  if (current && compareVersion(event.version, current.version) <= 0) return;

  if (event.type === 'deleted') {
    await tombstones.put(event.sourceId, event.version);
    await removeDerivedData(current?.chunkIds ?? [], event.sourceId);
    await manifests.markPurged(event.sourceId, event.version);
    return;
  }

  if (await tombstones.blocks(event.sourceId, event.version)) return;

  const next = await buildChunks(event);
  await vectorStore.upsert(next.records);
  await deleteIds(difference(current?.chunkIds ?? [], next.chunkIds));
  await caches.invalidateBySource(event.sourceId);
  await manifests.commit(next.manifest);
}

基盤が対応するならcompare-and-set、transaction、outboxなどを使う。正確なatomicityの方法はplatformごとに異なる。守るべきinvariantは、古いeventが新versionを上書きしないことと、同じeventを繰り返しても余計なrecordを作らないこと。

Step 4: tombstoneのlifecycleを設計する

明示的なstateを用意する。

active -> tombstoned -> derived-data-deleting -> purged

遅延event、retry、connectorのlookback、restore policyをカバーできる期間はtombstoneを保持する。万人に共通する固定日数はない。source systemと保持義務から決める。復元はtombstoneを無条件に消す操作ではなく、新しいversionを持つeventにする。

Step 5: vector・chunk・cacheをまとめて消す

source_id と記録済みchunk manifestをkeyに、削除処理をfan-outする。Pineconeの2026-04 APIは、1つのnamespace内でIDまたはmetadata filterを指定してrecordを削除でき、namespace全体を対象にする deleteAll も備える。ほかのstoreは仕様が異なるため、実APIの契約を確認し、最も狭く安全なselectorを選ぶ。

削除後は、正確なsource IDと代表的な本文を使い、関係するすべてのtenant・ACL scopeから検索する。keyword index、semantic cache、生成回答cache、enrichment artifactも確認する。Azureのenrichment cacheでは、blob削除をcacheとindexの両方へ同期するためにindexer deletion policyが必要とされている。

Step 6: 権限変更を独立した変更として反映する

各chunkへ acl_version を保存する。権限変更時は次を行う。

  1. 信頼できるrepositoryから現在のsource ACLを解決する
  2. すべての有効chunkへ新しいpermission fieldを書き込む
  3. 古い認可scopeをkeyにしたcacheを無効化する
  4. revokeされたprincipalと、新しく許可されたprincipalで試す
  5. ACL freshness SLOに対する完了時刻を記録する

必須ACL metadataが欠落・不一致ならfail closedにする。本文だけ速く更新できても、権限が古ければ十分にfreshとはいえない。

Step 7: schedule・監視・retryを運用する

低遅延が必要ならevent-driven、取りこぼし対策にはscheduled catch-up、必要なら両方を使う。同じsourceを複数workerが競合更新しないよう、version checkまたはsource単位の直列化を行う。

event受信、source parse、chunk出力、upsert受付、delete受付、cache無効化、検証完了をstage別に数え、lagを測る。Azure AI Searchのstatus APIでは最新結果と直近のexecution historyを取得でき、処理件数と失敗件数も確認できる。ただし、これはpipelineの証跡であって、アプリのretrievalが正しい証明ではない。end-to-end probeを追加する。

Step 8: 定期照合とreplayを用意する

定期的に次を比較する。

  • source inventoryとactive manifest
  • manifestのchunk IDとkeyword/vector ID
  • sourceのcontent・ACL versionとindex metadata
  • tombstoneと、現在も検索可能な派生record

不一致はmissing、stale、orphaned、ACL-divergent、duplicateなどに分類する。専用の未検証repair処理を作らず、通常の冪等handlerへversion付きrepair eventを流す。

connector、tenant、source、期間を絞ってreplayできるだけのimmutable eventまたはsnapshotを残す。Azure indexer resetは全件再処理のための製品機能だが、reset後にはrunが必要で、orphan documentを自動cleanupしない。replayと削除確認は別々に考える。

ありがちな落とし穴

  • retryのたびにrandomなchunk IDを作る
  • chunk配列のpositionだけを安定IDに使う
  • 新versionの後に届いた古いeventを適用する
  • downstream workerがdelete markerを見る前にsourceを物理削除する
  • resetや全件reindexでorphanも自動的に消えると思い込む
  • vectorだけ消し、keyword document、抽出text、cacheを残す
  • stale dataが入った後からdeletion policyを設定する
  • content timestampをACL変更timestampとして使う
  • retrievalの鮮度ではなくschedulerのsuccessだけを測る
  • storeのoverwrite・merge契約を確かめずにupsertをretryする
  • 廃止IDを特定する前にmanifestを置き換える
  • 通常経路と別の非冪等なrepair pathで照合結果を直す
  • tenant、connector、source単位のreplay境界を持たない
  • write受付responseだけでretrievalが収束したと判断する

チェックリスト

  • [ ] すべてのsourceに不変かつtenant-scopedな source_id がある
  • [ ] すべてのchunk IDがretry間で決定的に再生成できる
  • [ ] chunk identityを現在の配列positionだけに依存させていない
  • [ ] sourceのcontent versionとACL versionを別々に追跡する
  • [ ] 古いeventとduplicate eventが新しいstateを上書きしない
  • [ ] 選んだstoreのupsert、merge、consistency、error semanticsを確認した
  • [ ] source manifestに現在の全chunk IDを記録する
  • [ ] 新manifest確定前に廃止chunk IDを特定する
  • [ ] delete時は派生データcleanupより先にdurable tombstoneを作る
  • [ ] tombstone保持期間がretry、遅延配送、restore policyをカバーする
  • [ ] keyword record、vector、抽出artifact、enrichment、cacheを削除対象に含める
  • [ ] productionと同じretrieval経路で削除を検証する
  • [ ] ACLだけの変更でもchunk metadataとcacheを更新する
  • [ ] ACL metadata欠落・不一致はfail closedにする
  • [ ] 更新・削除・ACL反映に別々のfreshness SLOがある
  • [ ] dashboardでend-to-end lagと最古の未完了eventを確認できる
  • [ ] failure・partial runを重複recordなしでretryできる
  • [ ] 照合でmissing、stale、orphaned、ACL-divergentを検出する
  • [ ] repair eventを通常の冪等取り込み経路へ流す
  • [ ] connector、tenant、source、期間を絞ってreplayできる
  • [ ] 全件rebuild訓練にorphan cleanupとretrieval probeを含める
  • [ ] backupとexportにも削除・保持ruleを適用する

FAQ

1. 文書更新はupsertだけで十分?

storeのIDとoverwrite契約を理解し、旧chunkを削除できる場合に限る。Pineconeでは既存IDへのupsertがrecord全体をoverwriteする。ただし、以前のchunkingで作られた別IDまでは消えない。manifestを持ち、廃止された集合を明示的に削除する必要がある。

2. 全件reindexをすればdelete処理は不要?

一般論としては置き換えられない。既存recordをoverwriteしても、sourceから消えたorphanが残るrebuildがある。Azure AI Searchでもresetとrunだけではorphan documentを削除しない。対応する削除検出を最初から設定するか、明示的なdelete actionを発行し、retrievalで確認する。

3. freshness SLOはどう決める?

user影響とsecurity影響から逆算する。権限取り消しや法的削除は、通常の本文更新より厳しい期限が必要な場合がある。connector delay、queue、処理、index可視化、cache invalidationを含め、schedule間隔ではなく経路全体を測る。

4. vector削除後もtombstoneを残す理由は?

遅れて届いたupdate、retry、replayで削除済み文書が復活するのを防ぐため。tombstoneが削除versionを示し、それより古いeventを拒否する。保持期間はconnectorの最大遅延、replay window、restore動作、保持要件から決める。

5. 照合完了をどう判断する?

期待するsource母集団を定義し、source inventory、manifest、index、tombstone間でIDとversionを比較する。jobがerror 0で終わっても、最初からjobへ渡されなかったsourceの欠落は検出できない。

参考資料

内部リンク

免責事項

一般的な開発・セキュリティ情報です。lifecycle、API version、consistency、retention、削除、権限の実際の動作は、利用中のsource system、search platform、vector store、契約、法規制に照らして検証してください。

人気記事

  1. 1Permit2とは何か?Approveが変わった理由と安全な使い方(チェックリスト)
  2. 2署名(Sign)画面の読み方|Approve/Permit/NFT全権限を30秒で判別するチェックリスト
  3. 3仕様→実装に落とすプロンプトテンプレ(AI開発)|AIに“迷わせない”仕様の書き方
  4. 4EVMのトークン承認(Approve)を見直す方法|Revokeの手順と判断基準(チェックリスト)
  5. 5曖昧な依頼を要件定義に変換する質問リスト(AI開発)|AIに実装させる前に聞くべきこと

関連記事