1.屡次INSERT单次扫描表

默许状况下,Hive会履行屡次表扫描。因而,假如要在某张hive表中履行多个操作,主张运用一次扫描并运用该扫描来履行多个操作。

比方将一张表的数据屡次查询出来装载到别的一张表中。如下面的示例,表my_table是一个分区表,分区字段为dt,假如需求在表中查询2个特定的分区日期数据,并将记载装载到2个不同的表中。

INSERT INTO temp_table_20201115 SELECT * FROM my_table WHERE dt =’2020-11-15′;

INSERT INTO temp_table_20201116 SELECT * FROM my_table WHERE dt =’2020-11-16′;

在以上查询中,Hive将扫描表2次,为了防止这种状况,咱们能够运用下面的方法:

FROM my_table

INSERT INTO temp_table_20201115 SELECT * WHERE dt =’2020-11-15′

INSERT INTO temp_table_20201116 SELECT * WHERE dt =’2020-11-16′

这样能够保证只对my_table表履行一次扫描,然后能够大大减少履行的时刻和资源。

2.分区表

关于一张比较大的表,将其设计成分区表能够进步查询的功能,关于一个特定分区的查询,只会加载对应分区途径的文件数据,因而,当用户运用特定分区列值履行挑选查询时,将仅针对该特定分区履行查询,由于将针对较少的数据量进行扫描,所以能够供给更好的功能。值得留意的是,分区字段的挑选是影响查询功能的重要因素,尽量防止层级较深的分区,这样会形成太多的子文件夹。

现在问题来了,该运用哪些列进行分区呢?一条根本的法则是:挑选低基数特点作为“分区键” ,比方“地区”或“日期”等。

一些常见的分区字段能够是:

  • 日期或许时刻

比方year、month、day或许hour,当表中存在时刻或许日期字段时,能够运用些字段。

  • 地理位置

比方国家、省份、城市等

  • 业务逻辑

比方部分、出售区域、客户等等

CREATE TABLE table_name (

col1 data_type,

col2 data_type)

PARTITIONED BY (partition1 data_type, partition2 data_type,….);

3.分桶表

一般,当很难在列上创建分区时,咱们会运用分桶,比方某个经常被筛选的字段,假如将其作为分区字段,会形成很多的分区。在Hive中,会对分桶字段进行哈希,然后供给了中额外的数据结构,进行进步查询功率。

与分区表类似,分桶表的组织方法是将HDFS上的文件分割成多个文件。分桶能够加快数据采样,也能够进步join的功能(join的字段是分桶字段),由于分桶能够保证某个key对应的数据在一个特定的桶内(文件),所以巧妙地挑选分桶字段能够大幅度进步join的功能。一般状况下,分桶字段能够挑选经常用在过滤操作或许join操作的字段。

咱们能够运用set.hive.enforce.bucketing = true启用分桶设置。

当运用分桶表时,最好将bucketmapjoin标志设置为true,详细装备参数为:

SET hive.optimize.bucketmapjoin = true

CREATE TABLE table_name

PARTITIONED BY (partition1 data_type, partition2 data_type,….) CLUSTERED BY (column_name1, column_name2, …)

SORTED BY (column_name [ASC|DESC], …)]

INTO num_buckets BUCKETS;

4.对中心数据启用紧缩

复杂的Hive查询一般会转换为一系列多阶段的MapReduce作业,而且这些作业将由Hive引擎链接起来以完成整个查询。因而,此处的“中心输出”是指上一个MapReduce作业的输出,它将用作下一个MapReduce作业的输入数据。

紧缩能够明显减少中心数据量,然后在内部减少了Map和Reduce之间的数据传输量。

咱们能够运用以下特点在中心输出上启用紧缩。

set hive.exec.compress.intermediate=true;

set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;

set hive.intermediate.compression.type=BLOCK;

为了将终究输出到HDFS的数据进行紧缩,能够运用以下特点:

set hive.exec.compress.output=true;

下面是一些能够运用的紧缩编解码器

org.apache.hadoop.io.compress.DefaultCodec

org.apache.hadoop.io.compress.GzipCodec

org.apache.hadoop.io.compress.BZip2Codec

com.hadoop.compression.lzo.LzopCodec

org.apache.hadoop.io.compress.Lz4Codec

org.apache.hadoop.io.compress.SnappyCodec

5.Map端JOIN

map端join适用于当一张表很小(能够存在内存中)的状况,即能够将小表加载至内存。大数据培训Hive从0.7开端支撑自动转为map端join,详细装备如下:

SET hive.auto.convert.join=true; — hivev0.11.0之后默许true

SET hive.mapjoin.smalltable.filesize=600000000; — 默许 25m

