第一個使用案例讓我們比較了用 Python 與用 SQL 實作同一個簡單功能。掌握足夠的 SQL 之後,許多資料處理與呈現都能直接在查詢裡完成,應用程式碼可能只剩下包在「以資料庫為中心」的架構外的一層薄殼。

  • 在某些簡單情境(後續章節會再談),把處理放進 SQL 是正確性的必要條件。
  • 在許多情況下,讓 SQL 承擔資料相關的重活也能帶來淨效能收益——因為往返時間、延遲、記憶體與頻寬用量,都直接取決於結果集的大小。
  • 本書(第一卷)聚焦於教授 SQL 慣用寫法與資料庫建模、正規化與反正規化,處理軟體架構本身;如何、何時使用這些工具,必須逐案判斷。

不過,學進階 SQL 時有幾個概念值得放在心上,有助於決定功能該實作在哪裡:

  • 關聯式資料庫管理系統(RDBMS):PostgreSQL 在架構中的角色,是處理多個應用程式(或應用的多個部分)對即時資料的並行存取——典型場景有前台、依角色而異的使用者後台、各式報表(會計、財務、分析),以及散落的 glue scripts 與 crontab。
  • ACID(原子、一致、隔離、持久):並行存取語意的核心是交易(transaction)。交易要原子且隔離,後者讓線上備份成為可能;RDBMS 還要維持資料隨時符合業務規則的一致性——這正是建模與正規化重要、PostgreSQL 支援進階約束(constraint)的原因;持久則保證已提交的變更絕不遺失,連作業系統當機都不允許危及資料——剩下的磁碟損毀風險,正是線上備份如此重要的理由。
  • 資料存取 API 與服務:在容器與微服務的世界裡,PostgreSQL 就是資料存取服務,它的 API 是 SQL。它看起來比典型微服務重得多,但請記得它實作的是有狀態的服務;在其上構築的其他部分天生就容易做到可擴展與高可用,因為無狀態服務解決這些問題容易得多。
  • 結構化查詢語言:SQL 是宣告式語言,開發者的工作是詳細描述想要的結果集;PostgreSQL 的工作則是找出「只存取必要資料」的最有效路徑,並執行它產出的計畫。
  • 可擴充性(JSON、XML、陣列、範圍型別):SQL 是靜態型別的——每條查詢定義的新關聯必須在執行前被系統完全理解,這也是查詢裡有時需要 cast 的原因。PostgreSQL 的實作誕生於 1980 年代,明確以可擴充性為目標:運算子與函數登錄在系統目錄(catalog)、於執行期查找,支援多型,系統幾乎每個部分都可擴充。這讓 PostgreSQL 能「改良 SQL」,以乾淨的語意在語言內深入支援複合資料型別與文件處理。

設計軟體架構時,別把 PostgreSQL 當成儲存層,而應視為能處理資料運算的並行資料存取服務。要把多少處理放進 SQL 這一側,取決於團隊規模、技能組合與維運限制等多重因素。

為什麼選 PostgreSQL?#

本書只針對 SQL 標準的 PostgreSQL 實作,理由都是「世界上最先進的開源資料庫」這句話的具體展現:

  • 開源,採用類 BSD 的 PostgreSQL 授權。
  • 專案完全公開運作:所有討論、貢獻與決策都在公開郵件列表上進行,甚至自行託管所有基礎設施,避免被特定公司左右。
  • 雖由志願者公開開發維護,如今多數開發者是以專業身分貢獻——同時為雇主的利益與解決真實客戶問題。
  • 大約每年發布一個大版本,遵循「準備好才發布」(when it’s ready)的節奏。
  • 從柏克萊時期由麥可・史東布雷克(Michael Stonebraker)主持以來的設計,允許以非常進階的方式增強 SQL(見本書資料型別與索引支援的部分)。
  • 文件是你能找到最好的參考手冊之一——因為程式碼補丁必須同時修改對應文件才會被接受。
  • 面對 NoSQL 系統在維運、保證、查詢語言與 API 上的不同取捨,作者要說:PostgreSQL 是 YeSQL

尤其是可擴充性讓這個二十歲的系統得以不斷自我更新——例如它因此成為最好的 JSON 處理平台之一,甚至能從「userland 程式碼」為新資料型別加入進階支援,並整合處理函數、運算子與其索引支援。書中會看到許多這類整合,其中之一來自〈Schemaless Design in PostgreSQL〉一節,處理從 JSON 資料集匯入的《魔法風雲會》(Magic™: The Gathering)卡片:

select jsonb_pretty(data)
  from magic.cards
 where data @> '{
                  "type":"Enchantment",
                  "artist":"Jim Murray",
                  "colors":["White"]
                }';
  • @> 運算子讀作 contains,實作 JSON 搜尋,若建有特化的 GIN 索引還能獲得索引支援;jsonb_pretty() 如其名輸出美化的 JSON 文件。
  • 這條查詢完全遵守 SQL 規則,沒有任何取巧:只是函數與運算子出現在該出現的位置——搜尋條件在 where 子句、建構輸出格式的投影在 select 子句。

PostgreSQL 文件#

本書不是 PostgreSQL 手冊的替代品——9.6 版手冊的 A4 PDF 厚達 3,376 頁,光目錄就 32 頁。

  • 本書採取與參考手冊截然不同的取向,兩者互補:必要處引用文件片段,其餘大量連結到實務案例中用到的函數與 SQL 指令參考頁。
  • 建議養成查閱並仔細閱讀官方文件的習慣。章節組織符合邏輯,熟悉瀏覽方式後一切都會變簡單。
  • psql 也內建線上說明:\h <sql command>

其他論壇與部落格或許提供有趣的建議與範例,但說到底,對 PostgreSQL 有任何疑問時:read the fine manual——真的,這本手冊是 fine 的。