HIVE详解

HIVE详解

HIVE基本概念

HIVE简介

什么是hive?

hive是基于hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。

为什么使用Hive

直接使用hadoop所面临的问题:

​ 人员学习成本太高

​ 项目周期要求太短

​ MapReduce实现复杂查询逻辑开发难度太大

为什么使用HIve

​ 操作接口采用类SQL语法,提供快速开发的能力

​ 避免去屑MapReduce,减少开发人员的学习成本

​ 扩展功能很方便

Hive的特点

可扩展:

​ Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。

延展性:

​ Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数

容错:

​ 良好的容错性,节点出现问题SQL仍然可以执行。

Hive架构

架构图

hive架构

Jobtracker是hadoop1.x中的组件,他的功能相当于:Resoucemanager+AppMaster

TaskTracker相当于:NodeManager+yarnchild

基本组成

​ 用户接口:包括CLI、JDBC/ODBC、WebGUI。

​ 元数据存储:通常是储存在关系数据库如mysql,derby中

​ 解释器、编译器、优化器、执行器。

各组建基本功能

用户接口主要由三个:CLI、JDBC/ODBC和webGUI。其中,CLI为shell命令行;JDBC/ODBC是HIVE的JAVA实现,与传统数据库JDBC类似;WebGUI是通过浏览器访问HIVE。

元数据存储:HIVE将元数据存储在数据库中。HIVE中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

解释器、编译器、优化器完成HQL查询语句从词法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS中,并在随后由MapReduce调度执行。

Hive与Hadoop的关系

Hive利用HDFS存储数据,利用MapReduce查询数据

Hive与Hadoop的关系

Hive与传统数据库对比
HiveRDBMS
查询语言HQL
数据存储HDFS
MapReduce
执行延迟
处理数据规模
索引0.8版本之后加入位图索引

总结:hive具有sql数据库的外表,但应用场景完全不同,hive只适合用来做批量数据统计分析。

Hive的数据存储

1.Hive中所有的数据都存储在HDFS中,没有专业的数据储存格式(可支持Text,SequenceFile,ParquetFile,RCFILE等)

2.只需要在创建表的时候告诉HIve数据中的列分割符合行分割符,Hive就可以解析数据。

3.Hive中包含以下数据模型:DB,Table,External table,Partition,Bucket。

​ db:在hdfs中表现为${hive.metastore.warehouse.dir}目录下一个文件夹

​ table:在hdfs中表现所属db目录中下一个文件夹

​ external table:外部表,与table类似,不过其数据存放位置可以指定任意路径。普通标删除之后,hdfs上的文件都删了。

​ external外部表删除之后,hdfs上的文件没有删除,只是把文件删除了

​ partition:在hdfs中表现为目录下的子目录。

​ bucket:桶,在hdfs中表现为同一个表目录下根据hash散列之后的多个文件,会根据不同的文件吧数据放到不同的文件中。

Hive使用

hive交互shell

bin/hive

Hive thrift服务

启动方式:

启动为前台:

bin/hiveserver2

启动为后台:

nohup bin/hiveserver2 1>/var/log/hiveserver.log 2 > /var/log/hiveserver.err&

启动成功后,可以在别的节点上有beeline去连接

方式(1):

hive/bin/beeline 回车,进入beeline的命令界面

输入命令连接hiveserver2

beeline>!connect jdbc:hive2//YOURIP:10000

方式(2):

启动时直接连接:

bin/beeline -u jdbc:hive2://yourIP:10000 -n hadoop

HIVE基本操作

DDL操作

创建表

建表语法:

CREATE   [EXTERNAL] TABLE [IF NOT EXISTS] TABLE_NAME

[(COL_NAME DATA_TYPE[COMMENT COL_COMMENT])]

[COMMENT TABLE_COMMENT]

[PARTITIONED BY (COL_NAME DATA_TYPE[COMMENT COL_COMMENT],....)]

[CLUSTERED BY (COL_NAME,COL_NAME)

[SORTED BY(COL_NAME[ASC|DESC],...)] INTO NUM_BUCKETS BUCKERTS]

