把壓力溫度數據寫入DynamoDB:打造無伺服器歷史記錄資料庫
工廠IT技術人員專用AWS DynamoDB無伺服器資料庫ATLANTIS 自有品牌
把壓力溫度數據寫入DynamoDB:打造無伺服器歷史記錄資料庫
ATLANTIS的品牌使命「Re-Atlantis」,是重現古代理想文明對精密秩序的追求——而秩序的一個重要面向,是記憶。沒有歷史記錄的即時監控,就像沒有記憶的智慧,只能看見當下,卻無法從過去的模式中學習。這也是為什麼本篇要帶你認識DynamoDB這個無伺服器資料庫服務。詳見 ATLANTIS 品牌故事。
一、為什麼選DynamoDB,而不是傳統的關聯式資料庫?
工廠IT技術人員多半熟悉MySQL、SQL Server這類關聯式資料庫,但IoT感測器數據有一個明顯特性:寫入頻繁、結構單純、依時間查詢。DynamoDB是AWS的無伺服器NoSQL資料庫服務,天生就是為這種「時間序列」數據設計的,不需要管理資料庫伺服器、不需要規劃儲存容量、也不需要煩惱擴充問題。
資料庫伺服器
(依請求容量模式)
(隨選容量模式)
免寫刪除排程
DynamoDB vs 關聯式資料庫:核心差異
| 比較項目 | 關聯式資料庫(如MySQL) | DynamoDB |
|---|---|---|
| 伺服器管理 | 需自行維運或使用RDS代管 | 完全無伺服器,AWS全權管理 |
| 擴充方式 | 需規劃執行個體規格與儲存空間 | 隨選容量模式自動依流量擴充 |
| 資料結構彈性 | 需預先定義固定欄位結構(Schema) | 除主鍵外,每筆資料欄位可彈性不同 |
| 查詢彈性 | 支援複雜JOIN、聚合查詢 | 依主鍵設計查詢,複雜分析建議搭配其他服務 |
| 適合場景 | 複雜關聯資料、報表分析 | 高頻寫入的時間序列數據、鍵值查詢 |
對於「感測器每30秒回報一次數據」這種場景,DynamoDB的高頻寫入能力與免維運特性,正是工廠IT技術人員最需要的——你不需要成為資料庫管理員,也能打造一套穩定運作的歷史記錄系統。
二、架構總覽:兩種把資料寫入DynamoDB的方式
兩種方式的選擇原則很單純:如果只是單純儲存原始數據,不需要額外判斷邏輯,用IoT Core規則直接寫入DynamoDB最省事;如果需要先解析封包、判斷異常再決定要不要記錄,就透過Lambda函式寫入,本篇會分別示範這兩種作法。
三、資料表設計:主鍵(Partition Key)與排序鍵(Sort Key)
DynamoDB的查詢效能高度依賴主鍵設計,這是整篇文章最關鍵的觀念。對於時間序列的感測器數據,業界最常見的設計是:Partition Key用裝置ID,Sort Key用時間戳記。
| 欄位名稱 | 角色 | 範例值 | 設計理由 |
|---|---|---|---|
| device_id | Partition Key(分區鍵) | ATL-STT-001 | 相同裝置的資料會被分到同一分區,方便依裝置查詢 |
| timestamp | Sort Key(排序鍵) | 1784812345 | 同一裝置底下的資料依時間排序,方便查詢時間範圍 |
| temperature | 一般屬性 | 68.4 | 實際量測數值 |
| unit | 一般屬性 | "C" | 單位標記 |
| ttl | TTL屬性(選用) | 1787404345 | 超過此Unix時間戳記後,DynamoDB自動刪除該筆資料 |
這樣的設計讓你可以用一次查詢,取得「某裝置在某時間範圍內」的所有歷史數據,例如「查詢ATL-STT-001裝置過去24小時的所有溫度記錄」,這是本篇後段查詢範例會實際示範的操作。
建立資料表:主控台設定重點
在DynamoDB主控台建立資料表時,只需要指定Partition Key(device_id,字串型態)與Sort Key(timestamp,數字型態),其餘欄位不需要事先定義,這正是NoSQL資料庫「結構彈性」的優勢——不同型號感測器可以有不同的屬性欄位,不需要統一的資料表結構。
四、方式一:用Lambda寫入DynamoDB(含判斷邏輯)
延續第三篇的最小Lambda函式,加上寫入DynamoDB的邏輯,這是最靈活、最容易理解的作法。
範例一:Lambda解析並寫入DynamoDB
import time
import boto3
from decimal import Decimal
dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-1")
table = dynamodb.Table("factory_temperature_history")
def lambda_handler(event, context):
device_id = event.get("device_id", "unknown")
temperature = event.get("temperature")
timestamp = event.get("timestamp", int(time.time()))
if temperature is None:
return {"statusCode": 400, "body": "缺少temperature欄位"}
# DynamoDB不接受Python float,需轉換為Decimal型態
table.put_item(
Item={
"device_id": device_id,
"timestamp": timestamp,
"temperature": Decimal(str(temperature)),
"unit": "C",
"ttl": timestamp + (90 * 24 * 60 * 60) # 保留90天
}
)
print(f"已寫入DynamoDB:裝置{device_id} 溫度{temperature}°C")
return {"statusCode": 200, "body": json.dumps("寫入完成")}
這裡有一個Python工程師常踩的坑:DynamoDB不接受Python原生的float型態,必須轉換為Decimal,否則boto3會直接拋出例外。另外,ttl欄位若在建立資料表時已啟用TTL功能並指定該屬性名稱,DynamoDB會在超過該時間戳記後自動刪除該筆資料,不需要額外寫排程刪除的程式。
IAM權限:Lambda需要哪些DynamoDB權限?
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["dynamodb:PutItem", "dynamodb:Query"],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/factory_temperature_history"
}
]
}
五、方式二:IoT Core規則引擎直接寫入DynamoDB(不需要Lambda)
若你只需要單純儲存原始數據,不需要任何額外判斷邏輯,AWS IoT Core規則引擎本身就內建「DynamoDBv2」動作,可以直接把訊息寫入資料表,完全不需要撰寫或維護Lambda函式。
規則SQL語句(與第三篇相同的篩選邏輯)
FROM 'factory/+/+/temperature/#'
在規則的「動作」設定中,選擇「將訊息寫入DynamoDB資料表(DynamoDBv2)」,並將訊息中的device_id對應到資料表的Partition Key、ts對應到Sort Key,其餘欄位會以JSON格式整筆存入。這種方式的好處是架構更簡單、少一層Lambda執行費用,缺點是無法在寫入前執行任何自訂運算邏輯(如封包解析)。
兩種寫入方式比較
| 比較項目 | 方式A:規則直接寫入 | 方式B:透過Lambda寫入 |
|---|---|---|
| 是否需要Lambda | 不需要 | 需要 |
| 可否先做封包解析 | 不行,僅能簡單欄位對應 | 可以,Lambda內可執行任意邏輯 |
| 可否在寫入前判斷是否記錄 | 僅能用規則SQL的WHERE條件 | 可以在Lambda內做複雜條件判斷 |
| 費用 | 僅IoT Core規則與DynamoDB費用 | 額外增加Lambda執行費用 |
| 建議情境 | 資料已是乾淨格式,僅需儲存 | 需要解析封包、判斷告警邏輯後再儲存 |
六、查詢歷史數據:用Query取得某裝置過去24小時的溫度記錄
資料存進去後,下一步是查詢。DynamoDB的Query操作專門針對「已知Partition Key,查詢特定Sort Key範圍」的情境設計,效能遠優於全表掃描(Scan)。
範例二:查詢單一裝置過去24小時的溫度記錄
import time
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-1")
table = dynamodb.Table("factory_temperature_history")
def query_last_24_hours(device_id: str):
now = int(time.time())
yesterday = now - (24 * 60 * 60)
response = table.query(
KeyConditionExpression=(
Key("device_id").eq(device_id) &
Key("timestamp").between(yesterday, now)
)
)
return response.get("Items", [])
# 使用範例
records = query_last_24_hours("ATL-STT-001")
print(f"共取得 {len(records)} 筆歷史記錄")
for record in records:
print(record["timestamp"], record["temperature"])
這段程式碼是後續系列文章「儀表板串接」的核心基礎——任何前端圖表或報表工具,最終都是呼叫類似這樣的Query操作取得歷史數據,再交給圖表函式庫繪製趨勢線。
七、補回第五篇的缺口:用DynamoDB實作告警狀態追蹤
在第五篇中,我們提到「狀態變化觸發」與「冷卻時間」都需要外部狀態儲存,現在有了DynamoDB,可以正式補完這個機制。
範例三:用DynamoDB記錄裝置告警狀態,避免重複通知
import boto3
dynamodb = boto3.resource("dynamodb", region_name="ap-northeast-1")
state_table = dynamodb.Table("factory_device_alert_state")
COOLDOWN_SECONDS = 900 # 15分鐘冷卻時間
def should_send_alert(device_id: str, is_abnormal: bool) -> bool:
now = int(time.time())
response = state_table.get_item(Key={"device_id": device_id})
item = response.get("Item", {})
last_state = item.get("last_state", "normal")
last_alert_time = item.get("last_alert_time", 0)
current_state = "abnormal" if is_abnormal else "normal"
# 條件一:狀態由normal轉為abnormal,或
# 條件二:持續異常但已超過冷卻時間
newly_abnormal = (last_state == "normal" and current_state == "abnormal")
cooldown_passed = (now - int(last_alert_time)) > COOLDOWN_SECONDS
should_notify = current_state == "abnormal" and (newly_abnormal or cooldown_passed)
update_expr = "SET last_state = :s"
expr_values = {":s": current_state}
if should_notify:
update_expr += ", last_alert_time = :t"
expr_values[":t"] = now
state_table.update_item(
Key={"device_id": device_id},
UpdateExpression=update_expr,
ExpressionAttributeValues=expr_values
)
return should_notify
把這個函式放進第五篇的Lambda函式中,在呼叫sns_client.publish()之前先呼叫should_send_alert()判斷,就能真正做到「只在異常剛發生時通知一次,且持續異常時每15分鐘提醒一次」,而不是每30秒轟炸值班人員的手機——這正是完整的事件驅動告警架構。
八、費用與容量模式:隨選 vs 預置
| 容量模式 | 計費方式 | 適合情境 |
|---|---|---|
| 隨選容量(On-Demand) | 依實際讀寫請求數計費,無需預先設定 | 流量不穩定、剛起步的PoC專案,工廠IT入門首選 |
| 預置容量(Provisioned) | 預先設定讀寫容量單位,超出需另計費或被限流 | 流量穩定可預測、長期大規模運行的正式環境 |
對於本系列文章設定的「工廠IT技術人員入門」情境,建議一律使用隨選容量模式,不需要預估流量、不會因設定過低而被限流,等系統規模穩定成長後,再評估是否切換至預置容量模式節省長期成本。實際費率請以AWS官網最新公告為準。
TTL與S3歸檔:長期歷史數據的儲存策略
DynamoDB適合儲存「近期、需要快速查詢」的數據(如過去90天),但若需要保留數年的完整歷史記錄用於稽核或長期趨勢分析,建議搭配TTL機制:資料超過設定天數後自動從DynamoDB刪除,刪除前可透過DynamoDB Streams觸發Lambda將資料同步寫入S3做低成本長期歸檔,兼顧查詢效能與儲存成本。
九、ATLANTIS 適合搭配歷史記錄系統的量測與記錄產品

