iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
Build on AWS

DynamoDB銀河傳說首部曲-打造宇宙都打不倒的高效服務系列 第 22

Day 22:從關聯設計到索引設計的思維昇華

  • 分享至 

  • xImage
  •  

這天大師讓洛基晚上再過來,洛基對於這時間站在大師門外感到些許新鮮。

手還沒碰到門把,而他腦中想著這幾天的學習,每一天都是一個新的挑戰,每一天都在學習「選擇」。

但現在,站在這裡,他突然意識到一件事——

這五天,他一直在學「怎麼做」。如何處理一對一、如何設計一對多、如何保證一致性...技巧學會了,但有個更深的問題他從未真正思考過:

「為什麼是這樣設計?」

洛基帶著疑問深吸一口氣,推開門。

茶室裡的氛圍不同以往。大師沒有站在白板前,而是坐在窗邊,手裡拿著一杯茶,看著窗外的星空。茶室裡只有一盞柔和的燈光。

「坐,」大師說,沒有轉頭,「今天不用白板。」

洛基困惑地坐下,等待大師開口。

過了一會兒,大師轉過頭,看著他:「這五天,你學會了很多技巧。但你學會了 Access Pattern 了嗎?」

洛基當然知道那是什麼,原想回答「當然」,但話到嘴邊卻停住了。他發現自己無法給出一個清晰的答案。

大師微笑:「很好的沉默。這就是今天的起點。」


從技巧到本質的昇華

大師站起身,走到窗邊,指著外面的星空:「你看那些星球,它們都有自己的軌道。為什麼是那樣的軌道?」

洛基想了想:「引力、速度、質量...各種因素的平衡。」

「正確,」大師轉身,「軌道不是設計出來的,而是由這些星球的本質特性『決定』出來的。」

他回到桌邊坐下:「DynamoDB 的設計也是一樣。不是『我想要這樣設計』,而是『查詢需求決定了我必須這樣設計』。」

洛基開始理解了:「所以 Access Pattern 不是一個設計原則,而是...」

「是設計的『決定性因素』,」大師說,「就像引力決定軌道一樣。」

他拿出筆記本,翻到第 18 天的筆記快速瀏覽一下,「當時我學到的是『選擇』,」洛基說,「嵌入或分離,取決於更新頻率。」

「沒錯,」大師說,「但為什麼更新頻率會影響設計?」

洛基思考了一會兒:「因為...嵌入的話,每次更新 profile 就要重寫整個項目。如果 profile 常更新,成本會很高。」

「再深入一點,」大師引導,「為什麼重寫整個項目成本會高?」

「因為 DynamoDB 是按項目大小計算 WCU 的...」洛基停頓,「所以根本原因不是『更新頻率』,而是『WCU 消耗模式』?」

大師點頭:「現在你開始觸及本質了。不是技巧,而是理解『為什麼這個技巧有效』。」


Access Pattern 的真正意義

洛基翻到第 19 天的筆記,「這個設計,」洛基說,「當時我學到的是『選擇查詢方向』。」

「是的,」大師說,「但為什麼只能選一個方向?」

洛基想起第 2 天學到的:「因為 PK 決定分區,SK 決定排序。一個表的主鍵只能有一組 PK/SK。」

「正確,」大師說,「這是 DynamoDB 的技術限制。但這個限制帶來什麼影響?」

洛基慢慢理解:「它強迫我們『選擇』——必須決定哪個查詢是主要的、最重要的、最頻繁的。」

「這就是 Access Pattern 的核心,」大師說,「不是『有哪些查詢』,而是『哪些查詢最重要』。」

他在筆記本上寫下:

SQL 思維:
- 設計實體關係(ER 圖)
- 建立表結構
- 所有查詢都能支援(JOIN)
- 查詢是對稱的

DynamoDB 思維:
- 分析查詢需求(Access Pattern)
- 識別核心查詢(最重要、最頻繁)
- 主鍵設計支援核心查詢
- 查詢是不對稱的(有主有次)

洛基盯著這個對比,突然有種頓悟的感覺:「所以...第 6 天的時候,大師說『查詢優先』,不只是一個原則,而是 DynamoDB 架構本身的必然結果?」

「沒錯,」大師說,「分散式架構不能做 JOIN,這個技術限制『決定』了設計必須從查詢出發。」


從「學過」到「理解」的距離

大師繼續:「第 20 天你學了多對多關係,雙向索引的設計。」

洛基翻到筆記,「這個設計,」洛基說,「我當時理解的是『兩個查詢方向都重要,所以存兩份』。」

「對,」大師說,「但為什麼要存兩份?能不能只存一份,然後用某種方式反向查詢?」

洛基想了想:「不行。如果只存 PK: USER#alice, SK: EVENT#xxx,要查『某個活動的所有參與者』,就只能 Scan 整個表。」

「為什麼?」

「因為沒有辦法用 PK 來查詢『所有包含 EVENT#science-conf 的項目』...」洛基停頓,「PK 必須精確匹配,不能做『包含』或『反向』查詢。」

「這又是技術限制,」大師說,「而這個限制『決定』了必須存兩份。不是設計偏好,而是技術必然。」

洛基感覺腦中的某些東西連接起來了:「所以...這五天學的每個設計模式,本質上都是『在 DynamoDB 的技術限制下,如何滿足查詢需求』?」

大師笑了:「現在你真正理解 Access Pattern 了。」

他在筆記本上寫下洛基的這句話:

在 DynamoDB 的技術限制下,如何滿足查詢需求

「這就是 DynamoDB 設計的本質,」大師說,「不是學會幾個模式,而是理解『為什麼只能這樣設計』。」


