map/reduce的原理| hive 用户手册| hive SERDE | map参数调整 | UDF

map/reduce简单的原理介绍


Hadoop Map/Reduce框架为每一个InputSplit产生一个map任务,而每个InputSplit是由该作业的InputFormat产生的。

然后,框架为这个任务的InputSplit中每个键值对调用一次 map(WritableComparable, Writable, OutputCollector, Reporter)操作。
通过调用 OutputCollector.collect(WritableComparable,Writable)可以收集输出的键值对。

Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接受的数据量相当小,
则直接存储在内存中(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),
如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中。

Hive外部表,编写正则表达式解析Nginx日志

nginx日志的format配置:

'$proxy_add_x_forwarded_for - $remote_user [$time_local] "$request"'
'$status $request_body "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for" $request_time  $upstream_response_time';
生成的日志大致格式:
218.202.xxx.xxx – - [2014-08-19 22:17:08.446671] “POST /xxx/xxx-web/xxx HTTP/1.1″ 200 stepid=15&tid=U753HifVPE0DAOn%2F&output=json&language=zh_CN&session=114099628&dip=10920&diu=DBDBF926-3210-4D64-972A7&xxx=056a849c70ae57560440ebe&diu2=2DFDB167-1505-4372-AAB5-99D28868DCB5&shell=e3209006950686f6e65352c3205004150504c450000000000000000000000000000&compress=false&channel=&sign=438BD4D701A960CD4B7C1DE36AA8A877&wua=0&appkey=0&adcode=150700&t=0 HTTP/1.1″ 200 302 “-” “xxx-iphone” 31.0ms