TDL-R/D-6C 可攜式螢幕觸控溫度紀錄器(六組通道型)—— 每通道可獨立設定高/低溫警報並繪製溫度曲線,理念與雲端歷史記錄資料庫相通

DPG-X112 高精度藍芽數位壓力錶(可旋轉式)—— 支援Type-C或藍芽功能匯出記錄數據,適合作為DynamoDB歷史記錄的現場資料來源
LTPT-410RS系列 溫度液位傳送器 —— 同時測量溫度與液位,適合需要多欄位歷史記錄的雲端資料庫應用

SLPTX系列 數位式HART智能型液位傳送器 —— 三重保護功能防止結露問題,長期穩定輸出適合建立可信賴的歷史趨勢資料庫
完整規格請參考 ATLANTIS 產品型錄與工業4.0壓力感測器整合指南。
十、案例分享:某桃園食品廠的溫度歷史數據導入過程
以下案例經匿名化處理,客戶為桃園一家食品加工廠,因應HACCP衛生管理規範要求,需要保留完整的冷藏冷凍溫度歷史記錄供稽核使用。
| 階段 | 作法 | 導入前 | 導入後 |
|---|---|---|---|
| 資料儲存 | IoT Core規則直接寫入DynamoDB(方式A) | 紙本記錄,人工每小時抄寫一次 | 每30秒自動記錄,資料完整度大幅提升 |
| 稽核查詢 | 依裝置ID與時間範圍Query歷史數據 | 稽核時需翻閱大量紙本表單 | 稽核人員可即時查詢任意時間區間的完整記錄 |
| 長期保存 | 設定TTL 2年,搭配DynamoDB Streams歸檔至S3 | 紙本保存空間有限,容易佚失 | 雲端永久保存,符合法規稽核追溯要求 |
資深工程師賴祥德分享:「食品業與製藥業的溫度記錄,往往不只是內部管理需求,更是法規稽核的硬性要求。過去看過工廠因為紙本記錄不完整被稽核單位開罰,導入雲端歷史記錄資料庫後,這類風險幾乎可以完全避免——重點是資料要『自動記錄』,而不是依賴人為記憶。」
資料來源與延伸閱讀
本文技術架構參考 AWS DynamoDB 官方文件(docs.aws.amazon.com/dynamodb)與 AWS IoT Core 規則引擎動作官方文件。費用與容量模式資訊請以AWS官網最新公告為準。ATLANTIS產品技術規格引用自內部產品規格書。
十二、20 大常見問題 FAQ(DynamoDB 歷史記錄資料庫)
1. DynamoDB的Partition Key選錯了,之後可以修改嗎?
2. 為什麼DynamoDB不接受Python的float型態?
boto3的DynamoDB資源介面要求數字必須以Decimal型態傳入,以避免浮點數精度誤差問題,直接傳入float會拋出型態錯誤例外。3. TTL屬性刪除資料是立即發生的嗎?
4. Query和Scan有什麼差別?為什麼建議優先用Query?
5. 隨選容量模式會不會比預置容量貴很多?
6. 我可以在同一張資料表存溫度和壓力兩種數據嗎?
7. 用IoT Core規則直接寫入DynamoDB,可以同時設定TTL欄位嗎?
8. DynamoDB Streams是什麼?跟資料歸檔有什麼關係?
9. 查詢超過24小時的數據,程式邏輯需要改動很多嗎?
yesterday變數的計算方式(例如改為7天或30天前的時間戳記),KeyConditionExpression的邏輯結構完全不變,這是Sort Key範圍查詢的彈性優勢。10. 告警狀態表(factory_device_alert_state)需要保留歷史記錄嗎?
11. get_item()和query()有什麼不同?
get_item()用於取得單一已知Partition Key(及Sort Key,若有的話)的單筆資料,效能最快;query()用於取得符合Partition Key且Sort Key符合條件範圍的多筆資料,本文範例二即為此類應用。12. 我可以用DynamoDB做即時儀表板嗎,還是一定要另外用其他服務?
13. 資料表的讀寫權限,Lambda執行角色要怎麼設定才安全?
dynamodb:PutItem而非全部權限),並將Resource範圍限定為特定資料表的ARN,避免過於寬鬆的萬用字元授權。14. update_item()和put_item()有什麼差別?
put_item()會整筆覆寫(或新增)該主鍵對應的項目;update_item()則只更新指定的屬性欄位,保留其他既有欄位不變,本文範例三的告警狀態更新即使用update_item()以保留未變動的欄位。15. 感測器離線一段時間後恢復,歷史數據會有缺口嗎?
16. 我需要為每一種感測器類型建立獨立的資料表嗎?
17. DynamoDB的資料一致性如何?寫入後馬上查詢得到嗎?
18. 這套歷史記錄架構,資料保存期限要設多久比較合適?
19. 我可以用DynamoDB做跨裝置的統計分析(如全廠平均溫度)嗎?
20. 學會DynamoDB歷史記錄後,下一步該學什麼?
十三、下一步:讓 ATLANTIS 協助你規劃符合稽核需求的雲端歷史記錄架構
31年工業儀錶製造經驗 × 數位化歷史記錄解決方案
從變送器選型、資料表主鍵設計,到符合HACCP/GMP稽核需求的長期保存規劃,我們可以陪工廠IT團隊打造完整的雲端歷史記錄資料庫。
📞 02-2820-3405 免費選型諮詢 📧 線上快速詢價
業務一部 Ian:ian@atlantis.com.tw | 業務二部 Nori:nori@atlantis.com.tw
文章更新時間:2026年7月|作者:ATLANTIS 應用工程團隊|本文為系列教學文章第六篇,下一篇將深入「AWS IoT Core規則引擎實戰:感測器資料自動路由到Lambda與S3」。