Hive的基本理论与安装可参看做者上一篇博文《Apache Hive 基本理论与安装指南》。html
全部的hive命令均可以经过hive命令行去执行,hive命令行中仍有许多选项。使用$hive -H查看:java
-e 选项后面能够直接接一个hql语句,不用进入到hive命令行用户接口再输入hql语句。sql
-f 选项后面接一个hql语句的文件。shell
-i 选项在hql语句执行以前的初始化hql文件。例如添加、导入等操做均可以写在这个hql语句文件中。数据库
在hive使用中,大可能是写不少脚本,在hive命令行中输入是属于交互式的,这就必须有工做人员在工做,不适合作批量处理。可使用-f或-i选项,一次性执行能够将全部的hql语句放在一个hql脚本文件中。例如:apache
$ mkdir -p /opt/shell/sql $ vim /opt/shell/sql/test.sql
select * from table_name limit 5; select * from table_name where professional="student"; select count(*) from table_name; select count(*) from table_name group by professional; select * from table_name where professional="student" order by age;
将脚本保存退出后,再批量执行:json
$ hive -f /opt/shell/sql/test.sql
详见官方文档。重点在于建立表和建立函数。vim
从官方文档的Create Table中能够查看hive建表的命令,以下:数组
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later) [(col_name data_type [COMMENT col_comment], ... [constraint_specification])] [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 BUCKETS] [SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)] ON ((col_value, col_value, ...), (col_value, col_value, ...), ...) [STORED AS DIRECTORIES] [ [ROW FORMAT row_format] [STORED AS file_format] | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later) ] [LOCATION hdfs_path] [TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later) [AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables) CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name LIKE existing_table_or_view_name [LOCATION hdfs_path];
data_type : primitive_type | array_type | map_type | struct_type | union_type -- (Note: Available in Hive 0.7.0 and later)
data_type,有两种类型:一种是复杂类型,例如array_type(ARRAY < data_type >)、map_type(MAP < primitive_type, data_type >)、struct_type(STRUCT < col_name : data_type [COMMENT col_comment], ...>)、union_type(UNIONTYPE < data_type, data_type, ... >);简单类型有SMALLINT(占2个字节的整数)、INT(占4个字节的整数)、BIGINT(占8个字节的整数)、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY、TIMESTAMP、DECIMAL、DATE、VARCHAR(0.12以后)、CHAR(字符,0.13以后)。浏览器
primitive_type : TINYINT | SMALLINT | INT | BIGINT | BOOLEAN | FLOAT | DOUBLE | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later) | STRING | BINARY -- (Note: Available in Hive 0.8.0 and later) | TIMESTAMP -- (Note: Available in Hive 0.8.0 and later) | DECIMAL -- (Note: Available in Hive 0.11.0 and later) | DECIMAL(precision, scale) -- (Note: Available in Hive 0.13.0 and later) | DATE -- (Note: Available in Hive 0.12.0 and later) | VARCHAR -- (Note: Available in Hive 0.12.0 and later) | CHAR -- (Note: Available in Hive 0.13.0 and later)
row_format : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] [NULL DEFINED AS char] -- (Note: Available in Hive 0.13 and later) | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
row_format:须要指出每一行是由什么隔开,而且要指出每一行中的每个字段是用什么隔开的。
对于字段的隔开,复杂数据类型和简单数据类型不同。例如数组类型是复杂类型,其隔开符[COLLECTION ITEMS TERMINATED BY char],Map类型的要使用[MAP KEYS TERMINATED BY char]。[LINES TERMINATED BY char]能够设置行隔开符,若是不写,默认为回车换行。
file_format: : SEQUENCEFILE | TEXTFILE -- (Default, depending on hive.default.fileformat configuration) | RCFILE -- (Note: Available in Hive 0.6.0 and later) | ORC -- (Note: Available in Hive 0.11.0 and later) | PARQUET -- (Note: Available in Hive 0.13.0 and later) | AVRO -- (Note: Available in Hive 0.14.0 and later) | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
SEQUENCEFILE表示序列压缩格式,以及RCFILE、ORC、PARQUET、AVRO都是压缩格式。TEXTFILE是默认的格式,文本格式。
为举例说明,这里先生成数据文件:
vim /root/person.txt
1,zhangsan,31,books-sports-math,city:shanghai-street:lujiazui-zipcode:313100 2,lisi,35,books-music,city:hangzhou-street:xihu-zipcode:222100 3,wangwu,25,computer-games,city:guangzhou-street:baiyun-zipcode:212300
根据数据建立一我的类表,包含人的编号、姓名、年龄、爱好、地址五个字段。
vim /opt/shell/sql/t_person.sql
create table t_person ( id int, name string, age int, likes array<string>, address map<string,string> ) row format delimited fields terminated by ',' collection items terminated by '-' map keys terminated by ':' lines terminated by '\n' stored as textfile;
根据表结构,字段之间按,隔开;likes的类型是array,因此能够有多个爱好,元素之间按-隔开,以,做为数组的结束;地址是map类型,也是collection类型, key和value按:隔开,每对key和value之间用-隔开(和collection一致);回车表明换行符。
执行建立表脚本:
$ hive -f /opt/shell/sql/t_person.sql
hive> load data local inpath '/root/person.txt' into table t_person;
当咱们要在关系型数据库中查找某一数据时,通常须要匹配数据库中的全部数据,因此能够经过分区来提升查询效率。把经常使用的查询条件做为一种分区,例如要查某一天的数据,事实上就是能够只匹配当天的数据,其余数据不匹配。下面以建一个日志管理表为例:
文件常常按照天、小时等进行分割。故在此建立多个文件以下:
vim /root/log_2016-03-11.txt
111,1,200,2016-03-11 135,4,100,2016-03-11 211,3,300,2016-03-11 141,1,200,2016-03-11 131,2,400,2016-03-11
vim /root/log_2016-03-12.txt
121,2,300,2016-03-12 125,3,400,2016-03-12 211,1,400,2016-03-12 161,3,100,2016-03-12 171,5,200,2016-03-12
create table t_log (id string,type int,pid string,logtime string) partitioned by (day string) row format delimited fields terminated by ',' stored as textfile;
这里指定了按照天作分区。
hive> load data local inpath '/root/log_2016-03-11.txt' into table t_log partition (day='2016-03-11'); hive> load data local inpath '/root/log_2016-03-12.txt' into table t_log partition (day='2016-03-12');
hive> select * from t_log;
从上图能够看出,数据增长了一个字段,左边是logtime,右边是分区day。因此,添加一个分区能够理解为添加一个字段;可是又不一样于添加一个字段,由于查询按照分区作限定(查询分区day='2016-03-11')时其余分区的数据不读取,而若是是字段的话,须要每一条数据进行匹配过滤。也能够从浏览器看出建立分区表的目录结构以下:
建立分区,就会为每个分区建一个目录,因此在查询时,只在限定的分区目录里查询。
查看某一天的数据量
hive> select count(*) from t_log where day='2016-03-11';
查看某一个月的数据量
hive>select count(*) from t_log where day between 'xxx' and 'xxx';
固然,这里须要先转换格式,略。
详见官方文档。DML是对数据进行增删改的脚本。可是数据在hdfs中,实际上不提供修改,只提供追加(insert),支持删除。
load file将数据导入到表中。其语法为:
hive> LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
local:若是导入的数据在Linux主机本地,就要添加[local],若是数据已经在hdfs上就不能加local;overwrite:覆盖;partition:若是表有分区就要加partition。
首先,上传Linux文件到hdfs
$ hdfs dfs -put /root/log_2016-03-1* /usr/input
其次,在hive中执行导入
hive>load data inpath '/usr/input/log_2016-03-12.txt' into table t_log partition (day='2016-03-12');
hive>load data inpath '/usr/input/log_2016-03-12.txt' overwrite into table t_log partition (day='2016-03-12');
注意:导入的分区要存在,导入到hive表后原来hdfs路径下的文件就不复存在了,即存在hdfs的目录变了,实际就是元数据变了,block的位置没有变。若是使用overwrite,则原来该表中指定分区的数据将所有清空,而后上传该文件。若是load相同文件名名到表中时,会默认生成副本filename_copy_1。文件中的数据格式要和表的结构相吻合。
hive>load data local inpath '/root/log_2016-03-11.txt' into table t_log partition (day='2016-03-11');
hive> INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
hive> INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
其中的select_statement1 FROM from_statement;是一个sql语句。这是用于查询hive中已经存在的数据,将查询结果给到一张新表中。
hive> INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES values_row [, values_row ...]
这个语句是和关系型数据库的insert语句用法是同样的。区别有三:一是,有partition;二是,能够一次插入多条数据;三是,这种语句是转成MapReduce去执行的。
由于hive是一个工具,其做用是查询和统计hdfs上的数据的,对于查询结果通常就在控制台上显示,因此这个insert语句做用就是将查询的结果保存下来,用于后期的展现。
hive> insert into table t_log partition (day='2016-03-13’) values ('888',2,'100','2016-03-13’);
这个会启动MapReduce,由于数据在文件中不存在,要插到文件中至关于上传,会生成一个新的文件。这个不经常使用。因此实际上inset into语句的实际意义在于将查询结果放到新的表中。
删除数据通常能够不在hive中删除,直接在hdfs上删除文件。由于删数据实际上就是删除文件。例如要删除以前插入到hive的t_log表day=2016-03-11分区下的log_2016-03-11.txt,能够执行以下命令:
#hdfs dfs -rm /user/hive/warehouse/t_log/day=2016-03-11/t_log-2016-03-11.txt
详见官方文档。
见文档
见文档
见文档
【1】map(构造map对象)
Creates a map with the given key/value pairs. (key1,value1,key2,value2,…)
【2】struct(建立架构数组)
Creates a struct with the given field values. (val1,val2,val3,…)。Struct的属性名和列名相对应。struct能够认为是面向对象的对象类型,是一个构造体,里面能够定义属性的值,field的名称是预先定义的,就像Java类的属性预先定义好了。
【3】named_struct
Creates a struct with the given field names and values. (name1,val1,name2,val2, …)。根据给定的Struct的属性名来建立构建数组
【4】array(建立数组对象)
Creates an array with the given elements. (val1,val2,val3,…)。把各(若干)个字段的值变成一个array。
【5】create_union
Creates a union type with value that is being pointes to by the tag parameter.
【1】A[n]
A是array类型,n是int类型。A[n]表示数组A的第n+1个元素。
【2】M[key]
M是map类型,key是map集合中键的类型。M[key]是取map集合中键为key的值。注意使用是key须要使用单引号。
【3】S.x
S是struct类型,x表示struct中的某个属性。S.x,将会返回S这个struct中定义的x属性型中存储的值。
略。
UDAF和UDF的区别在于传给函数的参数不同。UDF表示传给函数的参数只有一个值或一行值;UDAF是给函数传多个值或者多行值的函数,例如count(*),sum(col)等都是多行的值。
UDAF(User- Defined Aggregation Funcation) 汇集函数,多进一出,例如count/max/min等。
详见文档。
HivePlugins,Creating Custom UDFs。自定义函数须要如下几个步骤:首先要自定义一个类,继承UDF;其次,打成jar包;第三,将jar包加载到hive的classpath;第四,建立自定义函数;第五,使用函数。
例如,要建立一个将字符串转成日期的函数。
package com.huidoo.hive; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.hive.serde2.io.TimestampWritable; import org.apache.hadoop.io.Text; public class StringToDate extends UDF { /** * 定义evaluate方法。返回值类型定义为TimestampWritable * @param str * @param datefmt * @return * @throws Exception */ public TimestampWritable evaluate(final Text str,final Text datefmt) throws Exception{ SimpleDateFormat sdf= new SimpleDateFormat(datefmt.toString()); //datefmt是传入的格式化字符串,须要建立SimpleDateFormat对象,Text类型要转成Java中的String类型。 Date date= sdf.parse(str.toString()); //将字符串str,按照格式sdf转成java.util的Date类型 TimestampWritable time=new TimestampWritable();//建立Hadoop的时间戳对象 time.setTime(date.getTime());//将date转成Timestamp类型,而后使用Hadoop时间戳对象设置成相应的时间。 return time; } }
略。std.jar
hive> add jar /path/to/std.jar;
语法:create 函数名(不能与内置的同样) as ‘自定义类的全限定名’;
hive> create function std as 'com.huidoo.hive.StringToDate';
这就建立了一个函数,名为std。
hive> select std('2016-02-06 01:19:30','yyyy-MM-dd HH:mm:ss') from t_log limit 3;
hive> select * from table_name;
查看当前数据库:
hive> SELECT current_database();
"db_name.table_name" allows a query to access tables in different databases.能够查询不一样数据库中的表。
使用某数据库:
hive> USE database_name;
hive>SELECT * FROM sales WHERE amount > 10 AND region = "US"
使用distinct关键字去重查询,以下列出两个查询的区别:
hive> SELECT col1, col2 FROM t1
1 3
1 3
1 4
2 5
hive> SELECT DISTINCT col1, col2 FROM t1
1 3
1 4
2 5
join用于表链接。两个表即两个文件能链接起来就必定有相同点,这就是说其中一个文件中某域的值和另外一个文件的某域的值相同,就能够链接。
hive> select col1,col2,col3 from t1 join t2 on+条件;
这种查询语法就只要把partition当成一个字段便可。若是查询时要引入外键关联表也可使用JION…ON语句。
语法:
hive> select table_name.* from table_name where table_name.partition_name +条件;
案例:
SELECT page_views.* FROM page_views WHERE page_views.date >= '2016-03-01' AND page_views.date <= '2016-03-31';
语法:
hive> select table_name1.* from table_name1 join table_name2 on (table_name1.外键 = table_name2.主键 And table_name1.partiton_name +条件);
案例:
SELECT page_views.* FROM page_views JOIN dim_users ON (page_views.user_id = dim_users.id AND page_views.date >= '2016-03-01' AND page_views.date <= '2016-03-31');
hive> select col[list] from table_name group by col;
sort by和order by的用法基本一致,都是作排序的,通常用order by。例如:
hive> select * from t_log order by id;
having从句必须依附于group by从句,在group从句后面接having从句,至关于增长一个条件。having后面能够接聚合函数,例如sum、avg等。
hive> select day from t_log group by day;
其查询结果为:
2016-03-11
2016-03-12
hive>select day from t_log group by day having avg(id)>150;
其查询结果为:
2016-03-12
hive> select day from (select day, avg(id) as avgid from t_log group by day) table2 where table2.avgid>150;
这里将t_log表经过select day, avg(id) as avgid from t_log group by day查询获得的结果做为表再查询的。和上述的hiving从句获得的结果同样。
限定查询返回的行数。
hive> select * from t_log limit 5;