想象你剛開了一間咖啡店。第一天,你把每筆訂單寫在記事本上:日期、品項、金額。生意不錯,一個月後你翻開記事本,想找「上個月賣了多少杯拿鐵」,結果要一頁一頁翻、用計算機加總。這就是你遇到第一個問題:找一筆資料要翻多久。
於是你轉用 Excel。打開試算表,用篩選功能找「拿鐵」,用 SUM 函數加總金額,秒殺。但某天你和合夥人同時在改這份 Excel,他剛加了新訂單,你存檔後他的修改不見了。這是第二個問題:兩個人同時改怎麼辦?
更慘的是,某個下午停電,Excel 來不及存檔,半天的訂單全丟了。這是第三個問題:停電了怎麼辦?
這三個問題,就是數據庫要解決的核心問題。
為什麼需要數據庫
記事本、Excel、數據庫,這三者的演進不是因為你變厲害了,而是資料量與使用場景變複雜了。
記事本適合極少量、線性的記錄。它的問題是沒有結構,找資料只能從頭翻到尾。
Excel適合個人或小團隊的結構化資料。它有欄位、有公式、有篩選,但本質上是一個檔案。當檔案超過幾萬行,開啟就變慢;當兩個人同時編輯,就容易衝突;當電腦當機,未存檔的內容就消失了。
數據庫是專門為「大量資料、多人同時存取、不能丟失」這三個需求設計的系統。它解決了上述三個問題:
- 快速查找:透過索引結構,從幾億筆資料中找一筆,只需要幾毫秒。
- 併發控制:多個使用者同時讀寫同一份資料,不會互相覆蓋。
- 崩潰恢復:即使突然斷電,重啟後資料也能恢復到一致狀態。
從今天開始,你要記住的第一個觀念:數據庫不是「更厲害的 Excel」,而是一個專門為「大量、多人、不丟失」設計的系統。
數據庫怎麼存資料
你可能以為數據庫把資料存在某個神祕的地方,但其實它就是把資料寫到硬碟上的檔案裡。差別在於,它不是隨便寫,而是有組織地寫。
想象一個巨大的檔案櫃。檔案櫃有很多抽屜,每個抽屜裡有很多資料夾,每個資料夾裡有很多張紙。數據庫的結構也類似:
- 資料庫(Database):整個檔案櫃。
- 資料表(Table):一個抽屜。比如「客戶表」「訂單表」。
- 列(Row):一張紙,代表一筆記錄。比如一個客戶的資料。
- 欄位(Column):紙上的欄位,比如「姓名」「電話」「地址」。
但數據庫內部還有一層更細的結構:頁(Page)。
儲存引擎會把資料切成固定大小的區塊,通常是 4KB、8KB 或 16KB,稱為「頁」。這是數據庫讀寫的最小單位。當你查詢一筆資料,數據庫不是只讀那一筆,而是把那一筆所在的整個頁都讀進記憶體。這就像你從檔案櫃拿資料,不會只抽那一張紙,而是把整個資料夾拿出來,再看你要哪一頁。
為什麼要這樣設計?因為硬碟讀寫的特性是:讀取一個區塊的時間,遠小於讀取多個分散區塊的時間。把相關的資料放在一起,可以減少硬碟的搜尋時間。
這裡要記住第二個觀念:數據庫的儲存單位是「頁」,一頁可以容納多筆記錄。讀寫都是以頁為單位。
索引原理:從翻書到查目錄
現在你有一張「客戶表」,裡面有一百萬筆記錄。你想找「陳大文」的電話。如果沒有索引,數據庫只能從第一筆開始,一筆一筆比對,直到找到陳大文。這就像你拿到一本一百萬頁的電話簿,要找「陳大文」,只能從第一頁翻起。平均要翻五十萬頁,這就是 O(n) 的時間複雜度。
但現實中你不會這樣翻電話簿。你會先翻到目錄,找到「陳」的頁碼範圍,再翻到那一頁。這就是索引的原理。
數據庫最常用的索引結構是 B-tree(平衡樹)。它的樣子像一棵倒過來的樹:
- 根節點:樹的最上層,只有一個。比如「A 到 M 的資料在左邊,N 到 Z 的資料在右邊」。
- 分支節點:中間層,繼續分流。比如「A 到 F 在左邊,G 到 M 在右邊」。
- 葉子節點:最底層,存放實際資料的指標(指向資料頁的位置)。
當你查詢「陳大文」,數據庫從根節點開始:「陳」在 N 到 Z 之間,走右邊;到分支節點,「陳」在 C 到 H 之間,走左邊;再到下一個分支,最後到葉子節點,找到「陳大文」這一列的指標。整個過程只需要走 3 到 4 層。
這就是為什麼 B-tree 能把查詢時間從 O(n) 降到 O(log n)。一百萬筆資料,翻書平均要五十萬次,B-tree 只需要 3 到 4 次。十億筆資料,也只需要 4 到 5 次。這就是索引的威力。
但索引不是免費的。每次你新增一筆資料,數據庫不僅要把資料寫進資料頁,還要更新索引結構。所以索引越多,寫入越慢。另外,索引本身也要佔用硬碟空間。這就是為什麼數據庫管理員要仔細規劃:哪些欄位需要建索引,哪些不需要。
記住第三個觀念:索引是用空間與寫入速度換取讀取速度的交易。
事務與 ACID:銀行轉帳的例子
現在來看數據庫最精妙的設計之一:事務(Transaction)。
想象你正在做銀行轉帳。你從帳戶 A 轉 100 元到帳戶 B。這個操作包含兩步:
- 帳戶 A 的餘額減 100。
- 帳戶 B 的餘額加 100。
如果第一步完成後,系統崩潰了,第二步沒執行,會發生什麼事?你的 100 元憑空消失了。這在金融系統是不可接受的。
數據庫用「事務」來解決這個問題。事務是一組操作,要嘛全部成功,要嘛全部失敗。這就是 ACID 原則中的 原子性(Atomicity)。
ACID 是四個特性的縮寫:
原子性(Atomicity):事務裡的每一步,要嘛全部完成,要嘛全部不做。轉帳例子中,如果 A 扣款成功但 B 加款失敗,整個事務會回滾,A 的扣款也會撤銷。
一致性(Consistency):事務執行前後,資料必須符合所有規則。比如銀行規定帳戶餘額不能為負,如果轉帳會導致 A 變成負數,這個事務就會被拒絕。
隔離性(Isolation):多個事務同時執行時,不會互相干擾。如果你和合夥人同時在改訂單表,數據庫會確保你們的修改不會衝突。具體實現方式是「鎖」或「多版本併發控制」,這裡不深入。
持久性(Durability):事務一旦提交成功,即使系統崩潰,資料也不會丟失。
那數據庫是怎麼做到持久性的?答案是 預寫式日誌(Write-Ahead Log,WAL)。
WAL 的原理很簡單:在修改資料頁之前,先把修改的內容寫進一個日誌檔。這個日誌檔是順序寫入的,速度很快。即使資料頁還沒來得及寫入硬碟,只要日誌已經寫入,崩潰後重啟時,數據庫就可以重播日誌,把資料恢復到崩潰前的狀態。
這就是為什麼數據庫能在斷電後恢復資料。它不是靠記住「資料頁寫到哪了」,而是靠日誌記錄「做了哪些修改」。
記住第四個觀念:WAL 是先寫日誌再寫資料,崩潰後靠重播日誌恢復。
數據庫家族地圖
現在你已經理解了數據庫的核心原理,接下來看看有哪些種類的數據庫。每種數據庫都有自己的強項,就像交通工具:汽車適合公路,船適合水上,飛機適合長途。沒有「最好」的數據庫,只有「最適合」的數據庫。
關聯式數據庫:表格+SQL+事務
原理:資料存在表格中,每個表格有固定的欄位。表格之間可以透過「外鍵」建立關聯。查詢語言是 SQL(結構化查詢語言)。
生活比喻:就像 Excel 的多個工作表,但更嚴格、更強大。
代表產品:SQLite(單檔嵌入式)、PostgreSQL(功能最完整)、MySQL(Web 應用最常見)。
適用場景:需要事務、需要複雜查詢、資料結構固定的場景。比如金融系統、ERP、內容管理系統。
鍵值數據庫:字典比喻
原理:資料以「鍵-值」對的形式儲存。你給一個鍵(key),數據庫返回對應的值(value)。
生活比喻:就像一本字典,你查「apple」,得到「蘋果」的解釋。但字典只能按鍵查,不能按解釋反查鍵。
代表產品:Redis(最流行,支援多種資料結構)。
適用場景:快取、會話管理、計數器。需要極快讀寫,但查詢模式簡單的場景。
文件數據庫:JSON 整包存
原理:資料以文件(通常是 JSON 格式)為單位儲存。每個文件可以有不同的結構。
生活比喻:就像一個檔案夾,裡面可以放不同格式的文件,有的三頁,有的十頁,有的有目錄,有的沒有。
代表產品:MongoDB(最流行)。
適用場景:資料結構不固定、需要快速迭代的場景。比如內容管理、使用者檔案、日誌系統。
圖數據庫:節點+邊
原理:資料以「節點」與「邊」的形式儲存。節點代表實體(人、公司),邊代表關係(朋友、任職)。
生活比喻:就像社交網絡。你是節點,你的朋友是節點,你們之間的友誼是邊。要找「朋友的朋友」,在圖數據庫裡是原生操作。
代表產品:Neo4j(最流行)、Apache AGE(基於 PostgreSQL 的開源方案)。
適用場景:需要多跳查詢的場景。比如社交網絡分析、供應鏈追蹤、知識圖譜。
向量數據庫:語義搜索的新物種
原理:資料以向量(一串數字)的形式儲存。向量代表語義,語義相近的資料,向量在空間中的距離也相近。
生活比喻:想象一個三維空間,「貓」的向量在「狗」附近,但離「汽車」很遠。你輸入「小貓」,數據庫找到距離最近的向量,返回「貓」或「狗」。
代表產品:Qdrant、Milvus、pgvector(PostgreSQL 擴展)。
適用場景:語義搜索、推薦系統、RAG(檢索增強生成)。這是 AI 時代的核心組件。
時序數據庫:按時間戳優化
原理:專門為時間序列資料優化。資料按時間戳排序,查詢通常是「過去一小時的數據」「過去一天的趨勢」。
生活比喻:就像股票行情,每秒都有新的價格,你關心的是趨勢與歷史對比。
代表產品:InfluxDB、TimescaleDB。
適用場景:監控系統、物聯網、金融行情。
記住第五個觀念:沒有最好的數據庫,只有最適合場景的數據庫。
向量數據庫深入:AI 時代的新物種
向量數據庫是 2023 年以來最熱門的數據庫類型,因為它是 AI 應用的核心組件。這裡要深入講它的原理。
Embedding:文字變數字
首先,什麼是 embedding?簡單說,就是把一段文字(一個詞、一句話、一篇文檔)變成一串數字。這串數字代表這段文字的「語義」。
比如「貓」這個詞,用某個模型轉換後可能變成 [0.12, -0.34, 0.56, ...],一共 1024 個數字(稱為 1024 維向量)。「狗」的向量可能跟「貓」很接近,因為它們都是動物。「汽車」的向量就離它們很遠。
常用的 embedding 模型有 OpenAI 的 text-embedding-3、開源的 bge-m3 等。bge-m3 產生 1024 維向量,支援多種語言。
相似度計算
有了向量,怎麼判斷兩段文字是否相似?最常用的方法是計算「餘弦相似度」(cosine similarity)。
兩個向量的夾角越小,餘弦值越接近 1,代表越相似。夾角 90 度時餘弦值為 0,代表完全無關。夾角 180 度時餘弦值為 -1,代表完全相反。
為什麼全量比對太慢
假設你有一百萬筆文檔,每筆都轉成了向量。現在你輸入一個查詢,也要找最相似的 10 筆。最簡單的方法是:把查詢向量跟一百萬筆向量都算一次相似度,然後排序取前 10。這就是「暴力搜索」或「精確搜索」。
一百萬筆,每筆算一次,需要一百萬次計算。如果有一億筆呢?一億次計算。這太慢了。
ANN:近似最近鄰搜索
為了解決這個問題,科學家發明了「近似最近鄰搜索」(Approximate Nearest Neighbor,ANN)。它的核心思想是:犧牲一點精確度,換取大幅的速度提升。
ANN 有很多算法,這裡介紹兩種最流行的:
HNSW(Hierarchical Navigable Small World):這是一種多層圖結構。底層包含所有向量,每層是底層的子集。查詢時從最上層開始,找到最近的節點,再往下層走,逐步逼近目標。就像坐飛機從台北到高雄,先飛到高空(高層),再逐步下降(低層),最後降落。
HNSW 的優點是查詢快、召回率高,缺點是建構索引慢、佔用記憶體多。
IVF(Inverted File Index):先把所有向量分簇(用 K-means 算法),查詢時只搜索查詢向量所在的簇及相鄰簇。就像你要找某個城市的朋友,先確定他在哪個區域,再在該區域搜索。
IVF 的優點是建構快、佔用空間少,缺點是召回率比 HNSW 低。
代價:近似可能漏
ANN 的核心是「近似」,這意味著它可能漏掉真正最近的鄰居。比如你搜索「貓」,精確搜索會返回「貓」「狗」「老鼠」,但 ANN 可能只返回「貓」「狗」,漏掉「老鼠」。
這是速度與精確度的交易。在大多數 AI 應用中,這種交易是可接受的,因為使用者通常只關心前幾筆結果。
記住第六個觀念:向量搜索是用「近似」換取速度,精確度會略有損失。
混合數據庫:2024 到 2026 的主流方向
2023 年向量數據庫爆紅後,2024 到 2026 年的趨勢是「混合數據庫」:把向量搜索能力整合到傳統數據庫中,而不需要額外部署一個專門的向量庫。
pgvector 0.8:PostgreSQL 加向量欄位
pgvector 是 PostgreSQL 的擴展,讓 PostgreSQL 可以儲存向量、建立向量索引、執行向量搜索。2024 年發布的 0.8 版加入了 HNSW 索引與 iterative scan(迭代掃描)功能。
優勢:向量可以跟關聯資料存在同一張表,用同一條 SQL 查詢。比如「找到與查詢語義最相似的文檔,且作者必須是張三,且發布日期在 2025 年之後」。這種「向量搜索+關聯過濾」的查詢,在專門的向量庫中需要兩步(先向量搜索,再關聯過濾),在 pgvector 中只需要一條 SQL。
另外,向量資料可以跟其他資料一起備份、一起恢復、一起參與事務。這大大簡化了維運。
sqlite-vec:單檔嵌入式
sqlite-vec 是 SQLite 的擴展,讓 SQLite 可以儲存向量、執行暴力 KNN(K 最近鄰)搜索。
優勢:整個數據庫就是一個檔案,零服務、零維運。適合單進程應用、桌面應用、移動應用。
限制:目前只支援暴力 KNN,沒有 ANN 索引。當向量數量超過十萬,搜索速度會明顯下降。適合小規模場景(≤十萬級向量)。
Apache AGE:Postgres 裡跑圖查詢
Apache AGE 是 PostgreSQL 的擴展,讓 PostgreSQL 可以執行 Cypher 查詢語言(Neo4j 的查詢語言)。這意味著你可以在 PostgreSQL 中同時使用 SQL 與 Cypher,處理關聯資料與圖資料。
優勢:不需要額外部署 Neo4j,用 PostgreSQL 就能做圖查詢。圖資料可以跟關聯資料一起查詢、一起事務。
一個引擎=SQL+向量+圖+全文
混合數據庫的終極形態是:一個引擎同時支援 SQL(關聯查詢)、向量搜索(KNN)、圖查詢(多跳遍歷)、全文搜索。PostgreSQL 加上 pgvector、Apache AGE、tsvector(內建全文搜索),就能達到這個效果。
優勢:一個引擎、一個備份、一件事務。維運簡單、資料一致性高。
代價:需要一個常駐的 PostgreSQL 伺服器。相比之下,SQLite 是零服務的(直接讀寫檔案)。
記住第七個觀念:混合數據庫是趨勢,但要看場景選擇,不是所有場景都需要混合。
選型對比表與決策樹
最後,給你一個實用的選型指南。
嵌入式 vs 伺服器
這是第一個分水嶺:
- 嵌入式數據庫(SQLite):數據庫以函式庫的形式嵌入到應用程式中,直接讀寫檔案。適合單進程應用、桌面應用、移動應用、小型網站。
- 伺服器數據庫(PostgreSQL、MySQL、Redis):數據庫是一個獨立的服務,應用程式透過網路連線存取。適合多客戶端併發寫入、大型網站、企業應用。
分水嶺:是不是有多個進程或伺服器需要同時寫入資料。如果是,用伺服器數據庫;如果只有一個進程寫入,嵌入式數據庫就夠了。
什麼時候 SQLite 夠用
- 單進程應用(桌面軟體、CLI 工具、移動 App)
- 小型網站(每日訪問量低於十萬)
- 原型開發、快速驗證
- 資料量低於幾十 GB
SQLite 的優點是零配置、零維運、單檔可攜。很多時候,SQLite 就夠了。
什麼時候上 Postgres
- 多客戶端併發寫入
- 需要複雜查詢(多表 JOIN、子查詢、窗口函數)
- 需要嚴格的事務支援
- 資料量大於幾十 GB
- 需要向量搜索(用 pgvector)
- 需要圖查詢(用 Apache AGE)
- 需要全文搜索
PostgreSQL 是功能最完整的開源關聯數據庫,幾乎能處理所有場景。
什麼時候需要專門向量庫
- 向量數量大於百萬級
- 需要極致的搜索性能(毫秒級響應)
- 不需要複雜的關聯查詢
- 團隊有維運專門向量庫的能力
專門向量庫(Qdrant、Milvus)的優點是性能極致、功能豐富(支援多種 ANN 算法、過濾、分頁),缺點是需要額外維運。
決策樹
-
是不是單進程應用?
- 是 → SQLite
- 否 → 下一步
-
需不需要向量搜索?
- 不需要 → PostgreSQL 或 MySQL
- 需要 → 下一步
-
向量數量是不是大於百萬級?
- 否 → PostgreSQL+pgvector
- 是 → 下一步
-
需不需要複雜關聯查詢或事務?
- 需要 → PostgreSQL+pgvector
- 不需要 → 專門向量庫(Qdrant、Milvus)
記住第八個觀念:選型先看場景,不看流行。SQLite 夠用就不要上 Postgres,Postgres 夠用就不要上專門向量庫。
下一步
恭喜你讀到這裡。你已經理解了數據庫的核心原理、家族分類、向量搜索的機制、以及選型的決策邏輯。這些知識能幫助你在實際項目中做出正確的數據庫選擇。
接下來,你可以繼續閱讀:
- 搜索引擎比較:了解傳統搜索引擎與向量搜索的差異,以及為什麼現代搜索系統往往兩者結合。
- RAG 深度解析:RAG(檢索增強生成)是 AI 時代的核心架構,向量數據庫是其中的關鍵組件。了解 RAG 如何運作。
- Transformer 架構解析:了解 embedding 模型背後的技術原理,為什麼文字可以變成向量。
- Memory Hub 架構設計:一個實際的向量數據庫應用案例,了解如何為 AI 助手設計長期記憶系統。
- 什麼是 API 與 SDK:如果你對「應用程式如何與數據庫互動」感興趣,這篇是入門指南。
數據庫的世界很廣闊,這篇文章只是起點。但有了這些基礎,你可以更深入地探索每個領域。祝你學習愉快。