[ROW FORMAT ROW_FORMAT]

[STORED AS FILE_FORMAT]

[LOCATION HDFS_PATH]

说明:

1.create table 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用IF NOT EXISTS选项来忽略这个异常

2.EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive创建内部表示,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据数据所在路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据一起被删除,而外部表只删除元数据,不删除数据。

3.LIKE允许用户复制现有的表结构,但是不复制数据。

4.

ROW FORMAT 
DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] 
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] 
   | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

用户在创建表的时候可以自定义SerDe或者使用自带的Serde。如果没有指定ROW FORMAT 或者ROW FORMAT DELIMITED,将会使用自带的Serde。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的serde,hive通过serde缺的表的具体的列的数据。

5.

STORED AS
    SEQUENCEFILE|TEXTFILE|RCFILE

如果文件数据是纯文本,可以使用STORED AS TEXTFILE。如果数据需要压缩,使用STORED AS SEQUENCEFILE。

6.CLUSTERED BY

​ 对于每一个表(table)或者分区,HIVE可以进一步组织成桶,也就是说通是更为细粒度的数据范围划分。HIVE也是针对某一列进行桶的组织。HIVE采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在那个桶中。

​ 把表(或者分区)组织成桶有两个理由:

​ (1)获得更高的查询处理效率。桶为表加上了额外的结构,hive在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列)相同列上划分了通的表,可以使用map端连接(Map-side join)高效实现。比如Join操作。对于join操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行join操作就可以,可以大大减少join的数据量。

​ (2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一部分上测试运行查询,会带来很多方便。

具体实例

创建外部表mytable

create table if not exists mytable (sid int,sname string)
row format delimited fields terminated by '\005' stored as textfile;

创建外部表

create external table if not exists pageview(
    pageid int,
    page_url string comment 'The page URL')
row format delimited fields terminated by ','
location 'hdfs://192.168.7.1:9000/user/hive/warehouse';

创建分区表invites

create table student_p(sno int,snamr string,sex string,sage int,sdept string) partitioned by(part string) row format delimited fields terminated by ',' stored as textfile;

创建带桶的表

create table student(id int,age int,name string)
partitioned by (stat_data string)
clustered by (id) sorted by (age) into 2 buckets
row format delimited fields terminated by ',';
修改表
ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...
partition_spec:
: PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)

ALTER TABLE table_name DROP partition_spec, partition_spec,...

具体实例

alter table student_p add partiotion(part='a') partition(part='b')
命名表

语法结构

ALTER TABLE table_name RENAME TO new_table_name

具体实例:

alter table mytable rename to mystudent;
增加/更新列

语法结构

ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...) 

注:ADD是代表新增一字段,字段位置在所有列后面(partition列前),replace则是表示替代表中所有字段

ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]
显示命令
show tables
show databases
show partitions
show functions
desc extended t_name;
desc formatted table_name;

DML操作

load

语法结构

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO 
TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]

说明:

​ 1.Load操作只是单纯的复制/移动操作,将数据文件移动到hive表对应的位置。

​ 2.filepath:

​ 相对路径,例如:project/data1

​ 绝对路径:例如:/user/hive/project/data1

包含完整的urI,例如:

​ hdfs://namenode:9000/user/hive/project/data1

​ 3.Local关键字

​ 如果指定了Local,load命令回去查找本地文件系统中的filepath。

​ 如果没有指定Local关键字,则根据inpath中的uri查找文件。

​ 4.Overwrite关键字

​ 如果使用了overwrite关键字,则目标集中的内容会被删除,然后再将filepath指向的文件/目录中的内容添加到表/分区中。

​ 如果目标表(分区)已经有一个文件,并且文件名和filepath中的文件名冲突,那么现有的文件会被新文件所替代。

具体实例:

加载相对路径数据

load data local inpath 'buckets.txt' into table student patition{stat_data='20131231'}

加载绝对路径的数据

load data local inpath '/root/app/datafile/buckets.txt' into table student partition(stat_date='20131231')

加载包含模式数据

