中階閱讀時間 5 分鐘

DynamoDB 向量搜尋

DynamoDB 在 2026 年 8 月 5 日獲得了原生的向量搜尋。你把內嵌向量以普通的 NumberList 存在項目上,新增一個向量索引,然後用新的 SearchVectors API 執行近似最近鄰查詢。

在此之前,相似度搜尋意味著把你的資料表複製到 OpenSearch 或一個獨立的向量資料庫,並讓兩邊保持同步。那條管線不再需要了。而取代它的計費模型,在 DynamoDB 裡前所未見。

DynamoDB 支援向量搜尋嗎?

支援——自 2026 年 8 月 5 日起原生支援。你把內嵌向量以普通的 NumberList 存放、新增一個向量索引,然後用 SearchVectors API 執行近似最近鄰查詢—— 不需要 OpenSearch 副本,也不需要獨立的向量資料庫。它只能用在隨需資料表上,最多 4,096 個維度,並按寫入、搜尋與儲存的位元組數計費。

  • 第三個索引家族:向量索引與 和 LSI 並列。一個新的讀取 API(SearchVectors)、僅支援 ANN、僅限隨需資料表、最多 4,096 個維度。
  • 快,而且經過實測:對照我們在 us-east-1 實際建立的 1024 維索引,SearchVectors 回應得和來自同一個用戶端的 GetItem 一樣快(p50 39 ms 對 44 ms),而一筆剛寫入的向量約 136 ms 後就能被搜尋到。
  • 按位元組計費:向量寫入每 GB $0.52、每次搜尋所檢查的向量資料每 GB $0.002、儲存每 GB-月 $0.25(us-east-1)。替內嵌向量建立索引後,它在基礎資料表的副本恰好按每個維度 4 個位元組計費;同一個 list 不建索引則約按 1.9 倍計費。
  • S3 Vectors 仍然是大宗儲存的家:靜態儲存約便宜 8 倍,批次載入也便宜得多。DynamoDB 的優勢在毫秒級讀取、串流式寫入,以及讓向量與它所描述的項目住在一起。

向量索引是如何運作的

沒有新的屬性型別。內嵌向量就是項目上一個普通的數字 list,在線路上是 {"L": [{"N": "0.0132"}, {"N": "-0.0475"}, …]},用你已經在用的 PutItemUpdateItem 寫入。

索引是一個獨立的結構。DynamoDB 以 32 位元浮點數的精確度把向量非同步複製進去,連同你投影或用來過濾的任何屬性。搜尋結果是最終一致的,就像一次 讀取。

這個延遲在實務上很小。對照我們實際建立的測試索引,一個剛寫入的向量在 PutItem 返回後約 136 ms 就出現在搜尋結果裡。儘管如此,永遠別把「讀你自己剛寫的」流程建立在它之上。

非同步複製,f32PutItem / UpdateItem基礎資料表內嵌向量存為 Number List向量索引向量 + 過濾屬性SearchVectorsTopK + 等值過濾帶分數的 Top-K 項目

它與你熟悉的索引類型並排時的位置:

向量索引GSILSI
每個資料表上限5205
讀取 APISearchVectorsQueryScanQueryScan
PartiQL
容量模式僅限隨需兩者皆可兩者皆可
一致性最終一致最終一致有強一致可用
建表後新增

每個索引在建立時就固定了維度數(最多 4,096)和三種距離函數之一。COSINEEUCLIDEAN 的分數越低越相似;DOT_PRODUCT 的分數越高越相似,而且可以是負值。這些之後都不能再改。

在你做任何基準測試之前,先說一個精確度上的注意事項。索引以 f32 持有向量;更高精確度的值會被接受,但在進入時會損失精確度。如果你帶著 float64 的內嵌向量而來,每一次距離都是對 f32 副本計算的,所以召回率要對著 f32 去量測,而不是對你的原始向量。

建立一個並對它搜尋

假設你要對支援工單做語意搜尋,讓客服不必匹配關鍵字就能找到「之前也遇過這個問題的客戶」。每個工單項目都帶著一個由它的主旨與內文產生的內嵌向量,用什麼模型產生都行(Titan Text Embeddings V2 在 Bedrock 上每百萬輸入 token 收 $0.02)。

