什麼是 Postgres?許多 App 背後的資料庫白話解說
Postgres(正式名稱為 PostgreSQL)是免費、開放原始碼的關聯式資料庫:一個把 App 的資料存在由列與欄組成的資料表中、將這些資料表彼此連結,並以名為 SQL 的語言回答相關問題的程式。它以可靠、對資料正確性要求嚴格,以及足夠彈性而能處理從候補名單到大型企業紀錄的各種情況而聞名。許多網路 App,以及託管它們的許多服務,都是建立在它之上的。
用 AI 製作 App 時為什麼重要
當 AI App 製作工具為你的專案加入「一個資料庫」時,很有可能就是 Postgres。你不需要會寫 SQL 也能使用它,但對它有一點了解會很有幫助:
- 你可以用資料庫需要的形式來描述資料。 「客戶有許多訂單;每筆訂單有許多品項」可以直接轉換成資料表。
- 你可以要求正確的保護措施。 如果 AI 設定了規則,Postgres 本身就能拒絕錯誤的資料,例如重複的電子郵件,或是指向不存在客戶的訂單。
- 你可以閱讀 AI 所做的事。 資料表名稱、欄位與關聯,即使你從不碰程式碼,也很容易在資料表檢視器中檢查。
日常比喻:一間非常嚴格的檔案室
想像一間檔案室,每種東西都有一個櫃子:一個放客戶,一個放訂單,一個放產品。每個抽屜中的每張卡片都有相同的印刷欄位要填寫。每張卡片都有唯一的編號,而訂單卡片不會重複客戶的詳細資料,只會寫「客戶 #214」,指向客戶櫃子中的那張卡片。
這位職員非常嚴格。如果訂單指向一個不存在的客戶,他不會收檔。如果必填的日期欄位空白,他也不會接受這張卡片。而且,如果你要求把一個帳戶卡片上的金額轉到另一個帳戶卡片,他要麼兩邊都完成,要麼兩邊都不做,絕不會只完成一半。
這位職員就是 Postgres。抽屜就是資料表,印刷欄位就是欄,每張卡片就是一列,而「客戶 #214」這個連結就是外部鍵(foreign key)。
Postgres 擅長什麼
| 功能 | 白話的意思 |
|---|---|
| 資料表與關聯 | 資料存放在彼此指向的資料表中,因此不會在五個地方重複複製 |
| SQL | 提出問題的標準語言:「上個月所有未付款的訂單,最新的排在前面」 |
| 交易(ACID) | 一組變更要嘛全部完成,要嘛全部不做,即使伺服器在中途當機 |
| 限制條件(Constraints) | 資料庫自己強制執行的規則:必填欄位、唯一的電子郵件、資料表之間有效的連結 |
| 索引(Indexes) | 查詢捷徑,讓資料表變大時搜尋仍然快速 |
| JSONB | 當固定結構不合適時,把彈性的、類似文件的資料存在一個欄位中 |
| 全文搜尋 | 在簡單的情況下,無需另外的搜尋服務,就能搜尋文字欄位中的字詞 |
| 擴充功能(Extensions) | 附加元件,例如用於地圖與位置的 PostGIS,或用於儲存 AI 向量嵌入的 pgvector |
| 列層級安全性(Row-level security) | 資料庫內部的規則,決定特定使用者可以看到哪些列 |
Postgres 起源於 1980 年代加州大學柏克萊分校的一個研究計畫,自 1990 年代起由全球社群公開開發。這段悠久的歷史,正是它常被當成預設選擇的原因:文件完善、支援廣泛,而且每一家主要雲端供應商都提供代管版本。
實際範例:把試算表變成資料表
假設你經營一家小型餐飲外燴公司,所有資料都記錄在一份試算表中:每一列是一場活動,包含客戶的姓名、電話、電子郵件、日期、菜單品項與價格。
問題很快就會出現。同一位客戶出現在六列中,還有兩組不同的電話號碼。菜單品項被打在同一個儲存格裡,寫成「小點心 x40、沙拉 x2」,因此你無法加總這個月做了多少份小點心。
在 Postgres 中,同樣的資訊會變成四個資料表:
| 資料表 | 欄位 | 說明 |
|---|---|---|
| clients | id, name, phone, email | 電子郵件必須唯一 |
| events | id, client_id, date, venue, status | client_id 必須對應到真實的客戶 |
| menu_items | id, name, unit_price | 每道菜一列 |
| event_items | event_id, menu_item_id, quantity | 連結活動與菜色,並記錄數量 |
現在,客戶的電話號碼只存在一個地方。「三月我們做了多少份小點心?」只需要一個 SQL 查詢。而當你記錄一場新活動及其品項時,交易會確保你不會得到一場只儲存了一半品項的活動。
很多人在請 AI「把我的試算表做成 App」時,都會跳過這一步。把試算表變成 App 的指南會再深入介紹。
關鍵術語
- 資料表、列、欄: 一類事物、這類事物中的一個實例,以及關於它的一項資訊。
- 主鍵(Primary key): 每一列的唯一 ID,通常是
id。 - 外部鍵(Foreign key): 指向另一個資料表中某一列的欄位,例如
client_id。 - 結構定義(Schema): 所有資料表與欄位的設計。
- 遷移(Migration): 對結構定義所做的一次已儲存、可重複執行的變更,例如「在 events 中新增一個
venue欄位」。 - 查詢(Query): 以 SQL 撰寫的問題或指令。
- 連線字串(Connection string): 你的後端用來連到資料庫的位址與密碼。它是機密,請參閱環境變數與機密。
- 代管的 Postgres(Managed Postgres): 替你執行、備份並更新 Postgres 的服務。
至於每個 App 對這些資料表都會執行的日常操作(建立、讀取、更新、刪除),請參閱什麼是 CRUD。
常見錯誤與迷思
- 一張巨大的資料表。 把試算表的欄位原封不動照搬,會導致同樣的重複問題。把會重複的東西拆成各自的資料表。
- 把清單存在一個文字欄位中。 在單一欄位中寫入「小點心 x40、沙拉 x2」,無法正確計數或搜尋。請改用連結資料表。
- 沒有限制條件。 如果沒有「電子郵件必須唯一」或「每場活動都必須有客戶」這類規則,錯誤的資料會悄悄進入,並在幾個月後才被發現。
- 在正式環境中手動變更資料庫。 結構變更應該以遷移的方式提出,這樣變更才會被記錄,也可以重複執行。
- 讓瀏覽器直接與資料庫溝通。 前端應該透過你的後端存取資料,後端負責檢查權限。資料庫密碼永遠不應該出現在頁面程式碼中。
- 「Postgres 只適合大公司。」 它在一個只有 50 列的候補名單上也同樣運作得很好,而且隨著你成長,你也不需要改用其他資料庫。
- 以為資料庫就是備份。 資料庫用來儲存資料,它不會自動保護你免於刪除資料。請確認你的主機提供哪些備份功能。
可以向 AI 製作工具提出的要求
- 「把[東西]存入資料庫。資料表:……,欄位:……。把每一筆[訂單]連結到一位[客戶]。」
- 「讓客戶的電子郵件欄位唯一。把這些欄位設為必填。不允許沒有客戶的訂單。」
- 「每一次結構變更都使用遷移。」
- 「為我們最常做的查詢新增索引:依客戶與依日期查詢訂單。」
- 「所有資料庫存取都經過伺服器。把連線字串保存在環境變數中。」
如果你對資料庫這個概念還很陌生,可以先從什麼是資料庫開始,再回來閱讀本文。全端 App 一文則說明資料庫如何與前端及後端並列在同一個系統中。
Mythex 中的 Postgres
Mythex 會替每個需要資料庫的專案提供一個專屬的 Postgres 資料庫。你無需設定:在聊天中提出需求(「把候補名單的電子郵件存到資料庫」),或使用 /database 指令,Mythex 就會附加資料庫,把連線資訊注入你的 App,並可替你建立資料表。已發佈的 App 其資料庫在閒置五分鐘後會進入休眠,並在下一次請求時喚醒;你只需為它實際醒著的時間付費,費用從與製作相同的點數餘額扣除。詳情請參閱資料庫文件,而儀表板範本則是查看具有資料支援的 App 的好地方。
常見問題
Postgres 和 PostgreSQL 是同一樣東西嗎?
是的。PostgreSQL 是正式名稱,Postgres 則是常用的簡稱,兩者指的都是同一個開放原始碼關聯式資料庫。
Postgres 免費嗎?
免費。PostgreSQL 採用寬鬆的 PostgreSQL License 開放原始碼授權,因此你可以免費使用,包括用於商業產品。你只需為運行它的伺服器或代管服務付費。
Postgres 和 MySQL 有什麼差別?
兩者都是免費的關聯式 SQL 資料庫,對大多數 App 來說都很合適。Postgres 以嚴謹的資料完整性、豐富的資料類型(例如 JSONB 與陣列),以及龐大的擴充功能生態系聞名;MySQL 則以簡單易用,以及在網站託管領域悠久的歷史著稱。
Postgres 適合小型 App 嗎?
適合。它既能勝任只有單一資料表的候補名單,也能支撐大型的正式系統,因此隨著 App 成長,你不需要更換資料庫。代管服務讓你無需資料庫管理員也能輕鬆運行。