zoukankan      html  css  js  c++  java
  • 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 '01'
       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 '01'
      	COLLECTION ITEMS TERMINATED BY '	'
      	MAP KEYS TERMINATED '	'
      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. 每一行为一条记录,每行都以换行符 “ ” 结尾,数据不做压缩时,磁盘占用和数据解析开销比较大
      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类

    压缩格式
    zlib org.apache.hadoop.io.compress.DefaultCodec
    gzip org.apache.hadoop.io.compress.GzipCodec
    bzip2 org.apache.hadoop.io.compress.Bzip2Codec
    lzo org.apache.hadoop.io.compress.lzo.LzoCodec
    lz4 org.apache.hadoop.io.compress.LzoCodec
    snappy org.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压缩
        
  • 相关阅读:
    twfont
    判断数组中某个元素的个数
    vue swiper中的大坑
    this指向问题
    vue.nextTick简单的用法
    类图解析
    设计模式
    设计模式
    Http Notes
    VS Notes
  • 原文地址:https://www.cnblogs.com/starzy/p/14338664.html
Copyright © 2011-2022 走看看