NoSQL 與 SQL

一文分辨NoSQL 還是 SQL

 

隨着大數據時代的到來,越來越多的網站、應用系統需要支撐海量數據存儲,高併發請求、高可用、高可擴展性等特性要求,傳統的關係型數據庫在應付這些調整已經顯得力不從心,暴露了許多能以克服的問題。由此,各種各樣的NoSQL(Not Only SQL)數據庫作爲傳統關係型數據的一個有力補充得到迅猛發展。

本文將分析傳統數據庫的存在的相關問題,以及幾大類NoSQL如何解決這些問題,希望給大家提供在不同業務場景下,關於存儲方面技術選型提供參考。

1 傳統數據庫缺點

  • 大數據場景下I/O較高 因爲數據是按行存儲,即使只針對其中某一列進行運算,關係型數據庫也會將整行數據從存儲設備中讀入內存,導致I/O較高
  • 存儲的是行記錄,無法存儲數據結構
  • 表結構schema擴展不方便 如要需要修改表結構,需要執行執行DDL(data definition language),語句修改,修改期間會導致鎖表,部分服務不可用
  • 全文搜索功能較弱 關係型數據庫下只能夠進行子字符串的匹配查詢,當表的數據逐漸變大的時候,like查詢的匹配會非常慢,即使在有索引的情況下。況且關係型數據庫也不應該對文本字段進行索引
  • 存儲和處理複雜關係型數據功能較弱 許多應用程序需要了解和導航高度連接數據之間的關係,才能啓用社交應用程序、推薦引擎、欺詐檢測、知識圖譜、生命科學和 IT/網絡等用例。然而傳統的關係數據庫並不善於處理數據點之間的關係。它們的表格數據模型和嚴格的模式使它們很難添加新的或不同種類的關聯信息。

2 NoSQL解決方案

NoSQL,泛指非關係型的數據庫,可以理解爲SQL的一個有力補充。

在NoSQL許多方面性能大大優於非關係型數據庫的同時,往往也伴隨一些特性的缺失,比較常見的,是事務庫事務功能的缺失。 數據庫事務正確執行的四個基本要素:ACID如下:

名稱 描述 A Atomicity

(原子性) 一個事務中的所有操作,要麼全部完成,要麼全部不完成,不會在中間某個環節結束。

事務在執行過程中發生錯誤,會被回滾到事務開始前的狀態,就像這個事務從來沒有執行過一樣。 C Consistency

一致性 在事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。 I Isolation

隔離性 數據庫允許多個併發事務同時對數據進行讀寫和修改的能力。隔離性可以防止多個事務併發執行時由於交叉執行而導致數據的不一致。 D Durability

持久性 事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。 下面介紹5大類NoSQL數據針對傳統關係型數據庫的缺點提供的解決方案:

2.1 列式數據庫

列式數據庫是以列相關存儲架構進行數據存儲的數據庫,主要適合於批量數據處理和即時查詢。相對應的是行式數據庫,數據以行相關的存儲體系架構進行空間分配,主要適合於小批量的數據處理,常用於聯機事務型數據處理。

基於列式數據庫的列列存儲特性,可以解決某些特定場景下關係型數據庫I/O較高的問題

2.1.1 基本原理

傳統關係型數據庫是按照行來存儲數據庫,稱爲“行式數據庫”,而列式數據庫是按照列來存儲數據。

將表放入存儲系統中有兩種方法,而我們絕大部分是採用行存儲的。 行存儲法是將各行放入連續的物理位置,這很像傳統的記錄和文件系統。 列存儲法是將數據按照列存儲到數據庫中,與行存儲類似,下圖是兩種存儲方法的圖形化解釋:

一文分辨NoSQL 還是 SQL

 

2.1.2 常見列式數據庫

  • HBase

一文分辨NoSQL 還是 SQL

 

  •  

HBase是一個開源的非關係型分佈式數據庫(NoSQL),它參考了谷歌的BigTable建模,實現的編程語言爲 Java。它是Apache軟件基金會的Hadoop項目的一部分,運行於HDFS文件系統之上,爲 Hadoop 提供類似於BigTable 規模的服務。因此,它可以容錯地存儲海量稀疏的數據。

  • BigTable

一文分辨NoSQL 還是 SQL

 

BigTable是一種壓縮的、高性能的、高可擴展性的,基於Google文件系統(Google File System,GFS)的數據存儲系統,用於存儲大規模結構化數據,適用於雲端計算。

2.1.3 相關特性

優點如下:

  • 高效的儲存空間利用率**

列式數據庫由於其針對不同列的數據特徵而發明的不同算法使其往往有比行式數據庫高的多的壓縮率,普通的行式數據庫一般壓縮率在3:1 到5:1 左右,而列式數據庫的壓縮率一般在8:1到30:1 左右。 比較常見的,通過字典表壓縮數據: 下面中才是那張表本來的樣子。經過字典表進行數據壓縮後,表中的字符串才都變成數字了。正因爲每個字符串在字典表裏只出現一次了,所以達到了壓縮的目的(有點像規範化和非規範化Normalize和Denomalize)

一文分辨NoSQL 還是 SQL

 

  • 查詢效率高

讀取多條數據的同一列效率高,因爲這些列都是存儲在一起的,一次磁盤操作可以數據的指定列全部讀取到內存中。 下圖通過一條查詢的執行過程說明列式存儲(以及數據壓縮)的優點

一文分辨NoSQL 還是 SQL

 

執行步驟如下:

i. 去字典表裏找到字符串對應數字(只進行一次字符串比較)。

ii. 用數字去列表裏匹配,匹配上的位置設爲1。

iii. 把不同列的匹配結果進行位運算得到符合所有條件的記錄下標。

iv. 使用這個下標組裝出最終的結果集。

複製代碼

  • 適合做聚合操作
  • 適合大量的數據而不是小數據

缺點如下:

  • 不適合掃描小量數據
  • 不適合隨機的更新
  • 不適合做含有刪除和更新的實時操作
  • 單行的數據是ACID的,多行的事務時,不支持事務的正常回滾,支持 I(Isolation)隔離性(事務串行提交),D(Durability)持久性,不能保證 A(Atomicity)原子性, C(Consistency)一致性

2.1.4 使用場景

以HBase爲例說明:

  • 大數據量 (100s TB級數據) 且有快速隨機訪問的需求
  • 寫密集型應用,每天寫入量巨大,而相對讀數量較小的應用 比如IM的歷史消息,遊戲的日誌等等
  • 不需要複雜查詢條件來查詢數據的應用 HBase只支持基於rowkey的查詢,對於HBase來說,單條記錄或者小範圍的查詢是可以接受的,大範圍的查詢由於分佈式的原因,可能在性能上有點影響,HBase不適用與有join,多級索引,表關係複雜的數據模型
  • 對性能和可靠性要求非常高的應用 由於HBase本身沒有單點故障,可用性非常高。
  • 數據量較大,而且增長量無法預估的應用,需要進行優雅的數據擴展的 HBase支持在線擴展,即使在一段時間內數據量呈井噴式增長,也可以通過HBase橫向擴展來滿足功能。
  • 存儲結構化和半結構化的數據

2.2 K-V數據庫

指的是使用鍵值(key-value)存儲的數據庫,其數據按照鍵值對的形式進行組織、索引和存儲。

KV 存儲非常適合不涉及過多數據關係業務關係的數據,同時能有效減少讀寫磁盤的次數,比 SQL 數據庫存儲擁有更好的讀寫性能,能夠解決關係型數據庫無法存儲數據結構的問題

2.2.1 常見 K-V數據庫

  • Redis

一文分辨NoSQL 還是 SQL

 

Redis是一個使用ANSI C編寫的開源、支持網絡、基於內存、可選持久性的鍵值對存儲數據庫。從2015年6月開始,Redis的開發由Redis Labs贊助,而2013年5月至2015年6月期間,其開發由Pivotal贊助。在2013年5月之前,其開發由VMware贊助。根據月度排行網站DB-Engines.com的數據顯示,Redis是最流行的鍵值對存儲數據庫。

  • Cassandra

一文分辨NoSQL 還是 SQL

 

Apache Cassandra(社區內一般簡稱爲C*)是一套開源分佈式NoSQL數據庫系統。它最初由Facebook開發,用於儲存收件箱等簡單格式數據,集Google BigTable的數據模型與Amazon Dynamo的完全分佈式架構於一身。Facebook於2008將 Cassandra 開源,此後,由於Cassandra良好的可擴展性和性能,被 Apple, Comcast,Instagram, Spotify, eBay, Rackspace, Netflix等知名網站所採用,成爲了一種流行的分佈式結構化數據存儲方案。

  • LevelDB

