2.1 NoSQL一詞的出現

最近,“NoSQL”一詞變得非常流行和流行,各種軟件解決方案都在這個標誌下積極開發和推廣。NoSQL 已經成為海量數據、線性可伸縮性、集群、容錯、非關係性的代名詞。然而,很少有人清楚地了解NoSQL存儲是什麼,這個詞是怎麼出現的,它們有什麼共同的特點。讓我們嘗試填補這個空白。

這個詞最有趣的地方在於,儘管它在 90 年代末首次使用,但直到 2009 年年中才以現在使用的形式獲得了真正的意義。最初,這是一個開放的名稱- 由 Carlo Strozzi 創建的源數據庫,它將所有數據存儲為 ASCII 文件,並使用 shell 腳本而不是 SQL 來訪問數據。它與當前形式的“NoSQL”無關。

2009 年 6 月,Johan Oskarsson 在舊金山組織了一次會議,討論 IT 存儲和處理市場的新趨勢。會議的主要推動力是新的開源產品,如 BigTable 和 Dynamo。對於會議的亮點,有必要找到一個能夠完美融入 Twitter 主題標籤的寬泛而簡潔的術語。其中一個術語是由來自 RackSpace 的 Eric Evans 提出的——“NoSQL”。該術語僅計劃用於一次會議,並沒有深的語義負載,但碰巧它像病毒式廣告一樣傳遍了全球網絡,並成為 IT 行業整個趨勢的事實上的名稱。順便說一句,Voldemort(Amazon Dynamo 克隆)、Cassandra、Hbase(Google BigTable 的類似物)、Hypertable、CouchDB、MongoDB 在會議上發言。

值得再次強調的是,“NoSQL”一詞完全是自發的,並沒有一個普遍接受的定義或背後的科學機構。這個名稱更像是遠離關係數據庫的 IT 開發向量的特徵。它代表 Not Only SQL,儘管有支持者直接定義 No SQL。Pramod Sadalaj 和 Martin Fowler 在他們最近出版的“NoSQL Distilled”一書中試圖對有關 NoSQL 世界的知識進行分組和系統化。

2.2 NoSQL數據庫的基本特徵

所有 NoSQL 幾乎沒有共同特徵,因為許多異構系統現在都隱藏在 NoSQL 標籤下(也許最完整的列表可以在 http://nosql-database.org/ 找到)。許多特性是某些 NoSQL 數據庫特有的,我在列出時肯定會提到這一點。

1.沒有使用SQL

我的意思是 ANSI SQL DML,因為許多數據庫嘗試使用類似於眾所周知的最喜歡的語法的查詢語言,但沒有人設法完全實現它並且不太可能成功。儘管有傳言稱有初創公司正在嘗試實施 SQL,例如在 hadup(http://www.drawntoscalehq.com/http://www.hadapt.com/)中。

2.非結構化(schemaless)

意思是在 NoSQL 數據庫中,與關係數據庫不同,數據結構不受規範(或弱類型,如果我們用編程語言類比)——您可以在單獨的行或文檔中添加任意字段,而無需先聲明性地更改結構整張桌子。因此,如果需要更改數據模型,那麼唯一足夠的操作就是在應用程序代碼中反映更改。

例如,重命名 MongoDB 中的字段時:

BasicDBObject order = new BasicDBObject();
order.put("date", orderDate); // this field was a long time ago
order.put("totalSum", total); // before we just used "sum"

如果我們更改應用程序邏輯,那麼我們在讀取時也會期望有一個新字段。但是由於缺少數據模式,其他已經存在的 Order 對像中缺少 totalSum 字段。在這種情況下,有兩種選擇可以採取進一步行動。

第一種是爬取所有文檔並更新所有現有文檔中的這個字段。由於數據量大,這個過程發生時沒有任何鎖(相當於 alter table rename column 命令),所以在更新期間,已經存在的數據可以被其他進程讀取。因此,第二種選擇——簽入應用程序代碼——是不可避免的:

BasicDBObject order = new BasicDBObject();
Double totalSum = order.getDouble("sum"); // This is the old model
if (totalSum  == null)
totalSum = order.getDouble("totalSum"); // This is the updated model

並且當我們重新記錄時,我們將以新格式將此字段寫入數據庫。

沒有模式的一個令人愉快的結果是處理稀疏數據的效率。如果一個文檔有 date_published 字段,而第二個沒有,則不會為第二個創建空的 date_published 字段。這在原則上是合乎邏輯的,但一個不太明顯的例子是列系列 NoSQL 數據庫,它使用熟悉的表/列概念。但是,由於缺少模式,列不會以聲明方式聲明,並且可以在用戶的數據庫會話期間更改/添加。這尤其允許使用動態列來實現列表。

非結構化模式有其缺點——除了上面提到的更改數據模型時在應用程序代碼中的開銷——缺少來自基礎的各種限制(非空、唯一、檢查約束等),再加上在並行處理不同項目的數據庫時,在理解和控制結構數據方面會遇到額外的困難(數據庫一側沒有字典)。然而,在瞬息萬變的現代世界中,這種靈活性仍然是一種優勢。一個例子是推特,五年前,除了推文,它只存儲了一些額外的信息(時間、推特句柄和更多字節的元信息),但現在,除了消息本身,還有更多的信息千字節的元數據存儲在數據庫中。

(以下主要討論key-value、document和column-family數據庫,圖數據庫可能沒有這些特性)

2.3. 以聚合(聚合)形式表示數據

與關係模型將應用程序的邏輯業務實體存儲到各種物理表中以實現規範化目的不同,NoSQL 存儲將這些實體作為整體對象進行操作:

此示例演示標準電子商務概念關係模型“訂單 - 訂單項目 - 付款 - 產品”的聚合。在這兩種情況下,訂單與位置組合成一個邏輯對象,而每個位置存儲一個指向產品的鏈接及其一些屬性,例如名稱(為了在檢索時不請求產品對象,這種非規範化是必要的一個順序——分佈式系統的主要規則是對象之間的“連接”)。在一種聚合中,付款與訂單結合在一起,並且是對象的組成部分,在另一種聚合中,它們被放置在一個單獨的對像中。這展示了在 NoSQL 數據庫中設計數據結構的主要規則 - 它必須服從應用程序的要求,並儘可能針對最頻繁的查詢進行優化。

許多人會反對,並指出在查詢不適合聚合結構時嘗試對數據進行任意查詢時,使用大型的、通常是非規範化的對象會充滿許多問題。如果我們將訂單與訂單行項目和付款一起使用(這就是應用程序的工作方式),但企業要求我們計算上個月售出的特定產品的數量怎麼辦?在這種情況下,我們不必掃描 OrderItem 表(在關係模型的情況下),而是必須檢索 NoSQL 存儲中的整個訂單,儘管我們不需要太多此類信息。不幸的是,這是在分佈式系統中必須做出的妥協:我們不能像在傳統的單服務器系統中那樣規範化數據,

我試圖將兩種方法的優缺點分組在一個表中: