本文主要总结的是DDL和DML的相关语法,简单介绍了内部表、外部表、分区表、分桶表、序列化与反序列化的内容。希望能帮助到大家语法查询,也方便自己复习。任重道远,缓缓前行。
Hive 数据类型 | Java 数据类型 | 长度 | 例子 |
---|---|---|---|
TINYINT | byte | 1byte 有符号整数 | 20 |
SMALINT | short | 2byte 有符号整数 | 20 |
INT | int | 4byte 有符号整数 | 20 |
BIGINT | long | 8byte 有符号整数 | 20 |
BOOLEAN | boolean | 布尔类型,true 或者false | TRUE FALSE |
FLOAT | float | 单精度浮点数 | 3.14159 |
DOUBLE | double | 双精度浮点数 | 3.14159 |
STRING | string | 字符系列。可以指定字 符集。可以使用单引号或者双 引号。 | ‘ now is the time ’ “for all good men” |
TIMESTAMP | 时间类型 | ||
BINARY | 字节数组 |
因为字符串有日期格式的字符串可以自动转换为日期类型,所以时间类型的数据基本不会用。用的较多的是INT、BIGINT、DOUBLE和STRING。
数据类型 | 描述 | 语法示例 |
---|---|---|
STRUCT | 和 c 语言中的 struct 类似,都可以通过“点”符号访 问元素内容。例如,如果某个列的数据类型是 STRUCT{first STRING, last STRING},那么第 1 个元素可以通过字段.first 来 引用。 | struct()例如struct |
MAP | MAP 是一组键-值对元组集合,使用数组表示法可以 访问数据。例如,如果某个列的数据类型是 MAP,其中键->值对是’first’->’John’和’last’->’Doe’,那么可以 通过字段名[‘last’]获取最后一个元素 | map() 例如 map |
ARRAY | 数组是一组具有相同类型和名称的变量的集合。这些 变量称为数组的元素,每个数组元素都有一个编号,编号从 零开始。例如,数组值为[‘John’, ‘Doe’],那么第 2 个元素可以通过数组名[1]进行引用。 | Array()例如 array |
创建表的语句:
0: jdbc:hive2://hadoop100:10000> create table testCluster(name string, children map<string, int>, address struct<street:string, city:string>)
. . . . . . . . . . . . . . . .> row format delimited fields terminated by ','
. . . . . . . . . . . . . . . .> collection items terminated by '_'
. . . . . . . . . . . . . . . .> map keys terminated by':'
. . . . . . . . . . . . . . . .> lines terminated by '\n';
字段解释:
这种使用方法也不常用,不是重点。
1)隐式类型转换规则如下
(1)任何整数类型都可以隐式地转换为一个范围更广的类型,如 TINYINT 可以转换成
INT,INT 可以转换成 BIGINT。
(2)所有整数类型、FLOAT 和 STRING 类型都可以隐式地转换成 DOUBLE。
(3)TINYINT、SMALLINT、INT 都可以转换为 FLOAT。
(4)BOOLEAN 类型不可以转换为任何其它的类型。
2)可以使用 CAST 操作显示进行数据类型转换
例如 CAST(‘1’ AS INT)将把字符串’1’ 转换成整数 1;如果强制类型转换失败,如执行 CAST(‘X’ AS INT),表达式返回空值 NULL。
建表语句:
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[MANAGEDLOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
LOCATION 是指定外部表的存储路径,MANAGEDLOCATION 是指定管理表的存储路径(hive 4.0.0 才支持),官方建议默认就行,让所有的表都在一个根目录下。
create database if not exists db_hive comment "2021-10-21dbtest" location '/db_hive';
上述语句很好理解,执行完之后可以在HDFS上看到相应的目录已经建立了,然后再元数据中DBS已经有新建表的信息。
desc database db_hive;
查询结果与元数据中那个表格一样(见上图)
切换数据库:
use db_hive
怎么查看当前在使用哪个数据库呢?
select current_database();
alter database db_hive set dbproperties('createtime'='20001021');
通用语法:
如果数据库下有表,则不允许删除;如果要删除,后面加 CASCADE。RESTRICT 为默认值,默认不允许删除。
如果数据库下有表,则不允许删除;如果要删除,后面加 CASCADE。RESTRICT 为默认值,默认不允许删除。举个例子:
drop database if exists db_hive2;
(1)首先介绍一下外部表和内部表(管理表)的区别和联系:
讲到外部表,那么日志场景用的会很多。通常服务器上会每时每刻产生日志,而这些日志会实时的发送到消息中间件,再通过 flume 等工具直接存储到 hdfs 上了,并没有 hive 什么事。但 hive 能把 hdfs 的文件映射成一张表,那么这种表就是外部表。外部表一般用的比较多。
(2)接下来介绍一下简单介绍一下分区表和分桶表:
1)为啥需要引入分区表?
引入分区表主要是为了更快的查询。从文件上来看,分区是 hdfs 的一个目录,可以指定多个分区,这样在插入数据的时候,hdfs 会产生多个目录。如果按照分区组织数据,查询数据的时候指定分区,底层直接返回该分区的数据,就会快很多。比如按照日期组织日志数据,就可以较快的查询出每天的日志。
2)为啥需要引入分桶表?
主要原因有两点:一是提高 join 查询的效率;二是利于抽样。从文件的角度来看,分桶表是根据数据的hash值,把数据存为不同的文件,也就是说向分桶表中插入数据的时候必然要执行一次MapReduce, 对于两个数据表,某两列都做了桶划分,可以使用map端的join高效的完成join(桶和桶之间的join,大大减少了join的次数)。对于map端连接的情况,两个表以相同方式划分桶。处理左边表内某个桶的 mapper 知道右边表内相匹配的行在对应的桶内。因此,mapper只需要获取那个桶 (这只是右边表内存储数据的一小部分)即可进行连接。抽样也是如此,直接对每个桶进行抽样。
上面两个问题就可以建立对分区表和分桶表的简单印象,具体对比如下:
从表创建而言,被 external 关键字修饰的就是外部表(external table),未被 external 修饰的表是管理表(managed table),分区表使用partitioned by 子句指定,分桶表由clustered by 子句指定。举个例子:
(1)创建管理表:
create table if not exists student( id int, name string)
row format delimited fields terminated by '\t'
stored as textfile
location '/user/hive/warehouse/student';
(2)创建外部表(external关键字):
CREATE EXTERNAL TABLE IF NOT EXISTS my_hive (id INT,name STRING)
row format delimited
fields terminated by ','
LINES TERMINATED BY '\n'
stored as textfile
location '/user/hdfs/source/hive_test' ;
(3)分区表使用partitioned by 子句指定,以指定字段为伪列,需要指定字段类型;
create table if not exists par_test(
name string,
nid int,
phone string,
ntime date
)
partitioned by (year string,month string)
row format delimited
fields terminated by "|"
lines terminated by "\n"
stored as textfile;
(4)分桶表由clustered by 子句指定,指定字段为真实字段,需要指定桶的个数,插入数据的时候,会把 sex 取 hash,并对2取模,放到2个桶里面去。
create table bck_student(
id int,
name string,
sex string,
age int,
department string
)
clustered by(sex) into 2 buckets
row format delimited
fields terminated by ",";
上面四个小实例只是为了方便理解,详细的建表语句:
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]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]
详细的解释:
(1)CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常; 用户可以用 IF NOT EXISTS 选项来忽略这个异常。
(2)EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时可以指定一个指向实 际数据的路径(LOCATION),在删除表的时候,内部表的元数据和数据会被一起删除,而外 部表只删除元数据,不删除数据。
(3)COMMENT:为表和列添加注释。
(4)PARTITIONED BY 创建分区表
(5)CLUSTERED BY 创建分桶表
(6)SORTED BY 不常用,对桶中的一个或多个列另外排序
(7)ROW FORMAT:用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需 要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive 通过 SerDe 确定表 的具体的列的数据。SerDe 是 Serialize/Deserilize 的简称, hive 使用 Serde 进行行对象的序列与反序列化。
(8)STORED AS 指定存储文件类型 常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
(9)LOCATION :指定表在 HDFS 上的存储位置。
(10)AS:后跟查询语句,根据查询结果创建表。
(11)LIKE 允许用户复制现有的表结构,但是不复制数据。
(5)根据已有的表建表:
以目标查询结果来建表:
CREATE TABLE new_key_value_store
AS
SELECT (key % 1024) new_key, concat(key, value) key_value_pair
FROM key_value_store
SORT BY new_key, key_value_pair;
以存在的表创建表:
CREATE TABLE empty_key_value_store
LIKE key_value_store;
(6)定义数据倾斜和字段值:
对于一个或多个列具有倾斜值的表,可以使用该特性提高性能。通过指定的值经常出现(数据倾斜),hive将这些分割成单独的文件(或目录的列表用桶装)。自动查询期间,考虑到这一事实,以便它可以跳过或者包含整个文件查询计算。
CREATE TABLE list_bucket_multiple (col1 STRING, col2 int, col3 STRING)
SKEWED BY (col1, col2) ON (('s1',1), ('s3',3), ('s13',13), ('s78',78));
(7)根据指定的序列化与反序列化建表:
表数据行的序列化和反序列化大概过程如下:
在Hive的HQL语句中,select时将会用到序列化操作, insert 时会用到反序列化操作,下面是具体的操作过程。Hive创建表时,通过定义的SerDe或使用Hive内置的SerDe类型指定数据的序列化和反序列化方式。SerDe包括的内置类型:Avro、ORC、RegEx、Thrift、Parquet、CSV和JsonSerDe。这部分的内容有点像hadoop中写mapreduce程序中写序列化库的内容。
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;
(8)创建临时表:临时表,表示在当前用户会话内才有效,数据全都存在用户临时目录中,一旦退出对话,表和数据都会被清除掉
CREATE TEMPORARY TABLE list_bucket_multiple (
col1 STRING,
col2 int,
col3 STRING
);
(1)修改表名
alter table test rename to testRename;
(2)修改表属性
ALTER TABLE table_name SET TBLPROPERTIES ('comment' = new_comment);
(3)增加序列化与反序列化
ALTER TABLE apachelog SET SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES (
"input.regex" = "bduid\\[(.*)\\]uid\\[(\\d+)\\]"
)
(4)增加、修改和删除表分区
增加表分区:
ALTER TABLE page_view 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';
删除表分区:
ALTER TABLE page_view DROP PARTITION (dt='2008-08-08', country='us') location '/path/to/us/part080808'
PARTITION (dt='2008-08-09', country='us') location '/path/to/us/part080809';
查看分区:
show partitions dept_partition;
查看分区表结构:
desc formatted dept_partition;
(5)修改字段名
-- 创建一个表
CREATE TABLE test_change (a int, b int, c int);
-- 修改列 a 的名字为 a1
ALTER TABLE test_change CHANGE a a1 INT;
-- 修改列 a1 的名字为 a2,类型变成 STRING,并放在 字段 b 后面
ALTER TABLE test_change CHANGE a1 a2 STRING AFTER b;
-- 修改后的结构为: b int, a2 string, c int.
-- 修改列 c 的名字为 c1,并放在第一列
ALTER TABLE test_change CHANGE c c1 INT FIRST;
-- 修改后的结构为 c1 int, b int, a2 string.
-- 增加一列 a1
ALTER TABLE test_change CHANGE a1 a1 INT COMMENT 'this is column a1';
DROP TABLE [IF EXISTS] table_name [PURGE]
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)
(1) filepath 可以是绝对路径,也可以是相对路径,也可以是 hdfs 路径;
(2) 如果指定了 LOCAL,则会从本地加载文件到目标地址;如果没有指定,则会把 filepath 的文件 移动 到目标表里去;
(3) 如果指定了 overwrite,则会先把目标表的内容清空,再把数据添加进去。如果没有指定,则会把数据添加到表中;
(4) 如果是分区表,则需要指定一个分区
(1)insert语法
-- insert overwrite
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]]
select_statement1 FROM from_statement;
-- insert into
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)]
select_statement1 FROM from_statement;
上面挺好理解的,也存在multi insert:multi insert 可以将一张表的数据,写入到多张表中去。hive 只会读取一次表数据。
FROM src
INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100
INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200
INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300;
(1)Insert导出
INSERT OVERWRITE [LOCAL] DIRECTORY directory1
[ROW FORMAT row_format] [STORED AS file_format] (Note: Only available starting with Hive 0.11.0)
SELECT ... FROM ...
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/reg_3' SELECT a.* FROM events a;
(2)hadoop命令导出
dfs -get /user/hive/warehouse/student/student.txt
/opt/module/data/export/student3.txt;
(3)hive shell导出:查询结果重定向到本地文件中
bin/hive -e 'select * from default.student;' >
/opt/module/hive/data/export/student4.txt;
(4)export导出
export table default.student to 目录
export导出后可以直接导入,因为其自动生成了一个元数据目录
import table student2
from '/user/hive/warehouse/export/student';
数据查询会单出一篇文章来复习,这篇文章偏工具性一点,忘了就来查。贴个官网连接,写的详细又明白,不过是英文的。