把索引加到現有的資料表上。HASH 元素把每次搜尋限定在一個 product 值內;INLINE_FILTER 屬性(最多 18 個)允許在搜尋時做等值過濾:

aws dynamodb update-table \
  --table-name SupportTickets \
  --attribute-definitions AttributeName=product,AttributeType=S \
                          AttributeName=severity,AttributeType=S \
  --vector-index-updates '[{"Create": {
    "IndexName": "TicketEmbeddings",
    "VectorAttribute": {"AttributeName": "embedding"},
    "SearchSchema": [
      {"AttributeName": "product", "SearchSchemaElementType": "HASH"},
      {"AttributeName": "severity", "SearchSchemaElementType": "INLINE_FILTER"}
    ],
    "Projection": {"ProjectionType": "KEYS_ONLY"},
    "Dimensions": 1024,
    "DistanceFunction": "COSINE"
  }}]'

這次建置的行為像一次 GSI 回填,但稜角更鋒利。整個建置期間 SearchVectors 都返回 ValidationException,沒有部分結果。

AWS 警告,即使 DescribeTable 已經顯示 ACTIVE,搜尋 endpoint 仍可能繼續拒絕一段時間。沒有 waiter 可用;用一個放在重試迴圈裡的真實搜尋去探測。當我們把索引和一張空資料表一起建立時,它在 26 秒後變為 ACTIVE,再過 0.6 秒就接受了搜尋。

搜尋時,查詢用的內嵌向量以 {"N": …} 值組成的裸 JSON 陣列傳入。別把它包進 DynamoDB 的 L。儲存的屬性用 list 型別,請求參數卻不用,把兩者搞混是最容易犯的第一個錯:

aws dynamodb search-vectors \
  --table-name SupportTickets \
  --index-name TicketEmbeddings \
  --search-vector file://query-embedding.json \
  --top-k 5 \
  --search-condition-expression "product = :p AND severity = :sev" \
  --expression-attribute-values '{":p": {"S": "checkout"}, ":sev": {"S": "high"}}'

你會拿回最多 TopK 個項目,按最相似優先排序,每個都帶一個 Score,另外在你要求時附上 ConsumedCapacityTopK 上限是 100,沒有分頁,回應上限是 16 MB。

內嵌向量本身不會出現在結果裡,除非你投影了它並且要求返回。這個預設是刻意的;返回向量會同時撐大回應和搜尋帳單。

過濾表達式只接受等值,沒有 BETWEENINbegins_with。當索引定義了 HASH 屬性時,每次搜尋都必須為它釘死恰好一個值。AWS 對範圍運算子的措辭是 "not yet available",所以這一點日後可能放寬。

有兩個維運上的意外值得在第一次部署前就知道。SearchVectors 需要新的 dynamodb:SearchVectors IAM 動作,而你現有的任何讀取政策都不包含它。

它還會連到一個獨立的 endpoint:search-dynamodb.{region}.amazonaws.com。只涵蓋 dynamodb.{region} 的出站允許清單和 VPC endpoint 設定,會單單弄壞向量搜尋,而那個連線錯誤永遠不會告訴你原因。

向量索引如何計費

三個新的計費項,全都按位元組計費、每次寫入與每次搜尋請求最低 1 KB,並疊加在正常的資料表費用之上(us-east-1,取自 AWS 定價 API,2026-08-15):

計費項StandardStandard-IA
向量寫入$0.52/GB$0.65/GB
每次搜尋檢查的向量資料$0.002/GB$0.0025/GB
儲存(資料表與索引)$0.25/GB-月$0.10/GB-月

文件警告,內嵌向量在基礎資料表的副本——以 List 裡的十進位字串儲存——可能比索引裡的 f32 副本 "considerably larger"。我們在 us-east-1 對實際運行的資料表量測了寫入單位計費,而真相更加離奇。

一個放在沒有向量索引的屬性上的內嵌向量,按文件記載的十進位規則計費,約為 f32 大小的 1.9 倍。把一個向量索引指向同一個屬性,它在基礎資料表的計費就降到恰好每個維度 4 個位元組:

維度數未建索引的 List 屬性(計費額)同一個屬性、建了向量索引(計費額)
2561,914 B1,024 B
7685,760 B3,072 B
1,0247,653 B4,096 B
1,53611,501 B6,144 B
3,07222,957 B12,288 B

量測方式是用一個填充屬性對寫入單位的邊界做二分搜尋,每次寫入都用全新的項目鍵,校準到位元組。我們完整的 1024 維工單項目計了 5 個寫入單位;同一個項目若 embedding 上沒有索引則計 8 個。

在同一批量測裡,向量寫入這個計費項緊貼著 f32 大小。VectorWriteRequestBytes 回報為每個維度 4 個位元組,在裸索引上外加 11 B 的鍵負擔,在我們帶兩個屬性的 search schema 上則外加 65 B。

搜尋計費是那個你無法事先算出的計費項。VectorSearchRequestBytes 追蹤 ANN 遍歷檢查了多少向量資料,而 AWS 自己的指引是透過 ReturnConsumedCapacity 去實測,而不是從維度數去估算。

我們的探測給出了第一批資料點。對一個 50 個向量的分割區做 TopK=10,每次搜尋檢查了 22.2-22.4 KB;同一個搜尋在只有 1 個向量的分割區上仍檢查了 21.4 KB,所以在小規模下,每次查詢有一個約 21 KB(約 $0.00000004)的下限。AWS 的教學對它自己的 50 個向量範例回報了 31,449 個位元組。

定價計算器裡為資料表側的成本建個模;向量計費項會疊加在它已經算出的寫入單位之上。

DynamoDB 向量搜尋與 S3 Vectors 的對比

AWS 現在賣兩種無伺服器的向量儲存,而它們是為相反的存取模式打造的。S3 Vectors(2025 年 12 月 GA)每個索引最多容納 20 億個向量、每 GB-月 $0.06,在 100 毫秒到 1 秒的範圍內回應,且每次查詢都按整個索引的大小計費。

DynamoDB 以毫秒級回應,並按這次搜尋檢查了多少計費,而不是按索引持有多少。

DynamoDB 向量搜尋S3 Vectors
GA2026 年 8 月2025 年 12 月
延遲等級個位數毫秒(AWS 宣稱)頻繁存取約 100 毫秒、不頻繁存取低於 1 秒(AWS 宣稱)
規模上限未公布向量數上限;建立索引有 600 GB 資料表大小上限(軟性)每個索引 20 億個向量
最大維度數4,0964,096
距離函數餘弦、歐幾里得、點積餘弦、歐幾里得
索引寫入從資料表非同步複製(最終一致)強一致
過濾僅等值,≤18 個屬性 + 1 個分割區索引鍵豐富的中繼資料過濾,每個向量可過濾部分上限 2 KB
TopK100,無分頁10,000,可分頁
儲存$0.25/GB-月,兩份(資料表 + 索引)$0.06/GB-月,一份
寫入$0.52/GB,每次請求最低 1 KB$0.20/GB,每次 PUT 最低 128 KB
查詢按檢查量 $0.002/GB每百萬次請求 $2.50 + 按整個索引的處理位元組計費

寫入的最低計費量決定了串流場景的勝負,而它們指向與儲存費率相反的方向。一次寫一個 1024 維向量、以每百萬次寫入計(由已驗證的費率,加上我們實測的每個項目 5 個寫入單位 + 4,161 個向量寫入位元組算出):

寫入模式DynamoDBS3 Vectors
逐一寫入單個向量每百萬約 $5.14每百萬約 $24.41
批次(每次 PutVectors 500 個)不適用(寫入以項目為單位)每百萬約 $0.78

S3 每次 PUT 最低 128 KB 的計費量,讓它恰恰在人們以為它便宜的那種工作負載上成了昂貴的選項。把向量一個一個串流進 S3 Vectors,你要付近 5 倍於 DynamoDB 的費率;批次載入則便宜約 7 倍。

一個 1024 維語料在每月 100 萬次查詢下的每月儲存與查詢總額,由已驗證的費率算出(寫入成本見上面的每百萬次表格)。S3 Vectors 的查詢費用遵循它公布的公式:整個索引的大小乘以一個分級費率。

DynamoDB 的查詢費用取決於被檢查的位元組數,所以我們給出一個敏感度區間,而不是假裝知道你的遍歷情況:

