HBase 的資料模型及表格設計

EREN
erens-tech-book
Published in
7 min readSep 25, 2017

--

原文: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 個時間戳。

A slice of an example table that stores Web pages
A Table in HBase

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 表格:

  1. 該如何設置列鍵(Row Key)的結構?它又該包含什麼資訊?
  2. 表格應該有幾個行族(Column Family)?
  3. 行族中應該儲存什麼樣的資料?
  4. 每個行族中應該有多少的行?
  5. 行名是什麼?儘管創建表格時,不需要定義行名,但在寫入及讀取資料時仍要知道它們。
  6. 單元(Cell)應該儲存什麼樣的資訊?
  7. 每個單元應該儲存多少個版本?

在 HBase 表格中最重要的就是列鍵的結構。為了有效地定義其存取模式,必須考慮 HBase 表格中的幾個性質:

  1. 表格的索引(Index)是通過 Key 來進行。
  2. 表格是基於列鍵的字典排序對每列的資料進行儲存。表格中的每個區域(Region)的空間都是由列鍵來決定的。
  3. 所有儲存在 HBase 表格中的資料都是二進位的陣列 byte[ ],沒有資料型態。
  4. 原子性(Atomicity;交易(Transaction)中的所有操作,只有全部的步驟執行成功才算完成,否則宣告交易失敗並回復所有變更。)只在列之間內保證,列之間沒有保證原子性,這也意味其不具多列交易(Multi-Row Transactions)。
  5. 行族(Column Family)必須在表格創建前定義好。
  6. 行族中的行限定符(Column Qualifier)可以在表格創建後,插入資料時動態增加。以 byte[ ] 形式儲存,因此亦可儲存資料。

總結

  1. 列鍵(Row Key)是 HBase 表格設計中重要的一環,它會直接影響應用程式與 HBase 表格的交互與資料提取的性能。
  2. HBase 表格是靈活的(Flexible),你可以 byte[] 的形式儲存任何內容。
  3. 相同的行族中所有的資料都具相似的存取模式。
  4. 主要通過列鍵(Row Key)來建立索引。
  5. 縱向擴張為主的高表(Tall Table)能更快速且簡單的操作,但會犧牲原子性。而橫向擴張為主的寬表(Wide Table),行族中有很多的行,能保持在列內一定的原子性。
  6. HBase 不支援跨列交易(Cross-Row Transactions),你會希望避免在客戶端(Client)建構邏輯,所以要盡可能在單次的 API 請求中完成存取模式,而非多次的 API 調用。
  7. 雜湊(Hashing)允許固定長度的列鍵(Row Key)並使資料平均分配。但是,因為使用字串作為鍵(Key),會犧牲其資料的排序及讀取性能。
  8. 行限定符(Column Qualifiers)亦可儲存資料,如同單元(Cell)本身。
  9. 行限定符(Column Qualifiers)的長度會影響儲存空間,因為你可以將資料儲存其中。當存取資料時,長度同樣會影響磁碟及網路的 I/O 成本。因此,命名應該簡潔扼要。
  10. 行族(Column Family)的長度會影響資料(KeyValue 物件)通過線路發送到客戶端的大小。所以,命名應該簡潔扼要。

參考資料

--

--

EREN
erens-tech-book

“I’m quite illiterate, but I read a lot. “ — J.D.Salinger, The Catcher in the Rye