目录算法
1.查询性能的实用工具sql
1.1EXPLAIN语句数据库
1.1.1EXPLAIN语法express
1.1.2查询计划apache
1.1.3例子bash
1.2 ANALYZE语句session
1.2.1 ANALYZE语法数据结构
1.2.2例子并发
1.2.3查看统计信息app
HQL提供了EXPLAIN和ANALYZE命令语句,能够用来查看某个查询的性能。另外,Hive的日志包含了性能方面和线上故障排查的详细信息,能够结合在一块儿使用,进行性能调优。
Hive提供了EXPALIN语句,能够用来查看执行某个查询的执行计划(execution plan)。可使用该命令进行性能分析。
基本的语法为:
EXPLAIN [FORMATTED|EXTENDED|DEPENDENCY|AUTHORIZATION] hql_query
其中可选的四个关键字的具体含义为:
FORMATTED:返回JSON格式的查询计划
EXTENDED:返回更加详细的额外信息,好比文件的路径名
DEPENDENCY:返回JSON格式的输出,该输出包括查询所依赖的表的信息和分区的信息,从Hive v0.10.0开始,才添加的功能。好比
{"input_tables":[{"tablename":"default@music2","tabletype":"MANAGED_TABLE"}],"input_partitions":[]}
AUTHORIZATION:返回全部须要受权的条目,包括运行查询的输入和输出,若是受权失败,还会列出受权失败的信息,从从Hive v0.14.0开始,才添加的功能,好比:
INPUTS: default@music2 OUTPUTS: hdfs://kms-1.apache.com:8020/tmp/hive/kms/df84775a-f091-46da-9a76-5721ebb12566/hive_2019-02-28_10-25-56_312_8620977237876835177-1/-mr-10001 CURRENT_USER: kms OPERATION: QUERY
一个典型的查询计划包括下面三部分:
(1)抽象语法树(AST,Abstract Syntax Tree),Hive使用一个叫作ANTLR的解析生成器自动生成HQL的语法树。
(2)Stage依赖(Stage Dependencies): 列出全部的依赖以及stage的个数
(3)Stage 计划(Stage Plans): 包含了运行job的重要的信息,好比Map/Reduce操做和sort排序
hive (default)> explain select name ,count(1) from music2 where date_time="2019-2-16" group by name limit 3;
结果输出:
OK Explain STAGE DEPENDENCIES: Stage-1 is a root stage Stage-0 depends on stages: Stage-1 STAGE PLANS: Stage: Stage-1 Map Reduce Map Operator Tree: TableScan alias: music2 Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE Filter Operator predicate: (date_time = '2019-2-16') (type: boolean) Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE Select Operator expressions: name (type: string) outputColumnNames: _col0 Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE Group By Operator aggregations: count(1) keys: _col0 (type: string) mode: hash outputColumnNames: _col0, _col1 Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE Reduce Output Operator key expressions: _col0 (type: string) sort order: + Map-reduce partition columns: _col0 (type: string) Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE TopN Hash Memory Usage: 0.1 value expressions: _col1 (type: bigint) Reduce Operator Tree: Group By Operator aggregations: count(VALUE._col0) keys: KEY._col0 (type: string) mode: mergepartial outputColumnNames: _col0, _col1 Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE Limit Number of rows: 3 Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE File Output Operator compressed: false Statistics: Num rows: 1 Data size: 0 Basic stats: PARTIAL Column stats: NONE table: input format: org.apache.hadoop.mapred.SequenceFileInputFormat output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe Stage: Stage-0 Fetch Operator limit: 3 Processor Tree: ListSink Time taken: 1.188 seconds, Fetched: 55 row(s)
Hive的统计信息是可以描述更多细节的数据集合,好比行数、文件数、原始数据大小等。统计信息是元数据,保存在metastore数据库中。Hive支持统计表、分区、列的信息,这些统计信息做为Hive基于成本的优化器(Cost-Based Optimizer)的输入,该优化器可以挑选出消耗最低系统资源的执行计划。在Hive v3以后支持自定收集统计信息,也可使用ANALYZE语句收集表、分区、列的统计信息。对于当hive.stats.autogather=true时,会自动收集表的统计信息,可是,对于一个新表或者分区,只有在执行INSERT OVERWRITE/INTO语句时,才会自动收集统计信息,执行LOAD操做时,不会自动收集统计信息。
ANALYZE TABLE [db_name.]tablename [PARTITION(partcol1[=val1], partcol2[=val2], ...)] -- (Note: Fully support qualified table name since Hive 1.2.0, see HIVE-10007.) COMPUTE STATISTICS [FOR COLUMNS] -- (Note: Hive 0.10.0 and later.) [CACHE METADATA] -- (Note: Hive 2.1.0 and later.) [NOSCAN];
说明:
若是用户未指定任何分区规范,则会为表以及全部分区(若是有)收集统计信息。若是指定了某些分区规范,则仅为这些分区收集统计信息。对于分区表而言,收集统计信息时,必须指定分区列字段名。从 Hive 1.2.0开始,Hive在此命令中彻底支持限定表名,若是使用非限定表名,则用户只能计算当前数据库下的表的统计信息。指定可选参数NOSCAN时,该命令不会扫描文件,所以它应该很快,它只收集文件数量和物理大小(字节)的统计信息,而不是全部统计信息。
(1)非分区表
对于非分区表,可使用如下命令,收集表的统计数据。
ANALYZE TABLE Table1 COMPUTE STATISTICS;
对于非分区表,可使用如下命令,收集全部列的列统计信息
ANALYZE TABLE Table1 COMPUTE STATISTICS FOR COLUMNS;
执行结果:
hive (default)> ANALYZE TABLE youtube_orc COMPUTE STATISTICS; Table default.youtube_orc stats: [numFiles=8, numRows=189, totalSize=46769, rawDataSize=410237] OK youtube_orc.videoid youtube_orc.uploader youtube_orc.age youtube_orc.category youtube_orc.length youtube_orc.views youtube_orc.rate youtube_orc.ratings youtube_orc.comments youtube_orc.relatedid Time taken: 1.264 seconds
(2)分区表
假设表Table1有4个分区:
Partition1:(ds ='2008-04-08',hr = 11)
Partition2:(ds ='2008-04-08',hr = 12)
Partition3:(ds ='2008-04-09',hr = 11)
Partition4:(ds ='2008-04-09',hr = 12)
当使用如下命令时:仅为partition3(ds ='2008-04-09',hr = 11)收集统计信息。
ANALYZE TABLE Table1 PARTITION(ds='2008-04-09', hr=11) COMPUTE STATISTICS;
当使用如下命令时:为partition3的全部列收集列统计信息(ds ='2008-04-09',hr = 11)。这在Hive 0.10.0及更高版本中可用。
ANALYZE TABLE Table1 PARTITION(ds='2008-04-09', hr=11) COMPUTE STATISTICS FOR COLUMNS;
当使用如下命令时:仅收集分区3和4的统计数据(hr = 11和hr = 12)
ANALYZE TABLE Table1 PARTITION(ds='2008-04-09', hr) COMPUTE STATISTICS;
当使用如下命令时:仅为分区3和4(Hive 0.10.0及更高版本)收集全部列的列统计信息。
ANALYZE TABLE Table1 PARTITION(ds='2008-04-09', hr) COMPUTE STATISTICS FOR COLUMNS;
当使用如下命令时:而后收集全部四个分区的统计信息
ANALYZE TABLE Table1 PARTITION(ds, hr) COMPUTE STATISTICS;
当使用如下命令时:为全部四个分区(Hive 0.10.0及更高版本)收集全部列的列统计信息
ANALYZE TABLE Table1 PARTITION(ds, hr) COMPUTE STATISTICS FOR COLUMNS;
DESCRIBE EXTENDED employee_partitioned PARTITION(year=2018, month=12); DESCRIBE EXTENDED employee; DESCRIBE FORMATTED employee.name;
经过日志信息能够查看做业或者查询的详细信息,经过检查日志,能够检查运行时出现的问题以及影响性能的问题。主要有两种类型的日志,一种为系统日志,另外一种为做业日志。系统日志包含Hive运行时的状态状况,经过{HIVE_HOME}/conf/hive-log4j.properties配置,主要配置属性以下:
## set logger level hive.root.logger=WARN,DRFA ## set log file path hive.log.dir=/tmp/${user.name} ## set log file name hive.log.file=hive.log
能够经过$hive --hiveconf hive.root.logger=DEBUG,console命令设置session级别的日志输出。Job日志包含Job的信息,一般是由yarn管理。可使用yarn logs -applicationId <application_id>命令查看。
对大表而言,Hive的分区表是提升查询性能的有效方式。对于一个分区裁剪的查询而言,只会加载指定分区(子目录)的数据,全部能够提升查询的效率。分区key的选择是影响性能的重要因素,一般选择低基数的属性,从而避免生成大量的子目录。下面的属性一般会被做为分区key:
(1)日期和时间:使用日期和时间,好比年、月、日、小时做为分区键,关于日期或者时间列,能够是加载数据的日期,业务日期或者运行日期等。
(2)位置:使用国家、地区、城市做为分区键
(3)业务逻辑:使用部门、销售区域、顾客等做为分区键。
建立分区表的例子:
CREATE TABLE page_view(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(dt STRING, country STRING) ROW FORMAT DELIMITED<font></font> FIELDS TERMINATED BY '\001' STORED AS SEQUENCEFILE;
分桶表是以分开的文件来组织数据的,分桶表能够加快数据采样。若是分桶的字段与join的字段相同,则能够提升join查询的性能。选择合适的分桶字段提升join查询的性能,生产环境中一般使用具备标识的列,该列颇有可能做为where过滤条件或者join条件。
建立分桶表的例子:
CREATE TABLE page_view(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(dt STRING, country STRING) CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' COLLECTION ITEMS TERMINATED BY '\002' MAP KEYS TERMINATED BY '\003' STORED AS SEQUENCEFILE;
Hive支持索引的建立,Hive索引可以提供基于key的数据浏览和更好的数据访问,好比WHERE、GROUP BY、JOIN。使用索引一般比全表扫描更节省开销。
Hive索引的目标是提升表的某些列的查询查询速度。若是没有索引,带有谓词的查询(如'WHERE tab1.col1 = 10')会加载整个表或分区并处理全部行。可是若是col1存在索引,则只须要加载和处理文件的一部分。索引能够提供的查询速度的提升是以建立索引和存储索引的磁盘空间的额外处理为代价的。
CREATE INDEX index_name ON TABLE base_table_name (col_name, ...) AS index_type [WITH DEFERRED REBUILD] [IDXPROPERTIES (property_name=property_value, ...)] [IN TABLE index_table_name] [ [ ROW FORMAT ...] STORED AS ... | STORED BY ... ] [LOCATION hdfs_path] [TBLPROPERTIES (...)] [COMMENT "index comment"];
例子:
CREATE INDEX idx_id_employee_id ON TABLE employee_id (employee_id) AS 'COMPACT' WITH DEFERRED REBUILD; CREATE INDEX idx_gender_employee_id ON TABLE employee_id (gender_age) AS 'BITMAP' WITH DEFERRED REBUILD;
语法:DROP INDEX [IF EXISTS] index_name ON table_name;
例子:DROP INDEX idx_gender_employee_id ON employee_id;
(1)文件格式概述
Hive支持TEXTFILE, SEQUENCEFILE, AVRO, RCFILE, ORC和PARQUET 文件格式。
主要有两种方式指定文件的格式
第一种:CREATE TABLE ... STORE AS <file_format>: 建立时具体指定文件格式
第二种:ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT <file_format>: 修改文件的存储格式
当建立表的存储格式是text时,可使用load命令加载text数据。可是,当将text格式的文件加载到其余存储格式的表时,须要使用INSERT OVERWRITE/INTO TABLE ... SELECT命令,先将数据加载到text存储格式的表中,而后再查询数据,插入其余存储格式的表。能够设置hive.default.fileformat=TextFile(默认)属性,来改变默认的存储格式。
TEXT, SEQUENCE,和AVRO文件都是面向行的存储格式,所以对于不须要全字段扫描的查询而言,不是最优的存储格式。由于即使是查询一列数据,这些存储格式的表也会读取一整行的数据。对于混合的面向行的存储格式而言,好比RCFILE、 ORC、PARQUET,能够解决上述的问题。
TEXTFILE:
这是用于建立表的默认文件格式。文本文件是天然可分割的,能够并行处理。它也能够用算法进行压缩,例如gzip、lzo和Snappy。可是,大多数压缩文件不能并行拆分处理。所以,他们只使用一个做业和一个mapper来处理数据,处理速度很慢。使用压缩文本文件的最佳实践是确保文件不太大,接近几个HDFS块大小。
SEQUENCEFILE:
以键/值的形式进行二进制存储格式,比文本文件更紧凑,适合MapReduce输出格式。序列文件能够压缩成记录或块级别,其中块级别具备更好的压缩比。
AVRO:
是一种二进制格式。不只如此,它仍是一个系列化和反序列化框架。AVRO提供了一个描述数据结构的schema,schema与数据一块儿存储处理。
RCFILE:
是一种二进制文件,表示按列记录文件。RCFile除了按列的方式存储数据之外,其余方面和序列化文件相似。RCFile把表分红行分片,在每个分片中先存全部行的第一列,再存第二列,依次类推。
ORC:
这是Optimized Row Columnar缩写。从Hive V0.11开始支持的。ORC格式能够被视为RCFILE的改进版本。它默认状况下,提供更大的块大小256 MB(rcfile有4 MB和sequencefile有1 MB),针对hdfs上的大规模顺序读取进行了优化,支持较大的吞吐量和较少的文件,以减小名称节点中的过载。RCFILE依赖于元存储来了解数据类型,而ORC文件经过使用特定的编码器了解数据类型,根据不一样类型以便优化压缩。它还存储基本统计信息,例如列上的最小值、最大值、总和和计数,以及能够用于跳过不重要的行块
PARQUET:
是另外一种行列文件格式,其设计与ORC类似。更重要的是,在Hadoop生态中,parquet格式支持的最普遍,而ORC主要支持hive、pig和spark。在v0.13.0以后获得了本地支持。
(2)文件格式选取的最佳实践
根据使用的技术栈,若是主要使用Hive来定义和处理数据,那么建议使用ORC格式。若是仍是用hadoop生态的其余技术,考虑到适用性,建议使用parquet格式。
Hive经过适当压缩在mapper和reducer之间的中间和最终输出数据,能够显著减小数据传输量。所以,查询将具备更好的性能。压缩中间文件在多个MapReduce做业之间生成,咱们须要设置hive.exec.compress.intermediate 属性(默认false),在命令行会话或hive-site.xml文件中进行配置。
(1)压缩格式
deflate(.deflate)是一个默认的编解码器,具备平衡的压缩比和CPU消耗。gzip的压缩比很是高,CPU成本也很高。bzip2是可拆分的。当涉及到CPU消耗和压缩比的平衡时,LZ4或Snappy会比deflate要好,但Snappy更受欢迎。由于大多数压缩文件不可拆分,不建议压缩单个大文件。最佳作法是在几个HDFS块大小中生成压缩文件,这样每一个文件花费的处理时间就更少了。压缩编解码器能够在mapred-site.xml、hive-site.xml中指定,也能够在命令行session中指定。好比
SET hive.intermediate.compression.codec= org.apache.hadoop.io.compress.SnappyCodec
当指定hive.exec.compress.output(默认为false)为true时,须要设置mapreduce.output.fileoutputformat.compress.codec指定编码,好比
mapreduce.output.fileoutputformat.compress.codec= org.apache.hadoop.io.compress.SnappyCodec
在多数状况下,须要使用彻底分布式模式处理数据。但当处理的数据较少时,使用彻底分布式处理数据,启动彻底分布式模式所花费的时间会比做业处理的时间还要多。所以从hive V0.7.0开始,支持本地模式执行做业。
主要的配置:
> SET hive.exec.mode.local.auto=true; -- default false > SET hive.exec.mode.local.auto.inputbytes.max=50000000;--default 134217728,即128M > SET hive.exec.mode.local.auto.input.files.max=5; -- default 4
当开启了本地模式时,须要知足下面的条件,才会触发本地模式:
(1)输入数据的大小要小于hive.exec.mode.local.auto.inputbytes.max的值
(2)map task的数量小于hive.exec.mode.local.auto.input.files.max的值
(3)reduce task的数量为1或者0
启用了fetch ask以后,会对一些简单的查询不启用mapreduce做业。 新的hive版本中hive.fetch.task.conversion默认为more,表示在全表扫描、字段查找、limit查找都不会启用mapreduce做业。
JVM 重用是 Hadoop 调优参数的内容,其对 Hive 的性能具备很是大的影响,特别是对于很难避免小文件的场景或 task 特别多的场景,这类场景大多数执行时间都很短。Hadoop 的默认配置一般是使用派生 JVM 来执行 map 和 Reduce 任务的。这时 JVM 的启动过程可能会形成至关大的开销,尤为是执行的 job包含有成百上千task任务的状况。JVM重用可使得 JVM 实例在同一个 job 中从新使用 N 次。N 的值能够在 Hadoop 的mapred-site.xml 文件中进行配置。一般在 10-20 之间,具体多少须要根据具体业务场景测试得出。这个功能的缺点是,开启 JVM 重用将一直占用使用到的 task 插槽,以便进行重用,直到任务完成后才能释放。若是某个“不平衡的”job 中有某几个 reduce task 执行的时间要比他 Reduce task 消耗的时间多的多的话,那么保留的插槽就会一直空闲着却没法被其余的 job使用,直到全部的 task 都结束了才会释放。
开启JVM重用,能够设置一个job中进行JVM重用的task最大数量,默认是1,若是设为-1,则表示没有限制。
好比:SET mapreduce.job.jvm.numtasks=5;
Hive 会将一个查询转化成一个或者多个阶段。这样的阶段能够是 MapReduce 阶段、抽样阶段、合并阶段、limit 阶段。或者 Hive 执行过程当中可能须要的其余阶段。默认状况下,Hive 一次只会执行一个阶段。不过,某个特定的 job 可能包含众多的阶段,而这些阶段可能并不是彻底互相依赖的,也就是说有些阶段是能够并行执行的,这样可能使得整个 job 的执行时间缩短。不过,若是有更多的阶段能够并行执行,那么 job 可能就越快完成。经过设置参数 hive.exec.parallel 值为 true,就能够开启并发执行。不过,在共享集群中,
须要注意下,若是 job 中并行阶段增多,那么集群利用率就会增长。
set hive.exec.parallel=true; --打开任务并行执行,默认为false set hive.exec.parallel.thread.number=16; //同一个 sql 容许最大并行度,默认为 8。
普通的join又称为reduce端join,是HQL基本的join,一般耗费时间较长,对于普通的join,将大表放在右边,小表放在左边。即小表join大表。
Mapjoin是指当要join的某张表很是小,能够将该小表加载到内存中,这样能够加快处理的速度,可是会受到表大小的限制。从Hive v0.7.0开始,能够设置自动进行map join。
开启 MapJoin 参数设置:
(1)设置自动选择 Mapjoin
set hive.auto.convert.join = true; 默认为 true
(2)小表的大小设置(默认 25M 一下认为是小表):
set hive.mapjoin.smalltable.filesize=600000000 ;
(3)设置不须要map join hint
SET hive.auto.convert.join.noconditionaltask=true; -- 默认 true
SET hive.auto.convert.join.noconditionaltask.size=10000000; 默认10000000
一旦开启了join的自动转换,Hive就会自动检查小表的大小是否大于hive.mapjoin.smalltable.filesize的值,若是大于,则会使用普通的join。若是小于此值,则会使用map join。另外,只要开启了join的自动转换,就不须要写map join提示。
对于分桶表可使用bucket map join,启用bucket map join,须要设置一下属性:
(1)设置自动选择 Mapjoin
SET hive.auto.convert.join=true;
(2)开启bucket map join
SET hive.optimize.bucketmapjoin=true; -- 默认 false
在bucket map join中,全部的表必须是分桶表,并且分桶的字段与join的字段必须一致。另外,大表的分桶数量要是小表分桶数量的倍数。
当处理的数据分布不均匀时,会发生数据倾斜,即少数的计算节点要处理大量的计算数据,开启下面的属性,会对数据倾斜做出优化。
(1)若是存在数据倾斜,设置为true,默认为false
SET hive.optimize.skewjoin=true;
(2)hive 在运行的时候没有办法判断哪一个key 会产生多大的倾斜,因此使用这个参数控制倾斜的阈值,若是超过这个值,新的值会发送给其余未使用的reduce。默认值为100000
SET hive.skewjoin.key=100000;
Hive支持不一样的执行引擎,执行引擎的选择会影响性能。相对其余的配置而言,更换执行引擎的改变是最大的。能够经过下面的命令更换执行引擎
SET hive.execution.engine=<engine>; -- <engine> = mr|tez|spark
mr:默认的执行引擎,Hive2.0.0已通过时
Hive在提交一个最终的执行以前,会生成和优化查询的逻辑执行计划于物理执行计划。主要包括两种优化器,一种是Vectorize ,另外一种是Cost-Based Optimization (CBO)。
Vectorization优化器
SET hive.vectorized.execution.enabled=true; -- default false
Cost-based 优化器
使用 CBO, 设置如下属性:
SET hive.cbo.enable=true; -- default true after v0.14.0
SET hive.compute.query.using.stats=true; -- default false
SET hive.stats.fetch.column.stats=true; -- default false
SET hive.stats.fetch.partition.stats=true; -- default true
参考:
https://issues.apache.org/jira/browse/HIVE-11160
https://cwiki.apache.org/confluence/display/Hive/StatsDev
Apache Hive Essentials Second Edition