DynamoDB 平行掃描
平行掃描把一個 Scan 拆成 N 個獨立的 Scan 請求,每個都認領
資料表的一個 Segment,這樣多個工作者就能同時讀它。當你想讀
整張資料表、讀得比單一分區吞吐量所允許的更快時,這是唯一的辦法。
什麼是 DynamoDB 平行掃描?
DynamoDB 平行掃描透過 Segment 與 TotalSegments 把一個 Scan 拆成 N 個獨立請求,每個請求認領資料表的一個 Segment,讓多個工作者同時並行讀取。這是讓整張資料表的讀取速度突破單一分區吞吐量限制的唯一方法——但它仍是完整讀取,你要為掃描到的每個項目付費。
- 一次循序的
Scan一次讀一個分區——它的速度被釘在 單一分區的吞吐量上,無論資料表多大都一樣。 Segment+TotalSegments把讀取分片 到TotalSegments個工作者上; 每個工作者平行地掃自己的那片。- DynamoDB 對分區鍵做雜湊來指派區段,所以各片可能會 失衡——工作者更多不一定就更快。
- 它仍然是一個
Scan:你為讀取每個項目付費,而一個肥大的平行掃描 可能會把資料表的吞吐量從你的線上流量底下抽乾。
為什麼循序的 Scan 很慢
從 SQL 過來,整張資料表的讀取感覺像一個串流操作。在
DynamoDB 裡並非如此。資料表的資料分布在許多實體分區上,但
單一一個 Scan 是一次一個地走過它們,一頁 1 MB。
那意味著一個普通的 Scan 在某一刻只能從一個分區的吞吐量
預算裡拉取——即使資料表散布在數十個有閒置容量的分區上。
資料表越大,它爬得越久。
(AWS:平行掃描)
用 Segment 和 TotalSegments 拆分讀取
平行掃描修掉這個瓶頸。你挑一個工作者數,把 TotalSegments
設成那個數,再給每個工作者一個從零開始、各不相同的
Segment。每個工作者發出自己的 Scan;DynamoDB 並行地服務它們。
Worker 0 → Scan Segment=0 TotalSegments=4
Worker 1 → Scan Segment=1 TotalSegments=4
Worker 2 → Scan Segment=2 TotalSegments=4
Worker 3 → Scan Segment=3 TotalSegments=4
每個工作者仍各自用 LastEvaluatedKey 分頁——它從第一頁到最後一頁
都擁有自己的區段。應用程式再把這四道流縫回一起。你現在一次
讀取的是四個分區份量的吞吐量,而不是一個。
一個實作範例:每晚匯出
假設你經營一張遙測資料表,sensor-readings。每個項目是一台
現場裝置的一筆讀數:
PK = "DEVICE#a83f" (partition key — the device id)
SK = "TS#2026-06-22T03:14" (sort key — ISO timestamp)
batteryMv = 3120
tempC = 41.8
firmwareTag = "fw-7.2.1"每晚一個 cron job 把整張資料表傾印到 S3 給分析倉儲。
一次循序的 Scan 掃 80 GB 要花好幾個小時,卻幾乎用不到你預配的
讀取容量。所以你把它扇出到八個工作者:
Scan sensor-readings Segment=0 TotalSegments=8 ConsistentRead=false
…
Scan sensor-readings Segment=7 TotalSegments=8 ConsistentRead=false
八個工作者、八個區段,一次資料表讀取大約快上八倍。如果你
只需要最近的讀數,加一個 FilterExpression 在列被送上線之前把舊的
時間戳丟掉——在運算式建構器裡建立並檢視
那個運算式:
FilterExpression: begins_with(SK, :today)DynamoDB 如何把項目指派到區段
這裡是讓人栽跟頭的部分。DynamoDB 把每個項目指派到區段的方式是 對它的分區鍵做雜湊——不是依列數、不是依位元組數。
所以每個共用同一個 PK 的項目都落在同一個區段。在 sensor-readings
裡,DEVICE#a83f 的所有讀數都去到一個工作者,無論那台裝置有多少
時間戳、或它的項目集合有多大。
(AWS:平行掃描)
後果是:區段不均勻。一個工作者可能擁有三台有數百萬筆讀數的
多話裝置;另一個可能抽到空的那片。如果你的分區鍵擠成一團,
把 TotalSegments 開高也幫不上忙——你只是加了一些閒置工作者,
乾等那個熱的。鍵分布均勻,才是讓這個扇出划得來的東西。
在你跑它之前先看讀取成本
平行掃描是一個吞吐量事件,不是免費的午餐。誠實的問題是 「讀完這整張資料表會花多少讀取單位?」——而 DynoTable 會把一次掃描對著你 真實資料表所計量的讀取成本,逐區段顯示給你看, 這樣那個每晚的工作就不會在帳單上嚇到你。
陷阱與何時不必費這個事
- 吞吐量懸崖。 一個高
TotalSegments的掃描可能在幾秒內吃掉資料表的 全部讀取容量,餓死線上流量。在一張服務使用者的資料表上,用Limit參數節流每個工作者,或在離峰時段掃。 (AWS:平行掃描) - 對一個存取模式它仍是錯的工具。 平行掃描是用於 刻意的整張資料表作業——匯出、回填、遷移。如果你伸手去拿 一個來回答一個會重複出現的查詢,那是一個建模訊號:加一個 GSI,把它改成一個 Query。
- PartiQL 裡的
SELECT *是同一個掃描的偽裝。 它編譯成一個 循序的Scan。當你真的需要跨項目的分析——一個GROUP BY、 一個JOIN、一個聚合——DynoTable 的 SQL Workbench 會在一組有界的 結果集上於用戶端跑那些,而不是猛捶資料表。 - 強一致讓帳單翻倍。 一個
Scan預設是最終 一致讀取。對一次匯出,除非你真的需要一個時間點的快照, 否則就讓ConsistentRead=false。
後續步驟
把你的鍵建模到日常讀取永遠不需要掃描——從 單一資料表設計和 Query 與 Scan開始。當一次整張資料表的作業真的是 正確的選擇,試用 DynoTable對著你自己的資料表跑一次 平行掃描,並即時看著讀取成本。