當主鍵設計無法滿足需求

洛基沉浸在這個頓悟中。但大師接著提出一個新問題:

「現在,假設你有一個星際活動系統,」大師說,「主表的設計是:」

{
  PK: 'LOCATION#MARS',           // 按地點分區
  SK: 'EVENT#SY210-03-15-001', // 按時間排序
  eventName: '火星科學大會',
  hostRank: 'Captain',
  topic: 'Physics',
  status: 'ACTIVE'
}

「這個設計支援什麼查詢?」大師問。

洛基分析:「可以查詢『某個地點在某個時間範圍的活動』。」

「對,」大師說,「這是你的核心查詢。但現在有個新需求:『查詢所有由 Captain 職級主持的活動』。」

洛基皺眉:「hostRank 不在 PK 或 SK 裡...」

「你會怎麼做?」

洛基想起第 9 天學過的:「只能用 Scan,掃描整個表,然後用 FilterExpression 過濾 hostRank。」

「成本如何?」

洛基回憶第 10 天的學習:「Scan 要消耗所有項目的 RCU,即使最後只回傳 10 筆符合的資料,可能要掃描 10,000 筆...」

他停頓:「非常浪費。」

「對,」大師說,「所以問題來了——主表的 PK/SK 只能支援一種查詢模式。但真實系統常常需要多種查詢。」

洛基想到一個可能:「重新設計主表的 PK?把 hostRank 放進去?」

「那就失去了按地點查詢的能力,」大師說,「而且如果又有第三種查詢需求呢?第四種呢?」

洛基陷入沉思。主鍵只有一組,但查詢需求可能有很多種。這個矛盾一直以來都存在。

大師看著他思考的樣子,慢慢說:「第 17 天,我給你看過一個設計。」

洛基翻到筆記,找到那一頁:

// 大師展示的設計範例
{
  GSI1PK: 'RANK#Captain',
  GSI1SK: 'EVENT#SY210-03-15-001'
}

「當時我只看懂了語法,」洛基說,「但完全不知道為什麼要這樣設計。」

「現在呢?」大師問。

洛基盯著這個設計,結合剛才的討論:「這是...建立第二條查詢路徑?」

「正確,」大師點頭,「主表用 LOCATION 作為 PK,支援按地點查詢。GSI 用 RANK 作為 PK,支援按職級查詢。兩條獨立的查詢路徑。」

洛基的眼睛亮了:「所以 GSI 就是為了解決『主鍵只能支援一種查詢』的限制?」

「沒錯,」大師說,「這就是 Global Secondary Index 存在的原因。」


從局限到突破

大師站起身,這次走到白板前,開始畫圖:

主表設計:
PK: LOCATION#MARS
SK: EVENT#SY210-03-15-001
→ 支援查詢:「某地點的活動」

問題:如何查詢「某職級主持的活動」?

解法 1:Scan + FilterExpression
→ 成本高、效能差

解法 2:重新設計主表
→ 失去原有的查詢能力

解法 3:GSI
→ 建立第二條查詢路徑

洛基看著這個分析,所有的片段開始連接起來:

「第 9 天,大師提過『索引的額外存取路徑』,但當時我不理解。」

「第 17 天,大師展示了 GSI 的語法,但我只看到程式碼,不理解原理。」

「第 19 天,面對次要查詢,我只能接受 Scan,大師說『後面會有其他工具』。」

「現在我明白了,」洛基慢慢說,「GSI 不是一個新功能,而是對『主鍵只能支援一種查詢』這個限制的解決方案。」

大師請 Hippo 在白板上顯示設計三個層次:

https://ithelp.ithome.com.tw/upload/images/20251006/20178813npqbAO4dyK.jpg

「這五天,你從第一層走到第二層,」大師說,「現在,你開始觸及第三層。」


索引設計的新篇章

洛基看著白板,感覺整個學習路徑清晰起來。

「但是,」大師轉過身,「GSI 不是銀彈,一如其他的事物,它也有它的代價。」


從「知道」到「理解」

洛基收起筆記本,站起身準備離開。

大師叫住他:「第 6 天的時候,你聽到 Access Pattern 這個詞,感覺是什麼?」

洛基回想:「一個新概念,要背起來的設計原則。」

「現在呢?」

洛基沉思了一會兒:「現在我知道,它不是原則,而是必然。是 DynamoDB 的技術架構決定了設計必須從查詢出發。」

大師點頭:「這就是從『知道』到『理解』的距離。」

洛基走向門口,突然停下腳步,轉身問:「大師,為什麼要讓我學完五天的關聯設計,才教 GSI?」

大師看著他:「因為只有真正體會過主鍵設計的局限,才能理解 GSI 的價值。如果一開始就教 GSI,你只會把它當成另一個語法來背。」

洛基理解了。這五天的掙扎、選擇、權衡,都是為了今天的頓悟做準備。

他推開門走出去。夜空中,星球們沿著各自的軌道運行。

「不是我選擇軌道,」洛基喃喃自語,「是引力決定了軌道。」

他想起大師今天說的話:設計不是創造,而是在限制中找到最優解。

這個體悟,不只適用於 DynamoDB,也適用於人生的每個選擇。


時間設定說明:故事中使用星際曆(SY210 = 西元2210年),程式碼範例為確保正確執行,使用對應的西元年份。


上一篇
Day 21:Transaction 保證一致性
下一篇
Day 23:GSI 設計原則與陷阱
系列文
DynamoDB銀河傳說首部曲-打造宇宙都打不倒的高效服務24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言