一文分辨NoSQL 還是 SQL

 

  •  
  • LevelDB是一個由Google公司所研發的鍵/值對(Key/Value Pair)嵌入式數據庫管理系統編程庫, 以開源的BSD許可證發佈。

2.2.2 相關特性

以Redis爲例: 優點如下:

  • 性能極高:Redis能支持超過10W的TPS
  • 豐富的數據類型: Redis支持包括String,Hash,List,Set,Sorted Set,Bitmap和hyperloglog
  • 豐富的特性:Redis還支持 publish/subscribe, 通知, key 過期等等特性

缺點如下: 針對ACID,Redis事務不能支持原子性和持久性(A和D),只支持隔離性和一致性(I和C) 特別說明一下,這裏所說的無法保證原子性,是針對Redis的事務操作,因爲事務是不支持回滾(roll back),而因爲Redis的單線程模型,Redis的普通操作是原子性的

大部分業務不需要嚴格遵循ACID原則,例如遊戲實時排行榜,粉絲關注等場景,即使部分數據持久化失敗,其實業務影響也非常小。因此在設計方案時,需要根據業務特徵和要求來做選擇

2.2.3 使用場景

  • 適用場景 儲存用戶信息(比如會話)、配置文件、參數、購物車等等。這些信息一般都和ID(鍵)掛鉤
  • 不適用場景
  • 需要通過值來查詢,而不是鍵來查詢。Key-Value數據庫中根本沒有通過值查詢的途徑。
  • 需要儲存數據之間的關係。在Key-Value數據庫中不能通過兩個或以上的鍵來關聯數據
  • 需要事務的支持。在Key-Value數據庫中故障產生時不可以進行回滾。

2.3 文檔數據庫

文檔數據庫(也稱爲文檔型數據庫)是旨在將半結構化數據存儲爲文檔的一種數據庫。文檔數據庫通常以 JSON 或 XML 格式存儲數據。

由於文檔數據庫的no-schema特性,可以存儲和讀取任意數據。

由於使用的數據格式是JSON或者BSON,因爲JSON數據是自描述的,無需在使用前定義字段,讀取一個JSON中不存在的字段也不會導致SQL那樣的語法錯誤,可以解決關係型數據庫表結構schema擴展不方便的問題

2.3.1 常見文檔數據庫

  • MongoDB

一文分辨NoSQL 還是 SQL

 

  •  

MongoDB是一種面向文檔的數據庫管理系統,由C++撰寫而成,以此來解決應用程序開發社區中的大量現實問題。2007年10月,MongoDB由10gen團隊所發展。2009年2月首度推出。

  • CouchDB

一文分辨NoSQL 還是 SQL

 

  •  

Apache CouchDB是一個開源數據庫,專注於易用性和成爲"完全擁抱web的數據庫"。它是一個使用JSON作爲存儲格式,JavaScript作爲查詢語言,MapReduce和HTTP作爲API的NoSQL數據庫。其中一個顯著的功能就是多主複製。CouchDB的第一個版本發佈在2005年,在2008年成爲了Apache的項目。

2.3.2 相關特性

以MongoDB爲例進行說明

優點如下:

  • 新增字段簡單 無需像關係型數據庫一樣先執行DDL語句修改表結構,程序代碼直接讀寫即可
  • 容易兼容歷史數據 對於歷史數據,即使沒有新增的字段,也不會導致錯誤,只會返回空值,此時代碼兼容處理即可
  • 容易存儲複雜數據 JSON是一種強大的描述語言,能夠描述複雜的數據結構

相比傳統關係型數據庫,文檔數據庫的缺點主要是對多條數據記錄的事務支持較弱,具體體現如下:

  • Atomicity(原子性) 僅支持單行/文檔級原子性,不支持多行、多文檔、多語句原子性
  • Isolation(隔離性) 隔離級別僅支持已提交讀(Read committed)級別,可能導致不可重複讀,幻讀的問題
  • 不支持複雜查詢 例如join查詢,如果需要join查詢,需要多次操作數據庫

MongonDB還是支持多文檔事務的Consistency(一致性)和Durability(持久性)

雖然官方宣佈MongoDB將在4.0版本中正式推出多文檔ACID事務支持,最後落地情況還有待見證。

2.3.3 使用場景

適用場景

  • 數據量很大或者未來會變得很大
  • 表結構不明確,且字段在不斷增加,例如內容管理系統,信息管理系統

不適用場景

  • 在不同的文檔上需要添加事務。Document-Oriented數據庫並不支持文檔間的事務
  • 多個文檔直接需要複雜查詢,例如join

2.4 全文搜索引擎

傳統關係型數據庫主要通過索引來達到快速查詢的目的,在全文搜索的業務下,索引也無能爲力,主要體現在:

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

而全文搜索引擎的出現,正是解決關係型數據庫全文搜索功能較弱的問題

2.4.1 基本原理

全文搜索引擎的技術原理稱爲“倒排索引”(inverted index),是一種索引方法,其基本原理是建立單詞到文檔的索引。與之相對是,是“正排索引”,其基本原理是建立文檔到單詞的索引。

現在有如下文檔集合:

一文分辨NoSQL 還是 SQL

 

正排索引得到索引如下:

一文分辨NoSQL 還是 SQL

 

可見,正排索引適用於根據文檔名稱查詢文檔內容

簡單的倒排索引如下:

一文分辨NoSQL 還是 SQL

 

帶有單詞頻率信息的倒排索引如下:

一文分辨NoSQL 還是 SQL

 

可見,倒排索引適用於根據關鍵詞來查詢文檔內容

2.4.2 常見全文搜索引擎

  • Elasticsearch

一文分辨NoSQL 還是 SQL

 

  •  
  • Elasticsearch是一個基於Lucene的搜索引擎。它提供了一個分佈式,多租戶 -能夠全文搜索與發動機HTTP Web界面和無架構JSON文件。Elasticsearch是用Java開發的,並根據Apache License的條款作爲開源發佈。根據DB-Engines排名,Elasticsearch是最受歡迎的企業搜索引擎,後面是基於Lucene的Apache Solr。
  • Solr

一文分辨NoSQL 還是 SQL

 

  •  
  • Solr是Apache Lucene項目的開源企業搜索平臺。其主要功能包括全文檢索、命中標示、分面搜索、動態聚類、數據庫集成,以及富文本(如Word、PDF)的處理。Solr是高度可擴展的,並提供了分佈式搜索和索引複製

2.4.3 相關特性

以Elasticsearch爲例: 優點如下:

  • 查詢效率高 對海量數據進行近實時的處理
  • 可擴展性 基於集羣環境可以方便橫向擴展,可以承載PB級數據
  • 高可用 Elasticsearch集羣彈性-他們將發現新的或失敗的節點,重組和重新平衡數據,確保數據是安全的和可訪問的

缺點如下:

  • ACID支持不足 單一文檔的數據是ACID的,包含多個文檔的事務時不支持事務的正常回滾,支持 I(Isolation)隔離性(基於樂觀鎖機制的),D(Durability)持久性,不支持 A(Atomicity)原子性,C(Consistency)一致性
  • 對類似數據庫中通過外鍵的複雜的多表關聯操作支持較弱
  • 讀寫有一定延時,寫入的數據,最快1s中能被檢索到
  • 更新性能較低,底層實現是先刪數據,再插入新數據
  • 內存佔用大,因爲Lucene 將索引部分加載到內存中

2.4.4 使用場景

適用場景如下:

  • 分佈式的搜索引擎和數據分析引擎
  • 全文檢索,結構化檢索,數據分析
  • 對海量數據進行近實時的處理 可以將海量數據分散到多臺服務器上去存儲和檢索

不適用場景如下:

  • 數據需要頻繁更新
  • 需要複雜關聯查詢

2.5 圖形數據庫

一文分辨NoSQL 還是 SQL

 

圖形數據庫應用圖形理論存儲實體之間的關係信息。最常見例子就是社會網絡中人與人之間的關係。關係型數據庫用於存儲“關係型”數據的效果並不好,其查詢複雜、緩慢、超出預期,而圖形數據庫的獨特設計恰恰彌補了這個缺陷,解決關係型數據庫存儲和處理複雜關係型數據功能較弱的問題。

2.5.1 常見圖形數據庫

  • Neo4j

一文分辨NoSQL 還是 SQL

 

Neo4j是由Neo4j,Inc。開發的圖形數據庫管理系統。由其開發人員描述爲具有原生圖存儲和處理的符合ACID的事務數據庫,根據DB-Engines排名, Neo4j是最流行的圖形數據庫。

  • ArangoDB

一文分辨NoSQL 還是 SQL

 

