數(shù)據(jù)庫 與 數(shù)據(jù)倉庫的本質(zhì)區(qū)別是什么?
數(shù)據(jù)庫 Database (Oracle, Mysql, PostgreSQL)主要用于事務(wù)處理,數(shù)據(jù)倉庫 Datawarehouse (Amazon Redshift, Hive)主要用于數(shù)據(jù)分析。
用途上的不同決定了這兩種架構(gòu)的特點(diǎn)不同。
數(shù)據(jù)庫(Database)的特點(diǎn)是:
相對復(fù)雜的表格結(jié)構(gòu),存儲(chǔ)結(jié)構(gòu)相對緊致,少冗余數(shù)據(jù)。
讀和寫都有優(yōu)化。
相對簡單的read/write query,單次作用于相對的少量數(shù)據(jù)。
數(shù)據(jù)倉庫(Datawarehouse)的特點(diǎn)是:
相對簡單的(Denormalized)表格結(jié)構(gòu),存儲(chǔ)結(jié)構(gòu)相對松散,多冗余數(shù)據(jù)。
一般只是讀優(yōu)化。
相對復(fù)雜的read query,單次作用于相對大量的數(shù)據(jù)(歷史數(shù)據(jù))。
用圖書表格系統(tǒng)舉例子。如果是數(shù)據(jù)庫儲(chǔ)存的話,表單的設(shè)計(jì)如下:

這里有六張表,分別記錄了作者,圖書,圖書種類,發(fā)行商以及他們之間的關(guān)系。
如果我們把以上數(shù)據(jù)用數(shù)據(jù)倉庫來存儲(chǔ),表單設(shè)計(jì)需要對原始表單進(jìn)行Denormalization。
Denormalization?is a strategy used on a previously-normalized database to increase performance. In computing,?denormalization?is the process of trying to improve the read performance of a database, at the expense of losing some write performance, by adding redundant copies of data or by grouping data. -?Denormalization - Wikipedia
現(xiàn)在我們把這個(gè)數(shù)據(jù)庫的五張表以Books.Title作為主鍵,用如下圖的腳本Denormalize之后存到數(shù)據(jù)庫倉庫中.
-- Denormalization Script --?select?b.id,b.title,b.copyright,b.isbn,g.genre,a.firstname?as?AuthorFirstName,a.lastname?as?AuthorLastName,a.dateofbirth,a.gender,p.name?as?PublisherNamefrom?BOOKS?bleft?join?GENRE?g?on?b.genre?=?g.idleft?join?AUTHOR_BOOK_MAP?abm?on?b.id?=?abm.bookidleft?join?AUTHORS?a?on?a.id?=?abm.authoridleft?join?PUBLISHER_BOOK_MAP?pbm?on?b.id?=?pbm.bookidleft?join?PUBLISHER?p?on?p.id?=?pbm.publisherid;
那么數(shù)據(jù)倉庫中就只剩下一張表,如下圖所示。

存儲(chǔ)空間對比
很明顯,因?yàn)樵赿enormalization的過程中,如果數(shù)據(jù)庫主表和次表不是一對一的關(guān)系,那么最終數(shù)據(jù)倉庫主表或者次表一定會(huì)出現(xiàn)重復(fù)的數(shù)據(jù)。所以從存儲(chǔ)空間角度講,相比于數(shù)據(jù)庫緊密的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)倉庫則存在大量冗余重復(fù)的數(shù)據(jù)。


讀寫優(yōu)化對比
基本讀(Read)操作對比
下圖所示的兩種查詢,一個(gè)是找一本書(PrimaryKey)的信息,另一個(gè)是找一位作者(Non-Key)所有的作品信息。由于數(shù)據(jù)庫需要利用表之間的關(guān)聯(lián)才能找到所有需要的數(shù)據(jù),在效率上會(huì)相對低下。相比之下數(shù)據(jù)倉庫把這些關(guān)聯(lián)關(guān)系轉(zhuǎn)化成重復(fù)數(shù)據(jù)記錄到同一張表上了,查詢效率相對就會(huì)較高。數(shù)據(jù)倉庫相當(dāng)于犧牲了空間換取了查詢效率。

