DDIA CH 7 — 分片 Sharding (上)

2026年10月21日

💎 加入 E+ 會員方案 與超過千位工程師一同在社群成長,並獲得更多深度的軟體前後端學習資源

我們在 DDIA 導讀 CH 6 — 複寫 (上) 談到,在分散式資料庫中,可以透過在多個節點都複製資料,來把資料分散到多台機器上。複寫的做法能夠提高系統的可用性,避免單一機器壞掉導致整個系統不可用;同時也能不同的讀取請求,讓被分散到不同的副本上,藉此減輕單一機器的壓力。

除了複寫之外,分片 (Sharding) 也是把資料分散到不同機器的做法。然而,分片跟複寫在做法與解決的問題都有所不同。在這一章節的導讀,我們會來討論分片,包含介紹分片是什麼、使用時有哪些利弊,以及實作上有哪些不同的選擇。

分片是什麼?

先前在 DDIA 導讀 CH 6 — 複寫 (上) 提過,複寫的做法是在多台機器中複製「相同的資料」;對比起來,分片的做法是在多台機器中放「不同的資料」。換句話說,假如一個資料庫中有多筆資料,分片的做法不是在每台機器都放完整的資料,而是把資料切成很多的小區塊 (所以又被叫分片),然後不同的小區塊會被放到不同的機器中。

舉例來說,假如某個會員系統中有上億名會員,我們可以把會員資料做分片,例如會員編號 1 到 10,000,000 會放在分片 1,而會員編號 10,000,001 到 20,000,000 放到分片 2,接著以此類推。在這樣的分片之下,會員 12,345,678 會被判斷屬於分片 2。系統如果要查這個會員,就不用去每一台機器找資料,直接去找分片 2 即可。

在實務上,複寫跟分片不是互斥的,更常見的做法是兩者會一起使用。某一筆資料會被分配到某個分片,同時透過複寫的方式,把分片複製到多台機器。在這種做法下,某筆資料仍屬於一個分片,但同時可以透過多個副本來提高可用性。因此,雖然在多台機器的磁碟上都仍有這筆資料,但是從系統管理資料範圍的角度來說,只會屬於某個區塊,而不是在多個區塊中都有。

以上面的案例來說,如果分片 2 只放在一台機器上,當該機器故障,分片 2 的資料就暫時沒辦法用。不過如果搭配上複寫,則能在某台機器故障時,其他台有著相同分片的機器,持續支援來自客戶端的請求。

分片有哪些好處與成本?

同樣是把資料分散到多台機器,複寫可以提高系統的可用性,也能夠降低延遲,但分片有著不同的作用。具體來說,分片對系統帶來的最大好處是可擴展性 (scalability)。

當今天一個系統持續擴展,資料量越來越大,通常可以有兩種擴展方式,一種是垂直擴展,另一種是水平擴展。垂直擴展是把單台機器持續升級,例如增加更多的記憶體、更大容量的磁碟。然而,單台機器的磁碟終究會有上限,所以在極大資料量下,即使最頂規的機器,仍可能不足以應付。

相比起垂直擴展,水平擴展的做法不是升級規格更好的機器,而是用更多台機器,而分片就是屬於水平擴展的方式。今天資料量變大的情況下,可以透過把資料拆成多個分片,讓不同機器各自負責部分的資料,藉此來達到擴展。在這種做法下,當資料量或負載持續增加時,可以透過增加節點、拆分或搬移分片來擴充容量與處理能力。

每個系統都該用分片嗎?

雖然說從理論的角度來說,分片能夠帶來擴展面向的好處,但從實務上來看,其實不推薦所有的資料系統都做分片。特別是還在早期、規模還不大的系統。

先前談到的複寫,不論資料量多或少都能夠帶來可用性上的好處,因為即使資料量小,機器還是可能會故障,這時搭配適當的故障偵測與切換機制,副本可以提高系統在節點故障時維持服務的能力。但是分片就不一樣,對於資料量與讀寫負載都還在單節點能力範圍內,也沒有租戶隔離或等特殊需求的系統,分片帶來的效益通常有限,未必值得承擔額外的開發與維運成本。

特別是在硬體發展越來越進步的現代,單一台機器能夠負載的上限比過去高許多;因此,除非資料量或寫入量真的明顯超過單節點能力,而且未來還會持續成長,否則不一定要往分片的路線走。

分片有哪些實務上的困難與成本?

具體來說,實務上做分片有一些困難點,第一個是要選什麼分區鍵 (partition key)。

所謂的分區鍵,是系統用來判斷「這筆資料應該放在哪個分片」的欄位或欄位組合。」,例如可以用會員編號當分區鍵。分區鍵的選擇,會很大幅度影響後續查詢的速度。從系統的角度,假如知道分區鍵,查詢就會快很多。以上面提過的例子來說,假如已經知道會員 12,345,678 會被判斷屬於分片 2,這時直接去分片 2 拿資料就很快。

但問題在於,很多時候查詢的東西跟分片對不上,就會導致在查詢時必須掃過大量的分片,讓查詢的效率跟速度都大幅降低。特別是在關聯式資料模型下,假如同時有使用者、訂單、商品、付款等不同的資料與關聯,當這些資料散在不同分片,就可能讓查詢成本變高。

如果訂單資料也按照會員編號分片,查詢某個會員的訂單時,就可以把請求定位到對應的分片,避免跨分片查詢。但如果要查某個商品在全平台的購買紀錄,在沒有可用的全域索引或其他查詢結構時,就可能需要向多個分片發出查詢,再彙整結果,增加查詢成本。但反過來,如果用商品的編號來分片,查詢商品的資料就會快,但如果要查某個使用者的完整購買紀錄,成本可能就很高。

所以,從實務上來說,分片的第一大困難點,反而不在程式碼本身,而是在於對系統的理解深度。需要先理解系統中資料之間的關聯、平常會做什麼樣的查詢、哪些查詢最重要、哪些查詢頻率不高。有了這些通盤的了解後,才可能選對合適的分區鍵。

分片的第二個困難點在於處理資料庫交易。在單一台資料庫中,交易會相對容易處理;但分片後,假如 A 帳戶跟 B 帳戶在不同的分片,要從 A 轉帳給 B,就會變成跨分片操作,這會比在單一資料庫來得慢與複雜。

舉例來說,如果要讓 A 帳戶的扣款與 B 帳戶的入帳維持原子性,就需要跨分片的交易協調。以兩階段提交為例,協調者需要先確認各參與分片已準備好,再決定提交或中止;遇到節點故障或通訊中斷時,恢復處理也會更複雜。

因此在實務上,選擇分區鍵時,也會多考慮哪些資料可能常常需要一起更新,並以此出發來選分區鍵,藉此減少跨分片交易的頻率。


加入 E+ 會員方案

如果你覺得這篇分享有幫助,想閱讀更深入的內容,歡迎加入 E+ 會員。除了有會員專屬的深度文與影片,探討前後端開發、AI 工程、職涯發展,同時有 Discord 社群一同交流與成長。

許多 E+ 會員透過所任職公司的教育訓練補助 (E+ 會開立有統編的發票),不用花自己的錢,也能每週透過深度主題文與社群交流,拓展技術視野、加速職涯成長。

🧵 如果你想收到最即時的內容更新,可以在 Facebook、Instagram 上追蹤我們