HBase 的資料模型及表格設計
原文:Introduction to HBase Schema Design
隨著大量資料的增長,針對其處理的應用程序也隨之增長。為了支持這種新的應用程序以及擴展舊的應用程序,已經開發了不少新的資料管理系統。其中更有許多是由開源社群所開發,並已部署在幾家公司內。
Apache HBase 就是這樣的系統。
HBase 是一個開源的分散式資料庫,以 Google Bigtable 為模型,它被作為快速隨機存取大量資料的資料庫選擇之一。
HBase 建立在 Apache Hadoop,與之緊密結合。它與傳統的關聯式資料庫(MySQL、PostgreSQL、Oracle 等)非常不同,不管是它如何架構或者它所提供的功能。HBase 相對傳統資料庫有更加靈活的架構以及功能的可擴展性。
HBase 架構
HBase 資料模型
如 Bigtable 的論文所述,Bigtable 是一種稀疏(Sparse)、分散式(Distributed)、 持久的多維排序映射(Persistent Multidimensional Sorted Map),由列鍵(Row Key)、行鍵(Column Key)和時間戳(Timestamp)作為索引。
※ 台灣在 Row 與 Column的翻譯與中國有所差異,請參考兩岸線性代數用詞參照
有人稱 HBase 為鍵值儲存(key-value store)、行族導向資料庫(Column-Family-Oriented Database)或是儲存多時間戳的版本映射的資料處(Database storing versioned maps of maps)。
最原始簡單來描述 HBase 資料模型的方式就是它由行與列的表格所組成。就如同我們在關聯式資料庫所熟悉的,這是它們兩者之間的相似性,但事實上它們對行與列的概念有些不同。
- 表格(Table)
HBase 將資料組織成表格,表名由能用在文件路徑裡的字串組成。
- 列(Row)
在表格中,資料根據其列儲存,每一列由列鍵唯一標識。列鍵相當於關聯式資料庫中的主鍵(Primary Key),在創建表格時就已設定。
列鍵不具資料形態,始終視為 byte[ ] (byte array)。
- 行族(Column Family)
列中的資料由行族分組。行族也同樣影響 HBase 的物理儲存結構,因此它們必須被提前設置,且不易修改。
表格中的每一列都具相同的行族,但行族中的每一列不一定要有資料儲存(HBase 的稀疏性)。
行族名稱由能用在文件路徑裡的字串組成。
- 行限定符(Column Qualifier)
行族中的資料通過行限定符來映射搜尋。行限定符不需要提前設置,一旦確定行族後,由於行族會影響儲存結構,所以不能輕易修改,但行限定符及其對應的值可以動態增刪。
表格中的每一列都具相同的行族,但不需要在每一列保持一致的行限定符及值。
行鍵同樣不具資料形態,始終視為 byte[ ] (byte array)。
- 單元(Cell)
單元為列族、行族及行限定符的唯一組合。儲存於單元格的資料稱為單元格的值。
其值不具資料形態,同樣視為 byte[ ] (byte array)。
- 時間戳(Timestamp)
預設下,每一個插入單元的資料都會以時間戳來辨識其版本。寫入時,如未指定時間戳,預設使用當前時間。讀取時,如果沒有指定時間戳,則使用最新版本的時間戳,HBase 也支援指定多個版本做為查詢。
HBase 會保留每個行族的單元版本數量。預設為每個單元保存 3 個時間戳。
HBase 的 API 包含三個主要的資料操作:Get、Put 和 Scan 。
- Get 和 Put 需提供列鍵,並針對特定的列操作。
- Scan 則是對一定範圍的列操作,範圍可由起始和終止的列鍵所定義,如我沒有明確定義,則預設取得所有的列。
有時候,你可以將 HBase 的資料模型視為一個多維映射的模型,下列圖 2 將 圖 1 中的第一列視為多維映射:
你也使用鍵值儲存(Key-Value Store)來描述 HBase ,其中鍵(Key)是列鍵(Row Key),值(Value)是行中其餘的資料,如下列圖 3 所示:
這種表示方式也是 KeyValue 物件在 HBase API 內部的實際工作原理。
HBase 表格設計基礎
你可以透過回答下述的問題來設計 HBase 表格:
- 該如何設置列鍵(Row Key)的結構?它又該包含什麼資訊?
- 表格應該有幾個行族(Column Family)?
- 行族中應該儲存什麼樣的資料?
- 每個行族中應該有多少的行?
- 行名是什麼?儘管創建表格時,不需要定義行名,但在寫入及讀取資料時仍要知道它們。
- 單元(Cell)應該儲存什麼樣的資訊?
- 每個單元應該儲存多少個版本?
在 HBase 表格中最重要的就是列鍵的結構。為了有效地定義其存取模式,必須考慮 HBase 表格中的幾個性質:
- 表格的索引(Index)是通過 Key 來進行。
- 表格是基於列鍵的字典排序對每列的資料進行儲存。表格中的每個區域(Region)的空間都是由列鍵來決定的。
- 所有儲存在 HBase 表格中的資料都是二進位的陣列 byte[ ],沒有資料型態。
- 原子性(Atomicity;交易(Transaction)中的所有操作,只有全部的步驟執行成功才算完成,否則宣告交易失敗並回復所有變更。)只在列之間內保證,列之間沒有保證原子性,這也意味其不具多列交易(Multi-Row Transactions)。
- 行族(Column Family)必須在表格創建前定義好。
- 行族中的行限定符(Column Qualifier)可以在表格創建後,插入資料時動態增加。以 byte[ ] 形式儲存,因此亦可儲存資料。
總結
- 列鍵(Row Key)是 HBase 表格設計中重要的一環,它會直接影響應用程式與 HBase 表格的交互與資料提取的性能。
- HBase 表格是靈活的(Flexible),你可以 byte[] 的形式儲存任何內容。
- 相同的行族中所有的資料都具相似的存取模式。
- 主要通過列鍵(Row Key)來建立索引。
- 縱向擴張為主的高表(Tall Table)能更快速且簡單的操作,但會犧牲原子性。而橫向擴張為主的寬表(Wide Table),行族中有很多的行,能保持在列內一定的原子性。
- HBase 不支援跨列交易(Cross-Row Transactions),你會希望避免在客戶端(Client)建構邏輯,所以要盡可能在單次的 API 請求中完成存取模式,而非多次的 API 調用。
- 雜湊(Hashing)允許固定長度的列鍵(Row Key)並使資料平均分配。但是,因為使用字串作為鍵(Key),會犧牲其資料的排序及讀取性能。
- 行限定符(Column Qualifiers)亦可儲存資料,如同單元(Cell)本身。
- 行限定符(Column Qualifiers)的長度會影響儲存空間,因為你可以將資料儲存其中。當存取資料時,長度同樣會影響磁碟及網路的 I/O 成本。因此,命名應該簡潔扼要。
- 行族(Column Family)的長度會影響資料(KeyValue 物件)通過線路發送到客戶端的大小。所以,命名應該簡潔扼要。