hbase的rowkey設計決定了數據的分區和查詢的方式,是使用hbase前一定要想清楚的,以下簡單列舉了設計hbase rowkey時需要考慮的問題
rowkey相同的記錄在hbase里被認為是同一條數據的多個版本,查詢時默認返回最新版本的數據,所以通常rowkey都需要保證唯一,除非用到多版本特性
rowkey就好比數據庫的里的主鍵,他唯一確定了一條記錄,它可以是一個字段也可以是多個字段拼接起來:
每個用戶只有一條記錄: [userid]
每個用戶有多條交易記錄:[userid][orderid]
rowkey的設計限制了數據的查詢方式,hbase只有兩種查詢方式:
1. 根據完整的rowkey查詢(get)
類似傳統DB的sql:
select * from table where rowkey = ‘abcde’
這種查詢方式需要知道完整的rowkey,即組成rowkey的所有字段的值都是確定的
2. 根據rowkey的范圍查詢(scan):
類似傳統DB的sql:
select * from table where ‘abc’ < rowkey <’abcx’
這種查詢方式需要知道數據rowkey左邊的值,就好像一本英文字典,你可以查詢pre開頭的所有單詞,也可以查詢prefi開頭的所有單詞,但是沒辦法查詢中間是efi或結尾是ix的所有單詞,除非翻閱整個字典
在有限的查詢方式下如何實現復雜查詢:
1.再建另外一張表作為索引表,應用雙寫
2.使用filter,在服務端過濾掉不需要的數據
3.使用二級索引
4.如何實現倒序(新的數據排在前面,如:order by orderTime desc):
? 使用反向scan:scan.setReverse(true)
? #反向scan的性能比正常scan要差,如果倒序的場景占大頭可以設計上就把數據倒序:
? [hostname][log-event][timestamp]? => [hostname][log-event][Long.MAX_VALUE – timestamp]
散列的目的是數據可以分散到不同的分區,不至于產生熱點,把某一臺服務器累死,其他服務器閑置,充分發揮分布式和并發的優勢
1.md5
? [userId][orderid]? =>? [md5(userid).subStr(0,4)][userId][orderid]
2.反轉
? [userId][orderid] => [reverse(userid)][orderid]
3.取模
? [timestamp][hostname][log-event]? => [bucket][timestamp][hostname][log-event]
? long bucket = timestamp % numBuckets;
4.增加隨機數
? [userId][orderid] => [userId][orderid][random(100)]
短的rowkey可以減少數據量 ,提高查詢寫入性能
1. 使用long或int型代替String
? 如: '2015122410' => Long(2015122410)
2. 使用編碼代替名稱
? 如:’淘寶‘ => tb
假設有以下場景:
table1的rowkey是: colume1+ colume2+ colume3
現在需要查詢colume1= host1 的所有數據:
scan 'table1',{startkey=> 'host1',endkey=> 'host2'}
此時如果有一條記錄colume1=host12,這條記錄也會被查詢出來:因為:
'host1' < 'host12' < 'host2'
但顯然這條記錄不是我們想要的
1. 字段定長
? [colume1][colume2] => [rpad(colume1,'x',20)][colume2]
2. 添加分隔符
? [colume1][colume2] => [colume1][_][colume2]
查詢場景:
1.查詢某臺機器某個指標某段時間內的數據
[hostname][log-event][timestamp]
2.查詢某臺機器某個指標最新的幾條數據
timestamp = Long.MAX_VALUE – timestamp
[hostname][log-event][timestamp]
3.數據只有時間一個維度或某一個維度數據量特別大
long bucket = timestamp % numBuckets;
[bucket][timestamp][hostname][log-event]
查詢場景:
1.查詢某個賣家某段時間內的交易記錄
[seller id][timestmap][order number]
2.查詢某個買家某段時間內的交易記錄
[buyer id][timestmap][order number]
3.根據訂單號查詢
[order number]
4.同時滿足1,2,3
三張表:
一張買家維度表,rowkey為:
[buyer id][timestmap][order number]
一張賣家維度表,rowkey為:
[seller id][timestmap][order number]
一張訂單索引表,rowkey為:
[order number]