在數(shù)據(jù)庫里面寫這段query的時(shí)候,我們需要了解表單的結(jié)構(gòu)與他們之間的關(guān)系——這對于做數(shù)據(jù)報(bào)告或者數(shù)據(jù)分析非常不友好,尤其是在表單結(jié)構(gòu)很復(fù)雜的時(shí)候(比如表單使用了邏輯樹的儲(chǔ)存結(jié)構(gòu))。這時(shí)候數(shù)據(jù)倉庫簡單明了的Denormalized表單結(jié)構(gòu)就對于生成數(shù)據(jù)報(bào)告就非常有優(yōu)勢了。
除此之外,由于數(shù)據(jù)報(bào)告和數(shù)據(jù)分析常常涉及到大規(guī)模的查詢,這些查詢很可能會(huì)占用很高的CPU資源,從而可能影響到數(shù)據(jù)庫的常規(guī)讀寫操作——因?yàn)閿?shù)據(jù)庫常常是Single-Instance的(接下來會(huì)提到);這一點(diǎn)上數(shù)據(jù)倉庫的Multi-instances的結(jié)構(gòu)就不會(huì)有太多這個(gè)問題。
大數(shù)據(jù)讀(Read)操作對比
當(dāng)數(shù)據(jù)量非常大的時(shí)候,特定條件下的數(shù)據(jù)倉庫的讀優(yōu)化所帶來的優(yōu)勢就開始碾壓數(shù)據(jù)庫了。大部分的數(shù)據(jù)庫都是Single-instance的,而數(shù)據(jù)倉庫則是Multi-instances的distributed system。數(shù)據(jù)倉庫在分配儲(chǔ)存的節(jié)點(diǎn)的時(shí)候是根據(jù)PrimaryKey/PartitionKey來分配的,查詢的時(shí)候不僅根據(jù)查詢鍵的值來搜索對應(yīng)節(jié)點(diǎn)位置,同時(shí)進(jìn)行大量的并行查詢。這使得在對大數(shù)據(jù)進(jìn)行查詢的時(shí)候有極大的優(yōu)勢。

但是,并不是所有的讀操作,數(shù)據(jù)倉庫一直都有優(yōu)勢。比如在如下兩種情況時(shí),數(shù)據(jù)倉庫的讀表現(xiàn)并不如數(shù)據(jù)庫:
在對小量數(shù)據(jù)進(jìn)行讀取操作的時(shí)候,由于數(shù)據(jù)倉庫要進(jìn)行找Node的location之類的預(yù)運(yùn)算,整體效率上反倒不如數(shù)據(jù)庫。
如果讀取操作的目標(biāo)不是主鍵(PrimaryKey)或者分配鍵(PartitionKey),那么數(shù)據(jù)倉庫的查詢也需要進(jìn)行全局掃描,效率上就不好說是否勝過數(shù)據(jù)庫了。
這兩點(diǎn)也是為什么現(xiàn)在即使有像Amazon Redshift這般強(qiáng)大的Datawarehouse應(yīng)用,SQL Database仍然無法被取代的一部分主要原因。
寫(Write)操作對比
大多數(shù)情況下,數(shù)據(jù)倉庫不太會(huì)進(jìn)行精確的寫操作。因?yàn)槿哂嘈袛?shù)太多,有時(shí)候只是改一個(gè)很小的字段,也會(huì)修改大量的行數(shù)。而對于數(shù)據(jù)庫來說,由于其緊湊的表格結(jié)構(gòu),寫操作就可以非常精細(xì)有效了。比如,我需要修改《Java Complete》這本書的版權(quán),從1999改到2002,數(shù)據(jù)庫里面只需要該一行,而數(shù)據(jù)倉庫里面需要改5行。

