Hive 實戰(2)--hive分區分桶實戰


前言:

  互聯網應用, 當Mysql單機遇到性能瓶頸時, 往往采用的優化策略是分庫分表. 由於互聯網應用普遍的弱事務性, 這種優化效果非常的顯著.而Hive作為數據倉庫, 當數據量達到一定數量時, 查詢性能會有所下降, 那如何利用數據的特點進行優化? 分區分桶作為Hive的優化的一個有力武器.

*). 分區(靜態、動態)

  Hive沒有索引, 查詢中一般會掃描整個表內容,會消耗很多時間做沒必要的工作。倘若只需要掃描表中關心的一部分數據,因此建表時引入了partition概念。分區表指的是在創建表時指定的partition的分區空間。 
  1). 靜態分區
  hive默認采用靜態分區, 數據的導入需至少指定一個分區字段

  1.1). 創建分區表

CREATE TABLE tb_part_shop (
    shop_id int,
    shop_name string,
    shopkeeper string
) PARTITIONED BY (province_id int, city_id int)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t';

  1.2). 描述分區表(describe extended <table_name>)
  DESCRIBE EXTENDED tb_part_shop;

> DESCRIBE EXTENDED tb_part_shop;
OK
shop_id int None 
shop_name string None 
shopkeeper string None 
province_id int None 
city_id int None 

# Partition Information	
# col_name data_type comment 

province_id int None 
city_id int None

  1.3). 導入分區和數據

  ALTER TABLE tb_part_shop ADD PARTITION (province_id = 1001, city_id = 10001);

  數據內容
  33068201 Wal-Mart wal-mart
  33068202 Carrefour carrefour

  LOAD DATA LOCAL INPATH '/path/to/data.txt' INTO TABLE tb_part_shop PARTITION(province_id = 1001, city_id = 10001);

  對於小數據量導入, 可采用如下的語句來實現
  INSERT INTO VALUES() 等價實現 INSERT INTO TABLE <table_name> SELECT ... FORM <table_name> LIMIT 1;

  1.4). 分區表的目錄結構

  分區表, 在hdfs中的目錄結構如圖所示:

  2). 動態分區表
  2.1). 設置開啟動態分區開關
  set hive.exec.dynamic.partition=true;

  2.2). 嚴格模式

  set hive.exec.dynamic.partition.mode=strict; # strict/nonstrict
  默認為strict, 對於分區表, 若插入語句沒有指定至少一個靜態分區字段, 則執行失敗

  如下例子:
  set hive.exec.dynamic.partition.mode=strict;
  hive> insert into table tb_part_shop select 1, "2haodian", "shopper", 1001, 20012 from tb_user limit 1;
  FAILED: SemanticException 1:18 Need to specify partition columns because the destination table is partitioned. Error encountered near token 'tb_part_shop'

  2.3). 其他限制條件
  set hive.exec.max.dynamic.partitions=3000; # 具體的數值, 表示總共能創建的動態分區數
  set hive.exec.max.dynamic.partitions.pernode=1000; # 在mapper/reducer節點中, 允許創建的分區數

  SHOW PARTITIONS tb_part_shop;
  

  分區適合於字段值可枚舉, 離散有限個數值, 比如按時間年/月/日, 省份/市區號編碼, 而不適合取值特別多的應用場景, 因為一個值就對應一個目錄, 目錄無休止的增加對查詢的性能, 反而是有害的. 

*). 分桶
  Hive采用對列值哈希來組織數據的方式, 稱之為分桶, 適合采樣和map-join.
  看看分桶表如何建立
  1). 創建分桶表

CREATE TABLE tb_bucket_shop (
    shop_id int,
    shop_name string,
    shopkeeper string
) CLUSTERED BY (shop_id) INTO 4 BUCKETS
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t';

  2). 數據導入
  set hive.enforce.bucketing=true;
  INSERT OVERWRITE TABLE tb_bucket_shop SELECT shop_id, shop_name, shopkeeper FROM tb_part_shop CLUSTER BY shop_id;

  若沒有使用hive.enforce.bucketing屬性, 則需要設置和分桶個數相匹配的reducer個數, 同時SELECT后添加CLUSTER BY
  set mapred.reduce.tasks=4;
  INSERT OVERWRITE TABLE tb_bucket_shop SELECT shop_id, shop_name, shopkeeper FROM tb_part_shop CLUSTER BY shop_id;

  分桶適合於sampling, 不過其數據正確的導入到hive表中, 需要用戶自己來保證, 因為table中信息僅僅是元數據, 而不影響實際填充表的命令.

總結:
  分區分桶是hive性能優化的一個手段, 不同的字段, 其數值屬性不同, 其對應的優化方式也不同. 也不能簡單的認為分區分桶對應傳統關系型數據庫的分庫分表, 完全不一樣.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM