Hive 实战(2)--hive分区分桶实战

前言:

  互联网应用, 当Mysql单机遇到性能瓶颈时, 往往采用的优化策略是分库分表. 由于互联网应用普遍的弱事务性, 这种优化效果非常的显著.而Hive作为数据仓库, 当数据量达到一定数量时, 查询性能会有所下降, 那如何利用数据的特点进行优化? 分区分桶作为Hive的优化的一个有力武器.

*). 分区(静态、动态)

  Hive没有索引, 查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。倘若只需要扫描表中关心的一部分数据,因此建表时引入了partition概念。分区表指的是在创建表时指定的partition的分区空间。 
  1). 静态分区
  hive默认采用静态分区, 数据的导入需至少指定一个分区字段

  1.1). 创建分区表

1
2
3
4
5
6
7
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;

1
2
3
4
5
6
7
8
9
10
11
12
13
> 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). 创建分桶表

1
2
3
4
5
6
7
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性能优化的一个手段, 不同的字段, 其数值属性不同, 其对应的优化方式也不同. 也不能简单的认为分区分桶对应传统关系型数据库的分库分表, 完全不一样.

posted on   mumuxinfei  阅读(16443)  评论(0编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示