zoukankan      html  css  js  c++  java
  • 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 '	';

      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 '	';

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

  • 相关阅读:
    通过Android studio编写用户注册信息表单(实现用户交互)小demo
    2020年PHP基础学习day01
    js冒泡事件
    关于锚点跳转及jQuery下相关操作与插件
    (11)用css设计电子相册 {上}
    (10)用css建立表单
    (9)css 链接
    (8)css表格
    (8)盒子的定位
    (7)盒子的浮动
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/3820523.html
Copyright © 2011-2022 走看看