數(shù)據(jù)倉庫的寫操作都是整段(表)刷新或者整段數(shù)據(jù)插入, 這也和它的用途——做數(shù)據(jù)分析有關(guān)系。由于數(shù)據(jù)倉庫的整表刷新和分布式儲(chǔ)存的特質(zhì),我們可以通過把PartitionKey設(shè)置成數(shù)據(jù)創(chuàng)建/更新的時(shí)間,然后記錄一段時(shí)間內(nèi)的歷史數(shù)據(jù)。這對于數(shù)據(jù)分析以及利用數(shù)據(jù)進(jìn)行決策都有重要意義。
雖然這里進(jìn)行了數(shù)據(jù)庫和數(shù)據(jù)倉庫的對比,但是并不是想得出兩者孰優(yōu)孰劣的結(jié)論。實(shí)際情況是,很多的架構(gòu)的存儲(chǔ)方案都是數(shù)據(jù)庫和數(shù)據(jù)倉庫一起使用的。下面會(huì)介紹一種這類架構(gòu)的簡單例子。
常見相關(guān)架構(gòu)以及數(shù)據(jù)目錄(Data Catalog)
通常的軟件架構(gòu)簡化一下就是,用戶通過API和數(shù)據(jù)庫交互。

這里如果要直接在數(shù)據(jù)庫上做數(shù)據(jù)分析,數(shù)據(jù)監(jiān)控等等任務(wù)的話,會(huì)有以下幾個(gè)問題:
數(shù)據(jù)分析通常涉及大量數(shù)據(jù)查詢,可能會(huì)占用太多CPU從而影響軟件的基本功能。
數(shù)據(jù)庫的表單結(jié)構(gòu)通常比較復(fù)雜,需要數(shù)據(jù)分析人員對DB結(jié)構(gòu)有深入的了解。
數(shù)據(jù)庫在進(jìn)行大量數(shù)據(jù)查詢的時(shí)候效率較低。
開放數(shù)據(jù)庫訪問權(quán)限(即便只是讀權(quán)限),尤其是給外組人員,會(huì)有安全隱患。
為了解決以上四個(gè)問題,我們可以通過利用腳本,每隔一段時(shí)間把數(shù)據(jù)庫里面的所有數(shù)據(jù)Denormalize到數(shù)據(jù)倉庫里面,在數(shù)據(jù)倉庫里面進(jìn)行數(shù)據(jù)分析。根據(jù)之前提到的數(shù)據(jù)倉庫的所有的特性(獨(dú)立不影響業(yè)務(wù),表結(jié)構(gòu)簡單,讀數(shù)據(jù)速度快,相對安全),這四個(gè)問題都可以得到很好的解決。

但是這里還是有一個(gè)小問題。如果有很多不同的組需要共享這個(gè)Datawarehouse,那么同樣他們的腳本可能會(huì)相互影響。這里引入一下數(shù)據(jù)目錄(Data Catalog)的概念來解決這個(gè)問題。
A?data catalog?is a metadata management tool designed to help organizations find and manage large amounts of data – including tables, files and databases – stored in their ERP, human resources, finance and e-commerce systems as well as other sources like social media feeds. - ?https://searchdatamanagement.techtarget.com/definition/data-catalog
通過數(shù)據(jù)目錄儲(chǔ)存元數(shù)據(jù),然后發(fā)布出去讓不同組的數(shù)據(jù)倉庫都可以同步這個(gè)數(shù)據(jù)。這樣,每個(gè)不同組的數(shù)據(jù)倉庫都拿到了同樣的Denormalized數(shù)據(jù),但是卻相互獨(dú)立開了。

這樣一個(gè)架構(gòu)基本上是把做事務(wù)處理的數(shù)據(jù)庫和做數(shù)據(jù)分析的數(shù)據(jù)倉庫解耦了。同時(shí)增加了整個(gè)系統(tǒng)的可擴(kuò)展性。