hbase的rowkey設(shè)計(jì)決定了數(shù)據(jù)的分區(qū)和查詢的方式养篓,是使用hbase前一定要想清楚的烂完,以下簡(jiǎn)單列舉了設(shè)計(jì)hbase rowkey時(shí)需要考慮的問(wèn)題
rowkey相同的記錄在hbase里被認(rèn)為是同一條數(shù)據(jù)的多個(gè)版本茄菊,查詢時(shí)默認(rèn)返回最新版本的數(shù)據(jù)疯潭,所以通常rowkey都需要保證唯一,除非用到多版本特性
rowkey就好比數(shù)據(jù)庫(kù)的里的主鍵面殖,他唯一確定了一條記錄竖哩,它可以是一個(gè)字段也可以是多個(gè)字段拼接起來(lái):
每個(gè)用戶只有一條記錄: [userid]
每個(gè)用戶有多條交易記錄:[userid][orderid]
rowkey的設(shè)計(jì)限制了數(shù)據(jù)的查詢方式脊僚,hbase只有兩種查詢方式:
1. 根據(jù)完整的rowkey查詢(get)
類似傳統(tǒng)DB的sql:
select * from table where rowkey = ‘a(chǎn)bcde’
這種查詢方式需要知道完整的rowkey相叁,即組成rowkey的所有字段的值都是確定的
2. 根據(jù)rowkey的范圍查詢(scan):
類似傳統(tǒng)DB的sql:
select * from table where ‘a(chǎn)bc’ < rowkey <’abcx’
這種查詢方式需要知道數(shù)據(jù)rowkey左邊的值,就好像一本英文字典辽幌,你可以查詢pre開(kāi)頭的所有單詞增淹,也可以查詢prefi開(kāi)頭的所有單詞,但是沒(méi)辦法查詢中間是efi或結(jié)尾是ix的所有單詞乌企,除非翻閱整個(gè)字典
在有限的查詢方式下如何實(shí)現(xiàn)復(fù)雜查詢:
1.再建另外一張表作為索引表虑润,應(yīng)用雙寫
2.使用filter,在服務(wù)端過(guò)濾掉不需要的數(shù)據(jù)
3.使用二級(jí)索引
4.如何實(shí)現(xiàn)倒序(新的數(shù)據(jù)排在前面加酵,如:order by orderTime desc):
? 使用反向scan:scan.setReverse(true)
? #反向scan的性能比正常scan要差拳喻,如果倒序的場(chǎng)景占大頭可以設(shè)計(jì)上就把數(shù)據(jù)倒序:
? [hostname][log-event][timestamp]? => [hostname][log-event][Long.MAX_VALUE – timestamp]
3. 數(shù)據(jù)足夠分散,會(huì)產(chǎn)生熱點(diǎn)嗎猪腕?
散列的目的是數(shù)據(jù)可以分散到不同的分區(qū)冗澈,不至于產(chǎn)生熱點(diǎn),把某一臺(tái)服務(wù)器累死码撰,其他服務(wù)器閑置渗柿,充分發(fā)揮分布式和并發(fā)的優(yōu)勢(shì)
1.md5
? [userId][orderid]? =>? [md5(userid).subStr(0,4)][userId][orderid]
2.反轉(zhuǎn)
? [userId][orderid] => [reverse(userid)][orderid]
3.取模
? [timestamp][hostname][log-event]? => [bucket][timestamp][hostname][log-event]
? long bucket = timestamp % numBuckets;
4.增加隨機(jī)數(shù)
? [userId][orderid] => [userId][orderid][random(100)]
短的rowkey可以減少數(shù)據(jù)量 ,提高查詢寫入性能
1. 使用long或int型代替String
? 如: '2015122410' => Long(2015122410)
2. 使用編碼代替名稱
? 如:’淘寶‘ => tb
5. scan時(shí)會(huì)不會(huì)查詢出不需要的數(shù)據(jù)?
假設(shè)有以下場(chǎng)景:
table1的rowkey是: colume1+ colume2+ colume3
現(xiàn)在需要查詢colume1= host1 的所有數(shù)據(jù):
scan 'table1',{startkey=> 'host1',endkey=> 'host2'}
此時(shí)如果有一條記錄colume1=host12朵栖,這條記錄也會(huì)被查詢出來(lái):因?yàn)?
'host1' < 'host12' < 'host2'
但顯然這條記錄不是我們想要的
1. 字段定長(zhǎng)
? [colume1][colume2] => [rpad(colume1,'x',20)][colume2]
2. 添加分隔符
? [colume1][colume2] => [colume1][_][colume2]
查詢場(chǎng)景:
1.查詢某臺(tái)機(jī)器某個(gè)指標(biāo)某段時(shí)間內(nèi)的數(shù)據(jù)
[hostname][log-event][timestamp]
2.查詢某臺(tái)機(jī)器某個(gè)指標(biāo)最新的幾條數(shù)據(jù)
timestamp = Long.MAX_VALUE – timestamp
[hostname][log-event][timestamp]
3.數(shù)據(jù)只有時(shí)間一個(gè)維度或某一個(gè)維度數(shù)據(jù)量特別大
long bucket = timestamp % numBuckets;
[bucket][timestamp][hostname][log-event]
查詢場(chǎng)景:
1.查詢某個(gè)賣家某段時(shí)間內(nèi)的交易記錄
[seller id][timestmap][order number]
2.查詢某個(gè)買家某段時(shí)間內(nèi)的交易記錄
[buyer id][timestmap][order number]
3.根據(jù)訂單號(hào)查詢
[order number]
4.同時(shí)滿足1,2陨溅,3
三張表:
一張買家維度表终惑,rowkey為:
[buyer id][timestmap][order number]
一張賣家維度表,rowkey為:
[seller id][timestmap][order number]
一張訂單索引表门扇,rowkey為:
[order number]