第42期:RDB與NoSQL的訪問性能
我們繼續從軟件角度上看外存數據源的性能,來考察數據庫的性能特點,在這篇文章中,我們只關心數據的訪問性能,而不涉及計算性能。
一、關系數據庫
關系數據庫也是很常見的數據存儲方式。本質上講,數據庫其實也是一種特殊的二進制文件,但它的性能會弱于直接寫在操作系統下的文件,主要原因在于數據庫通常都要提供數據更新的能力,這就會產生影響性能的因素:
1. 緊湊性與壓縮手段
數據庫要考慮數據的更新,一般會采用段頁式的分塊存儲,在存儲數據時不會把分塊完全填滿,而會留一小部分空白區用于后續的修改動作。這樣,占用的硬盤空間就會比不考慮更新動作的文件更大一點。
因為要更新數據,也很難實現數據壓縮。比如上一篇所說的把小整數存成較短字節的方案,如果采用了這種方案,一旦這個小整數被改成了大整數,原來的空間就存不下了,就要把后續數據都向后移動,這會使數據更新成本過高,所以一般數據庫都不采用壓縮手段,而直接根據數據類型分配空間,也會造成空間的浪費,極端情況會出現占用空間大于文本的現象。
2. 事務一致性帶來的復雜性
許多商業數據庫還會同時支持OLTP業務,在讀取數據時要提供一致性的能力,這會使訪問數據的動作復雜度變大很多。同一條數據,由于其它事務的寫操作,可能出現多個備份,在讀取時數據庫要根據事務的啟動時刻找到正確的那一個,這是個非常麻煩的動作,對性能影響很大。
另外,前面文章還提到過,按塊存儲的結構對于分段也不夠自由,不象文件那樣可以實施更靈活的并行手段,也會導致數據庫的性能表現弱于直接 文件。
數據庫普遍還有一個IO性能不佳的問題,數據在數據庫中運算時性能尚可,但要通過數據庫接口取出來就非常慢,實測的情況表明,這個性能經常可能會比用文本存儲還慢。對于這個問題,在數據庫本身負擔不重時,可以采用并行取數的方法來解決,具體細節及代碼我們將在以后再詳述。
二、NoSQL數據庫
NoSQL常常被用作大數據處理,但是,它真地能獲得高性能嗎?
這要分情況,看進行什么樣的處理。
NoSQL產品一般都不提供事務一致性的能力,這是在數據訪問時的動作要比關系數據庫簡單了許多,不需要考慮回滾段、多備份等問題。而且,放棄事務的NoSQL一般也更容易橫向擴展,使用更多機器來承載更大的業務量。在這方面,NoSQL確實會有更高的性能,特別是高并發寫入時的優勢要比關系數據庫大得多。
不過,對于單純的分析型業務,卻不完全是這樣。
許多分析型關系數據庫也不考慮事務一致性的問題,訪問動作同樣也較為簡單。NoSQL不處理事務一致性帶來的性能優勢,與這些分析型數據庫比并沒有特別的地方。
NoSQL產品常常使用Key-Value型存儲組織,Value的隨意性會帶來結構多樣性的好處,即使用NoSQL存儲數據時不需要事先確定數據結構,不象關系數據庫那樣必須先建個有特定數據結構的表才能使用,這是NoSQL非常方便的地方。
但是,多樣性和高性能是一對天生的矛盾!
多樣性意味著每條記錄的數據結構都可能不一樣。在存儲數據時同時也要存儲結構,增大了存儲量,在解析數據時也要去匹配數據結構中的字段,增加大了復雜度。而關系數據庫中同一表的數據結構是確定且相同的,結構只要存儲一份,解析數據時的字段對應也非常簡單,當數據量很大時,這個優勢就會非常明顯。
大多數Key-Value式的NoSQL產品,只是在用Key尋找Values時性能很好(這只要有個Hash索引就能夠用Key找到對應的記錄,關系數據庫建了索引也可以),但面臨需要對數據遍歷才能完成的計算時(比如過濾條件不是針對Key的),它的性能就會遠遠低于確定數據結構的關系數據庫。把NoSQL用于高性能大數據分析業務是個錯誤的選擇,但現實中卻經常有人在這么用。