一. DDL(数据定义语言)
1. DDL概述
数据定义语言 (Data Definition Language, DDL),是SQL语言集中对数据库内部的对象结构进行创建,删除,修改等的操作语言,这些数据库对象包括database(schema)、table、view、index等。核心语法由CREATE、ALTER与DROP三个所组成。DDL并不涉及表内部数据的操作。
2. DDL建表
2.1 完整建表语法树
蓝色字体是建表语法的关键字,用于指定某些功能。
[]中括号的语法表示可选。
|表示使用的时候,左右语法二选一。
建表语句中的语法顺序要和上述语法规则保持一致。
2.2 Hive数据类型
Hive中的数据类型指的是Hive表中的列字段类型。Hive数据类型整体分为两个类别:原生数据类型(primitive data type)和复杂数据类型(complex data type)。
原生数据类型包括:数值类型、时间类型、字符串类型、杂项数据类型;
复杂数据类型包括:array数组、map映射、struct结构、union联合体。
关于Hive的数据类型,需要注意:
英文字母大小写不敏感;
除SQL数据类型外,还支持Java数据类型,比如:string;
int和string是使用最多的,大多数函数都支持;
复杂数据类型的使用通常需要和分隔符指定语法配合使用。
如果定义的数据类型和文件不一致,hive会尝试隐式转换,但是不保证成功。
2.3 Hive读写文件机制
机制:SerDe(Serializer and Deserializer)序列化机制
Hive使用SerDe机制读写HDFS上文件
读文件
HDFS files --> InputFileFormat --> <key, value> --> Deserializer --> Row object
写文件
Row object --> Serializer --> <key, value> --> OutputFileFormat --> HDFS files
分隔符指定语法
语法格式
ROW FORMAT DELIMITED | SERDE
ROW FORMAT DELIMITED 表示使用LazySimpleSerDe类进行序列化解析数据
ROW FORMAT SERDE 表示使用其他SerDe类进行序列化解析数据
- ROW FORMAT DELIMITED具体的子语法
row format delimited
[fields terminated by char] #指定字段之间的分隔符
[collection items terminated by char] #指定集合元素之间的分隔符
[map keys terminated by char] #指定map类型kv之间的分隔符
[lines terminated by char] #指定换行符
默认分隔符
Hive在建表的时候,如果没有row format语法,则该表使用\001默认分隔符进行字段分割;
如果此时文件中的数据字段之间的分隔符也是\001 ,那么就可以直接映射成功。
针对默认分隔符,其是一个不可见分隔符,在代码层面是\001表示
在vim编辑器中,连续输入ctrl+v 、ctrl+a;
在实际工作中,Hive最喜欢的就是\001分隔符,在清洗数据的时候,有意识的把数据之间的分隔符指定为\001;
2.4 Hive数据存储路径
默认存储路径
Hive表默认存储路径是由${HIVE_HOME}/conf/hive-site.xml配置文件的hive.metastore.warehouse.dir属性指定。默认值是:/user/hive/warehouse。
指定存储路径
在Hive建表的时候,可以通过location语法来更改数据在HDFS上的存储路径,使得建表加载数据更加灵活方便。
语法:LOCATION '<hdfs_location>'。
对于已经生成好的数据文件,使用location指定路径将会很方便。
3. DDL其他语法
3.1 Database|schema(数据库) DDL操作
Create database
Hive中DATABASE的概念和RDBMS中类似,我们称之为数据库。在Hive中, DATABASE和SCHEMA是可互换的,使用DATABASE或SCHEMA都可以。
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
COMMENT:数据库的注释说明语句
LOCATION:指定数据库在HDFS存储位置,默认/user/hive/warehouse
WITH DBPROPERTIES:用于指定一些数据库的属性配置。
Describe database
Hive中的DESCRIBE DATABASE语句用于显示Hive中数据库的名称,其注释(如果已设置)及其在文件系统上的位置等信息。
DESCRIBE DATABASE/SCHEMA [EXTENDED] db_name;
Use database
Hive中的USE DATABASE语句用于选择特定的数据库,切换当前会话使用哪一个数据库进行操作。
USE database_name;
Drop database
Hive中的DROP DATABASE语句用于删除(删除)数据库。
默认行为是RESTRICT,这意味着仅在数据库为空时才删除它。要删除带有表的数据库,我们可以使用CASCADE。
DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE];
Alter database
Hive中的ALTER DATABASE语句用于更改与Hive中的数据库关联的元数据。
--更改数据库属性
ALTER (DATABASE|SCHEMA) database_name SET DBPROPERTIES (property_name=property_value, ...);
--更改数据库所有者
ALTER (DATABASE|SCHEMA) database_name SET OWNER [USER|ROLE] user_or_role;
--更改数据库位置
ALTER (DATABASE|SCHEMA) database_name SET LOCATION hdfs_path;
3.2 Table(表)DDL操作
Describe table
Hive中的DESCRIBE table语句用于显示Hive中表的元数据信息。
describe formatted [db_name.]table_name;
describe extended [db_name.]table_name;
如果指定了EXTENDED关键字,则它将以Thrift序列化形式显示表的所有元数据。如果指定了FORMATTED关键字,则它将以表格格式显示元数据。
Drop table
DROP TABLE删除该表的元数据和数据。如果已配置垃圾桶(且未指定PURGE),则该表对应的数据实际上将移动到.Trash/Current目录,而元数据完全丢失。删除EXTERNAL表时,该表中的数据不会从文件系统中删除,只删除元数据。
如果指定了PURGE,则表数据不会进入.Trash/Current目录,跳过垃圾桶直接被删除。因此如果DROP失败,则无法挽回该表数据。
DROP TABLE [IF EXISTS] table_name [PURGE]; -- (Note: PURGE available in Hive 0.14.0 and later)
Truncate table
从表中删除所有行。可以简单理解为清空表的所有数据但是保留表的元数据结构。如果HDFS启用了垃圾桶,数据将被丢进垃圾桶,否则将被删除。
TRUNCATE [TABLE] table_name;
Alter table
--1、更改表名
ALTER TABLE table_name RENAME TO new_table_name;
--2、更改表属性
ALTER TABLE table_name SET TBLPROPERTIES (property_name = property_value, ... );
--更改表注释
ALTER TABLE student SET TBLPROPERTIES ('comment' = "new comment for student table");
--3、更改SerDe属性
ALTER TABLE table_name SET SERDE serde_class_name [WITH SERDEPROPERTIES (property_name = property_value, ... )];
ALTER TABLE table_name [PARTITION partition_spec] SET SERDEPROPERTIES serde_properties;
ALTER TABLE table_name SET SERDEPROPERTIES ('field.delim' = ',');
--移除SerDe属性
ALTER TABLE table_name [PARTITION partition_spec] UNSET SERDEPROPERTIES (property_name, ... );
--4、更改表的文件存储格式该操作仅更改表元数据。现有数据的任何转换都必须在Hive之外进行。
ALTER TABLE table_name SET FILEFORMAT file_format;
--5、更改表的存储位置路径
ALTER TABLE table_name SET LOCATION "new location";
--6、更改列名称/类型/位置/注释
CREATE TABLE test_change (a int, b int, c int);
-- First change column a's name to a1.
ALTER TABLE test_change CHANGE a a1 INT;
-- Next change column a1's name to a2, its data type to string, and put it after column b.
ALTER TABLE test_change CHANGE a1 a2 STRING AFTER b;
-- The new table's structure is: b int, a2 string, c int.
-- Then change column c's name to c1, and put it as the first column.
ALTER TABLE test_change CHANGE c c1 INT FIRST;
-- The new table's structure is: c1 int, b int, a2 string.
-- Add a comment to column a1
ALTER TABLE test_change CHANGE a1 a1 INT COMMENT 'this is column a1';
--7、添加/替换列
--使用ADD COLUMNS,您可以将新列添加到现有列的末尾但在分区列之前。
--REPLACE COLUMNS 将删除所有现有列,并添加新的列集。
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type,...);
3.3 Partition(分区)DDL操作
Add partition
分区值仅在为字符串时才应加引号。位置必须是数据文件所在的目录。
ADD PARTITION会更改表元数据,但不会加载数据。如果分区位置中不存在数据,查询将不会返回任何结果。
-- 增加分区
ALTER TABLE table_name ADD PARTITION (dt='20170101') location
'/user/hadoop/warehouse/table_name/dt=20170101';
--一次添加一个分区
ALTER TABLE table_name ADD PARTITION (dt='2008-08-08', country='us') location '/path/to/us/part080808' PARTITION (dt='2008-08-09', country='us') location '/path/to/us/part080809';
rename partition
-- 重命名分区
ALTER TABLE table_name PARTITION partition_spec RENAME TO PARTITION partition_spec;
ALTER TABLE table_name PARTITION (dt='2008-08-09') RENAME TO PARTITION (dt='20080809');
delete partition
可以使用ALTER TABLE DROP PARTITION删除表的分区。这将删除该分区的数据和元数据。
-- 删除分区
ALTER TABLE table_name DROP [IF EXISTS] PARTITION (dt='2008-08-08', country='us');
ALTER TABLE table_name DROP [IF EXISTS] PARTITION (dt='2008-08-08', country='us') PURGE; --直接删除数据 不进垃圾桶
msck partition
Hive将每个表的分区列表信息存储在其metastore中。但是,如果将新分区直接添加到HDFS(例如通过使用hadoop fs -put命令)或从HDFS中直接删除分区文件夹,则除非用户ALTER TABLE table_name ADD/DROP PARTITION在每个新添加的分区上运行命令,否则metastore(也就是Hive)将不会意识到分区信息的这些更改。
但是,用户可以使用修复表选项运行metastore check命令。
-- 修复分区
MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
MSC命令的默认选项是“添加分区”。使用此选项,它将把HDFS上存在但元存储中不存在的所有分区添加到元存储中。DROP PARTITIONS选项将从已经从HDFS中删除的metastore中删除分区信息。SYNC PARTITIONS选项等效于调用ADD和DROP PARTITIONS。
如果存在大量未跟踪的分区,则可以批量运行MSCK REPAIR TABLE,以避免OOME(内存不足错误)。
alter partition
--修改分区
--更改分区文件存储格式
ALTER TABLE table_name PARTITION (dt='2008-08-09') SET FILEFORMAT file_format;
--更改分区位置
ALTER TABLE table_name PARTITION (dt='2008-08-09') SET LOCATION "new location";
4. Hive Show显示语法
Show相关的语句提供了一种查询Hive metastore的方法。可以帮助用户查询相关信息。
--1、显示所有数据库 SCHEMAS和DATABASES的用法 功能一样
show databases;
show schemas;
--2、显示当前数据库所有表/视图/物化视图/分区/索引
show tables;
SHOW TABLES [IN database_name]; --指定某个数据库
--3、显示当前数据库下所有视图
Show Views;
SHOW VIEWS 'test_*'; -- show all views that start with "test_"
SHOW VIEWS FROM test1; -- show views from database test1
SHOW VIEWS [IN/FROM database_name];
--4、显示当前数据库下所有物化视图
SHOW MATERIALIZED VIEWS [IN/FROM database_name];
--5、显示表分区信息,分区按字母顺序列出,不是分区表执行该语句会报错
show partitions table_name;
--6、显示表/分区的扩展信息
SHOW TABLE EXTENDED [IN|FROM database_name] LIKE table_name;
show table extended like student;
--7、显示表的属性信息
SHOW TBLPROPERTIES table_name;
show tblproperties student;
--8、显示表、视图的创建语句
SHOW CREATE TABLE ([db_name.]table_name|view_name);
show create table student;
--9、显示表中的所有列,包括分区列。
SHOW COLUMNS (FROM|IN) table_name [(FROM|IN) db_name];
show columns in student;
--10、显示当前支持的所有自定义和内置的函数
show functions;
--11、Describe desc
--查看表信息
desc extended table_name;
--查看表信息(格式化美观)
desc formatted table_name;
--查看数据库相关信息
describe database database_name;
二. DML(数据操纵语言)
1. Load加载数据
Load语法
在将数据load加载到表中时,Hive不会进行任何转换。
加载操作是将数据文件移动到与Hive表对应的位置的纯复制/移动操作。
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] [INPUTFORMAT 'inputformat' SERDE 'serde'] (3.0 or later)
filepath
filepath表示的待移动数据的路径,可以引用一个文件(在这种情况下,Hive将文件移动到表中),也可以是一个目录(在这种情况下,Hive将把该目录中的所有文件移动到表中)。
相对路径,例如:project/data1
绝对路径,例如:/user/hive/project/data1
具有schema的完整URI,例如:hdfs://namenode:9000/user/hive/project/data1
LOCAL
如果指定了LOCAL, load命令将在本地文件系统中查找文件路径。如果指定了相对路径,它将相对于用户的当前工作目录进行解释。用户也可以为本地文件指定完整的URI-例如:file:///user/hive/project/data1。
注意,如果对HiveServer2服务运行此命令。这里的本地文件系统指的是Hiveserver2服务所在机器的本地Linux文件系统,不是Hive客户端所在的本地文件系统。
如果没有指定LOCAL关键字,如果filepath指向的是一个完整的URI,hive会直接使用这个URI。 否则如果没有指定schema或者authority,Hive会使用在hadoop配置文件中定义的schema 和authority,即参数fs.default.name指定的(不出意外,都是HDFS)。
OVERWRITE
如果使用了OVERWRITE关键字,则目标表(或者分区)中的内容会被删除,然后再将 filepath 指向的文件/目录中的内容添加到表/分区中
2. Insert插入数据
2.1 insert + select
Hive中insert主要是结合select查询语句使用,将查询结果插入到表中,例如:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
2.2 multiple inserts多重插入
multiple inserts可以翻译成为多次插入,多重插入,核心是:一次扫描,多次插入。其功能也体现出来了就是减少扫描的次数。
2.3 dynamic partition insert动态分区插入
所谓动态分区插入指的是:分区的值是由后续的select查询语句的结果来动态确定的。根据查询结果自动分区。
配置参数
hive.exec.dynamic.partition
true
需要设置true为启用动态分区插入
hive.exec.dynamic.partition.mode
strict
在strict模式下,用户必须至少指定一个静态分区,以防用户意外覆盖所有分区;在nonstrict模式下,允许所有分区都是动态的
三. DQL(数据查询语言)
基础查询
1.1 语法树
[WITH CommonTableExpression (, CommonTableExpression)*]
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT [offset,] rows]
table_reference指示查询的输入。它可以是普通物理表,视图,join查询结果或子查询结果。
表名和列名不区分大小写
1.2 select_expr
每个select_expr表示您要检索的列。必须至少有一个 select_expr
1.3 ALL 、DISTINCT
ALL和DISTINCT选项指定是否应返回重复的行。如果没有给出这些选项,则默认值为ALL(返回所有匹配的行)。DISTINCT指定从结果集中删除重复的行。
1.4 WHERE
WHERE条件是一个布尔表达式。在WHERE表达式中,您可以使用Hive支持的任何函数和运算符,但聚合函数除外。
从Hive 0.13开始,WHERE子句支持某些类型的子查询。
1.5 分区查询、分区裁剪
通常,SELECT查询将扫描整个表(所谓的全表扫描)。如果使用PARTITIONED BY子句创建的分区表,则在查询时可以指定分区查询,减少全表扫描,也叫做分区裁剪。
所谓分区裁剪指的是:对分区表进行查询时,会检查WHERE子句或JOIN中的ON子句中是否存在对分区字段的过滤,如果存在,则仅访问查询符合条件的分区,即裁剪掉没必要访问的分区
1.6 GROUP BY
GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。需要注意的是,出现在GROUP BY中select_expr的字段:要么是GROUP BY分组的字段;要么是被聚合函数应用的字段。原因很简单,避免出现一个字段多个值的歧义。
分组字段出现select_expr中,一定没有歧义,因为就是基于该字段分组的,同一组中必相同;
被聚合函数应用的字段,也没歧义,因为聚合函数的本质就是多进一出,最终返回一个结果
1.7 HAVING
在SQL中增加HAVING子句原因是,WHERE关键字无法与聚合函数一起使用。
HAVING子句可以让我们筛选分组后的各组数据,并且可以在Having中使用聚合函数,因为此时where,group by已经执行结束,结果集已经确定
having与where的区别:
having是在分组后对数据进行过滤
where是在分组前对数据进行过滤
having后面可以使用聚合函数
where后面不可以使用聚合
1.8 LIMIT
LIMIT子句可用于约束SELECT语句返回的行数。
LIMIT接受一个或两个数字参数,这两个参数都必须是非负整数常量。
第一个参数指定要返回的第一行的偏移量(从 Hive 2.0.0开始),第二个参数指定要返回的最大行数。当给出单个参数时,它代表最大行数,并且偏移量默认为0。
1.9 查询执行顺序
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT [offset,] rows]
在查询过程中执行顺序:from>where>group(含聚合)>having>order>select。
所以聚合语句(sum,min,max,avg,count)要比having子句优先执行,而where子句在查询过程中执行优先级别优先于聚合语句(sum,min,max,avg,count)。
2. 高阶查询
2.1 SORT/ORDER/CLUSTER/DISTRIBUTE BY
ORDER BY
ORDER BY [ASC|DESC]
Hive SQL中的ORDER BY语法类似于SQL语言中的ORDER BY语法。会对输出的结果进行全局排序,因此底层使用MapReduce引擎执行的时候,只会有一个reducetask执行。也因此,如果输出的行数太大,会导致需要很长的时间才能完成全局排序。
默认排序顺序为升序(ASC),也可以指定为DESC降序。
在Hive 2.1.0和更高版本中,支持在“ order by”子句中为每个列指定null类型结果排序顺序。ASC顺序的默认空排序顺序为NULLS FIRST,而DESC顺序的默认空排序顺序为NULLS LAST
CLUSTER BY
SELECT expression… FROM table CLUSTER BY col_name;
Hive SQL中的CLUSTER BY语法可以指定根据后面的字段将数据分组,每组内再根据这个字段正序排序(不允许指定排序规则),概况起来就是:根据同一个字段,分且排序。
分组的规则hash散列。hash_func(col_name) % reduce task nums
DISTRIBUTE BY +SORT BY
如果说CLUSTER BY的功能是分且排序(同一个字段),那么DISTRIBUTE BY +SORT BY就相当于把cluster by的功能一分为二:DISTRIBUTE BY负责分,SORT BY负责分组内排序,并且可以是不同的字段。如果DISTRIBUTE BY +SORT BY的字段一样,可以得出下列结论:
CLUSTER BY=DISTRIBUTE BY +SORT BY(字段一样)
总结
order by会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
distribute by(字段)根据指定字段将数据分到不同的reducer,分发算法是hash散列。
Cluster by(字段) 除了具有Distribute by的功能外,还会对该字段进行排序。
如果distribute和sort的字段是同一个时,此时,cluster by = distribute by + sort by
2.2 Union联合查询
UNION用于将来自多个SELECT语句的结果合并为一个结果集。语法如下:
select_statement UNION [ALL | DISTINCT] select_statement UNION [ALL | DISTINCT] select_statement ...
使用DISTINCT关键字与只使用UNION默认值效果一样,都会删除重复行。
使用ALL关键字,不会删除重复行,结果集包括所有SELECT语句的匹配行(包括重复行)。
1.2.0之前的Hive版本仅支持UNION ALL,在这种情况下不会消除重复的行。
每个select_statement返回的列的数量和名称必须相同。
2.3 Common Table Expressions(CTE)
公用表表达式(CTE)是一个临时结果集,该结果集是从WITH子句中指定的简单查询派生而来的,该查询紧接在SELECT或INSERT关键字之前。
CTE仅在单个语句的执行范围内定义。一个或多个CTE可以在Hive SELECT,INSERT, CREATE
3. join连接查询
3.1 Hive join语法
在Hive中,当下版本3.1.2总共支持6种join语法。分别是:
inner join(内连接)、left join(左连接)、right join(右连接)、full outer join(全外连接)、left semi join(左半开连接)、cross join(交叉连接,也叫做笛卡尔乘积)。
3.2 规则树
join_table:
table_reference [INNER] 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
| table_reference CROSS JOIN table_reference [join_condition] (as of Hive 0.10)
table_reference:
table_factor
| join_table
table_factor:
tbl_name [alias]
| table_subquery alias
| ( table_references )
join_condition:
ON expression
table_reference:是join查询中使用的表名,也可以是子查询别名(查询结果当成表参与join)。
table_factor:与table_reference相同,是联接查询中使用的表名,也可以是子查询别名。
join_condition:join查询关联的条件, 如果在两个以上的表上需要连接,则使用AND关键字。
3.3 inner join
内连接是最常见的一种连接,它也被称为普通连接,而关系模型提出者E.FCodd(埃德加•科德)最早称之为自然连接。其中inner可以省略。inner join == join 等价于早期的连接语法。
内连接,只有进行连接的两个表中都存在与连接条件相匹配的数据才会被留下来。
3.4 left join
left join中文叫做是左外连接(Left Outer Jion)或者左连接,其中outer可以省略,left outer join是早期的写法。
left join的核心就在于left左。左指的是join关键字左边的表,简称左表。
通俗解释:join时以左表的全部数据为准,右边与之关联;左表数据全部返回,右表关联上的显示返回,关联不上的显示null返回
3.5 right join
right join中文叫做是右外连接(Right Outer Jion)或者右连接,其中outer可以省略。
right join的核心就在于Right右。右指的是join关键字右边的表,简称右表。
通俗解释:join时以右表的全部数据为准,左边与之关联;右表数据全部返回,左表关联上的显示返回,关联不上的显示null返回。
很明显,right join和left join之间很相似,重点在于以哪边为准,也就是一个方向的问题。
3.6 full outer join
full outer join 等价 full join ,中文叫做全外连接或者外连接。
包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行 在功能上,它等价于对这两个数据集合分别进行左外连接和右外连接,然后再使用消去重复行的操作将上述两个结果集合并为一个结果集。
3.7 left semi join
左半开连接(LEFT SEMI JOIN)会返回左边表的记录,前提是其记录对于右边的表满足ON语句中的判定条件。
从效果上来看有点像inner join之后只返回左表的结果。
3.8 cross join
交叉连接cross join,将会返回被连接的两个表的笛卡尔积,返回结果的行数等于两个表行数的乘积。对于大表来说,cross join慎用。
在SQL标准中定义的cross join就是无条件的inner join。返回两个表的笛卡尔积,无需指定关联键。
在HiveSQL语法中,cross join 后面可以跟where子句进行过滤,或者on条件过滤。
版权归原作者 煜筱子 所有, 如有侵权,请联系我们删除。