建表DDL语句
1.语法树大全
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db name.]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,..)]
[lNT O num_buckets BUCKETSI]
[ROW FORMAT DELIMITED|SERDE serde _name WITH SERDEPROPERTiES (property_name=property_value...)]
[STORED AS file format]
--用来指定文件的格式。
如果不写,Hive默认会使用TEXTFILE作为表的存储文件格式,就是我们通常说的文本文件,其中的字段默认是通过'\001'进行分割的。在TEXTFILE格式的文件中,如果想要改变分隔符类型(不使用'\001'),可以在创建表的时候通过ROW FORMAT子句来指定。
什么情况下才需要写:某些文件格式的压缩性能、存储性能等比TEXTFILE更好,可能需要改变存储格式以使用这些更高级的存储格式。
需要注意的是,当你建表的时候指定了文件格式,那么在上数据文件的时候格式必须对应,否则报错;还有一种情况是数据文件格式是默认格式,但是建表的时候指定的文件格式是其他,这个时候就得先把数据文件加载到普通的文本表中,然后再用insert into ... select...的方式插入数据,数据加载模块有详细的案例说明。
[LOCATlON hdfs_path]
--当你在`CREATE TABLE`语句中使用`LOCATION`子句指定HDFS的路径,如果这个路径不存在,Hive会在执行这个`CREATE TABLE`语句时创建这个路径。
[TBLPROPERTES (property_name=property_value...)];
--用于给表设置属性。举例;TBLPROPERTIES ('creator'='John', 'created_at'='2022-01-01');在这个例子中,“creator” 和 “created_at” 是通过 `TBLPROPERTIES` 设置的表属性。这些属性可以被用于追踪表的元信息,例如了解谁创建了表,表是何时被创建的等。表属性的值只能是字符串,并且可以通过 `ALTER TABLE` 语句来修改。如果设置的属性不存在,Hive 会自动添加它。如果属性已存在,Hive 会更新它的值。
- 红色字体是建表语法的关键字,用于指定某些功能。
- []中括号的语法表示可选。
- |表示使用的时候,左右语法二选一。
- 建表语句中的语法顺序要和上述语法规则保持一致。
- 说明:TEMPORARY(temporary,指临时表。它的生命周期仅仅在当前的Hive会话中,当会话关闭时(Hive客户端连接被关闭或者退出),临时表就会自动地被删除。临时表通常用于存储一些中间结果,对于一些复杂的查询操作,可以首先将中间结果生成为临时表,然后基于临时表进行后续的查询,可以提高查询的效率。)EXTERNAL(外部表)IF NOT EXISTS(它是一个条件判断语句。如果使用"IF NOT EXISTS",那么在表或数据库已经存在的情况下,该CREATE语句就不会执行,也就是说它不会改变原有的表或数据库,也不会报错。而如果不使用"IF NOT EXISTS",在表或数据库已经存在的情况下,尝试再次创建会导致错误。
2.建表语法使用案例大全
2-1 和数据文件格式相关的案例
hive常用的数据文件格式说明(必读):
hive中常用的数据文件总体可以分为两大类,第一大类是文本类型的文件(数据以文本形式存储,字段之间有明确的分隔符的文件,可以用hive默认的serde,使用row format delmited 语句来建表,以上语句只适用于有特定分隔符的文本类型的文件),第二大类是不可以用hive默认的serde(但是Hive提供了用来处理这些格式的内置或者自定义SerDe)的文件类型。
第一大类包括:1)TEXTFILE:是Hive默认的文件格式。当没特殊声明文件格式时,是按照文本文件处理。它表示数据存储为文本格式,可以是.txt文件,也可以是.csv文件,或者其他任何纯文本格式的文件。每行表示一条记录,每条记录中的字段通过某种分隔符(比如逗号或者制表符等)进行分隔。TEXTFILE更像是Hive中的一个概念,用来表达数据以文本形式存储,而.txt等是具体的文件格式。在Hive中处理.txt文件时,会将其当成TEXTFILE进行处理。
第二大类(不能用Hive 默认的SerDe解析,但是Hive提供了用来处理这些格式的自定义SerDe):1)SEQUENCEFILE:二进制序列文件;2) RCFILE:Record Columnar File,一种面向列的文件格式;3)ORCFILE:一种新的列式存储格式;4)PARQUET:开源列式存储格式等。以上这些文件格式都有自己的数据存储特点,并不简单的依靠分隔符来处理数据,所以不会使用row format delmited 语句,而是用自己对应的serde。
情况1 文件格式为TEXTFILE(txt,csv等文本格式)
可以使用默认serde;需要用ROW FORMAT DELIMITED语句来指定数据分隔符;不需要STORED AS 来指定文件类型(也可以写,不影响)
案例:有一份儿txt文件,字段之间用 ',' 进行分隔,hive中如何建表,表名为 table1?
CREATE TABLE table1 ( name STRING, age INT, city STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;
--STORED AS TEXTFILE可以省略
情况2 文件格式为SEQUENCEFILE,RCFILE,ORCFILE,PARQUET
需要使用各文件格式自定义的serde;需要STORED AS 来指定文件类型。
这几种文件格式情况下,hive在写建表语句的时候,不使用row format delimited语句,他们需要用各自对应的serde来进行建表
2-2 和 location 语句相关的案例
概括起来就是一句话,你创建的时候把数据库/数据表的文件定义在了什么文件夹下,那么数据库/数据表对应的文件就会放在什么文件夹下。
需要了解的问题:hive中,在建表的时候用LOCATlON语句把表的存储位置放在了不属于这个数据库的其他路径下,那么这个表还属于当前数据库吗?
回答:当你使用LOCATION语句创建表时,你其实是在告诉Hive不要将表的数据存放在默认的HDFS目录(通常是/user/hive/warehouse)下,而是存放在你指定的其他HDFS目录中。但是这并不会改变表所属的数据库。
你可以通过在Hive中运行`use database_name;`来切换当前数据库,然后运行`show tables;`来查看该数据库下的所有表,其中就会包括你刚才创建的那个表,即使它的数据存放在了其他的HDFS路径下。
情况1:在数据库 test1 下创建表 ceshi_1 ,不指定路径
CREATE TABLE ceshi_1 (grade STRING comment '年级',class STRING,name STRING,Chinese INT,math INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--文件存储路径:/user/hive/warehouse/test1.db/ceshi_1
--hdfs会自动在test1.db的下面创建一个和新建表名字一样的子文件夹,这个表相关的文件就会被放到下面
情况2:在数据库 test1 下创建表 ceshi_2 ,指定路径 /user/hive/warehouse/test1.db/ceshi_2
CREATE TABLE ceshi_2 (grade STRING comment '年级',class STRING,name STRING,Chinese INT,math INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/user/hive/warehouse/test1.db/ceshi_2';
--文件存储路径:/user/hive/warehouse/test1.db/ceshi_2
--hdfs会自动在test1的下面创建一个和路径下文件名字一样的子文件夹.如果这个路径还不存在,hive会自动创建它
情况3:在数据库 test1 下创建表 ceshi_3 ,指定路径 /user/hive/warehouse/test1.db/dsb
CREATE TABLE ceshi_3 (grade STRING comment '年级',class STRING,name STRING,Chinese INT,math INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/user/hive/warehouse/test1.db/dsb';
--文件存储路径:/user/hive/warehouse/test1.db/dsb
--hdfs会自动在test1的下面创建一个和路径下文件名字一样的子文件夹.如果这个路径还不存在,hive会自动创建它。种情况告诉我们,表文件最终存储的那个文件夹名字不一定非得和表自身的名字一样,也可以去自定义,当然,最好还是保持一致。
情况4:在数据库 test1 下创建表 ceshi_4 ,指定路径 /user/hive/warehouse/test1.db
CREATE TABLE ceshi_4 (grade STRING comment '年级',class STRING,name STRING,Chinese INT,math INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/user/hive/warehouse/test1.db';
--文件存储路径:/user/hive/warehouse/test1.db
--此时,hdfs不会和情况3一样再创建一个新的文件夹,而是会把这个表对应的文件直接存储在test1.db文件夹下面
情况5:在数据库 test1 下创建表 ceshi_5 ,指定路径 /user/warehouse1/test3/ceshi_5
CREATE TABLE ceshi_5 (grade STRING comment '年级',class STRING,name STRING,Chinese INT,math INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/user/warehouse1/test3/ceshi_5';
--文件存储路径: /user/warehouse1/test3/ceshi_5
--如果这个路径还不存在,hive会自动创建它
3. 复杂数据类型字段
建表时,复杂数据类型类型的字段需要用到分隔符
3-1 创建数组(Array) 类型数据
CREATE TABLE table_name (int_array ARRAY<int>);
其中,ARRAY<int>表示int_array字段是一个整型数组。您可以更改 <INT> 为任意hive支持的其他数据类型,复杂数据类型也是可以的,但是因为这种嵌套的复杂数据类型数据难以管理,所以一般不会进行应用。
情况1:数组内的元素为简单数据类型
数据文件内格式如下,建表语句如下:
CREATE TABLE test_array ( id INT, numbers ARRAY<INT>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
--这段代码表达的含义是: 创建一个名为 test_array 的表,该表具有两个字段,id和numbers。其中,id是整数类型,而numbers是一个数组。在这个数组中,每个元素都是整数类型。 行格式被定义为分隔的,字段之间是用制表符('\t')分隔的,数组内的元素之间则是用逗号(',')分隔的。
情况2:数组内的各元素为复杂数据类型
数据文件内格式如下,建表语句如下:其中第3、4列就可以看作是元素为复杂数据类型的数组。但是在建表的时候通常把第3、4列作为结构体和映射去创建字段,因为数组<映射>这种复杂数据类型嵌套的字段太难管理,一般不会使用的。
CREATE TABLE ceshi_6 (id int ,int_array ARRAY<int>,person_info STRUCT<name:STRING, grade:STRING>,string_int_map MAP<STRING, STRING>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';
建表成功之后,查询结果如下:
3-2 创建映射(Map)类型数据
CREATE TABLE tablename (string_int_map MAP<STRING, INT>);
--其中,MAP<STRING, INT>表示string_int_map字段是一个由字符串映射到整数的映射,字符串为此映射的键,整数为值。
情况1:数据文件中,每一行只包含一个键值对
数据格式如下:
CREATE TABLE ceshi_6 (string_int_map MAP<STRING, STRING>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
MAP KEYS TERMINATED BY ':';
情况2:数据文件中,每一行包含多个键值对(这种情况下,不需要把映射类型的数据看作是各元素为映射类型的数组,映射是允许存在多组键值对的)
数据格式如下,第四列
CREATE TABLE ceshi_6 (id int ,int_array ARRAY<int>,person_info STRUCT<name:STRING, grade:STRING>,string_int_map MAP<STRING, STRING>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';
建表成功之后,查询结果如下:
3-3 创建结构体(Struct)类型数据
CREATE TABLE tablename (person_info STRUCT<name:STRING, age:INT>);
--其中,STRUCT<name:STRING, age:INT>表示该person_info字段是一个结构体,该结构体有两个字段:字符串类型的name字段和整数类型的age字段。
案例:
假设我们有这样一条记录:
john,25
CREATE TABLE test_struct ( id INT, details STRUCT<name: STRING, age: INT> )
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
--这段代码的意义是: 创建一个名为 test_struct 的表,该表有两个字段 - id和details。其中,id 是整数类型,details 是一个结构体字段,结构体内包含 name 和 age 两个字段,name 是字符串类型,age 是整数类型。 行格式被定义为分隔的,字段之间用制表符 ('\t') 分隔,结构体中的项用逗号 (',') 分隔。结构体中的键值之间的分隔符是不能被自定义的,默认是'\001'
对于 test_struct 表,这条记录将表示为:
{ "name" : "john", "age" : 25 }
4.SerDe相关语法
涉及到的语法树
4-1 文件格式为文本类型
CREATE TABLE my_table (name STRING, age INT, address STRING)
ROW FORMAT DELIMITED --用于定义字段、集合项、映射键等的分隔符
FIELDS TERMINATED BY ','; --定义字段分隔符
--如果使用的是默认分隔符,完全可以省略`ROW FORMAT DELIMITED`以及之后的部分。
-哪些文件格式是可以使用hive默认serde的?
TEXTFILE:文本文件,是Hive默认的文件格式。它表示数据存储为文本格式,可以是.txt文件,也可以是.csv文件,或者其他任何纯文本格式的文件。TEXTFILE更像是Hive中的一个概念,用来表达数据以文本形式存储,而.txt是具体的文件格式。在Hive中处理.txt文件时,会将其当成TEXTFILE进行处理。 等当没特殊声明文件格式时,是按照文本文件处理。需要手动设置字段的分隔符、数组元素分隔符等。
4-2 文件格式为非文本类型文件
此时,就不能用hive默认的SerDe来进行相关的建表了,需要我们使用文件对应的其他SerDe。
例子:我有一个键值对格式文本文件,请问该如何建表才能保证数据可以成功映?
键值对格式文本文件信息如下:
name=John Doe
age=30
city=New
York job=Engineer
建表语句如下:
CREATE TABLE my_table (key STRING, value STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
--需要指定对应的SerDe名称
WITH SERDEPROPERTIES ("field.delim" = "=");
--在这个示例中,`field.delim`设为"=",这表示在数据中的每一行,字段之间是由("=")分隔的。 注意,不同的SerDe可能有支持不同的属性,并且同一属性的含义可能会有所不同。在使用SerDe属性之前,最好查阅具体的SerDe文档以了解它们的具体含义和用法。
4-3 如何查看表的serde
DESCRIBE FORMATTED tablename
例子:DESCRIBE FORMATTED my_table;
--这个命令将会返回关于你的表的各种信息,包括SerDe库的名称,以及SerDe所使用的属性。你可以在结果中查找`SerDe Library`和`SerDe Properties`,这两个部分会告诉你表使用的是哪个SerDe以及SerDe的配置。
5.分区表
CREATE TABLE table_name (column1 data_type, column2 data_type)
PARTITIONED BY (partition1 data_type, partition2 data_type,….);
--具体的建表语句,需要根据数据文件类型去灵活使用,建议直接看加载数据板块。注意:分区字段不能是表中已经存在的字段,因为分区字段最终也会以虚拟字段的形式显示在表结构上。
6.分桶表
CREATE [EXTERNAL] TABLE [db_name.]table_name
[(col_name data_type, ...)]
CLUSTERED BY (col_name)
INTO N BUCKETS;
--其中CLUSTERED BY (col_name)表示根据哪个字段进行分;INTO N BUCKETS表示分为几桶(也就是几个部分)。需要注意的是,分桶的字段必须是表中已经存在的字段。
--在创建分桶表时,还可以指定分桶内的数据排序规则,例如:
CLUSTERED BY(state) sorted by (cases desc) INTO 5 BUCKETS;
--根据state州分为5桶 每个桶内根据cases确诊病例数倒序排序
数据加载
1.普通表加载
(说明:在hive中,先创建了一个表,用hadoop fs -put和load data命令把本地文件上传到了表对应的hdfs路径当中去,效果是一样的吗?
答:是的,从数据能否被查询的角度来看,用`hadoop fs -put`命令把本地文件上传到Hive表对应的HDFS文件夹,与用Hive的`LOAD DATA`命令加载本地文件到Hive表,效果是一样的。都是使得Hive能读取到这份数据。
但是实施上他们还是有一些不同:
1) `hadoop fs -put`是HDFS的命令,用于将本地的文件上传到HDFS的任意路径,这个路径并不一定与Hive表关联。而`LOAD DATA`是Hive的命令,用于将数据加载到Hive表,无论是本地文件还是HDFS的文件。
2.)`hadoop fs -put`命令上传数据后,如果要使得Hive能识别这份数据,需要该路径被Hive表关联,比如创建一个新的Hive表时指定`LOCATION`为该路径,或者该路径就是已经存在的Hive表的路径。而`LOAD DATA`在加载数据的同时就已经关联了Hive表,不需要额外操作。
3) `hadoop fs -put`命令只是简单地将本地文件复制到HDFS的路径,不会对数据做任何处理。`LOAD DATA`命令同样不会对数据处理,复制或移动的数据保持原样,但`LOAD DATA`运行时,可以选择是否覆盖目标表原有数据。
所以他们确实有一些不同,使用哪种方式取决于你的具体需求。在绝大多数情况下,我们都会选择使用`LOAD DATA`命令,因为这直观,容易操作。)
情况1
从windows系统(本地系统)加载到hdfs表对应的文件夹下面。
方式1:第一步:使用 "hadoop fs -put" 命令将文件上传到HDFS
命令:hadoop fs -put /path/to/localfile /path/to/hdfs
--这里 "/path/to/localfile" 是你要上传文件在Windows中的根路径(完整 的),"/path/to/hdfs" 是你想要把文件存放在HDFS中的路径。
例子:hadoop fs -put C:\Users\lenovo\Desktop\user1.txt /user/hive/warehouse/dsb.db/t_user_1/
--这里,C:\Users\lenovo\Desktop\user1.txt 是你要上传的文本文件的根路径,而 /user/hive/warehouse/dsb.db/t_user_1/ 是你想在HDFS中放置文件的路径。
第二步:使用 "LOAD DATA" 命令将数据加载到Hive表中。
命令:LOAD DATA INPATH '/path/to/hdfs' 【或者 OVERWRITE INTO】 INTO TABLE your_table_name;
--这里,"/path/to/hdfs" 是第一步中你上传文件的HDFS路径,"your_table_name" 是你的Hive表名。【OVERWRITE INTO】:可选,如果加上表示要覆盖掉hive中已有的数据。
例子:LOAD DATA INPATH '/user/hadoop/data/myfile.txt' INTO TABLE mytable
方式2:使用 "LOAD DATA LOCAL" 命令
命令:LOAD DATA LOCAL INPATH 'C:/path/to/myfile.txt' INTO【或者 OVERWRITE INTO】 TABLE your_table_name;
--这里, 'C:/path/to/myfile.txt' 是你本地文件所在的路径,"your_table_name" 是你的Hive表名。【OVERWRITE INTO】:可选,如果加上表示要覆盖掉hive中已有的数据。
例子1:一次加载一个文件
LOAD DATA LOCAL INPATH 'C:\Users\lenovo\Desktop\源文件\人员汇总.txt' INTO【或者 OVERWRITE INTO】 TABLE ceshi_8;
例子2:一次加载一个文件夹内所有的文件
LOAD DATA LOCAL INPATH 'C:\Users\lenovo\Desktop\源文件\复杂数据类型\*' INTO TABLE ceshi_8;
LOAD DATA LOCAL INPATH 'C:\Users\lenovo\Desktop\源文件\复杂数据类型' INTO TABLE ceshi_8;
--把 '复杂数据类型' 文件夹里面所有的数据一次性加载到了hdfs对应的路径中。两种方式都可以。
--在用LOAD DATA 移动整个文件夹里面所有的文件时,如果这个文件夹在联想系统本地,那么在写路径的时候,结尾必须用 '文件名' 或者 '文件名/*' ,不能用 '文件名/',如果文件夹在hdfs系统上,那以上3种写法都可以。
方式3:使用 "hadoop fs -put" 命令将文件上传到HDFS表对应的路径下
命令:hadoop fs -put /path/to/local_file /path/to/hdfs
--这里 "/path/to/local_file" 是你要上传文件在Windows中的根路径(完整 的),"/path/to/hdfs" 是你想要把文件存放在HDFS目标表的路径。注意,两个路径中间必须打一个空格,否则会显示路径不正确
例子1:一次加载一个文件
hadoop fs -put C:\Users\lenovo\Desktop\user1.txt /user/hive/warehouse/dsb.db/t_user_1/
--这里,C:\Users\lenovo\Desktop\user1.txt 是你要上传的文本文件的根路径,而 /user/hive/warehouse/dsb.db/t_user_1/ 是你想在HDFS中放置文件的路径。
例子2:一次加载一个文件夹内所有的文件
HDFS命令不直接支持一次性移动多个文件,但是可以移动一个文件夹中的所有文件:
hadoop fs -put C:\Users\lenovo\Desktop\* /user/hive/warehouse/dsb.db/t_user_1/
--上面的命令将把 `C:\Users\lenovo\Desktop\` 文件夹中的所有内容(包括文件和子文件夹)移动到 `/user/hive/warehouse/dsb.db/t_user_1/`。注意:被移动的文件夹一方最后必须要以 '文件夹/*' 结尾,不能以文件夹名称结尾,否则就会把文件夹本身也给移动过去。hdfs命令和load data命令的区别在于,hdfs命令可以移动文件夹本身,但是load data命令只能移动文件夹内的文件。
情况2
将hdfs系统的文件加载到hdfs表对应的文件夹下面。
方式1:
命令:LOAD DATA INPATH '/path/to/hdfs' INTO【或者 OVERWRITE INTO】 TABLE your_table_name;
--这里,"/path/to/hdfs" 是第一步中你上传文件的HDFS路径,"your_table_name" 是你的Hive表名。【OVERWRITE INTO】:可选,如果加上表示要覆盖掉hive中已有的数据。
--这种情况下,文件将从原来的位置移动到Hive表在HDFS中的位置。
例子1:一次加载一个文件
LOAD DATA INPATH '/user/hive/warehouse/test1.db/ceshi_8/人员汇总.txt' INTO TABLE ceshi_9;
例子2:一次加载一个文件夹内所有的文件
LOAD DATA INPATH '/user/hive/warehouse/test1.db/ceshi_8/' INTO TABLE ceshi_9;
LOAD DATA INPATH '/user/hive/warehouse/test1.db/ceshi_8' INTO TABLE ceshi_9;
LOAD DATA INPATH '/user/hive/warehouse/test1.db/ceshi_8/*' INTO TABLE ceshi_9;
--把 'ceshi_8' 文件夹里面所有的数据一次性加载到了hdfs对应表的路径中。以上3种写法都一样。
--在用LOAD DATA 移动整个文件夹里面所有的文件时,如果这个文件夹在联想系统本地,那么在写路径的时候,结尾必须用 '文件名 或者 '文件名/*' ,不能用 '文件名/',如果文件夹在hdfs系统上,那以上3种写法都可以。
方式2:
例子:hadoop fs -mv /user/hadoop/dir1/myfile.txt /user/hadoop/dir2/
--上述命令会将`/user/hadoop/dir1/myfile.txt`文件移动到`/user/hadoop/dir2/`目录中。
例子1:一次加载一个文件
hadoop fs -mv /user/hive/warehouse/test1.db/ceshi_8/人员汇总.txt /user/hive/warehouse/test1.db/ceshi_9
hadoop fs -mv /user/hive/warehouse/test1.db/ceshi_8/人员汇总.txt /user/hive/warehouse/test1.db/ceshi_9/
--两种写法一样。都是把人员汇总.txt 移动到ceshi_9 文件夹中
例子2:一次加载一个文件夹内所有的文件
hadoop fs -mv /user/hive/warehouse/test1.db/ceshi_8/* /user/hive/warehouse/test1.db/ceshi_9/
--被移动的文件夹一方最后必须要以 '文件夹/*' 结尾,不能以文件夹名称结尾,否则就会把文件夹本身也给移动过去。hdfs命令和load data命令的区别在于,hdfs命令可以移动文件夹本身,但是load data命令只能移动文件夹内的文件。
2.分区表加载
情况1 只有1份儿数据文件(一份儿文件里面包含多个分区的数据)
案例:
我有一个普通的hive表 putong_1,里面包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分区表,分区表的字段包括"grade,class, name, Chinese, math"5个字段,以'grade'字段进行分区,请问建表语句、静态分区加载数据、动态分区加载数据如何进行?
第一步 :建分区表
方式1:CREATE TABLE fenqu_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--分区字段'nianji'的名称可以自己随便取,不能和表中的字段一致
方式2:CREATE TABLE fenqu_1 (class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
方式3:CREATE TABLE fenqu_1 (class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (grade STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--用表中的字段作为分区字段
注意:建表用的方式几,加载数据的时候就得用方式几
第二步:在hdfs上创建一个未分区的表,将文件加载上去,表名 putong_1
第三步:加载数据,有两种方式,一种是静态分区加载,一种是动态分区加载
静态分区加载:
注意:如果一份数据文件包含了多个分区的数据,直接使用 `LOAD DATA`语句加载到分 区表可能无法达到你的预期效果,因为`LOAD DATA` 是简单地将文件移动到某个分区下,无法 根据文件内容的分区字段来应用到多个分区。
1)将本地文件加载到hdfs的未分区表 putong_1 中
2)用insert 命令插入数据
方式1:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级') SELECT grade, class, name, Chinese, math FROM putong_1 WHERE grade='1年级';
方式2:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级') SELECT class, name, Chinese, math FROM putong_1 WHERE grade='1年级';
方式3:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (grade='1年级') SELECT class, name, Chinese, math FROM putong_1 WHERE grade='1年级';
--INSERT OVERWRITE:那么会先清空表中的数据(或者指定分区中的数据),再加载新的数据;INSERT INTO:会将新数据添加到表现有的数据中,而不是覆盖现有数据。
--在上述语法中,`INSERT OVERWRITE TABLE` 是插入或覆盖指定分区表的命令,`fenqu_1` 是分区表的名称,`(nianji='1年级')` 是指定的分区,select后面的字段是要从 `putong_1'源表 中抽取的字段。
动态分区加载
1) 首先,开启Hive的动态分区设置:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
2) 然后进行动态分区加载数据:
方式1:INSERT OVERWRITE(或者INSERT INTO) TABLE fenqu_1 PARTITION(nianji) SELECT grade, class, name, Chinese, math, grade as nianji FROM putong_1;
--在select语句中,grade相当于是被查询了两次,第一次是当做插入的字段,第二次是当做分区的字段,分区的字段必须放在最后面
方式2:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(nianji) SELECT class, name, Chinese, math,grade FROM putong_1;
方式3:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(grade) SELECT class, name, Chinese, math,grade FROM putong_1;
--动态分区加载注意事项:(1)分区字段的名字可以不和数据源表上的字段一致;PARTITION后括号内的字段是作为表的分区字段,而SELECT后的字段是指定数据来源的字段。只要数据类型和顺序能够匹配,那字段名称就可以不同。 (2)在`PARTITION`子句中未显式指定值的分区列都会被视为动态分区列。例如,`PARTITION (city = 'Beijing', state)`,这里city是静态分区列,state是动态分区列。(3)动态分区字段必须放在SELECT语句的最后。
情况2 存在多份儿数据文件
例子:我在本地有6份儿txt文件,每一份儿文件的信息包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分区表,分区表的字段包括"grade, class, name, Chinese, math"5个字段,以'grade'字段进行分区。请问建表语句、静态分区加载数据、动态分区加载数据如何进行?
第一步 :建分区表
方式1:CREATE TABLE fenqu_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
方式2:CREATE TABLE fenqu_1 (class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING,) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--以上两种建表方式为自己定义分区字段的名字,分区字段'nianji'的名称可以自己随便取,不要和表中的字段一致就可以。
方式3:CREATE TABLE fenqu_1 (class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (grade STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--方式3的建表方式为,直接把表中的字段作为分区字段
注意:建表用的方式几,加载数据的时候就得用方式几
第二步:加载数据,有两种方式,一种是静态分区加载,一种是动态分区加载
静态分区加载:
静态分区加载方式1:用insert into 命令
1)将本地文件加载到hdfs的未分区表 putong_1 中
2)用insert 命令插入数据
方式1:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级') SELECT grade, class, name, Chinese, math FROM putong_1 WHERE grade='1年级';
方式2:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级') SELECT class, name, Chinese, math FROM putong_1 WHERE grade='1年级';
方式3:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (grade='1年级') SELECT class,name, Chinese, math FROM putong_1 WHERE grade='1年级';
--INSERT OVERWRITE:那么会先清空表中的数据(或者指定分区中的数据),再加载新的数据;INSERT INTO:会将新数据添加到表现有的数据中,而不是覆盖现有数据。
--在上述语法中,`INSERT OVERWRITE TABLE` 是插入或覆盖指定分区表的命令,`fenqu_1` 是分区表的名称,select后面的字段是要从 `putong_1'源表 中抽取的字段。
静态分区加载方式2:用load data命令
注意:如果用这种方式加载数据,那么在建分区表的时候就只能用方式一,必须保证表中的字段和txt文件中的字段数量&字段类型保持一致才行。
需要为每个分区单独执行一条LOAD DATA语句。
LOAD DATA LOCAL INPATH '/path/to/your_file1.txt'
OVERWRITE INTO TABLE fenqu_1 PARTITION (nianji='1年级');
--如果有多个分区,重复以上代码,注意修改分区值
动态分区加载
1)将本地文件加载到hdfs的未分区表 putong_1 中
2) 首先,开启Hive的动态分区设置:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
3) 然后进行动态分区加载数据:
方式1:INSERT OVERWRITE(或者INSERT INTO) TABLE fenqu_1 PARTITION(nianji) SELECT grade, class, name, Chinese, math, grade as nianji FROM putong_1;
--在select语句中,grade相当于是被查询了两次,第一次是当做插入的字段,第二次是当做分区的字段,分区的字段必须放在最后面
方式2:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(nianji) SELECT class,name, Chinese, math,grade FROM putong_1;
方式3:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(grade) SELECT class,name, Chinese, math,grade FROM putong_1;
情况3 多重分区表加载数据
和 情况1&情况2 的做法基本一致,只要把原来的一个分区字段变为多个就可以。
情况3-1 只有一份儿数据文件的情况下
例子:我在本地有1份儿txt文件,信息包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分区表,分区表的字段包括"grade, class, name, Chinese, math"5个字段,以'grade, class'字段进行分区。请问建表语句、静态分区加载数据、动态分区加载数据如何进行?
第一步 :建分区表
方式1:CREATE TABLE fenqu_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING, banji STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
方式2:CREATE TABLE fenqu_1 (name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING, banji STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--以上两种建表方式为自己定义分区字段的名字,分区字段'nianji,banji'的名称可以自己随便取,不要和表中的字段一致就可以。
方式3:CREATE TABLE fenqu_1 (name STRING,Chinese INT,math INT) PARTITIONED BY (grade STRING, class STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--方式3的建表方式为,直接把表中的字段作为分区字段
注意:建表用的方式几,加载数据的时候就得用方式几
第二步:加载数据,有两种方式,一种是静态分区加载,一种是动态分区加载
静态分区加载:
注意:如果一份数据文件包含了多个分区的数据,直接使用 `LOAD DATA`语句加载到分 区表可能无法达到你的预期效果,因为`LOAD DATA` 是简单地将文件移动到某个分区下,无法 根据文件内容的分区字段来应用到多个分区。
1)将本地文件加载到hdfs的未分区表 putong_1 中
2)用insert 命令插入数据
方式1:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级',banji='1班') SELECT grade, class, name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
方式2:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级',banji='1班') SELECT name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
方式3:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (grade='1年级',class='1班') SELECT name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
--INSERT OVERWRITE:那么会先清空表中的数据(或者指定分区中的数据),再加载新的数据;INSERT INTO:会将新数据添加到表现有的数据中,而不是覆盖现有数据。
--在上述语法中,`INSERT OVERWRITE TABLE` 是插入或覆盖指定分区表的命令,`fenqu_1` 是分区表的名称,select后面的字段是要从 `putong_1'源表 中抽取的字段。
动态分区加载
1)将本地文件加载到hdfs的未分区表 putong_1 中
2) 首先,开启Hive的动态分区设置:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
3) 然后进行动态分区加载数据:
方式1:INSERT OVERWRITE(或者INSERT INTO) TABLE fenqu_1 PARTITION(nianji,banji) SELECT grade, class, name, Chinese, math, grade as nianji,class as banji FROM putong_1;
--在select语句中,grade,class 相当于是被查询了两次,第一次是当做插入的字段,第二次是当做分区的字段,分区的字段必须放在最后面
方式2:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(nianji,banji) SELECT name, Chinese, math,grade,class FROM putong_1;
方式3:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(grade,class) SELECT name, Chinese, math,grade,class FROM putong_1;
情况3-2 有多份儿数据文件的情况下
例子:我在本地有6份儿txt文件,信息包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分区表,分区表的字段包括"grade, class, name, Chinese, math"5个字段,以'grade, class'字段进行分区。请问建表语句、静态分区加载数据、动态分区加载数据如何进行?
第一步 :建分区表
方式1:CREATE TABLE fenqu_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING, banji STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
方式2:CREATE TABLE fenqu_1 (name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING, banji STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--以上两种建表方式为自己定义分区字段的名字,分区字段'nianji,banji'的名称可以自己随便取,不要和表中的字段一致就可以。
方式3:CREATE TABLE fenqu_1 (name STRING,Chinese INT,math INT) PARTITIONED BY (grade STRING, class STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--方式3的建表方式为,直接把表中的字段作为分区字段
注意:建表用的方式几,加载数据的时候就得用方式几
第二步:加载数据,有两种方式,一种是静态分区加载,一种是动态分区加载
静态分区加载:
静态分区加载方式1:用insert into 命令
1)将本地文件加载到hdfs的未分区表 putong_1 中
2)用insert 命令插入数据
方式1:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级',banji='1班') SELECT grade, class, name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
方式2:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (nianji='1年级',banji='1班') SELECT name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
方式3:INSERT OVERWRITE(或者INSERT INTO)TABLE fenqu_1 PARTITION (grade='1年级',class='1班') SELECT name, Chinese, math FROM putong_1 WHERE grade='1年级',class = '1班';
--INSERT OVERWRITE:那么会先清空表中的数据(或者指定分区中的数据),再加载新的数据;INSERT INTO:会将新数据添加到表现有的数据中,而不是覆盖现有数据。
--在上述语法中,`INSERT OVERWRITE TABLE` 是插入或覆盖指定分区表的命令,`fenqu_1` 是分区表的名称,select后面的字段是要从 `putong_1'源表 中抽取的字段。
静态分区加载方式1:用load data命令
注意:如果用这种方式加载数据,那么在建分区表的时候就只能用方式一,必须保证表中的字段和txt文件中的字段数量&字段类型保持一致才行。
需要为每个分区单独执行一条LOAD DATA语句。
LOAD DATA LOCAL INPATH '/path/to/your_file1.txt'
OVERWRITE INTO TABLE fenqu_1 PARTITION (nianji='1年级',banji = '1班');
--如果有多个分区,重复以上代码,注意修改分区值
动态分区加载
1)将本地文件加载到hdfs的未分区表 putong_1 中
2) 首先,开启Hive的动态分区设置:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
3) 然后进行动态分区加载数据:
方式1:INSERT OVERWRITE(或者INSERT INTO) TABLE fenqu_1 PARTITION(nianji,banji) SELECT grade, class, name, Chinese, math, grade as nianji,class as banji FROM putong_1;
--在select语句中,grade,class 相当于是被查询了两次,第一次是当做插入的字段,第二次是当做分区的字段,分区的字段必须放在最后面
方式2:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(nianji,banji) SELECT name, Chinese, math,grade,class FROM putong_1;
方式3:INSERT OVERWRITE(或者 INSERT INTO) TABLE fenqu_1 PARTITION(grade,class) SELECT name, Chinese, math,grade,class FROM putong_1;
情况4 使用HDFS命令加载数据
(1)使用hdfs命令直接在 hdfs创建文件夹
hdfs dfs -mkdir /user/hive/warehouse/mydb.db/mytable/partition1/
--请注意路径 `/user/hive/warehouse/mydb.db/mytable/partition1/` 是你希望在HDFS上创建的新目录。"hdfs dfs" 是执行HDFS文件系统操作的命令;"-mkdir" 是创建新目录的命令选项;
(2)使用hdfs命令直接在把数据文件加载上去
hadoop fs -put /path/to/localfile /path/to/hdfs
--当文件在本地时 --这里 "/path/to/localfile" 是你要上传文件在Windows中的根路径(完整 的),"/path/to/hdfs" 是你想要把文件存放在HDFS中的路径。
hadoop fs -mv /user/hadoop/dir1/myfile.txt /user/hadoop/dir2/
--当文件在hdfs其他的文件夹时
(3)这时候,虽然对应的文件夹和数据都有了,但是hive的分区表还是查询不到数据,为什么呢?这是因为hive的元数据信息没有更新,它并不知道hdfs上多了或者少了数据,这时候就需要用MSCK [REPAIR] TABLE命令来对分区进行修复,让hive知道自己自己的表多了或者少了哪些东西。这种办法在分区多的时候也很方便,省的区分静态分区和动态分区了
MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
-- MSC命令的默认选项是“添加分区”。使用此选项,它将把HDFS上存在但元存储中不存在的所有分区添加到元存储中。DROP PARTITIONS选项将从已经从HDFS中删除的metastore中删除分区信息。SYNC PARTITIONS选项等效于调用ADD和DROP PARTITIONS。 table_name [ADD/DROP/SYNC PARTITIONS];
3.分桶表加载
例子:我有一个普通的hive表 putong_1,里面包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分桶表 fentong_1,以'grade'字段进行分桶,分为3桶;以'Chinese' 字段进行桶内降序排序。请问建表语句、加载数据如何进行?
第一步:建分桶表
CREATE TABLE fentong_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) CLUSTERED BY(grade) SORTED BY (Chinese DESC) INTO 3 BUCKETS ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
第二步:加载数据
1)开启分桶的功能
set hive.enforce.bucketing=true;
2)把源数据加载到普通hive表中 putong_1 中
3)使用insert+select语法将数据加载到分桶表中
insert into fentong_1 select * from putong_1;
--到HDFS上查看 fentong_1底层数据结构可以发现,数据被分为了3个部分。
--注意: 首次加载数据时,通常使用INSERT OVERWRITE,它会删掉同名桶中的现有数据。如果接下来想再继续加载数据到该表,就可以使用INSERT INTO,它会保留已有数据,把新的插入数据也按照分桶列的哈希值分配到对应的桶。
4.分区-分桶表加载
例子:我有一个普通的hive表 putong_1,里面包括"grade, class, name, Chinese, math"5个字段;现在我想创建一个分区-分桶表,分区表的字段包括"grade,class, name, Chinese, math"5个字段,以'grade'字段进行分区,'class'字段进行分为3桶,以'Chinese'字段进行桶内降序排序。请问建表语句、静态分区加载数据、动态分区加载数据如何进行?
第一步:创建一个分区-分桶表:
CREATE TABLE fenqufentong_1 (grade STRING,class STRING,name STRING,Chinese INT,math INT) PARTITIONED BY (nianji STRING) CLUSTERED BY(class) SORTED BY (Chinese DESC) INTO 3 BUCKETS ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
--建表的时候不需要把分区的字段单独排除出来,只要你分区字段的名称不和表中的字段名字一样就可以,分区字段的名称可以自己随便取;那么在加载数据的时候,不管是动态加载还是静态加载,只需要按照(表所有的字段,分区字段1,分区字段2,...)顺序来加载就行
第二步:加载数据
静态分区加载:
1)把源数据加载到hdfs的普通表中 ,表名source_table
2) 使用以下的 INSERT INTO 语句:
INSERT INTO TABLE fenqufentong_1 PARTITION(nianji='1年级')
SELECT grade,class,name,Chinese,math FROM putong_1 WHERE grade = '1年级';
--在上述命令中, PARTITION 子句用于指定要加载数据的分区。 SELECT 子句从源表中查询数据,然后插入到目标表的特定分区。数据会根据 分区字段的值自动分配到各个数据桶中。
动态分区加载:
1)把源数据加载到hdfs的普通表中 ,表名source_table
2)需要先开启动态分区功能
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
3) 使用以下的 INSERT INTO 语句:
INSERT INTO TABLE fenqufentong_1 PARTITION(nianji)
SELECT grade,class,name,Chinese,math, grade as nianji FROM putong_1;
-- 动态分区能够根据分区列的值自动创建多个分区,并将数据插入到相应的分区。这样,就可以一次性将所有 源表 的数据加载进分区表。
5. 建表时指定文件格式为非默认格式(TEXTFILE)
情形一:源数据文件的类型 和 建表时指定的数据文件类型都不属于默认格式(TEXTFILE)
用 load data local 命令直接加载
情形二:源数据文件的类型属于默认格式(TEXTFILE),建表时指定的数据文件类型不属于默认格式(TEXTFILE)
案例:我有一份儿text类型的数据文件,现在我建了一个hive表,指定表的文件类型为ORC格式。如何将数据文件成功加载到hive表中?
步骤一:创建一个临时文本表:
CREATE EXTERNAL TABLE tmp_text_table
( -- 你的列定义 )
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
-- 或者是你的文本文件使用的分隔符
LOCATION 'hdfs://path/to/your/text/data';
步骤二:创建一个ORC表:
CREATE TABLE orc_table
( -- 与临时文本表相同的列定义 )
STORED AS ORC;
步骤三:从临时文本表读取数据到ORC表:
INSERT OVERWRITE TABLE orc_table SELECT * FROM tmp_text_table;
-- 然后你就可以在`orc_table`中查询ORC格式的数据了。注意,这种方式将会对数据进行两次写操作(一次在创建临时表时,一次在从文本表插入ORC表时)
问题:hive中,临时文本表可以加载到任何格式的hive表中吗?
答:是的,一旦把数据加载到临时文本表中,然后你可以将这些数据以任何hive支持的格式写入另一张表。只需在创建那张表的时候指定你需要的文件格式,然后从临时表中select数据插入到这张表中即可。Hive支持的文件格式包括但不限于:TEXTFILE(默认)、SEQUENCEFILE、ORC、PARQUET、AVRO等。
Hive导出数据
1.语法树大全
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 --directory1表示需要导出的路径
[ROW FORMAT row_format]
[STORED AS file_format] --表示要导出的文件类型
SELECT ... FROM ... --表示要导出的内容(通常是将对表查询的结果进行导出)
--注意:导出操作是一个OVERWRITE覆盖操作,如果目标路径在导入操作开始之前已经存在数据,那么这些数据将会被新的查询结果完全替代(覆盖)。
--row_format 相关的写法(导出数据中如果有复杂类型的字段需要用到以下)
ROW FORMAT DELIMITED
[FIELDS TERMINATED BY char [ESCAPED BY char]] --字段之间的分隔符
[COLLECTION ITEMS TERMINATED BY char] --集合元素之间的分隔符
[MAP KEYS TERMINATED BY char] --Map映射和KV之间的分隔符
[LINES TERMINATED BY char] --行数据之间的分隔符
2.导出数据
2-1 导出查询结果到HDFS指定的目录下
案例:我有一张student表,如何将导出查询结果到HDFS指定目录下?
insert overwrite directory '/user/hive/warehouse/test1.db/ceshi_2/' select * from student;
2-2 导出查询结果到本地目录下
案例:我有一张student表,如何将导出查询结果到本地目录下?
insert overwrite local directory 'C:\Users\lenovo\Desktop\导出数据' select * from student;
-- 在Hive中,如果在导出数据时没有指定字段分隔符,那么默认会使用制表符('\t')作为字段分隔符。输出的文件默认以文本文件形式(TEXTFILE)存储,每一行都表示查询结果的一行,字段之间用制表符分隔。
2-3 导出查询结果到HDFS指定的目录下,并且指定分隔符和文件存储格式
insert overwrite local directory 'C:\Users\lenovo\Desktop\导出数据'
row format delimited fields terminated by ','
stored as TEXTFILE
select * from ceshi_1;
2-4 当查询结果中包含数组,map映射,结构体等复杂数据类型字段,导出查询结果到HDFS指定的目录下,并且指定分隔符和文件存储格式
insert overwrite local directory 'C:\Users\lenovo\Desktop\导出数据'
row format delimited fields terminated by ','
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':'
stored as TEXTFILE
select * from ceshi_6;
-- 需要注意的是,复杂类型数据在查询时,需要用特定的代码
2-5 当查询结果的某一个字段中中包含了和你设置的分隔符相同的字符,如何导出?
如果你的导出字段中包含了和你设置的分隔符相同的字符,并且你希望Hive在导出数据时将这个字符识别为字段内容的一部分,而不是分隔符。
针对这个问题,最常见的解决方案有两种。方式1:是更改你的字段分隔符,选择一个在所有字段内容中都不会出现的字符作为分隔符。例如,可以选择使用一个或者多个不可见字符作为分隔符,比如使用"\001","\002","\003"等。 方式2:你可能需要在数据生成时进行预处理,将字段内容中可能出现的分隔符进行替换或者删除。
方式2举例:
INSERT OVERWRITE DIRECTORY '/user/hive/exports/results'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
SELECT user_id, regexp_replace(user_address, ',', '\\\,') FROM user_table;
--在这个例子中,`regexp_replace(user_address, ',', '\,')` 这个函数会找到user_address字段中所有的逗号,用转义后的逗号替代(即`'\,'`)。
Hive增改删
1.事务表
1-1 hive中事务表的作用
从Hive0.14版本开始,具有ACID语义的事务(支持INSERT,UPDATE和 DELETE这些用例)已添加到Hive中,以解决以下场景下遇到的问题:
- 流式传输数据。使用如Apache Flume或Apache Kafka之类的工具将数据流式传输到现有分区中,但是这会使读者感到脏读(也就是说,开始查询后能看到写入的数据)。
- 变化缓慢的维度数据。在典型的星型模式数据仓库中,维度表随时间缓慢变化。例如,零售商将开设新商店,需要将其添加到商店表中,或者现有商店可能会更改其平方英尺或某些其他跟踪的特征。这些更改导致插入单个记录或更新记录(取决于所选策略)。
- 数据更新。有时发现收集的数据不正确,需要更正。
1-2 hive中使用事务表的限制条件
尚不支持BEGIN,COMMIT和ROLLBACK。所有语言操作都是自动提交的。
仅支持ORC文件格式(STORED AS ORC)。
默认情况下事务配置为关闭。需要配置参数开启使用。
表必须是分桶表(Bucketed)才可以使用事务功能。外部表无法创建事务表。
表参数transactional必须为true;
外部表不能成为ACID表,不允许从非ACID会话读取/写入ACID表。
1-3 hive中如何创建事务表
--Hive中事务表的创建使用
--1、开启事务配置(可以使用set设置当前session生效 也可以配置在hive-site.xml中)
set hive.support.concurrency = true; --Hive是否支持并发
set hive.enforce.bucketing = true; --从Hive2.0开始不再需要 是否开启分桶功能
set hive.exec.dynamic.partition.mode = nonstrict; --动态分区模式 非严格
set hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; --启用hive的事务管理器
set hive.compactor.initiator.on = true; --是否在Metastore实例上运行启动压缩合并
set hive.compactor.worker.threads = 1; --在此metastore实例上运行多少个压缩程序工作线程。
--2、创建Hive事务表
create table trans_student(
id int,
name String,
age int
)clustered by (id) into 2 buckets
stored as orc
TBLPROPERTIES('transactional'='true');
--3、针对事务表进行insert update delete操作
insert into trans_student (id, name, age)
values (1,"allen",18);
update trans_student
set age = 20
where id = 1;
delete from trans_student where id =1;
select *
from trans_student;
2. hive中Update、Delete数据
注意:在hive中insert、Update、Delete数据的前提是,目标表必须是事务表。
Hive 查询语句
说明:因为hive的查询和mysql的查询使用有很多相似的地方,所以在这里就不再赘述。以下只记录hive特有的查询功能。
hive的基础查询功能和mysql基本一致。
1. CLUSTER BY(cluster簇;团 by)
1-1 功能是什么?
Hive SQL中的CLUSTER BY语法可以指定根据后面的字段将数据分组,每组内再根据这 个字段正序排序(不允许指定排序规则),概况起来就是:根据同一个字段,分组且排序。
分组的规则hash散列:hash_func(col_name) % reduce task nums
分为几组取决于reduce task的个数。
2-2 语法
在Hive中,CLUSTER BY后可以跟任意数量的字段。你可以根据需要对一个或者多个字段进行分桶和排序。
情况1:
--不指定reduce task个数(分桶的个数)
--日志显示:Number of reduce tasks not specified. Estimated from input data size: 1
select * from student cluster by 字段名称;
--默认情况下,reduce task的个数由Hive在编译期间自己决定。
情况2:
--手动设置reduce task(分桶)个数
set mapreduce.job.reduces =2;
select * from student cluster by sno;
2-3 计算顺序
1. FROM子句和JOIN
2. WHERE子句的过滤
3. GROUP BY子句的分组
4. 聚合函数(如SUM, COUNT, AVG等)
5. HAVING子句的过滤
6. SELECT
7. CLUSTER BY
8. LIMIT子句
2-4 CLUSTER BY和GROUP BY的作用一样吗?可以一起使用吗
不一样。GROUP BY 主要用于对某些列的值进行分组,常常配合聚合函数(如 SUM、COUNT、AVG 等)使用,用于对每个组求取某些汇总信息。而 CLUSTER BY 则是用于对数据进行分桶和排序,使得所有具有相同值( 分组的规则是hash散列,类似于分桶表,把相同的数值分到一个桶里面)的行都会被分配到同一个组中。
CLUSTER BY和GROUP BY是可以一起使用的,举例说明:
SELECT col1, count(*) FROM table GROUP BY col1 CLUSTER BY col1;
--在这个例子中,首先通过GROUP BY将数据按col1进行分组,然后聚合每组的数量,最后使用CLUSTER BY对结果进行排序。此时,CLUSTER BY对使用了GROUP BY的查询结果进行操作,使得相同col1的所有记录都将在相同的reducer中进行处理,并且在每个reducer的输出结果中会按照col1的值排序。这种情况下,GROUP BY和CLUSTER BY配合使用,可以在进行数据聚合的同时,实现数据的分布式排序。
2. DISTRIBUTE BY +SORT BY
( distribute 分配 by + sort 分类 by )
2-1 功能是什么?
如果说CLUSTER BY的功能是分且排序(同一个字段),那么DISTRIBUTE BY +SORT BY 就相当于把cluster by的功能一分为二:DISTRIBUTE BY负责分,SORT BY负责分组内 排 序,并且可以是不同的字段。如果DISTRIBUTE BY +SORT BY的字段一样,可以得出下列结论:
CLUSTER BY=DISTRIBUTE BY +SORT BY(字段一样)
2-2 语法
案例:把学生表数据根据性别分为两个部分,每个分组内根据年龄的倒序排序
select * from student distribute by sex sort by sage desc;
2-3 CLUSTER BY 、DISTRIBUTE BY +SORT BY、order by 的区别是什么?
order by 是对全表进行排序,所以它在数据量大的时候,执行速度是很慢的
CLUSTER BY 是只能针对同一个字段进行分区且排序,属于局部排序
DISTRIBUTE BY +SORT BY 是可以针对不同的字段进行分区和排序,属于局部排序
DISTRIBUTE BY +SORT BY 和 order by 的排序结果是完全一致的,只不过前者在查询时按照分区分了多个reduce来进行排序,所以效率会比较高,但是后者就只有一个reduce。在实际应用中,对于大数据集,通常推荐使用DISTRIBUTE BY
和SORT BY
的组合来代替ORDER BY
,以提高查询性能。
注意:在使用Union联合查询连接多个查询语句时,如果想对所有的查询语句进行排序,此时,需要把ORDER BY,SORT BY,CLUSTER BY,DISTRIBUTE BY或LIMIT子句应用于整个UNION语句的后面,以上关键字通常用在group by & having 之后
3. Common Table Expressions(CTE),超级好用
3-1 定义
Common Table Expressions(CTE)是一个临时结果集,它让我们可以将子查询结果集命名,并在后续代码中引用这个结果集,使得复杂的SQL查询语句变得更加清晰和易于理解。CTE常常和WITH关键字一起使用。它可以在select、INSERT, UPDATE, DELETE, 和CREATE语句当中进行应用(类似于视图的功能,只不过它只能应用于当前语句,过后就会自动删除)
3-2 使用CTE的注意事项
1. CTE的作用域仅存在于定义它的查询中,在该查询执行完毕后,CTE就会失效,无法在其他查询中引用。
2. 在一个查询中可以定义多个CTE,但每个CTE都需要用逗号分隔,并且WITH关键字只能在最前面出现一次。
3. CTE不是一种存储数据的对象,它只是在查询执行过程中临时存储数据的结构。每次查询完成后,CTE中的数据就会被清空。
5. CTE虽然看起来像子查询,但与子查询不同,子查询的结果不会被缓存,每次在主查询中调用子查询时,子查询都会被重新执行。而CTE的结果会在内存中缓存,之后在主查询中的多次调用只使用缓存的数据。
6. Recursive(递归)CTE中的递归成员必须引用CTE一次,且只能一次。另外,递归成员中不能用聚合函数,GROUP BY, DISTINCT 等。
7. 在使用CTE时,一定要明确它只是一个临时的视图,不要视其为数据表,对其进行写操作,如Insert, Delete和Update等。
8.CTE和视图的区别:视图是数据库中的一个对象,它是持久的,一旦您创建了一个视图,它会一直存在,直到您明确地删除它。CTE是一个临时的结果集,仅在一个单独的查询执行期间存在。查询完成后,CTE将消失。
3-3 如何使用
(1)查询语句中的CTE
写法1:
with q1 as (select sno,sname,sage from student where sno = 95002)
select *
from q1;
写法2:
with q1 as (select sno,sname,sage from student where sno = 95002)
from q1
select *;
(2)使用多个CTE
with q1 as ( select * from student where sno = 95002),
q2 as ( select sno,sname,sage from q1)
select * from (select sno from q2) a;
(3)union案例
with q1 as (select * from student where sno = 95002),
q2 as (select * from student where sno = 95004)
select * from q1 union all select * from q2;
(4)创建表的时候使用CTE(使用create table... like...命令,复制一个新表的超级好办法)
1)建表 create table s1 like student;
-- 是SQL语句中用于创建表的语句。此语句的意思是创建一个新的表s1,它的表结构(包括列名,数据类型,是否为Null等)完全复制另一个已存在的表student,但 是不复制数据。这对于需要创建和已有表结构相同的新表非常有用。
2)导入数据
with q1 as ( select * from student where sno = 95002)
from q1
insert overwrite table s1
select *;
(5)创建表的时候使用CTE(使用Create Table ... As Select ... 命令,第二个复制一个新表的超级好办法)
注:Create Table As Select的缩写是CTAS,在SQL中是用来创建新表的。这个新表的结构和数据都是来源于SELECT查询的结果。这是一种简便的方式,根据一个查询的结果立即创建一张新表。
create table s2 as
with q1 as ( select * from student where sno = 95002)
select * from q1;
(6)创建视图的时候使用CTE
create view v1 as
with q1 as ( select * from student where sno = 95002)
select * from q1;
(7)INSERT, UPDATE, DELETE, 和CREATE VIEW语句中使用CTE
1)INSERT:
WITH cte AS ( SELECT column1, column2 FROM old_table WHERE condition ) INSERT INTO new_table (column1, column2) SELECT column1, column2 FROM cte; --在INSERT语句中,CTE被用于生成需要插入到新表中的数据。
2)UPDATE:
WITH cte AS ( SELECT id, new_value FROM some_table WHERE condition )
UPDATE my_table SET my_column = cte.new_value FROM cte WHERE my_table.id = cte.id;
--在UPDATE语句中,CTE被用于找出需要更新的记录和新的值。
3)DELETE:
WITH cte AS ( SELECT id FROM some_table WHERE condition )
DELETE FROM my_table WHERE id IN (SELECT id FROM cte);
--在DELETE语句中,CTE被用于找出需要删除的记录。
4. join相关语法
4-1 join的类型
inner join(内连接)、left(outer) join(左连接)、right(outer)join(右连接)、full (outer) join(全外连接)、left semi join(左半开连接)、cross join(交叉连接,也叫做笛卡尔乘积)。
其中,只有left semi join(左半开连接)是MySQL没有的,其他连接的用法与MySQL一致。
4-2 left semi join(左半开连接)
左半开连接(Left Semi Join)在Hive中是一种特殊类型的Join,用于从左表中筛选出那些在右表中存在匹配记录的行。不过,LEFT SEMI JOIN
只会返回左表的列,右表的列不会出现在结果集中。
例子:SELECT a.key, a.val FROM a LEFT SEMI JOIN b ON (a.key = b.key)
--在这个例子中,`LEFT SEMI JOIN`操作将返回表a中所有键值存在于表b的记录,且只返回表a的字段。
HDFS 存储文件路径
1.默认存储路径
Hive表默认存储路径是由${HIVE_HOME}/conf/hive-site.xml配置文件的hive.metastore.warehouse.dir属性指定。默认值是:/user/hive/warehouse。如果在配置文件中没有明确指定的话,Hive会使用这个默认路径
在该路径下,文件将根据所属的库、表,有规律的存储在对应的文件夹下。
2.指定存储路径
在Hive建表的时候,可以通过location语法来更改数据在HDFS上的存储路径,使得建表加载数据更加灵活方便。(它是用来修改单个表的存储路径,其他的文件还是存储在配置文件指定的路径下)
语法:LOCATION '<hdfs_location>'
。
对于已经生成好的数据文件,使用location指定路径将会很方便。
例子:
CREATE TABLE tablename ( column1 datatype, column2 datatype, ...
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/path/to/hdfs/directory';
以上SQL将在'/path/to/hdfs/directory'路径下创建一个名为'tablename'的表,并且表中有两列,数据以逗号为分隔符,存储为文本格式。
注意: (1) '/path/to/hdfs/directory'必须是一个有效的HDFS路径,并且Hive用户需要有在该路径下创建文件的权限。(2)如果路径已经存在并且里面有数据,Hive会试图将数据映射到新创建的表结构。数据需要符合定义在表结构中的格式。(3)如果路径不存在,Hive会在HDFS上创建一个新目录。(4)当删除表时,不会删除HDFS中的数据文件。也就是说如果你删除了表,你需要手动删除目录和目录里的文件(通常针对的外部表,内部表通常不会去自定义存储路径)。
3.HDFS相关命令操作(hadoop命令)
3-1 如何在HDFS上添加一个新的目录
1) 首先,打开你的Hadoop环境的命令行界面。
2.)然后,执行以下命令:
hdfs dfs -mkdir /user/hive/warehouse/mydb.db/mytable/partition1/
--请注意路径 `/user/hive/warehouse/mydb.db/mytable/partition1/` 是你希望在HDFS上创建的新目录。
- "hdfs dfs" 是执行HDFS文件系统操作的命令;
- "-mkdir" 是创建新目录的命令选项;
3) 命令执行成功后,新目录就会被创建在指定的路径下。你可以使用 "hdfs dfs -ls" 命令(这里是小写的ls,不是is)来验证新目录是否成功创建。例如:
hdfs dfs -ls /user/hive/warehouse/mydb.db/mytable/
--这个命令会列出 `/user/hive/warehouse/mydb.db/mytable/` 路径下的所有文件和目录,包括你刚才新创建的目录 `partition1/`。
例子:hdfs dfs -mkdir /user/hive/warehouse/test2/ceshi_8
--创建了一个名字为 ceshi_8 的文件夹(目录)
3-2 如何删除HDFS上的目录?(删除文件,空目录,非空目录)
hdfs dfs -rm -r 目录 -- 可以删除文件,空目录(没有文件和子目录),非空目录
hdfs dfs -rm 目录 -- 可以删除文件,无法删除目录
注意:HDFS不支持文件的回收站功能,一旦删除文件,文件将会永久删除,无法恢复。
案例:
-- 删除单个文件
hdfs dfs -rm /user/hive/warehouse/test5.db/ceshi_1/1年级.txt;
hdfs dfs -rm -r /user/hive/warehouse/test5.db/ceshi_1/2年级.txt;
-- 删除所有文件,不包含目录本身
hdfs dfs -rm /user/hive/warehouse/test5.db/ceshi_1/*;
hdfs dfs -rm -r /user/hive/warehouse/test5.db/ceshi_1/*;
-- 删除所有文件,包含目录本身
hdfs dfs -rm /user/hive/warehouse/test5.db/ceshi_1; -- rm不能删除非空目录,需要加-r 进行递归删除
hdfs dfs -rm -r /user/hive/warehouse/test5.db/ceshi_1;
-- 删除空目录
hdfs dfs -rm /user/hive/warehouse/test5.db/ceshi_2; -- rm不能删除空目录,需要加-r 进行递归删除
hdfs dfs -rm -r /user/hive/warehouse/test5.db/ceshi_2;
3-3 如何将HDFS上的文件移动到另外一个文件夹
使用 hdfs fs -mv 命令
例子1:移动单个文件
hdfs fs -mv /user/hive/warehouse/test2/ceshi_8/映射.txt /user/hive/warehouse/test2/ceshi_9/
例子2:移动整个ceshi_8文件夹,包括文件夹本身
hdfs fs -mv /user/hive/warehouse/test2/ceshi_8 /user/hive/warehouse/test2/ceshi_9/
例子3:移动ceshi_8文件夹里面所有的文件,但文件夹本身会保留
hdfs fs -mv /user/hive/warehouse/test2/ceshi_8/* /user/hive/warehouse/test2/ceshi_9/
例子4:移动到当前文件夹,相当于重命名文件
hdfs fs -mv /user/hive/warehouse/test2/ceshi_8/映射.txt /user/hive/warehouse/test2/ceshi_8/映射123.txt
执行以上命令后,源文件将不再存在。这是移动(mv)命令的工作方式,它将文件从一个地方移动到另一个地方。如果你希望保留源文件的副本,应该使用 'cp' 命令代替。
3-4 如何将HDFS上的文件移动到另外一个文件夹,当前的文件位置保持不变?
使用 `hdfs fs -cp` 命令
hdfs dfs -cp -- 可以复制文件,空目录(没有文件和子目录),非空目录
例子1:复制移动单个文件;原文件位置不变
hdfs dfs -cp /user/hive/warehouse/test2/ceshi_9/映射.txt /user/hive/warehouse/test2/ceshi_8/
例子2:复制移动多个文件;原文件位置不变
hdfs dfs -cp /user/hive/warehouse/test2/ceshi_9/映射.txt /user/hive/warehouse/test2/ceshi_9/映射2.txt /user/hive/warehouse/test2/ceshi_8/
例子3:复制移动ceshi_9文件夹里面所有的文件,但文件夹本身会保留;原文件位置不变
hdfs dfs -cp /user/hive/warehouse/test2/ceshi_9/* /user/hive/warehouse/test2/ceshi_8/
例子4:复制移动整个ceshi_9文件夹,包括文件夹本身;原文件位置不变
hdfs dfs -cp /user/hive/warehouse/test2/ceshi_9 /user/hive/warehouse/test2/ceshi_8/
如果目标文件夹已经存在一个同名文件,`-cp`命令将会把它覆盖掉。如果你不想覆盖现有文件,需要先确认目标文件夹没有同名文件。
Hive view视图
--hive中有一张真实的基础表t_usa_covid19
select * from itcast.t_usa_covid19;
--1、创建视图
create view v_usa_covid19 as select count_date, county,state,deaths from t_usa_covid19 limit 5;
--能否从已有的视图中创建视图呢 可以的
create view v_usa_covid19_from_view as select * from v_usa_covid19 limit 2;
--2、显示当前已有的视图
show tables;
show views;--hive v2.2.0之后支持
--3、视图的查询使用
select *
from v_usa_covid19;
--能否插入数据到视图中呢?
--不行 报错 SemanticException:A view cannot be used as target table for LOAD or INSERT
insert into v_usa_covid19 select count_date,county,state,deaths from t_usa_covid19;
--4、查看视图定义
show create table v_usa_covid19;
--5、删除视图
drop view v_usa_covid19_from_view;
--6、更改视图属性
alter view v_usa_covid19 set TBLPROPERTIES ('comment' = 'This is a view');
--7、更改视图定义
alter view v_usa_covid19 as select county,deaths from t_usa_covid19 limit 2;
--8、显示视图属性
DESCRIBE FORMATTED v_usa_covid19;
Hive DDL其他语法(除建表外)
1.Database|schema(数据库) DDL操作
1-1 Create database
语法树:
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:用于指定一些数据库的属性配置。
IF NOT EXISTS:条件判断语句,用于判断指定的表或数据库是否存在。如果使用"IF NOT EXISTS",那么,如果指定的表或数据库已经存在,Hive将不会执行创建操作,并且不会报错。如果不加"IF NOT EXISTS",在表或数据库已经存在的情况下再尝试创建,Hive将会报错。这样做的主要目的是为了避免因为重复创建表或数据库
需要注意的地方:(1)数据库的名称:1)应以字母开头,不能以数字开头,比如要建一个名字为123的数据库,就会报错; 2)只能包含字母、数字和下划线 ,不能包含空格或特殊字符(如`'`、`"`、`-`、`/`、`:`等);3)不能包含Hive的关键字;4)如果数据库名里包含除了字母、数字和下划线之外的其他字符,或者代码语句中的关键字,需要使用反引号将这个数据库名包围起来,将来在调用这个数据库时,也需要用反引号来包围数据库名,否则会引发语法错误
情况1:使用default(默认)数据库
文件存储路径:/user/hive/warehouse --默认的存储路径;可以在Hive的配置文件(hive-site.xml)中进行修改。如果我们没有指定其他数据库,直接通过hive建立表,那么这个表对应的文件夹就会出现在warehous下面
情况2:创建一个数据库test1 (不指定路径)
CREATE DATABASE IF NOT EXISTS test1;
文件存储路径:/user/hive/warehouse/test1.db --hdfs会自动在warehouse的下面创建一个和新建数据库名字一样的子文件夹,这个数据库相关的文件就会被放到下面
情况3:创建一个数据库test2 (指定路径,放在warehouse下面,/user/hive/warehouse/test2)
CREATE DATABASE IF NOT EXISTS test2 LOCATION '/user/hive/warehouse/test2';
文件存储路径:/user/hive/warehouse/test2 --hdfs会自动在warehouse的下面创建一个和路径下文件名字一样的子文件夹.如果这个路径还不存在,hive会自动创建它
情况4:创建一个数据库test2 (指定路径,放在warehouse下面,/user/hive/warehouse/dsb)
CREATE DATABASE IF NOT EXISTS test2 LOCATION '/user/hive/warehouse/dsb';
文件存储路径:/user/hive/warehouse/dsb --hdfs会自动在warehouse的下面创建一个和路径下文件名字一样的子文件夹.如果这个路径还不存在,hive会自动创建它。这种情况告诉我们,数据库的文件最终存储的那个文件夹名字不一定非得和数据库自身的名字一样,也可以去自定义,当然,最好还是保持一致。
情况5:创建一个数据库test2 (指定路径,放在warehouse下面,/user/hive/warehouse)
CREATE DATABASE IF NOT EXISTS test2 LOCATION '/user/hive/warehouse';
文件存储路径:/user/hive/warehouse --此时,hdfs不会和情况3一样再创建一个新的文件夹,而是会把这个数据库下的文件直接存储在warehouse文件夹下面
情况6:创建一个数据库test3(指定路径,自己自定义路径,/user/hive/warehouse1/test3)
CREATE DATABASE IF NOT EXISTS test3 LOCATION '/user/warehouse1/test3';
文件存储路径:/user/warehouse1/test3 --如果这个路径还不存在,hive会自动创建它
1-2 Describe database
语法树:
DESCRIBE DATABASE/SCHEMA [EXTENDED] db_name;
--DESCRIBE DATABASE语句用于显示Hive中数据库的名称,其注释(如果已设置)及其在文件系统上的位置等信息。EXTENDED:用于显示更多信息。
例子:DESCRIBE DATABASE EXTENDED test1;
1-3 Use database
用于选择特定的数据库,切换当前会话使用哪一个数据库进行操作。
1-4 Drop database
DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE];
--DROP DATABASE语句用于删除(删除)数据库。默认行为是RESTRICT,这意味着仅在数据库为空时才删除它。要删除带有表的数据库,我们可以使用CASCADE。IF EXISTS:通常更drop语句一起应用。如果`database_name`这个数据库存在,就将其删除。如果表不存在,那么这个命令不会做任何事情,也不会抛出错误。如果不加`IF EXISTS`子句,当表不存在时,会抛出一个错误。
1-5 备份数据库
在Hive中,备份数据库主要指备份数据库的表结构(Schema)和表数据。
第一步:备份表结构: "SHOW CREATE TABLE table name" 命令获取创建表的语句,然后将这些语句保存下来。这样就可以在需要的时候重新创建表。
第二步:备份表数据:Hive的数据是以文件的形式存储在HDFS中,假设你知道数据库的存储路径,可以使用 `hdfs dfs -cp` 命令将数据文件复制到一个备份位置,在需要的时候把数据文件重新导入到新表当中。对于大数据量的表,这些操作可能会花费较长时间。如果要备份多个表或整个数据库的话,可能需要写一个脚本来自动化这个过程。
1-6 Alter database
--更改数据库属性
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;
注意:更改了数据库的位置,Hive并不会移动数据库中已经存在的数据。因此,如果想要原来的数据在新的位置也可用,需要手动将这些数据从原位置迁移到新的位置。
2.Table(表)DDL操作
2-1 Describe table
describe formatted [db_name.]table_name;
describe extended [db_name.]table_name;
--DESCRIBE table语句用于显示Hive中 表的元数据信息。如果指定了EXTENDED关键字,则它将以Thrift序列化形式显示表的所有元数据。如果指定了FORMATTED关键字,则它将以表格格式显示元数据。
2-2 Drop table
DROP TABLE [IF EXISTS] table_name [PURGE];
--DROP TABLE删除该表的元数据和数据。如果已配置垃圾桶(且未指定PURGE),则该表对应的数据实际上将移动到.Trash/Current目录,而元数据完全丢失。删除EXTERNAL表时,该表中的数据不会从文件系统中删除,只删除元数据。
如果指定了PURGE,则表数据不会进入.Trash/Current目录,跳过垃圾桶直接被删除。因此如果DROP失败,则无法挽回该表数据。
IF EXISTS:通常更drop语句一起应用。如果`database_name`这个数据库存在,就将其删除。如果表不存在,那么这个命令不会做任何事情,也不会抛出错误。如果不加`IF EXISTS`子句,当表不存在时,会抛出一个错误。
注意的地方:(1)如果表名中有特殊字符,需要把表用反引号括起来
问题:如何启动垃圾桶?怎样看自己是否启动了垃圾桶?
答:在Hive中,垃圾桶的功能是由配置参数`hive.trash.interval`控制的。默认情况下,这个参数的值是0,表示垃圾桶功能被关闭。如果你想启动垃圾桶功能,需要将这个参数的值设置为一个大于0的整数,这个值表示删除的文件在被永久删除之前保留在垃圾桶中的时间,单位是分钟。
启动垃圾桶的步骤如下:(1)打开Hive CLI或者Hive的其他客户端。(2)输入`SET hive.trash.interval = 1440;`,这行命令将会把垃圾桶的保留时间设置为一天。(3)输入`SET;`,这个命令可以列出所有的配置参数以及它们的值。从输出的结果中找到`hive.trash.interval`,检查它的值是否为1440。 注意,在启动垃圾桶功能之后,您删除的文件将被移动到一个特殊的`.Trash`目录下,而不是被立即永久删除。过了设定的保留时间后,这些文件将被自动永久删除。您也可以使用`empty trash`命令立即清空垃圾桶。
2-3 Truncate table
TRUNCATE [TABLE] table_name;
--从表中删除所有行。可以简单理解为清空表的所有数据但是保留表的元数据结构。如果HDFS启用了垃圾桶,数据将被丢进垃圾桶,否则将被删除。
2-4 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";
--这个操作只是修改了Hive元数据中这个表的文件存储路径,实际上并不会自动将表中原有的文件移动到新的目录。 使用ALTER TABLE修改LOCATION之后,如果你再查询这个表,Hive会到新的目录下寻找数据文件。但由于原数据文件还在老的路径下,你可能会发现查询结果为空。
--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 .Partition(分区)DDL操作
3-1 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';
--一次添加多个分区
--注意:分区值仅在为字符串时才应加引号。位置必须是数据文件所在的目录。ADD PARTITION会更改表元数据,但不会加载数据。如果分区位置中不存在数据,查询将 不会返回任何结果。
3-2 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');
3-3 delete 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; --直接删除数据 不进垃圾桶
--IF EXISTS:通常更drop语句一起应用。如果这个分区存在,就将其删除。如果表不存在,那么这个命令不会做任何事情,也不会抛出错误。如果不加`IF EXISTS`子句,当表不存在时,会抛出一个错误。
delete partition删除该分区的元数据和数据。如果已配置垃圾桶(且未指定PURGE),则该表对应的数据实际上将移动到.Trash/Current目录,而元数据完全丢失。
如果指定了PURGE,则表数据不会进入.Trash/Current目录,跳过垃圾桶直接被删除。
3-4 msck partition
语法树:MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
--修改分区
-- MSC命令的默认选项是“添加分区”。使用此选项,它将把HDFS上存在但元存储中不存在的所有分区添加到元存储中。DROP PARTITIONS选项将从已经从HDFS中删除的但是metastore中还存在的分区删除分区信息。SYNC PARTITIONS选项等效于调用ADD和DROP PARTITIONS。repair是一个可选关键字,写和不写都是等价的。
什么时候会用到这个语法呢?
当你通过Hive命令将数据插入到Hive表中的时候(比如通过INSERT语句),Hive会自动地在元数据中添加相应的分区信息,此时这个命令是不需要用到的。
但是,如果直接往HDFS中的对应路径上传文件(hdfs dfs -put 命令),这个时候新添加的数据和分区并不会被Hive所知晓。在这种情况下,就需要使用MSCK REPAIR TABLE或者ALTER TABLE ADD PARTITION命令,让Hive能够识别到新添加的数据和分区,这两种方式起到的效果是一样的。
例子:在分区表下上传了一份儿数据文件,怎么能让hive识别到它?
方式1:MSCK REPAIR TABLE mytable;
--该命令会检查表的HDFS目录,并将找到的所有目录都添加为新的分区。
方式2:如果你知道新分区的名称和值,可以直接使用 ALTER TABLE 语句来添加该分区。
ALTER TABLE mytable ADD PARTITION (partitionkey='2022');
3-5 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";
Hive show 显示语法
--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;