云數據庫HBase的Rowkey設計在數據分區和數據查詢中很重要,本節介紹設計Rowkey前需要考慮的一些問題以及設計示例。
問題考慮
- 問題一:Rowkey是唯一的嗎?
相同的Rowkey在HBase中認為是同一條數據的多個版本,查詢時默認返回最新版本的數據,所以通常Rowkey都需要保證唯一,除非用到多版本特性。
最佳設計示例:Rowkey相當于數據庫的主鍵。Rowkey表示一條記錄。Rowkey可以是一個字段也可以是多個字段接起來。Rowkey為[userid]表示每個用戶只有一條記錄, Rowkey為[userid][orderid]表示每個用戶有多條記錄。
- 問題二:滿足哪種查詢場景?
Rowkey的設計限制了數據的查詢方式,HBase有兩種查詢方式。
- 根據完整的Rowkey查詢(get方式),例如
SELECT * FROM table WHERE Rowkey = ‘abcde’
。說明 get方式需要知道完整的Rowkey,即組成Rowkey所有字段的值都是確定的。 - 根據Rowkey的范圍查詢(scan方式),例如
SELECT * FROM table WHERE ‘abc’ < Rowkey <’abcx’
。說明 scan方式需要知道Rowkey左邊的值,例如您使用英文字典查詢pre開頭的所有單詞,也可以查詢prefi開頭的所有單詞,不能查詢中間或結尾為prefi的單詞。
最佳設計示例:在有限的查詢方式下如何實現復雜查詢?以下方法可以幫您實現。- 再新建一張表作為索引表。
- 使用Filter在服務端過濾不需要的數據。
- 使用二級索引。
- 使用反向scan方法實現倒序(將新數據排在前面),
scan.setReverse(true)
。說明 反向scan的性能比正常scan性能差,如果大部分是倒序場景可以體現在Rowkey設計上,例如[hostname][log-event][timestamp] => [hostname][log-event][Long.MAX_VALUE - timestamp]
。
- 根據完整的Rowkey查詢(get方式),例如
- 問題三:數據足夠分散,會存在堆積的熱點現象嗎?
散列的目的是將數據分散到不同的分區,不至于產生熱點使某一臺服務器終止,其他服務器空閑,充分發揮分布式和并發的優勢。
最佳設計示例:- 設計md5散列算法:
[userId][orderid] => [md5(userid).subStr(0,4)][userId][orderid]
。 - 設計反轉:
[userId][orderid] => [reverse(userid)][orderid]
。 - 設計取模:
[timestamp][hostname][log-event] => [bucket][timestamp][hostname][log-event]; long bucket = timestamp % numBuckets
。 - 增加隨機數:
[userId][orderid] => [userId][orderid][random(100)]
。
- 設計md5散列算法:
- 問題四:Rowkey可以再短點嗎?
短的Rowkey可以減少數據量,提高數據查詢和數據寫入效率。
最佳設計示例:- 使用Long或Int代替String,例如
'2015122410' => Long(2015122410)
。 - 使用編碼代替名稱,例如
'淘寶' => tb
。
- 使用Long或Int代替String,例如
- 問題五:使用scan方式會查詢出不需要的數據嗎?
會的。場景舉例:table1的Rowkey為
column1+ column2+ column3
,如果您需要查詢column1= host1
的所有數據,使用scan 'table1',{startkey=> 'host1',endkey=> 'host2'}
語句。如果有一條記錄為column1=host12
,那么此記錄也會查詢出來。最佳設計示例:- 設計字段定長,
[column1][column2] => [rpad(column1,'x',20)][column2]
。 - 添加分隔符,
[column1][column2] => [column1][_][column2]
。
- 設計字段定長,
常見設計示例
- 日志類、時間序列數據。列舉出以下三個場景設計Rowkey。
- 查詢某臺機器某個指標某段時間內的數據,Rowkey設計為
[hostname][log-event][timestamp]
。 - 查詢某臺機器某個指標最新的幾條數據,Rowkey設計為
timestamp = Long.MAX_VALUE - timestamp; [hostname][log-event][timestamp]
。 - 查詢的數據存在只有時間一個維度或某一個維度數據量巨大的情況,Rowkey設計為
long bucket = timestamp % numBuckets; [bucket][timestamp][hostname][log-event]
。
- 查詢某臺機器某個指標某段時間內的數據,Rowkey設計為
- 交易類數據。列舉出以下四個場景設計Rowkey。
- 查詢某個賣家某段時間內的交易記錄,Rowkey設計為
[seller id][timestamp][order number]
。 - 查詢某個買家某段時間內的交易記錄,Rowkey設計為
[buyer id][timestamp][order number]
。 - 根據訂單號查詢,Rowkey設計為
[order number]
。 - 查詢中同時滿足三張表,一張買家維度表Rowkey設計為
[buyer id][timestamp][order number]
。一張賣家維度表Rowkey設計為[seller id][timestamp][order number]
。一張訂單索引表Rowkey設計為[order number]
。
- 查詢某個賣家某段時間內的交易記錄,Rowkey設計為