hive性能调优之表设计层面调优

hive表建表设计层面调优主要合理设计组织数据方便后续高效计算,比如建表的字段数据类型、文件存出格式、文件压缩格式等

利用分区优化

分区表是在某一个或者几个维度上对数据进行分类存储,一个分区表对应一个目录。如果筛选条件里有分区字段,那么Hive只需要遍历对应分区目录下的文件即可,不需要遍历全局数据,使得处理的数据量大大减少,从而提高查询效率。

也就是说,当一个hive表的查询大多数情况下,会根据某一个字段进行筛选是,那么非常适合创建为分区表,该字段即为分区字段。

sql1:select ... ... from table where country = 'china'
sql2:select ... ... from table where country = 'china'
sql3:select ... ... from table where country = 'china'
sql4:select ... ... from table where country = 'china'

分门别类:这个country字段的每个值就单独形成一个分区,其实每个分区就对应HDFS的一个目录,在创建表时通过启用partitioned by 实现,用来partition 的维度并不是实际数据的某一列,具体分区的标志是有插入内容是给定的,当要查询某一分区的内容时可以采用where语句,形似tablename.partition_column = a 来实现。

  1. 创建分区表

    create table tmp.page_view
    (view_time INT,
     user_id BIGINT,
     page_url STRING,
     ip STRING COMMENT 'IP Address of the user')
     PARTITIONED BY (dt STRING,country STRING)
     ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001'
     STORED AS TEXTFILE;
  2. 导入数据并指定分区值

    load data local input '/root/data/input/pv_2021-01-26.txt' 
    into table tmp.page_view partition(dt='2021-01-26',country='US');
  3. 查询指定分区值数据

    SELECT t1.* from tmp.page_view where t1.dt='2021-01-26' and t1.country='US'

总结:

  1. 当意识到字段经常来做where建立分区表,并且使用此字段作为分区
  2. 在查询时,使用分区字段过滤可以避免全表扫描,只需扫描查询分区的数据即可

利用分桶优化

Hive Buck 分桶是指将数据以某特定列的值为key进行hash,hash到指定数目的桶中,这样做的目的和分区类似,使得筛选是不用全局遍历所有数据,只要遍历所在桶数据即可,并且可以支持高效采样。

采样多少百分比的数据,采样多少条数据,采样多大量数据
Doris等OLAP引擎中colocation join两张表的相同分桶编号的数据在同一个节点

分桶与分区类似,都是把数据分成多个不同类别,区别就是规则不同,具体如下

  1. 分区是按照字段值进行分区,一个分区包含此分区值的所有数据,并不会含有非此分区值的数据

  2. 分桶默认规则是按照Hash散列进行分桶,一个分桶包含多个不同值,且某个值的所有数据只会在一个分桶中。

  3. 创建分桶表

    create table(
    view_time INT,
    user_id BIGINT,
    page_url STRING,
    refer_url STRING,
    ip STRING COMMENT 'IP Address of the User')
    COMMENT 'This is the page view table'
    PARTITION BY (dt STRING,country STRING)
    CLUSTERED BY (user_id) STORED BY (view_time) INTO 32 BUCKETS
    ROW FORMAT DELIMITED
    	FIELDS TERMINATED BY '\001'
    	COLLECTION ITEMS TERMINATED BY '\t'
    	MAP KEYS TERMINATED '\t'
    STORED AS SEQUENCEFILE;
  4. 分桶语法说明

    CLUSTERED BY(userid) SORTED BY(view_time) INTO 32 BUCKETS

    • CLUSTERED BY(user_id):表示按照字段user_id来进行分桶
    • SORTED BY (view_time):表示按照字段view_time进行桶内排序
    • INTO 32 BUCKETS :设置分桶个数
  5. 分桶划分,两张表倍数关系

    create table order(cid int,price float) clustered by(cid) into 32 buckets;
    create table customer(id int,first string) clustered by(id) into 32 buckets;
    select price from order t join customer s on t.cid = s.id

    通常情况下,Sampling 在全体数据上进行采样这样效率自然会很低,则需要去访问所有数据,如果一张表已经将某一列进行分桶,就可以进行指定序号分桶进行数据采样,这样就会减少数据扫描数量。

    如下示例通过分桶方式对表page_view中的32个桶中的第3桶全部数据进行采样

    select * from tmp.page_view tablesample(BUCKET 3 OUT OF 32);

    如下示例所示就是采样了page_view中32个桶中的第三个桶的一半数据

    select * from tmp.page_view tablesample(bucket 3 out of 64);
  6. 利用分桶采样

    在大规模数据量数据分析及建模任务中,往往针对全量数据进行挖掘分析时会对十分耗时和占用集群资源,因此一般情况下只需要抽取一下部分数据进行分析及建模操作。Hive提供了数据抽样(SAMPLING)的功能,能够根据一定规则进行数据抽样目前支持数据块抽样、分桶抽样和随机抽样,具体如下所示

    • 数据快抽样(tablesample函数)

      1. tablesample(n percent) 根据Hive表数据的大小按比例抽取数据,并保存到Hive表中,如抽取Hive表中10%的数据

        create table page_view_new as select * from page_view tablesample(10 percent);

        注意:测试中发现,select语句不能带where条件且不支持子查询,可以通过新建中间表或者使用随机抽样解决

      2. tablesample(n M) 指定抽取数据大小,单位为M

      3. tablesample(n rows) 指定抽取数据行数,其中 n 代表每个map任务均取 n 行数据,map 数量可通过hive表的简单查询语句进行确认(关键词:number of mappers:x)

      数据块抽样缺点是数据不随机,只是按照文件中的顺序返回指定量的数据,对于分区表从头开始进行抽样可能造成只是抽样出前几个分区数据,但是数据块抽样速度快。

    • 分桶抽样

      hive中分桶其实就是根据某一个字段Hash取模,放入指定数量的桶中,比如将表page_view按照user_id分成32个桶,其算法是hash(user_id)%32,将hash(user_id) % 32 = 0的数据放到第一个桶中,以此类推将数据分别存放到32个桶。创建分桶语句:

      CLUSTER BY 语句

      分桶抽样语法

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

      其中x是要抽样的桶编号,桶编号从1开始,colname表示抽样的列,y表示桶的数量

      例如:将表随机分成10组,抽取其中第一个桶的数据

      select * from page_view tablesample(bucket 1 out of 10 on rand());
    • 随机抽样(rand函数)

      1. 使用rand函数进行随机抽样,limit关键字限制抽样返回的数据,其中rand函数前的distribute 和 sort 关键字可以保证数据在Mapper和Reducer阶段是随机分布的,如下

        select * from page_view where user_id = '001' 
        distribute by rand() sort by rand() limit num;  --推荐使用方式
      2. 使用order 关键词

        select * from page_view where user_id = '001' order by rand() limit num;

文件存储格式

常见数据存储格式分为以下三类

  1. 水平行存储结构 (horizontal row-store structure)
  2. 垂直列存储结构 (vertical column-store structure)
  3. PAX 混合存储结构 (hybrid PAX store structure)

hive默认存储格式textfile,在hive创建表create table语句中,可以通过stored as 进行指定表数据存储格式。Apache hive支持Hadoop 中使用的几种文件格式,例如TextFile、SequenceFile、RCFile、Avro、ORC、ParquetFile

存储格式一般需要根据业务进行选择,在实际使用中,绝大数表都采用TextFile与ParquetFile两种存储格式之一,TextFile是最简单存储格式,它是纯文本记录存储,也是hive默认存储格式,虽然磁盘开销大、查询效率也低,但是它更多地是作为跳板来使用。RCFile、ORC、Parquet等格式的表都不能由文件直接导入数据,必须由TextFile来作为中转。Parquet 和 ORC 都是Apache旗下开源列式存储格式,列式存储格式比起传统的行式存储更合适批量OLAP查询,并且支持更好的压缩和编码。