語料規模DynamoDB 儲存DynamoDB 查詢(檢查 4 / 40 / 400 MB)S3 Vectors 儲存S3 Vectors 查詢
100 萬個向量~$1.95$8 / $80 / $800~$0.23~$11
1,000 萬個向量~$19.50$8 / $80 / $800~$2.35~$80
1 億個向量~$195$8 / $80 / $800~$23.50~$217

從那張表能看出兩件事。DynamoDB 的單次查詢成本不隨語料規模成長——一次 ANN 搜尋檢查的是一個鄰域,而不是整個索引,而分割區索引鍵的限定還會讓它更小。

S3 Vectors 的儲存優勢(約 8 倍,因為 DynamoDB 以 4 倍的費率存了兩份 f32 副本)會永遠複利下去,不管有沒有人查詢。

何時該用哪一個

  • 向量描述的是你本來就存在 DynamoDB 裡的活項目(工單、商品、使用者工作階段、代理記憶):用向量索引。一條寫入路徑、一個項目、沒有會漂移的同步管線。
  • 數百萬個內嵌向量、偶爾才查詢(對文件做 RAG、封存、夜間作業):用 S3 Vectors。批次載入便宜、靜態儲存每 GB $0.06、容忍幾百毫秒。
  • 高 QPS 加混合排序(文字相關性 + 向量、分面、彙總):答案仍然是 OpenSearch,它的基礎設施門檻是一個經典無伺服器集合約每月 $350。
  • 向量要和關聯式資料連接:Aurora PostgreSQL 加 pgvector,它能縮到零,小型 RAG 工作負載每月不到約 $50。

對一家用 DynamoDB 的團隊來說,誠實的預設是兩個都用。把熱門、需要過濾的向量留在資料表上——那裡的寫入與項目是原子的——再把長尾封存到 S3 Vectors,它強一致的批次寫入使它成為一個乾淨的匯集端。

陷阱

  • 無聲的去索引化:一個缺少索引 HASH 屬性的項目照樣寫進資料表,卻永遠不會進入向量索引。我們實際重現了它:PutItem 成功了,而 15 秒後那個向量在每一個分割區裡都不存在。沒有錯誤、沒有結果,回應裡也沒有任何東西告訴你。
  • 維度不對的寫入會被拒絕:不做遷移就切換內嵌模型,每一次寫入都會以一個點名了該屬性與兩邊大小的 ValidationException 失敗(Invalid size for parameter,在它自己的頁面上有逐字記錄),因為索引把維度數永遠釘死了。
  • 陳舊的內嵌向量:DynamoDB 從不重算向量。改了工單的文字卻不重寫 embedding,搜尋就會悄悄匹配到舊內容。標準修法是 Streams 加一個負責重新產生的消費者。
  • TopK 總是返回 K 個項目:只有三個好結果卻用 --top-k 10,你照樣拿到 10 個。用 Score 判斷相關性,而不是用結果數量,並記得分數的方向會因距離函數而翻轉。
  • 1 KB 最低計費量:低維度向量不會按比例便宜地計費,寫入和搜尋都一樣。
  • 一切都是不可變的:維度數、距離函數,以及 INCLUDE 投影的屬性集合,要改都得刪掉重建。索引儲存在索引的整個生命週期裡都計費,不管有沒有人查詢。

在你自己的資料表上試試

向量搜尋繼承了 DynamoDB 其他部分教會你的成本紀律。在決定採用某個內嵌向量之前先量好它的大小,因為項目大小限制仍然適用,而一個 3072 維的內嵌向量會讓每次項目寫入在兩個計費項上都多出 12 KB。

如果你知道 GSI 是如何非同步複製的以及何時該選 GSI 而不是 LSI,索引的機制會讓你感到熟悉。至於對同一批資料做詞彙搜尋,DynamoDB 仍然沒有全文檢索引擎;向量搜尋匹配的是語意,而不是拼寫。

項目大小計算器裡查一個內嵌向量真實的位元組成本,然後試試 DynoTable,去瀏覽你向量索引背後的那些項目——內嵌向量就以普通 list 屬性的樣子,緊挨著你用來過濾的欄位呈現。

已更新