ArangoDB是由triAGENS GmbH開發的原生多模型數據庫系統。數據庫系統支持三個重要的數據模型(鍵/值,文檔,圖形),其中包含一個數據庫核心和統一查詢語言AQL(ArangoDB查詢語言)。查詢語言是聲明性的,允許在單個查詢中組合不同的數據訪問模式。ArangoDB是一個NoSQL數據庫系統,但AQL在很多方面與SQL類似。

  • Titan

一文分辨NoSQL 還是 SQL

 

  •  

Titan是一個可擴展的圖形數據庫,針對存儲和查詢包含分佈在多機羣集中的數百億個頂點和邊緣的圖形進行了優化。Titan是一個事務性數據庫,可以支持數千個併發用戶實時執行復雜的圖形遍歷。

2.5.2 相關特性

以Neo4j爲例:

Neo4j 使用數據結構中圖(graph)的概念來進行建模。 Neo4j 中兩個最基本的概念是節點和邊。節點表示實體,邊則表示實體之間的關係。節點和邊都可以有自己的屬性。不同實體通過各種不同的關係關聯起來,形成複雜的對象圖。

針對關係數據,2種2數據庫的存儲結構不同:

一文分辨NoSQL 還是 SQL

 

Neo4j中,存儲節點時使用了”index-free adjacency”,即每個節點都有指向其鄰居節點的指針,可以讓我們在O(1)的時間內找到鄰居節點。另外,按照官方的說法,在Neo4j中邊是最重要的,是”first-class entities”,所以單獨存儲,這有利於在圖遍歷的時候提高速度,也可以很方便地以任何方向進行遍歷

一文分辨NoSQL 還是 SQL

 

如下優點:

  • 高性能表現 圖的遍歷是圖數據結構所具有的獨特算法,即從一個節點開始,根據其連接的關係,可以快速和方便地找出它的鄰近節點。這種查找數據的方法並不受數據量的大小所影響,因爲鄰近查詢始終查找的是有限的局部數據,不會對整個數據庫進行搜索
  • 設計的靈活性 數據結構的自然伸展特性及其非結構化的數據格式,讓圖數據庫設計可以具有很大的伸縮性和靈活性。因爲隨着需求的變化而增加的節點、關係及其屬性並不會影響到原來數據的正常使用
  • 開發的敏捷性 直觀明瞭的數據模型,從需求的討論開始,到程序開發和實現,以及最終保存在數據庫中的樣子,它的模樣似乎沒有什麼變化,甚至可以說本來就是一模一樣的
  • 完全支持ACID 不像別的NoSQL數據庫Neo4j還具有完全事務管理特性,完全支持ACID事務管理

缺點如下:

  • 具有支持節點,關係和屬性的數量的限制
  • 不支持拆分

2.5.3 使用場景

適用場景如下:

  • 在一些關係性強的數據中,例如社交網絡
  • 推薦引擎。如果我們將數據以圖的形式表現,那麼將會非常有益於推薦的制定

不適用場景如下:

  • 記錄大量基於事件的數據(例如日誌條目或傳感器數據)
  • 對大規模分佈式數據進行處理,類似於Hadoop
  • 適合於保存在關係型數據庫中的結構化數據
  • 二進制數據存儲

3 總結

關係型數據庫和NoSQL數據庫的選型,往往需要考慮幾個指標:

  • 數據量
  • 併發量
  • 實時性
  • 一致性要求
  • 讀寫分佈和類型
  • 安全性
  • 運維成本

常見軟件系統數據庫選型參考如下:

  • 內部使用的管理型系統 如運營系統,數據量少,併發量小,首選考慮關係型
  • 大流量系統 如電商單品頁,後臺考慮選關係型,前臺考慮選內存型
  • 日誌型系統 原始數據考慮選列式,日誌搜索考慮選倒排索引
  • 搜索型系統 例如站內搜索,非通用搜索,如商品搜索,後臺考慮選關係型,前臺考慮選倒排索引
  • 事務型系統 如庫存,交易,記賬,考慮選關係型型+緩存+一致性型協議
  • 離線計算 如大量數據分析,考慮選列式或者關係型也可以
  • 實時計算 如實時監控,可以考慮選內存型或者列式數據庫

設計實踐中,要基於需求、業務驅動架構,無論選用RDB/NoSQL/DRDB,一定是以需求爲導向,最終數據存儲方案必然是各種權衡的綜合性設計

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章