创建表时(特别是宽表),尽量使用ORC、ParquetFile这些列式存储格式,因为列式存储表每一列的数据在物理上是存储在一起的,Hive查询时会只遍历所需要的列数据,大大减少处理的数据量。

  • TextFile存储格式
    1. 存储方式为行式存储,是hive的默认数据存储格式,若建表时不指定存储格式则存储为TextFile
    2. 每一行为一条记录,每行都以换行符 “\n” 结尾,数据不做压缩时,磁盘占用和数据解析开销比较大
    3. 可以结合Gzip、Bzip2等压缩方式一起使用(查询时系统会自动检查进行自动解压),推荐选用可切分压缩算法
  • Sequence File存储格式
    1. Hadoop API提供的一种二进制文件,使用方便、可分割、可压缩的特点。
    2. 支持三种压缩选择:NONE、RECORD、BLOCK。RECORD压缩率低,一般建议使用BLOCK。
  • RC File存储格式
    1. 数据存储按行分块,每块按照列存储。
      • 首先将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。
      • 其次快数据列式存储,有利于数据压缩和快速的列存取。
    2. 相对来说,RCFile对于提升任务执行性能提升不大,但是能节省一定的存储空间。可以使用升级版的ORC格式
  • ORC File存储格式
    1. 数据按行分块,每块按照列存储
    2. Hive提供数据存储的新格式,是RCFile的升级版,性能有大幅度提升,而且数据可以压缩存储且压缩快,快速列存取。
  • Parquet File存储格式
    1. 列式存储
    2. Parquet对于大型查询的类型查询效率高,对于扫描特定表格中的特定列查询,Parquet特别有用。
    3. Parquet 一般使用snappy、Gzip压缩,默认为snappy。
    4. Parquet 支持Impala查询
    5. 表的文件存储格式尽量采用Parquet或ORC,不仅减少占用存储空间,而且还有优化了查询、压缩和表关联性能。

文件压缩格式

Hive 语句最终是转化为 MapReduce 程序来执行的,而 MapReduce 的性能瓶颈在与 网络IO 和 磁盘IO,要解决性能瓶颈,最主要的是 减少数据量,对数据进行压缩是个好方式。压缩虽然是减少了数据量,但是压缩过程要消耗 CPU,但是在 Hadoop 中,往往性能瓶颈不在于 CPU,CPU 压力并不大,所以压缩充分利用了比较空闲的 CPU。

  1. 常用压缩方法对比
压缩方式是否可拆分是否自带压缩率速度Hadoop是否自带
gzip很高比较快
lzo比较高很快否,需安装
snappy比较高很快否,需安装
bzip2最高
  1. 如何选择压缩方式

    • 压缩比率
    • 压缩解压速度
    • 是否支持split

    支持分割的文件可以并行多个Mapper程序处理大数据操作,大多数文件不支持可分割是因为这些文件只能从头开始读

  2. 是否压缩

    • 计算密集型不压缩,否则增加了CPU负担
    • 网络密集型推荐压缩,减少网络传输
  3. 各个压缩方式对应的class类

压缩格式
zliborg.apache.hadoop.io.compress.DefaultCodec
gziporg.apache.hadoop.io.compress.GzipCodec
bzip2org.apache.hadoop.io.compress.Bzip2Codec
lzoorg.apache.hadoop.io.compress.lzo.LzoCodec
lz4org.apache.hadoop.io.compress.LzoCodec
snappyorg.apache.hadoop.io.compress.SnappyCodec
  1. 压缩使用

    • job输出文件按照block以及Gzip的方式进行压缩

      --默认值是false
      set mapreduce.output.fileoutputformat.compress=true;
      
      --默认值是record
      set mapreduce.output.fileoutputformat.compress.type=BLOCK
      
      --默认值是org.apache.hadoop.io.compress.DefaultCodec
      set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.GzipCodec
    • Map输出结果也可以进行Gzip压缩

      --启用map端输出压缩
      set mapred.map.output.compress=true
      
      --默认值是org.apache.hadoop.io.compress.DefaultCodec
      set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.GzipCodec
    • 对hive输出结果和中间都进行压缩

      set hive.exec.compress.output=true				--默认值是false,不压缩
      set hive.exec.compress.intermediate=true		--默认值是false,为true必须设置MR压缩
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值