HiveQL介绍
Hive支持原子和复杂数据类型。原子数据类型包括数值型、布尔型和字符串类型,其中数值型有int / bigint / smallint / tinyint /double / float,布尔型为boolean,字符串类型为string。复杂数据类型包括数组(Array)、集合(Map)和结构(Struct)。Hive 还提供了大量的内置函数,诸如数学和统计函数、字符串函数、日期函数、条件函数、聚集函数等。当无法用Hive提供的内置函数来表示时,用户可以使用 UDF(用户自定义函数)。Hive中有三种UDF:UDF(普通)、UDAF(用户定义聚集函数)和UDTF(用户定义表生成函数)。
第一部分:DDL
Hive提供的DDL包含如下操作:
•建表
1) 建立内部表
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 BUCKETS] [ROW FORMAT row_format] [STORED AS file_format] [LOCATION hdfs_path] |
CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXIST 选项来忽略这个异常
EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION) LIKE 允许用户复制现有的表结构,但是不复制数据 COMMENT可以为表与字段增加描述 STORED AS SEQUENCEFILE | TEXTFILE | RCFILE |INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname 如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCE 。 |
2)建立外部表
CREATE EXTERNAL TABLE page_view(viewTime INT, userid BIGINT,
page_url STRING, referrer_url STRING, ip STRING COMMENT ‘IP Address of the User’, country STRING COMMENT ‘country of origination’) COMMENT ‘This is the staging page view table’ ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\054′ STORED AS TEXTFILE LOCATION ‘<hdfs_location>’; |
3)建立分区表
CREATE TABLE par_table(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(date STRING, pos STRING) ROW FORMAT DELIMITED ‘\t’ FIELDS TERMINATED BY ‘\n’ STORED AS SEQUENCEFILE; |
3)建Bucket表
CREATE TABLE par_table(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(date STRING, pos STRING) CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS ROW FORMAT DELIMITED ‘\t’ FIELDS TERMINATED BY ‘\n’ STORED AS SEQUENCEFILE; |
4)复制一个空表
CREATE TABLE empty_key_value_store
LIKE key_value_store; |
•删除表
DROP TABLE table_name |
•修改表结构
修改表结构操作包括增加分区、删除分区、重命名表、修改列的名字、类型、位置、注释及增加/更新列、增加表的元数据信息。
增加分区 | ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] |
删除分区 | ALTER TABLE table_name DROP partition_spec, partition_spec,… |
重命名表 | ALTER TABLE table_name RENAME TO new_table_name |
修改列的名字、类型、位置、注释 | ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name] |
增加/更新列 | ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], …) |
增加表的元数据信息 | ALTER TABLE table_name SET TBLPROPERTIES table_properties table_properties: |
•改变表文件格式与组织
ALTER TABLE table_name SET FILEFORMAT file_format
ALTER TABLE table_name CLUSTERED BY(userid) SORTED BY(viewTime) INTO num_buckets BUCKETS |
这个命令修改了表的物理存储属性。
•创建/删除视图
CREATE VIEW [IF NOT EXISTS] view_name [ (column_name [COMMENT column_comment], …) ][COMMENT view_comment][TBLPROPERTIES (property_name = property_value, ...)] AS SELECT |
DROP VIEW view_name |
如果没有提供表名,视图列的名字将由定义的SELECT表达式自动生成。
如果修改基本表的属性,视图中不会体现,无效查询将会失败。 视图是只读的,不能用LOAD/INSERT/ALTER。 |
•创建数据库
CREATE DATABASE name |
•显示命令
show tables;
show databases;
show partitions ;
show functions
describe extended table_name dot col_name
DML包含如下操作:
•向数据表内加载文件
•LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] |
Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。
filepath 1.相对路径,例如:project/data1 2.绝对路径,例如: /user/hive/project/data1 3.包含模式的完整 URI,例如:hdfs://namenode:9000/user/hive/project/data1 |
•将查询结果插入到 Hive 表中
基本模式 | INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement |
多插入模式 | FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ... |
自动分区模式 | INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement |
将查询结果写入HDFS文件系统
|
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...
FROM from_statement INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1 [INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2] |
INSERT INTO | INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement |
Hive的SQL操作
•基本的 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. 使用ALL和DISTINCT选项区分对重复记录的处理。默认是ALL,表示查询所有记录。DISTINCT表示去掉重复的记录。
2. Where 条件:类似我们传统SQL的where 条件 3. 0.9版本支持between,还不支持EXIST ,NOT EXIST 4. ORDER BY与SORT BY的不同:ORDER BY 全局排序,只有一个Reduce任务,SORT BY 只在本机做排序 Limit:Limit 可以限制查询的记录数,如:SELECT * FROM t1 LIMIT 5 |
•基于 Partition 的查询
如下面的查询语句:SELECT day_table.* FROM day_table WHERE day_table.dt>= ’2008-08-08′; dt是day_table表的分区字段。 |
• Join 语句
•Hive 只支持等值连接(equality joins)、外连接(outer joins)和(left semi joins)。Hive 不支持所有非等值的连接,因为非等值连接非常难转化到 map/reduce 任务
•LEFT,RIGHT和FULL OUTER关键字用于处理join中空记录的情况 •LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现 •join 时,每次 map/reduce 任务的逻辑是这样的:reducer 会缓存 join 序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统 •实践中,应该把最大的那个表写在最后 join 查询时,需要注意几个关键点 •只支持等值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) •可以 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 任务 LEFT,RIGHT和FULL OUTER •例子 •SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key) •如果你想限制 join 的输出,应该在 WHERE 子句中写过滤条件——或是在 join 子句中写 •容易混淆的问题是表分区的情况 • SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key) WHERE a.ds=’2010-07-07′ AND b.ds=’2010-07-07‘ •如果 d 表中找不到对应 c 表的记录,d 表的所有列都会列出 NULL,包括 ds 列。也就是说,join 会过滤 d 表中不能找到匹配 c 表 join key 的所有记录。这样的话,LEFT OUTER 就使得查询结果与 WHERE 子句无关 •解决办法 •SELECT c.val, d.val FROM c LEFT OUTER JOIN d ON (c.key=d.key AND d.ds=’2009-07-07′ AND c.ds=’2009-07-07′) LEFT SEMI JOIN •LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行 •SELECT a.key, a.value FROM a WHERE a.key in (SELECT b.key FROM B); 可以被重写为: SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key) UNION ALL •用来合并多个select的查询结果,需要保证select中字段须一致 •select_statement UNION ALL select_statement UNION ALL select_statement …
|
第四部分:注意HiveQL区别于SQL的一些情况
SQL中对两表内联可以写成:
•select * from dual a,dual b where a.key = b.key;
Hive中应为
•select * from dual a join dual b on a.key = b.key;
分号字符
•分号是SQL语句结束标记,在HiveQL中也是,但是在HiveQL中,对分号的识别没有那么智慧,例如:
•select concat(key,concat(‘;’,key)) from dual;
但HiveQL在解析语句时提示:
FAILED: Parse Error: line 0:-1 mismatched input ‘<EOF>’ expecting ) in function specification
•解决的办法是,使用分号的八进制的ASCII码进行转义,那么上述语句应写成:
•select concat(key,concat(‘\073′,key)) from dual;
IS [NOT] NULL
•SQL中null代表空值, 值得警惕的是, 在HiveQL中String类型的字段若是空(empty)字符串, 即长度为0, 那么对它进行IS NULL的判断结果是False.
添加分区以及自动化分区
-
完成了上面的步骤,你就可以查询数据了,但面临一个问题,数据更新怎么办?
- 一个比较通用的做法就是每天跑一个定时任务将HBase表dump到HDFS,即每天一个快照
- 每天的快照可以存放在以日期命名的目录中,这样可以保存多份快照,出了问题也好追踪
-
hive如何利用这每天的快照?
- 那就是hive分区
- 分区的本意是数据量大了切分数据,但目前我们并未如此使用,而是利用分区来区分快照
-
删除之前的表
drop table task_history;
-
产生一张分区表
CREATE EXTERNAL TABLE task_history ( biz_type string, cid string, content string, ctime string, gmt_create string, hostName string, item string, mtime string, otags string, priority string, retry string, result string, srcImages string, src_url string, status string, summary string, task_type string, title string, userId string, userNick string, utags string, writer string ) PARTITIONED BY (dt string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' LOCATION '/group/wireless-arctic/task';
PARTITIONED BY (dt string)
-
添加分区
ALTER TABLE task_history ADD PARTITION(dt='20131223') LOCATION '/group/wireless-arctic/task/20131223';
-
如何自动化
- 通过工具比如
datax
或者其他导出工具将HBase表导出到HDFS,正如前面提到的每天一个目录(以日期命名) -
将每天的数据目录挂载到hive分区
hive -e "ALTER TABLE task_history ADD PARTITION(dt=`date -d yesterday +%Y%m%d`) LOCATION '/group/wireless-arctic/task/`date -d yesterday +%Y%m%d`';"
- 将前面2个步骤的脚本整合到crontab 中就可以做到自动化了
-
最后如何通过分区查询
select * from task_history where dt='20131223' limit 10;
dt='20131223'
- 通过工具比如
已有 0 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