天天看點

常見的NoSQL方案K-V 存儲文檔資料庫列式資料庫全文搜尋引擎

目錄

  • K-V 存儲
  • 文檔資料庫
  • 列式資料庫
  • 全文搜尋引擎
    • 全文搜尋基本原理
    • 全文搜尋的使用方式

關系庫并不完美,存在一些缺點:

  • 關系資料庫存儲的是行記錄,無法存儲資料結構;
  • 關系資料庫的 schema 擴充很不友善;
  • 關系資料庫在大資料場景下 I/O 較高;
  • 關系資料庫的全文搜尋功能比較弱;

針對上述問題,分别誕生了不同的 NoSQL 解決方案,這些方案與關系資料庫相比,在某些應用場景下表現更好。

但世上沒有免費的午餐,NoSQL 方案帶來的優勢,本質上是犧牲 ACID 中的某個或者某幾個特性,應該将 NoSQL 作為 SQL 的一個有力補充。

常見的 NoSQL 方案分為 4 類:

  • K-V 存儲:解決關系資料庫無法存儲資料結構的問題,以 Redis 為代表;
  • 文檔資料庫:解決關系資料庫強 schema 限制的問題,以 MongoDB 為代表;
  • 列式資料庫:解決關系資料庫大資料場景下的 I/O 問題,以 HBase 為代表;
  • 全文搜尋引擎:解決關系資料庫的全文搜尋性能問題,以 Elasticsearch 為代表;

K-V 存儲

K-V 存儲的全稱是 Key-Value 存儲,其中 Key 是資料的辨別,和關系資料庫中的主鍵含義一樣,Value 就是具體的資料。

Redis 是 K-V 存儲的典型代表,它是一款開源(基于 BSD 許可)的高性能 K-V 緩存和存儲系統。Redis 的 Value 是具體的資料結構,包括 string、hash、list、set、sorted set、bitmap 和 hyperloglog,是以常常被稱為資料結構伺服器。

Redis 的缺點主要展現在并不支援完整的 ACID 事務,Redis 雖然提供事務功能,但 Redis 的事務和關系資料庫的事務不可同日而語,Redis 的事務隻能保證隔離性和一緻性(I 和 C),無法保證原子性和持久性(A 和 D)。

雖然 Redis 并沒有嚴格遵循 ACID 原則,但實際上大部分業務也不需要嚴格遵循 ACID 原則。

文檔資料庫

為了解決關系資料庫 schema 帶來的問題,文檔資料庫應運而生。文檔資料庫最大的特點就是 no-schema,可以存儲和讀取任意的資料。目前絕大部分文檔資料庫存儲的資料格式是 JSON(或者 BSON),因為 JSON 資料是自描述的,無須在使用前定義字段,讀取一個 JSON 中不存在的字段也不會導緻 SQL 那樣的文法錯誤。

文檔資料庫的 no-schema 特性,給業務開發帶來了幾個明顯的優勢:

  • 新增字段簡單;
  • 曆史資料較好的相容,即使沒有新增的字段,也不會導緻錯誤,隻會傳回空值,代碼進行相容處理即可;
  • 可以很容易存儲複雜資料;

文檔資料庫的這個特點,特别适合電商和遊戲這類的業務場景。

文檔資料庫 no-schema 的特性帶來的這些優勢也是有代價的,最主要的代價就是事務支援上較麻煩,需要額外的編碼;

文檔資料庫另外一個缺點就是無法實作關系資料庫的 join 操作;

列式資料庫

關系資料庫按照行式來存儲資料,主要有以下幾個優勢:

  • 業務同時讀取多個列時效率高,因為這些列都是按行存儲在一起的,一次磁盤操作就能夠把一行資料中的各個列都讀取到記憶體中。
  • 能夠一次性完成對一行中的多個列的寫操作,保證了針對行資料寫操作的原子性和一緻性;否則如果采用列存儲,可能會出現某次寫操作,有的列成功了,有的列失敗了,導緻資料不一緻。

行式存儲的優勢是在特定的業務場景下才能展現,如果不存在這樣的業務場景,那麼行式存儲的優勢也将不複存在,甚至成為劣勢,典型的場景就是海量資料進行統計。

例如,計算某個城市體重超重的人員資料,實際上隻需要讀取每個人的體重這一列并進行統計即可,而行式存儲即使最終隻使用一列,也會将所有行資料都讀取出來。如果單行使用者資訊有 1KB,其中體重隻有 4 個位元組,行式存儲還是會将整行 1KB 資料全部讀取到記憶體中,這是明顯的浪費。而如果采用列式存儲,每個使用者隻需要讀取 4 位元組的體重資料即可,I/O 将大大減少。

除了節省 I/O,列式存儲還具備更高的存儲壓縮比,能夠節省更多的存儲空間。普通的行式資料庫一般壓縮率在 3:1 到 5:1 左右,而列式資料庫的壓縮率一般在 8:1 到 30:1 左右,因為單個列的資料相似度相比行來說更高,能夠達到更高的壓縮率。

同樣,如果場景發生變化,列式存儲的優勢又會變成劣勢。典型的場景是需要頻繁地更新多個列。因為列式存儲将不同列存儲在磁盤上不連續的空間,導緻更新多個列時磁盤是随機寫操作;而行式存儲時同一行多個列都存儲在連續的空間,一次磁盤寫操作就可以完成,列式存儲的随機寫效率要遠遠低于行式存儲的寫效率。此外,列式存儲高壓縮率在更新場景下也會成為劣勢,因為更新時需要将存儲資料解壓後更新,然後再壓縮,最後寫入磁盤。

基于上述列式存儲的優缺點,一般将列式存儲應用在離線的大資料分析和統計場景中,因為這種場景主要是針對部分列單列進行操作,且資料寫入後就無須再更新删除。

全文搜尋引擎

傳統的關系型資料庫通過索引來達到快速查詢的目的,但是在全文搜尋的業務場景下,索引也無能為力,主要展現在:

  • 全文搜尋的條件可以随意排列組合,如果通過索引來滿足,則索引的數量會非常多。
  • 全文搜尋的模糊比對方式,索引無法滿足,隻能用 like 查詢,而 like 查詢是整表掃描,效率非常低。

全文搜尋基本原理

全文搜尋引擎的技術原理被稱為“反向索引”(Inverted index),也常被稱為反向索引、置入檔案或反向檔案,是一種索引方法,其基本原理是建立單詞到文檔的索引。之是以被稱為“倒排”索引,是和“正排“索引相對的,“正排索引”的基本原理是建立文檔到單詞的索引。

全文搜尋的使用方式

全文搜尋引擎的索引對象是單詞和文檔,而關系資料庫的索引對象是鍵和行,兩者的術語差異很大,不能簡單地等同起來。是以,為了讓全文搜尋引擎支援關系型資料的全文搜尋,需要做一些轉換操作,即将關系型資料轉換為文檔資料。

目前常用的轉換方式是将關系型資料按照對象的形式轉換為 JSON 文檔,然後将 JSON 文檔輸入全文搜尋引擎進行索引。

--------來源《極客課程》∙ 學習摘要