今天和大家聊聊數(shù)據(jù)庫。
什么是數(shù)據(jù)庫?
這個問題相信對學編程的朋友們來說過于簡單了,大家想必都是增刪改查的好手。
但如果讓你說出 10 種不同類型的數(shù)據(jù)庫,閣下該如何應對?
這篇文章,是對數(shù)據(jù)庫技術的一個小科普,希望能幫大家了解到更多元化的數(shù)據(jù)庫,便于拓寬學習思路和項目的技術選型。
關系型數(shù)據(jù)庫
首先是我們接觸最多的、也是入門后端必學的 關系型數(shù)據(jù)庫 。
在關系型數(shù)據(jù)庫中,數(shù)據(jù)以 表 的形式進行組織和存儲,每個表就像一個 Excel 表格,包含多個 行 和多個 列 。
就比如我們經典的學生管理系統(tǒng),把學生信息存儲到關系型數(shù)據(jù)庫中,結構大概是這樣的:
學號 | 學生姓名 | 所屬班級號 |
---|---|---|
1 | 小李 | 1 |
2 | 小魚 | 2 |
3 | 小皮 | 3 |
?
上述學生表格中,每一行代表一個學生的信息,每一列代表學生的一個屬性。我們可以使用結構化查詢語言 SQL 來對關系型數(shù)據(jù)庫表的數(shù)據(jù)進行靈活地查詢、選擇、過濾等。
而關系型數(shù)據(jù)庫最大的特點,就是表和表之間可以 存在關系 。比如學生管理系統(tǒng)中還可以有班級表,結構如下:
?
班號 | 班級名稱 |
---|---|
1 | 快樂班 |
2 | 泰酷班 |
3 | 躺平班 |
?
那如果我想知道某個學生所屬的班級信息,只需要在查詢時將學生表的 所屬班級號 和班級表的 班號 進行關聯(lián),而不用把所有表格的列存儲在一起,非常靈活。
通過 SQL 可以連接查詢多張表,得到下面的查詢結果:
學號 | 學生姓名 | 所屬班級號 | 班級名稱 |
---|---|---|---|
1 | 小李 | 1 | 快樂班 |
2 | 小魚 | 2 | 泰酷班 |
3 | 小皮 | 3 | 躺平班 |
除了查詢靈活、數(shù)據(jù)表間存在關系外,關系型數(shù)據(jù)庫還具有很多其他的優(yōu)點。
比較重要的是 數(shù)據(jù)一致性 ,關系型數(shù)據(jù)庫遵循 ACID 原則(原子性、一致性、隔離性和持久性),支持事務,可以保證多個操作同時進行時,數(shù)據(jù)的狀態(tài)保持一致。比如 A 給 B 轉賬,A 扣錢 的同時 B 也會加錢,不會出現(xiàn) A 扣了錢 B 卻沒收到錢的情況。
兼顧查詢的靈活和寫入的準確性,使得關系型數(shù)據(jù)庫幾乎可以被應用于任何項目中!比如 CRM(客戶關系管理)和 HRM(人力資源管理)等各類管理系統(tǒng)、數(shù)據(jù)分析系統(tǒng)、金融銀行系統(tǒng)等。
比較經典的關系型數(shù)據(jù)庫產品有 MySQL、Oracle、PostgreSQL、Microsoft SQL Server 等。其中,MySQL 由于開源又易學,已經成為后端開發(fā)同學必學的數(shù)據(jù)庫技術。
關系型數(shù)據(jù)庫的底層核心實現(xiàn)是 基于關系模型的數(shù)學理論 ,最常見的實現(xiàn)方式是使用 B+ 樹來存儲索引結構,基于其平衡性,能夠在存儲大量數(shù)據(jù)時保持高效的查詢性能,并且兼顧增刪改操作的性能。
對于大多數(shù)項目,用 MySQL 等關系型數(shù)據(jù)庫來存儲數(shù)據(jù)就足夠了。但關系型數(shù)據(jù)庫不是銀彈!在某些場景下,比如要存儲的數(shù)據(jù)間沒有關系時,它并不是最佳的選擇。
舉個例子,當我們要寫一篇文章,沒有必要把數(shù)據(jù)存儲到 Excel 表格里,可能直接將單篇文本放到 Word 里會更方便閱讀和修改。
這個時候,我們就需要與之互補的 非關系型數(shù)據(jù)庫 。
非關系型數(shù)據(jù)庫
非關系型數(shù)據(jù)庫又叫 NoSQL。最簡單的理解方式:關系型數(shù)據(jù)庫適用于存儲相互之間 存在關系的數(shù)據(jù)表 ,那么非關系型數(shù)據(jù)庫適用于關系不強的、結構相對靈活的、需要被快速訪問的數(shù)據(jù),比如字符串、JSON 等。
實際項目開發(fā)中,最常用的非關系型數(shù)據(jù)庫當屬 KV 數(shù)據(jù)庫。
KV 即 Key-Value,數(shù)據(jù)是以 鍵值對 的方式存儲在數(shù)據(jù)庫中的。可以理解為一個 HashMap,數(shù)據(jù)庫中存儲的每個鍵都 唯一對應 一個值。鍵和值都可以是任意類型的數(shù)據(jù),例如字符串、數(shù)字、數(shù)組等,非常靈活。
比如存儲每位用戶的個人信息,結構大概是這樣的:
由于 KV 存儲的結構簡單清晰,我們能夠很輕松地根據(jù)某個鍵查找出對應的值,無論是讀寫數(shù)據(jù)性能都非常高。
此外,KV 數(shù)據(jù)庫還具備良好的可擴展性,由于數(shù)據(jù)間不存在直接關聯(lián),我們可以把鍵值對放到多個機器上存儲,通過數(shù)據(jù)分片、負載均衡等策略來支持海量數(shù)據(jù)的高并發(fā)訪問。
由于高性能和高可擴展性,KV 數(shù)據(jù)庫被廣泛應用于緩存、分布式會話、分布式鎖、實時統(tǒng)計等場景。
最經典的 KV 數(shù)據(jù)庫當屬 Redis 了,它是開源的、基于內存的、高性能的數(shù)據(jù)庫,不僅支持豐富的數(shù)據(jù)類型和功能,還有持久化等重要特性,也是后端同學必學的技術。其他的常用 KV 數(shù)據(jù)庫有 LevelDB、RocksDB、Apache Cassandra 等。
KV 數(shù)據(jù)庫的底層實現(xiàn)比較靈活,常見的實現(xiàn)方式是使用哈希表來存儲鍵值對。不同類型的值對應的實現(xiàn)方式也不同,比如 Redis 的字符串存儲采用簡單動態(tài)字符串(SDS)實現(xiàn)。
解決特定問題的數(shù)據(jù)庫
相信很多同學對數(shù)據(jù)庫的印象就停留在 MySQL 和 Redis。的確,以上兩類數(shù)據(jù)庫幾乎已經可以解決所有問題!
但是,未必是最適合的。
就像你完全可以用電腦自帶的記事本軟件來查看和編輯 HTML 網(wǎng)頁文件,但是往往會選擇一個更專業(yè)的開發(fā)工具來替代它。
數(shù)據(jù)庫也是一樣,除了傳統(tǒng)的關系和非關系型數(shù)據(jù)庫之外,還有很多用于解決特定問題的數(shù)據(jù)庫。它們往往針對特定的數(shù)據(jù)結構和應用場景進行了專門的優(yōu)化和設計,能夠提供更高效快捷的數(shù)據(jù)查詢和存儲,滿足特定領域的需求。
比如下面 8 種數(shù)據(jù)庫:
搜索引擎數(shù)據(jù)庫
顧名思義,搜索引擎數(shù)據(jù)庫是為了實現(xiàn)搜索引擎功能的數(shù)據(jù)庫。
它適用于存儲和管理大量的文本內容數(shù)據(jù),并提供更快速、準確、靈活的全文檢索功能。
比如想要讓用戶更輕松地在你的博客內搜索文章,就可以使用搜索引擎數(shù)據(jù)庫。
為什么它能做到更快更靈活的搜索呢?這是因為在搜索引擎數(shù)據(jù)庫中,數(shù)據(jù)一般是以 倒排索引 的方式存儲的。
倒排索引和傳統(tǒng)的關系表有什么區(qū)別呢?
以存儲博客文檔為例,傳統(tǒng)的關系型數(shù)據(jù)庫存儲結構是:
?
文檔 id | 文檔內容 |
---|---|
1 | 感謝關注魚皮 |
2 | 魚皮是一名程序員 |
3 | 感謝關注菜鳥教程 |
?
我們能夠根據(jù) id 來查找到對應的單篇文檔,也可以通過搜索精確的關鍵詞,來查找到多篇文檔。
比如搜索 “魚皮”,能搜出文檔 1、2。
但是,如果你搜索 “魚皮程序員”,是無法得到搜索結果的,因為沒有任何一個文檔的內容,完全包含 “魚皮程序員” 這個詞(文檔內容 2 只有 “魚皮”、“程序員” 這兩個詞)。
而在搜索引擎數(shù)據(jù)庫中,首先會將文檔內容按照單詞進行分割,也就是 分詞 。然后再構建單詞到文檔 id 的映射,示例結構如下:
?
單詞 | 文檔 id |
---|---|
感謝 | 1, 3 |
關注 | 1, 3 |
魚皮 | 1, 2 |
程序員 | 2 |
?
有了上述的倒排索引,當用戶搜索 “魚皮程序員” 時,搜索引擎數(shù)據(jù)庫會先對搜索詞進行分詞,得到 “魚皮” 和 “程序員”,然后根據(jù)這兩個詞匯就能找到文檔 id 1、2 了。不用再去遍歷表內所有的數(shù)據(jù),實現(xiàn)了更靈活、快速的 模糊搜索 。
此外,搜索引擎數(shù)據(jù)庫還支持 相關性排序 ,能夠根據(jù)用戶的搜索詞對所有搜索結果進行打分,把最接近的文檔排到最上面。
主流的搜索引擎數(shù)據(jù)庫技術有 Elasticsearch、Apache Solr、Apache Lucene 等,一般更建議大家學習 Elasticsearch,這玩意更新迭代得老快了。
文檔數(shù)據(jù)庫
顧名思義,文檔數(shù)據(jù)庫適用于存儲和管理 半結構化的 文檔數(shù)據(jù),比如存儲 JSON 格式。
相比于關系型數(shù)據(jù)庫中明確定義的表格行列,文檔數(shù)據(jù)庫的數(shù)據(jù)結構是類似于文檔的層次化結構,每個文檔都是獨立的,可以包含多個不同類型和格式的數(shù)據(jù)。
比如存儲博客文章,示例結構如下:
?
文檔 ID | 文檔數(shù)據(jù) |
---|---|
1 | {"_id": 1, "title": "文章標題1", "content": "這是文章1的內容"} |
2 | {"_id": 2, "title": "文章標題2", "author": "程序員魚皮"} |
?
當我們要給某個文檔新增一個字段時,不需要像關系型數(shù)據(jù)庫一樣改變表結構,非常靈活!
除了靈活之外,文檔數(shù)據(jù)庫也有很高的可擴展性,適用于內容管理系統(tǒng)(比如博客)、文檔協(xié)同編輯系統(tǒng)等。
個人比較推薦學習的文檔數(shù)據(jù)庫是 MongoDB,入門難度極低,對前端同學也很友好。當然,Couchbase 也是不錯的。
時序數(shù)據(jù)庫
時序數(shù)據(jù)庫是一種專門用于高效存儲和處理 時間序列 的數(shù)據(jù)庫系統(tǒng)。
時間序列是指以時間作為主要維度的數(shù)據(jù)序列,即每個數(shù)據(jù)單元都包含 時間戳 。
舉個例子,在實時溫度監(jiān)測系統(tǒng)中,我們需要 每分鐘連續(xù) 收集并觀察當前的溫度,數(shù)據(jù)結構示例如下:
?
時間戳 | 設備ID | 溫度值 |
---|---|---|
2023-07-01 10:00 | Device001 | 25.5 |
2023-07-01 10:01 | Device001 | 25.7 |
2023-07-01 10:02 | Device001 | 25.8 |
2023-07-01 10:03 | Device001 | 26.2 |
2023-07-01 10:04 | Device001 | 26.5 |
2023-07-01 10:05 | Device001 | 26.3 |
?
有了這些數(shù)據(jù),我們就能夠按照時間范圍進行高效查詢、聚合分析、數(shù)據(jù)可視化。
因此,時序數(shù)據(jù)庫非常適用于物聯(lián)網(wǎng)(比如傳感器數(shù)據(jù))、日志監(jiān)控、金融交易數(shù)據(jù)分析等場景。
主流的時序數(shù)據(jù)庫技術有 InfluxDB、TimescaleDB 等。一般情況下,建議將時序數(shù)據(jù)庫配合 Grafana 監(jiān)控看板一起使用,實現(xiàn)數(shù)據(jù)存儲 + 快速可視化。
不同時序數(shù)據(jù)庫底層的存儲方式也不同,我們可以簡單理解為,時序數(shù)據(jù)庫會根據(jù) 時間 字段構建索引,查詢時通過索引去定位實際數(shù)據(jù)。比如 InfluxDB 使用 TSM(Time-Structured Merge Tree)作為存儲引擎,底層使用 B+ 樹來存儲時間索引。
向量數(shù)據(jù)庫
向量數(shù)據(jù)庫是專門用于存儲和處理 高維向量數(shù)據(jù) 的數(shù)據(jù)庫系統(tǒng)。
什么是向量?每個向量可以表示一個實體,并且包含多個維度的數(shù)值。
舉個例子,在人臉識別系統(tǒng)中,我們可以通過人臉的 特征 來判斷是否為熟人。每張人臉圖像,都對應一個向量;每個人臉向量有可能包含成百上千個特征,比如鼻子大小、眼睛大小等,每個特征就是一個維度。
對應的數(shù)據(jù)結構示例如下:
人臉 ID | 人臉特征向量 |
---|---|
1 | [0.1, 0.2, 0.3, ..., 0.5] |
2 | [0.1, 0.3, 0.2, ..., 0.4] |
在上述表格中,人臉特征向量是一個浮點數(shù)數(shù)組。數(shù)組的每個下標就表示一個特征(維度),比如下標 0 的數(shù)值表示鼻子的大小,下標 1 的數(shù)值表示眼睛大小,以此類推。。。
我們只需要對比向量,就能夠判斷出人臉的相似度。
向量數(shù)據(jù)庫能夠高效存儲多維向量數(shù)據(jù)、計算向量的相似度、并實現(xiàn)各種不同算法的相似性搜索,適用于圖像識別、特征提取和匹配、推薦系統(tǒng)等場景。值得一提的是,AI 技術的發(fā)展也帶來了一波向量數(shù)據(jù)庫技術的熱潮,可以利用向量數(shù)據(jù)庫存儲投喂給 AI 的訓練 Embeddings 數(shù)據(jù)。
主流的向量數(shù)據(jù)庫技術有 Milvus、Pinecone、Faiss 等,有些數(shù)據(jù)庫(比如 PostgreSQL)可能也支持存儲向量類型的字段。
關于向量數(shù)據(jù)庫的底層實現(xiàn),還是比較復雜的。類似于上面提到的時序數(shù)據(jù)庫,向量數(shù)據(jù)庫的實現(xiàn)關鍵也是索引的設計。常見的向量索引結構有倒排索引、KD 樹、球樹等,可以理解為對相似的向量數(shù)據(jù)進行了分組和編碼,從而實現(xiàn)更快速地檢索匹配相似向量。此外,向量數(shù)據(jù)庫往往也會采用并行計算來加速處理。
空間數(shù)據(jù)庫
空間數(shù)據(jù)庫是專門用于存儲和處理 地理空間數(shù)據(jù) 的數(shù)據(jù)庫系統(tǒng)。
地理空間數(shù)據(jù)是指基于地理 坐標系 的 幾何對象 ,比如某個物體所處的經緯度或三維坐標(點)、某個物體的輪廓(線)、某個物體的表面(面)等。
舉個例子,假如你想存儲自己房間內每個物體的位置信息,對應的數(shù)據(jù)結構可能是:
物體 ID | X 坐標 | Y 坐標 | Z 坐標 |
---|---|---|---|
1 | 2.5 | 3.0 | 1.8 |
2 | 1.0 | 4.2 | 2.3 |
3 | 3.7 | 2.1 | 1.5 |
使用空間數(shù)據(jù)庫,能夠高效地存儲、查詢和分析空間數(shù)據(jù),比如計算兩個空間是否相交、對路徑進行規(guī)劃、可視化地理空間等。
空間數(shù)據(jù)庫不僅是地理信息系統(tǒng)(GIS)的核心組件,還能用于實現(xiàn)位置導航、城市路面規(guī)劃等場景。
對于具體的空間數(shù)據(jù)庫技術,我了解得不多,只知道可以用 PostGIS 插件來為 PostgreSQL 支持空間數(shù)據(jù)管理能力,朋友們可以幫忙補充下。
?
至于空間數(shù)據(jù)庫的底層實現(xiàn),最關鍵的部分依然是索引。常見的 空間索引 結構有 R 樹、Quadtree 等,這些結構可以對空間數(shù)據(jù)進行劃分、聚合和編碼,從而加速空間范圍的查詢處理。此外,空間數(shù)據(jù)庫涉及大量的空間分析算法,比如最近鄰查詢、空間關系查詢等。時間有限,不做展開說明了。
圖形數(shù)據(jù)庫
圖形數(shù)據(jù)庫是專門用于存儲和處理 圖形結構數(shù)據(jù) 的數(shù)據(jù)庫系統(tǒng)。
注意,這里的圖形可不是三角形、長方形,而是指 由節(jié)點和邊構成 的圖形結構。
比如我們要存儲一個朋友圈關系網(wǎng)(即 FoF:朋友的朋友),對應的圖形可能是:
上圖中,每個用戶可以表示為一個節(jié)點,用戶之間的好友關系可以表示為邊。
在圖形數(shù)據(jù)庫中,需要 2 個表格來存儲。
節(jié)點信息表:
節(jié)點 id | 節(jié)點名 |
---|---|
1 | 小王 |
2 | 小李 |
3 | 小劉 |
邊信息表:
邊 id | 邊類型 | 起始節(jié)點 | 結束節(jié)點 |
---|---|---|---|
1 | 好友 | 1 | 2 |
2 | 好友 | 1 | 3 |
?
通過存儲這些節(jié)點和邊的信息,圖形數(shù)據(jù)庫就能實現(xiàn)快速 查詢及分析 朋友圈網(wǎng)中的用戶關系,并且挖掘出用戶的社交情況、和其他用戶的隱藏關系等。
由此,圖形數(shù)據(jù)庫非常適于構建社交網(wǎng)絡關系圖譜、推薦系統(tǒng)、知識圖譜等。
比較主流的圖形數(shù)據(jù)庫有 Neo4j、TigerGraph 等,都支持復雜的圖形操作和算法、以及分布式擴展,能夠通過并行計算加速圖形處理。
圖形數(shù)據(jù)庫的核心實現(xiàn)相信學過算法的朋友們并不陌生,主要是用了類似鄰接表、鄰接矩陣等方式實現(xiàn)節(jié)點和邊數(shù)據(jù)的存儲,并且通過構建圖形索引進行加速。
列存數(shù)據(jù)庫
這是一種 非常主流 的數(shù)據(jù)庫!區(qū)別于傳統(tǒng)的行式數(shù)據(jù)庫,列存數(shù)據(jù)庫以列作為基本的存儲單位,把每列的數(shù)據(jù)存儲在一起。
拿某公司每天的收入來舉個例子,傳統(tǒng)的行式(關系型)數(shù)據(jù)庫是這么存儲的:
日期 | 銷售額 | 成本 | 利潤 |
---|---|---|---|
2022-01-01 | 500 | 600 | -100 |
2022-01-02 | 280 | 450 | -170 |
2022-01-03 | 290 | 480 | -190 |
而在列存數(shù)據(jù)庫中,底層大概是這么存儲的,相當于對矩陣做了一次轉置:
日期 | 2022-01-01 | 2022-01-02 | 2022-01-03 |
---|---|---|---|
銷售額 | 500 | 280 | 290 |
成本 | 600 | 450 | 480 |
利潤 | -100 | -170 | -190 |
這樣一來,如果我們要統(tǒng)計這幾天公司的總利潤,不需要依次讀取每一行的數(shù)據(jù),直接 讀取所需 的利潤那一列進行計算即可,從而提高了數(shù)據(jù)分析和聚合操作的效率。
此外,從計算機底層來分析,把相同類型的數(shù)據(jù)在同一列中連續(xù)存儲,可以實現(xiàn)更好的數(shù)據(jù)壓縮效果、節(jié)約空間。
因此,列存數(shù)據(jù)庫適用于實時數(shù)據(jù)分析、OLAP、大規(guī)模數(shù)據(jù)倉庫等場景。
比較主流的列存數(shù)據(jù)庫技術有 Apache HBase、ClickHouse、Druid 等,都是大數(shù)據(jù)方向同學的必修課。
ClickHouse 官方演示
多模數(shù)據(jù)庫
最后要講的數(shù)據(jù)庫也最特別,區(qū)別于上面所有存儲單一數(shù)據(jù)模型的數(shù)據(jù)庫,多模數(shù)據(jù)庫能夠 同時存儲處理多種不同類型的數(shù)據(jù) ,比如關系型數(shù)據(jù)、文檔數(shù)據(jù)、圖形數(shù)據(jù)等,非常靈活。
就拿大家學編程時最常做的電商系統(tǒng)來舉例。如果沒有多模數(shù)據(jù)庫,你要用關系型數(shù)據(jù)庫來存儲商品簡略信息(比如商品名稱、價格),要用文檔數(shù)據(jù)庫來存儲可能長達幾十頁的商品詳情,要用圖數(shù)據(jù)庫來存儲商品推薦關系。每次看數(shù)據(jù)庫信息時,要分別到三個數(shù)據(jù)庫中查看。
如果使用多模數(shù)據(jù)庫,可以直接在同一個數(shù)據(jù)庫里統(tǒng)一存儲和管理不同類型的數(shù)據(jù),非常方便。
此外,多模數(shù)據(jù)庫還支持事務,能夠更輕松地實現(xiàn)數(shù)據(jù)的一致性和完整性,不需要手動實現(xiàn)跨庫事務、跨庫數(shù)據(jù)同步等等。
比較常用的多模態(tài)數(shù)據(jù)庫技術有 ArangoDB、OrientDB 等,不過一般情況下,我們在開發(fā)中也很少會用到這種數(shù)據(jù)庫,感興趣的話再學習即可。
編輯:黃飛
?
評論
查看更多