SET hive.auto.convert.join.noconditionaltask=true; — 默许true,所以不需求指定map join hint

SET hive.auto.convert.join.noconditionaltask.size=10000000; — 控制加载到内存的表的大小

一旦敞开map端join装备,Hive会自动检查小表是否大于hive.mapjoin.smalltable.filesize装备的大小,假如大于则转为普通的join,假如小于则转为map端join。

关于map端join的原理,如下图所示:

大数据培训十大Hive调优技巧
大数据培训十大Hive调优技巧

首要,Task A(客户端本地履行的task)负责读取小表a,并将其转成一个HashTable的数据结构,写入到本地文件,之后将其加载至分布式缓存

然后,Task B使命会发动map使命读取大表b,在Map阶段,依据每条记载与分布式缓存中的a表对应的hashtable关联,并输出成果

留意:map端join没有reduce使命,所以map直接输出成果,即有多少个map使命就会产生多少个成果文件。

6.向量化

Hive中的向量化查询履行大大减少了典型查询操作(如扫描,过滤器,聚合和衔接)的CPU运用率。

标准查询履行系统一次处理一行,在处理下一行之前,单行数据会被查询中的一切运算符进行处理,导致CPU运用功率十分低。在向量化查询履行中,数据行被批处理在一起(默许=> 1024行),表示为一组列向量。

要运用向量化查询履行,有必要以ORC格局(CDH 5)存储数据,并设置以下变量

SET hive.vectorized.execution.enabled=true

在CDH 6中默许启用Hive查询向量化,启用查询向量化后,还能够设置其他特点来调整查询向量化的方法,详细能够参阅cloudera官网。

7.谓词下推

默许生成的履行计划会在可见的位置履行过滤器,但在某些状况下,某些过滤器表达式能够被推到更接近初次看到此特定数据的运算符的位置。

比方下面的查询:

select

a.*,

b.*

from

a join b on (a.col1 = b.col1)

where a.col1 > 15 and b.col2 > 16

假如没有谓词下推,则在完成JOIN处理之后将履行过滤条件**(a.col1> 15和b.col2> 16)**。因而,在这种状况下,JOIN将首要发生,而且可能产生更多的行,然后在进行过滤操作。

运用谓词下推,这两个谓词**(a.col1> 15和b.col2> 16)**将在JOIN之前被处理,因而它可能会从a和b中过滤掉衔接中较早处理的大部分数据行,因而,主张启用谓词下推。

经过将hive.optimize.ppd设置为true能够启用谓词下推。

SET hive.optimize.ppd=true

8.输入格局挑选

Hive支撑TEXTFILE, SEQUENCEFILE, AVRO, RCFILE, ORC,以及PARQUET文件格局,能够经过两种方法指定表的文件格局:

  • CREATE TABLE … STORE AS :即在建表时指定文件格局,默许是TEXTFILE
  • ALTER TABLE … [PARTITION partition_spec] SET FILEFORMAT :修改详细表的文件格局

假如未指定文件存储格局,则默许运用的是参数hive.default.fileformat设定的格局。

假如数据存储在小于块大小的小文件中,则能够运用SEQUENCE文件格局。假如要以减少存储空间并进步功能的优化方法存储数据,则能够运用ORC文件格局,而当列中嵌套的数据过多时,Parquet格局会很有用。因而,需求依据拥有的数据确定输入文件格局。

9.发动严格形式

假如要查询分区的Hive表,但不供给分区谓词(分区列条件),则在这种状况下,将针对该表的一切分区宣布查询,这可能会十分耗时且占用资源。因而,咱们将下面的特点界说为strict,以指示在分区表上未供给分区谓词的状况下编译器将引发过错。

SET hive.partition.pruning=strict

10.根据本钱的优化

Hive在提交终究履行之前会优化每个查询的逻辑和物理履行计划。根据本钱的优化会依据查询本钱进行进一步的优化,然后可能产生不同的决策:比方如何决定JOIN的顺序,履行哪种类型的JOIN以及并行度等。

能够经过设置以下参数来启用根据本钱的优化。

set hive.cbo.enable=true;

set hive.compute.query.using.stats=true;

set hive.stats.fetch.column.stats=true;

set hive.stats.fetch.partition.stats=true;

能够运用计算信息来优化查询以进步功能。根据本钱的优化器(CBO)还运用计算信息来比较查询计划并挑选最佳计划。经过检查计算信息而不是运行查询,功率会很高。

收集表的列计算信息:

ANALYZE TABLE mytable COMPUTE STATISTICS FOR COLUMNS;

检查my_db数据库中my_table中my_id列的列计算信息:

DESCRIBE FORMATTED my_db.my_table my_id

文章来源于Java与大数据架构