load data local inpath 'hdfs://192.168.11.191:9000/user/hive/warehouse/student/stat_data=20131230/bucket.txt' into table student partition(stat_date='20131230');

overwrite关键字使用:

load data inpath 'buckets.txt' overwrite into table studnet partition{stat_data='20131230'};
insert

将查询结果插入hive表

语法结构:

INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement

Multiple inserts:
FROM from_statement 
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 
[INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...

Dynamic partition inserts:
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement

导出表数据

语法结构:

INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...


multiple inserts:
FROM from_statement
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1
[INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2] ...

select

语法结构:

SELECT [ALL | DISTINCT] select_expr, select_expr, ... 
FROM table_reference
[WHERE where_condition] 
[GROUP BY col_list [HAVING condition]] 
[CLUSTER BY col_list 
  | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] 
] 
[LIMIT number]

注:

​ 1.order by会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。

​ 2.sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。

​ 3.distribute根据distribute by指定的内容将数据分到同一个reducer。

​ 4.cluster by除了具有Distribute by的功能之外,还会对该字段进行排序。因此,常常认为cluster by = distribute by + sort by.

hive join

语法结构

join_table:
  table_reference JOIN table_factor [join_condition]
  | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
  | table_reference LEFT SEMI JOIN table_reference join_condition

hive支持等值连接(equality joins)、外连接(outer joins)和(left/right joins).hive不支持等值连接,因为非等值连接非常难转化到map/reduce任务。另外,hive支持多余2两个表的连接。

写join查询时,需要注意几个关键点:

1.只支持等值join

​ 例如

select a.* from a join b on (a.id = b.id)
select a.* from a join b
    on (a.id = b.id and a.department = b.department)
    是正确的
    然而
    select a.* from a join b on (a.id > b.id)
    是错误的

注意:现在有一些书说可以实现不等值连接

2.可以join多于2个表

例如:

select a.val,b.val,c.val from a join b
on (a.key = b.key1) join c on (c.key = b.key2)
如果join中多个表的join key是同一个,则join会别转化为单个map/reduce任务,例如:
select a.val,b.val,c.val from a join b
on (a.key = b.key1) join c
on (c.key = b.key1)
被转化为单个map/reduce任务,因为join中只使用了b.key作为join key.
select a.val,b.val,c.val from a join b on (a.key = b.key1)
join c on (c.key = b.key2)
而这一join被转换为2个map/reduce任务。因为b.key1用于第一次Join条件,而b.key2用于第二次join.

3.join时,每次map/reduce任务的逻辑:

​ reducer会缓存join序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统。这一实现有助于在reduce端减少内存的使用量。实践中,应该把最大的那以表写到最后(否则浪费大量内存)。

例如

select a.val,b.val,c.val from a
    join b om (a.key = b.key) join c on (c.key = b.key1)
    所有表都使用相同一个join.key(使用一次map/reduce任务计算)。Reduce端会缓存a表和b表的记录,然后每次取得一个C表的记录就计算一次join结果。

4.left,right和full outer关键字用于处理join中空记录的情况

例如:

select a.val,b.val from a left outer join b on (a.key = b.key)
对用所有a表中的记录都有一条记录输出。输出的结果应该是a.val,b.val,当a.key = b.key时,而当b.key中找不到等值的a.key记录时也会输出。

Hive参数配置方式

开发hive应用时,不可避免的需要设定hive参数。设定hive参数可以调优HQL代码的执行效率,或帮助定位问题。然而时间中经常遇到的一个问题是,为什么设定了参数没有起到作用。这通常是错误的设定的方式导致的。

对于一般参数,有以下三种设定方式:

​ 配置文件

​ 命令行参数

​ 参数声明

配置文件:hive的配置文件包括:

​ 用户自定义配置文件:$HIVE_CONF_DIR/hive-site.xml

​ 默认配置文件:$HIVE_CONF_DIR/hive-default.xml

用户自定义配置会覆盖默认配置。

另外,hive也会读入hadoop的配置,因为hive是作为hadoop的客户端启动的,hive的配置会覆盖hadoop的配置。

配置文件的设定对本机启动的所有hive继承都有效

命令行参数:启动hive(客户端或server方式)是,可以在命令行添加-hiveconf param=value来设定参数。例如:

bin/hive -hiveconf hive.root.logger=INFO,console

这一设定对本次启动的session(对于server方式启动,则是所有请求的sessions)有效。

参数声明:可以在HQL中使用SET关键字设定参数,例如:

set mapred.reduce.tasks=100;

这一设定的作用域也是session的。

上述三种设定方式的优先级一次递增。即参数声明覆盖命令行参数,命令行参数覆盖配置文件设定。注意某些系统级的参数,例如log4j相关设定,必须用前两种方式设定,因为那些参数的读取在session建立以前就已经完成了。

Hive自定义函数和Transform

当hive提供的内置函数无法满足你的业务需要处理时,此时就可以考虑使用用户自定义函数(UDF:user-defined fuction)

自定义函数类别

UDF作用于单个数据行,产生一个数据行作为输出行。(数学函数,字符串函数)UDAF(用户自定义聚集函数):接受多个输入数据行,并产生一个输出数据行。

UDF开发实例

1.先开发一个java类,继承UDF,并重载evaluate方法

package com.mingming.udf
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public final class Lower extends UDF{
    public Text evaluate(final Text s){
        if(s==null){return null;}
        return new Text(s.toString().toLowerCase());
    }
}

2.打成jar包上传到服务器

3.将jar包添加hive的classpath

hive>JAR /home/hadoop/udf.ajr

4.创建临时函数与开发的java calss关联

Hive>create temporary function toLower as ‘com.mingming.udf.Lower’

5.即可在hql中使用自定义的函数toLower

select toLower(name),age from t_test;

Transform实现

hive的Transform关键字提供饿了SQl调用自写脚本的功能

适合实现HIVE中没有的功能又不想写UDF的情况

使用实例1:下面这句sql就是借用了weekday_mapper.py对数据进行了处理

CREATE TABLE u_data_new (
  movieid INT,
  rating INT,
  weekday INT,
  userid INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';

add FILE weekday_mapper.py;

INSERT OVERWRITE TABLE u_data_new
SELECT
  TRANSFORM (movieid, rating, unixtime,userid)
  USING 'python weekday_mapper.py'
  AS (movieid, rating, weekday,userid)
FROM u_data;

其中weekday_mapper.py的内容如下:

#!/bin/python
import sys
import datetime

for line in sys.stdin:
  line = line.strip()
  movieid, rating, unixtime,userid = line.split('\t')
  weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
  print '\t'.join([movieid, rating, str(weekday),userid])
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hive中,group_concat函数用于将分组中的值连接组合成一个字符串结果。它的语法是GROUP_CONCAT(\[DISTINCT\] expr \[,expr ...\] \[ORDER BY {unsigned_integer | col_name | formula} \[ASC | DESC\] \[,col ...\]\] \[SEPARATOR str_val\])。\[2\] 这个函数可以将一整列的值打印到一行中,并且可以指定分隔符,默认为逗号。例如,使用SELECT GROUP_CONCAT(id) AS ids FROM employee_tbl可以将employee_tbl表中的id列的值连接成一个字符串,并将结果命名为ids。\[3\] 需要注意的是,由于Hive版本的问题,低版本可能没有group_concat函数,可以使用其他方法来代替,比如结合group by与collect_set函数使用concat_ws函数,语法为concat_ws(SEPARATOR ,collect_set(column))。\[1\] 如果你对大数据技能和架构感兴趣,可以关注我的公众号,我收集了现在主流的大数据技能和架构,欢迎大家一起来学习交流。\[1\] #### 引用[.reference_title] - *1* *2* [hive中的拼接函数(concat,group_concat,concat_ws,collect_set)](https://blog.csdn.net/zll_1234/article/details/106329025)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [MySQL函数CONCAT、CONCAT_WS、GROUP_CONCAT详解](https://blog.csdn.net/m0_61532500/article/details/126660678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值