HBase模式案例研究:列表數據

以下是用戶 dist-list 中關於一個相當常見問題的的交流:如何處理 Apache HBase 中的每個用戶列表數據。

問題:

我們正在研究如何在 HBase 中存儲大量(每用戶)列表數據,並且我們試圖弄清楚哪種訪問模式最有意義。一種選擇是將大部分數據存儲在一個密鑰中,所以我們可以有如下的內容:


HBase模式案例研究:列表數據

我們的另一個選擇是完全使用如下內容:


HBase模式案例研究:列表數據

每行將包含多個值。所以在一種情況下,讀取前三十個值將是:


HBase模式案例研究:列表數據

而在第二種情況下會是這樣:

HBase模式案例研究:列表數據

一般的使用模式是隻讀取這些列表的前30個值,並且很少的訪問會深入到列表中。一些用戶在這些列表中總共有30個值,並且一些用戶將擁有數百萬(即冪律分佈)。

單值格式似乎會佔用 HBase 上的更多空間,但會提供一些改進的檢索/分頁靈活性。是否有任何顯著的性能優勢能夠通過獲取和掃描的頁面進行分頁?

我最初的理解是,如果我們的分頁大小未知(並且緩存設置恰當),那麼執行掃描應該會更快,但如果我們始終需要相同的頁面大小,則掃描速度應該更快。我聽到不同的人告訴了我關於表現的相反事情。我假設頁面大小會相對一致,所以對於大多數使用情況,我們可以保證我們只需要固定頁面長度的情況下的一頁數據。我還會假設我們將不經常更新,但可能會插入這些列表的中間(這意味著我們需要更新所有後續行)。

答案:

如果我理解正確,你最終試圖以“user,valueid,value”的形式存儲三元組,對嗎?例如:


HBase模式案例研究:列表數據

(但用戶名是固定寬度,而 valueids 是固定寬度)。

而且,您的訪問模式符合以下要求:“對於用戶 X,列出接下來的30個值,以valueid Y開頭”。是對的嗎?這些值應該按 valueid 排序返回?

tl、dr 版本是,你可能應該為每個用戶+值添加一行,除非你確定需要,否則不要自行構建複雜的行內分頁方案。

您的兩個選項反映了人們在設計 HBase 模式時常見的問題:我應該選擇“高”還是“寬”?您的第一個模式是“高(tall)”:每行代表一個用戶的一個值,因此每個用戶的表中有很多行;行鍵是 user + valueid,並且會有(可能)單個列限定符,表示“值(value)”。如果您希望按行鍵來掃描排序順序中的行, 這是很好的。你可以在任何用戶 + valueid 開始掃描,閱讀下一個30,並完成。你放棄的是能夠在一個用戶的所有行周圍提供事務保證,但它聽起來並不像你需要的那樣。

第二個選項是“寬”:使用不同的限定符(其中限定符是valueid)將一堆值存儲在一行中。簡單的做法是將一個用戶的所有值存儲在一行中。我猜你跳到了“分頁”版本,因為你認為在單行中存儲數百萬列會對性能造成影響,這可能是也可能不是真的; 只要你不想在單個請求中做太多事情,或者做一些事情,比如掃描並返回行中的所有單元格,它不應該從根本上變壞。客戶端具有允許您獲取特定的列的片段的方法。

請注意,這兩種情況都不會從根本上佔用更多的磁盤空間; 您只是將部分識別信息“移動”到左側(在行鍵中,在選項一中)或向右(在選項2中的列限定符中)。在封面下,每個鍵/值仍然存儲整個行鍵和列名稱。

正如你注意到的那樣,手動分頁版本有很多複雜性,例如必須跟蹤每個頁面中有多少內容,如果插入新值,則重新洗牌等。這看起來要複雜得多。在極高的吞吐量下它可能有一些輕微的速度優勢(或缺點!),而要真正知道這一點的唯一方法就是試用它。如果您沒有時間來構建它並進行比較,我的建議是從最簡單的選項開始(每個用戶 + valueid)。開始簡單並重復!


分享到:


相關文章: