1. 程式人生 > >從Hive表中進行資料抽樣-Sampling

從Hive表中進行資料抽樣-Sampling

在Hive中提供了資料取樣(SAMPLING)的功能,用來從Hive表中根據一定的規則進行資料取樣,Hive中的資料取樣支援分桶表取樣和資料塊取樣。

16.1 資料塊取樣(Block Sampling)

  • block_sample: TABLESAMPLE (n PERCENT)

根據輸入的inputSize,取樣n%。

比如:輸入大小為1G,TABLESAMPLE (50 PERCENT)將會取樣512M的資料;

看例子:

表lxw1總大小約為64816816,總記錄數為:2750714

bubuko.com,布布扣

使用下面的語句,從表lxw111中取樣50%的資料,建立一個新表:

CREATE TABLE lxw1234 AS

SELECT * FROM lxw1 TABLESAMPLE (50 PERCENT);

完成後看看錶lxw1234的記錄數和大小:

bubuko.com,布布扣

結果表記錄數:1376390,總大小:32432626,基本上是原表的50%。

  • block_sample: TABLESAMPLE (nM)

這種方式指定取樣資料的大小,單位為M。

比如,下面的語句:

CREATE TABLE lxw1234_2 AS

SELECT * FROM lxw1 TABLESAMPLE (30M);

將會從表lxw1中取樣30M的資料:

bubuko.com,布布扣

  • block_sample: TABLESAMPLE (n ROWS)

這種方式可以根據行數來取樣,但要特別注意:這裡指定的行數,是在每個InputSplit中取樣的行數,也就是,每個Map中都取樣n ROWS。

下面的語句:
SELECT COUNT(1) FROM (SELECT * FROM lxw1 TABLESAMPLE (200 ROWS)) x;

bubuko.com,布布扣

有5個Map Task(InputSplit),每個取樣200行,一共1000行。

16.2 分桶表取樣(Sampling Bucketized Table)

關於Hive中的分桶表(Bucket Table),在以後的文章中將會介紹,其實就是根據某一個欄位Hash取模,放入指定資料的桶中,比如將表lxw1234按照ID分成100個桶,其算 法是hash(id) % 100,這樣,hash(id) % 100 = 0的資料被放到第一個桶中,hash(id) % 100 = 1的記錄被放到第二個桶中。分桶表在建立時候使用CLUSTER BY語句建立。

Hive中分桶表取樣的語法是:

table_sample: TABLESAMPLE (BUCKET x OUT OF y [ON colname])

其中x是要抽樣的桶編號,桶編號從1開始,colname表示抽樣的列,y表示桶的數量。

例子1:

SELECT COUNT(1)

FROM lxw1 TABLESAMPLE (BUCKET 1 OUT OF 10 ON rand());

該語句表示將表lxw1隨機分成10個桶,抽樣第一個桶的資料;

前面介紹過,表lxw1總大小約為64816816,總記錄數為:2750714

bubuko.com,布布扣

出來的結果基本上是原表的十分之一,注意:這個結果每次執行是不一樣的,因為是按照隨機數進行分桶取樣的。

例子2

如果基於一個已經分桶表進行取樣,將會更有效率。

執行下面的語句,建立一個分桶表,並插入資料:

CREATE TABLE lxw1_bucketed (pcid STRING)

CLUSTERED BY(pcid) INTO 10 BUCKETS;

INSERT overwrite TABLE lxw1_bucketed

SELECT pcid FROM lxw1;

表lxw1_bucketed按照pcid欄位分成10個桶,下面的語句表示從10個桶中抽樣第一個桶的資料:

SELECT COUNT(1) FROM lxw1_bucketed TABLESAMPLE(BUCKET 1 OUT OF 10 ON pcid);

很好理解。

再看這個:

SELECT COUNT(1) FROM lxw1_bucketed TABLESAMPLE(BUCKET 1 OUT OF 20 ON pcid)

表只有10個桶,如果指定20,看結果:

bubuko.com,布布扣

結果差不多是源表記錄的1/20,Hive在執行時候,會在第一個桶中抽樣一半的資料。

還有一點:

如果從源表中直接分桶抽樣,也能達到一樣的效果,比如:

SELECT COUNT(1) FROM lxw1 TABLESAMPLE(BUCKET 1 OUT OF 20 ON pcid);

區別在於基於已經分桶的表抽樣,查詢只會掃描相應桶中的資料,而基於未分桶表的抽樣,查詢時候需要掃描整表資料,先分桶,再抽樣。

其它更詳細的用法請參考Hive的官方文件說明。