hive建表的语句:
CREATE EXTERNAL TABLE xxx_log(
host STRING,
log_date STRING,
method STRING,
uri STRING,
version STRING,
STATUS STRING,
flux STRING,
referer STRING,
user_agent STRING,
reponse_time STRING
)
PARTITIONED BY(YEAR STRING, MONTH STRING, DAY STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES ( "input.regex" = "([^ ]*)\\s+-\\s+-\\s+\\[([^\]]*)\\]\\s+\"([^ ]*)\\s+(.*?)\\s+([^ ]*)\"\\s+(-|[0-9]*)\\s+(-|[0-9]*)\\s+\"(.+?|-)\"\\s+\"(.+?|-)\"\\s+(.*)",
"output.format.string" = "%1$s %2$s %3$s %4$s %5$s %5$s %6$s %7$s %8$s %9$s %10$s" ) STORED AS TEXTFILE;
然后,将数据导入表中
方法1. 将指定路径下的文件导入,不移动文件
ALTER TABLE nugget_aos_log ADD partition (YEAR='2014', MONTH='08',DAY='19') location '/user/xxx/xx/year=2014/month=08/day=19';
或者
方法2. 导入指定文件,并将文件移动到用户的存储路径下
LOAD DATA inpath '/user/xxx/xx/2014/08/19' overwrite INTO TABLE xxx_log partition (YEAR='2014', MONTH='08',DAY='19');
接下来就可以查询表中的数据,做验证
hive>select * from xxx_log limit 100;
可能会碰到的情况,你的正则表达式在正则表达式工具(推荐:RegexBuddy)中,没有问题,但是在hive表显示时,每个字段值都是NULL,这说明正则表达式存在错误。这个时候可以用下面的办法解决,在hive中执行下面的命令:
hive>describe extended tablename;
– 查看表的详细信息,其中包括了hive表实际的input.regex正则表达式的值,看看建表的正则表达式转义字符是否缺少。
正则表达式的问题解决之后,再drop table xxx_log,再重新建表,导数据。最后能看到,nginx日志被拆分到了hive表的字段中,接下来就可以进行各种统计了。

hive 用户手册
Usage Examples
Creating tables
MovieLens User Ratings
CREATE TABLE u_data (
  userid INT,
  movieid INT,
  rating INT,
  unixtime STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;
Apache Access Log Tables
add jar ../build/contrib/hive_contrib.jar;
 
CREATE TABLE apachelog (
  host STRING,
  identity STRING,
  user STRING,
  time STRING,
  request STRING,
  status STRING,
  size STRING,
  referer STRING,
  agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  "input.regex" = "([^]*) ([^]*) ([^]*) (-|\\[^\\]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\"[^\"]*\") ([^ \"]*|\"[^\"]*\"))?",
  "output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s"
)
STORED AS TEXTFILE;
Control Separated Tables
CREATE TABLE mylog (
name STRING, language STRING, groups ARRAY<STRING>, entities MAP<INT, STRING>)
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY '\001'
  COLLECTION ITEMS TERMINATED BY '\002'
  MAP KEYS TERMINATED BY '\003'
STORED AS TEXTFILE;
Loading tables
MovieLens User Ratings
Download and extract the data:
wget http://www.grouplens.org/system/files/ml-data.tar+0.gz
tar xvzf ml-data.tar+0.gz
Load it in:
LOAD DATA LOCAL INPATH 'ml-data/u.data'
OVERWRITE INTO TABLE u_data;
Running queries
MovieLens User Ratings
SELECT COUNT(1) FROM u_data;
Running custom map/reduce jobs
MovieLens User Ratings
Create weekday_mapper.py:
import sys
import datetime
 
for line in sys.stdin:
  line = line.strip()
  userid, movieid, rating, unixtime = line.split('\t')
  weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
  print '\t'.join([userid, movieid, rating, str(weekday)])
Use the mapper script:
CREATE TABLE u_data_new (
  userid INT,
  movieid INT,
  rating INT,
  weekday INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
 
INSERT OVERWRITE TABLE u_data_new
SELECT
  TRANSFORM (userid, movieid, rating, unixtime)
  USING 'python weekday_mapper.py'
  AS (userid, movieid, rating, weekday)
FROM u_data;
 
SELECT weekday, COUNT(1)
FROM u_data_new
GROUP BY weekday;
Note: due to a bug in the parser, you must run the "INSERT OVERWRITE" query on a single line


hadoop map数目的分析和调整
Hadoop中在计算一个JOB需要的map数之前首先要计算分片的大小。计算分片大小的公式是:
goalSize = totalSize / mapred.map.tasks
minSize = max {mapred.min.split.size, minSplitSize}
splitSize = max (minSize, min(goalSize, dfs.block.size))
totalSize是一个JOB的所有map总的输入大小,即Map input bytes。参数mapred.map.tasks的默认值是2,我们可以更改这个参数的值。计算好了goalSize之后还要确定上限和下限。

下限是max {mapred.min.split.size, minSplitSize} 。参数mapred.min.split.size的默认值为1个字节,minSplitSize随着File Format的不同而不同。

上限是dfs.block.size,它的默认值是64兆。

举几个例子,例如Map input bytes是100兆,mapred.map.tasks默认值为2,那么分片大小就是50兆;如果我们把mapred.map.tasks改成1,那分片大小就变成了64兆。

计算好了分片大小之后接下来计算map数。Map数的计算是以文件为单位的,针对每一个文件做一个循环:

1.   文件大小/splitsize>1.1,创建一个split,这个split的大小=splitsize,文件剩余大小=文件大小-splitsize

2.   文件剩余大小/splitsize<1.1,剩余的部分作为一个split

举几个例子:

1.   input只有一个文件,大小为100M,splitsize=blocksize,则map数为2,第一个map处理的分片为64M,第二个为36M

2.   input只有一个文件,大小为65M,splitsize=blocksize,则map数为1,处理的分片大小为65M (因为65/64<1.1)

3.   input只有一个文件,大小为129M,splitsize=blocksize,则map数为2,第一个map处理的分片为64M,第二个为65M

4.   input有两个文件,大小为100M和20M,splitsize=blocksize,则map数为3,第一个文件分为两个map,第一个map处理的分片为64M,第二个为36M,第二个文件分为一个map,处理的分片大小为20M

5.   input有10个文件,每个大小10M,splitsize=blocksize,则map数为10,每个map处理的分片大小为10M

再看2个更特殊的例子:

1.   输入文件有2个,分别为40M和20M,dfs.block.size = 64M, mapred.map.tasks采用默认值2。那么splitSize = 30M ,map数实际为3,第一个文件分为2个map,第一个map处理的分片大小为30M,第二个map为10M;第二个文件分为1个map,大小为20M

2.   输入文件有2个,分别为40M和20M,dfs.block.size = 64M, mapred.map.tasks手工设置为1。

那么splitSize = 60M ,map数实际为2,第一个文件分为1个map,处理的分片大小为40M;第二个文件分为1个map,大小为20M

通过这2个特殊的例子可以看到mapred.map.tasks并不是设置的越大,JOB执行的效率就越高。同时,Hadoop在处理小文件时效率也会变差。

根据分片与map数的计算方法可以得出结论,一个map处理的分片最大不超过dfs.block.size * 1.1 ,默认情况下是70.4兆。但是有2个特例:

1.   Hive中合并小文件的map only JOB,此JOB只会有一个或很少的几个map。

2.   输入文件格式为压缩的Text File,因为压缩的文本格式不知道如何拆分,所以也只能用一个map。

考虑采用合适的压缩器(压缩速度vs性能)对输出进行压缩,提高HDFS的写入性能。
每个reduce不要输出多个文件,避免生成附属文件。我们一般用附属文件来记录统计信息,如果这些信息不多的话,可以使用计数器。
为输出文件选择合适的格式。对于下游消费者程序来说,用zlib/gzip/lzo等算法来对大量文本数据进行压缩往往事与愿违。因为zlib/gzip/lzo文件是不能分割的,只能整个进行处理。这会引起恶劣的负载均衡和故障恢复问题。作为改善, 可以使用SequenceFile和TFile格式,它们不但是压缩的,而且是可以分割的。
如果每个输出文件都很大(若干GB),请考虑使用更大的输出块(dfs.block.size)。
CREATE TABLE apachelog (
  host STRING,
  identity STRING,
  user STRING,
  time STRING,
  request STRING,
  status STRING,
  size STRING,
  referer STRING,
  agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  "input.regex" = "([^]*) ([^]*) ([^]*) (-|\\[^\\]*\\]) ([^ \"]*|\"[^\"]*\") (-|[0-9]*) (-|[0-9]*)(?: ([^ \"]*|\".*\") ([^ \"]*|\".*\"))?"
)
STORED AS TEXTFILE;

map数目调整

public static void setMinInputSplitSize(Job job,long size) {
     job.getConfiguration().setLong("mapred.min.split.size", size);
   }
   public static long getMinSplitSize(JobContext job) {
     return job.getConfiguration().getLong("mapred.min.split.size", 1L);
   }
    
 public static void setMaxInputSplitSize(Job job,long size) {
     job.getConfiguration().setLong("mapred.max.split.size", size);
   }
   public static long getMaxSplitSize(JobContext context) {
     return context.getConfiguration().getLong("mapred.max.split.size",Long.MAX_VALUE);
   }
如上我们可以看到,Hadoop在这里实现了对mapred.min.split.size和mapred.max.split.size的定义,且默认值分别为1和Long的最大。因此,我们在程序只需重新赋值给这两个值就可以控制InputSplit分片的大小了。
3.假如我们想要设置的分片大小为10MB
 则我们可以在MapReduce程序的驱动部分添加如下代码:

TextInputFormat.setMinInputSplitSize(job,1024L);//设置最小分片大小
 TextInputFormat.setMaxInputSplitSize(job,1024×1024×10L);//设置最大分片大小

UDF永久生效
hive根据不同的参数匹配evaluate();
udf比较简单一行生成一行,对一行进行计算,
udaf聚合函数比较麻烦,有merge函数等,在不同的map函数中和reduce中进行。
udtf有一行生成多行或者多列,initialize和progress以及close等,在建表的时候运用,可以用序列化和正则

来做到相同的效果     见http://www.uroot.com/archives/1059


UDF永久生效现在是只能修改源代码.不过可以变通一下处理也可以实现.
在HIVE_HOME的bin目录下新建一个.hiverc的文件,把写好的udf的注册语句写在这里就可以类似HIVE内置的用法一样用
原理是,在运行./hive命令时,同时会加载HIVE_HOME/bin/.hiverc and $HOME/.hiverc作为初始化所需要的文件 
在.hiverc文件中加入以下内容:
add jar /run/jar/Avg_test.jar
create temporary function avg_test 'hive.udaf.Avg';
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hive用户指南 目录 1. HIVE结构 6 1.1 HIVE架构 6 1.2 HiveHadoop 关系 7 1.3 Hive 和普通关系数据库的异同 8 1.4 HIVE元数据库 9 1.4.1 DERBY 9 1.4.2 Mysql 10 1.5 HIVE的数据存储 11 1.6 其它HIVE操作 11 2. HIVE 基本操作 12 2.1 create table 12 2.1.1 总述 12 2.1.2 语法 12 2.1.3 基本例子 14 2.1.4 创建分区 15 2.1.5 其它例子 16 2.2 Alter Table 17 2.2.1 Add Partitions 17 2.2.2 Drop Partitions 17 2.2.3 Rename Table 17 2.2.4 Change Column 18 2.2.5 Add/Replace Columns 18 2.3 Create View 18 2.4 Show 19 2.5 Load 19 2.6 Insert 21 2.6.1 Inserting data into Hive Tables from queries 21 2.6.2 Writing data into filesystem from queries 21 2.7 Cli 22 2.7.1 Hive Command line Options 22 2.7.2 Hive interactive Shell Command 24 2.7.3 Hive Resources 24 2.7.4 调用python、shell等语言 25 2.8 DROP 26 2.9 其它 27 2.9.1 Limit 27 2.9.2 Top k 27 2.9.3 REGEX Column Specification 27 3. Hive Select 27 3.1 Group By 28 3.2 Order /Sort By 28 4. Hive Join 29 5. HIVE参数设置 31 6. HIVE UDF 33 6.1 基本函数 33 6.1.1 关系操作符 33 6.1.2 代数操作符 34 6.1.3 逻辑操作符 35 6.1.4 复杂类型操作符 35 6.1.5 内建函数 36 6.1.6 数学函数 36 6.1.7 集合函数 36 6.1.8 类型转换 36 6.1.9 日期函数 36 6.1.10 条件函数 37 6.1.11 字符串函数 37 6.2 UDTF 39 6.2.1 Explode 39 7. HIVEMAP/REDUCE 41 7.1 JOIN 41 7.2 GROUP BY 42 7.3 DISTINCT 42 8. 使用HIVE注意点 43 8.1 字符集 43 8.2 压缩 43 8.3 count(distinct) 43 8.4 JOIN 43 8.5 DML操作 44 8.6 HAVING 44 8.7 子查询 44 8.8 Join中处理null值的语义区别 44 9. 优化与技巧 47 9.1 全排序 47 9.1.1 例1 48 9.1.2 例2 51 9.2 怎样做笛卡尔积 54 9.3 怎样写exist/in子句 54 9.4 怎样决定reducer个数 55 9.5 合并MapReduce操作 55 9.6 Bucket 与 sampling 56 9.7 Partition 57 9.8 JOIN 58 9.8.1 JOIN原则 58 9.8.2 Map Join 58 9.8.3 大表Join的数据偏斜 60 9.9 合并小文件 62 9.10 Group By 62 10. HIVE FAQ: 62
### 回答1: 好的,我来用中文回复。技本功|hive优化之spark执行引擎参数调优(二)这篇文章主要介绍了如何通过调整Spark执行引擎的参数来优化Hive查询的性能。文章中详细介绍了Spark执行引擎的各种参数,包括内存管理、并行度、序列化方式等等,以及如何根据不同的查询场景来进行参数调优。通过优化这些参数,可以显著提升Hive查询的速度和效率。 ### 回答2: 技能本功是指技术人员在学习和工作中的基本功夫,其重要性不言而喻。在进行hive优化之spark执行引擎参数调优时,也需要有扎实的基本功夫和深厚的理论知识作为支撑。这就需要我们在日常工作中不断地学习、积累,提高自己的实践和理论能力,才能够真正做到“技能娴熟、本领高强”。 在进行spark执行引擎参数调优时,需要注意以下几个方面: 1. 内存管理 首先需要考虑内存的管理问题,合理配置内存能够提高任务的执行效率。可以通过设置spark.executor.memory、spark.driver.memory、spark.memory.fraction等参数来达到最优的内存配置,充分利用内存资源。 2. 并行度设置 并行度是衡量spark作业执行效率的关键参数之一。根据数据量的大小、集群的规模等因素来合理设置并行度,既不能过高也不能过低,以充分利用集群资源,提高spark作业的执行效率。 3. 磁盘IO优化 磁盘IO是影响spark作业执行性能的重要因素,因此需要进行磁盘IO优化。可以通过设置spark.shuffle.spill.compress和spark.shuffle.compress等参数来压缩与解压数据以减少磁盘IO操作次数,并且从磁盘读写文件时也需要注意一些优化技巧,如将多个小文件合并成一个大文件、尽量避免频繁打开和关闭文件等。 4. GC调优 GC是指垃圾回收机制,是在Java虚拟机内存管理中非常重要的过程。在spark作业执行时,也会发生大量的对象创建和销毁,因此需要对垃圾回收机制进行调优,以减少因GC导致的性能下降。 总之,spark执行引擎参数调优是一个综合性强、需要不断提高和积累的过程。只有在积极研究和实践的过程中不断总结经验,才能将spark执行引擎的性能发挥到最大。 ### 回答3: 在进行 Hive SQL 查询时,可以通过调整 Spark 执行引擎的参数来优化性能,提高查询速度。以下是一些常见的参数调优方法: 1. 调整 executor 内存和 CPU 数量 在执行 Hive SQL 时,Spark 会将查询任务分配给若干个 executor 进行处理。每个 executor 都会占用一定的内存和 CPU 资源。如果 executor 的资源设置不合理,就会导致查询过程中出现瓶颈,影响查询速度。因此,可以通过调整 executor 的内存和 CPU 数量来优化查询性能。一般来说,较大的查询需要较大的内存和 CPU 数量,而较小的查询则需要较小的资源。 2. 增加 executor 数量 除了调整每个 executor 的资源,还可以增加 executor 的数量来提高执行速度。增加 executor 的数量可以让 Spark 并行处理多个查询任务,从而减少每个任务的处理时间。 3. 调整 shuffle 相关参数 在 Spark 中,shuffle 是数据分区和处理的关键环节,也是查询性能的一个重要因素。因此,我们可以通过设置 shuffle 相关参数来优化查询性能。具体来说,可以调整以下参数: (1)spark.shuffle.file.buffer:控制 Shuffle 时每个文件缓存的大小。增加该参数可以减少 Shuffle 阶段的磁盘 I/O 操作,从而提高查询速度。 (2)spark.shuffle.compress:是否对 Shuffle 时的中间结果进行压缩。启用压缩可以减少网络传输的数据量,加快查询速度。 4. 开启动态分区 在 Hive 中,可以通过设置 dynamic.partition.mode 参数来开启动态分区。开启动态分区可以让 Hive 自动根据查询结果的分布情况进行分区,从而减少不必要的操作,提高查询性能。 总之,通过对 Spark 执行引擎参数的调优,我们可以提高 Hive SQL 查询的性能和效率。在实际应用中,我们应该根据查询规模和数据量来灵活调整参数,以达到最优的性能表现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值