一、 DDL 操作
启动服务:
hive --service metastore &
hive --service hiveserver2 &
(一)数据库操作
1. 创建数据库
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
默认:创建的数据库将放在hdfs:/user/hive/warehouse
在Hive数据库是一个命名空间或表的集合。
在这里,IF NOT EXISTS是一个可选子句,通知用户已经存在相同名称的数据库。可以使用SCHEMA 在DATABASE的这个命令。下面的查询执行创建一个名为userdb数据库:
0: jdbc:hive2://192.168.71.130:10000> CREATE DATABASE IF NOT EXISTS userdb;
OK
No rows affected (0.139 seconds)
或
0: jdbc:hive2://192.168.71.130:10000> CREATE SCHEMA IF NOT EXISTS userdb;
OK
No rows affected (0.06 seconds)
下面的查询用于验证数据库列表:
0: jdbc:hive2://192.168.71.130:10000> SHOW DATABASES;
OK
+----------------+
| database_name |
+----------------+
| default |
| userdb |
+----------------+
2 rows selected (0.051 seconds)
数据表存放位置
数据表存放位置
2. 使用数据库
USE database_name;
0: jdbc:hive2://192.168.71.130:10000> USE userdb;
OK
No rows affected (0.049 seconds)
3. 删除数据库
DROP DATABASE是删除所有的表并删除数据库的语句。它的语法如下:
DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE];
假设要删除的数据库名称为userdb。
0: jdbc:hive2://192.168.71.130:10000> DROP DATABASE IF EXISTS userdb;
OK
No rows affected (0.141 seconds)
使用CASCADE查询删除数据库。这意味着要全部删除相应的表在删除数据库之前。
# 在数据库中创建表
0: jdbc:hive2://192.168.71.130:10000> create table employees(name string,sex char(10),age int,salary float,address varchar(50));
OK
No rows affected (0.39 seconds)
0: jdbc:hive2://192.168.71.130:10000> DROP DATABASE IF EXISTS userdb CASCADE;
OK
No rows affected (1.755 seconds)
使用SCHEMA查询删除数据库。
0: jdbc:hive2://192.168.71.130:10000> DROP SCHEMA userdb;
4. 修改数据库
(二)创建表
create Table是用于在Hive中创建表的语句。
语法
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[ROW FORMAT row_format]
[STORED AS file_format]
Hive中的表可以分为托管表
和外部表
,托管表的数据会存储在数据仓库目录下,由Hive管理,外部表的数据在指定位置,不在Hive的数据仓库中,只是在Hive元数据库中注册。
创建外部表采用create external tablename
方式创建,并在创建表的同时指定表的位置。
假设需要使用CREATE TABLE语句创建一个名为employee表。下表列出了employee表中的字段和数据类型:
编号 字段名称 数据类型
1 Eid int
2 Name String
3 Salary Float
4 Designation string
Eid 编号
Name 员工姓名
Salary 工资
Designation 任命管理人员
1. 创建托管表
CREATE TABLE IF NOT EXISTS employee ( eid int, name String,salary String, destination String)
COMMENT '员工信息'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
说明:
字段分隔符为:\t
行分隔为 \n
存储类型为:textfile
保存文件类型:
文件类型为:textfile
create table users(id int) stored as textfile;
表注释:
COMMENT 'Employee details'
# 表注释
create table users(id int) comment 'users table';
2. 外部表
可以使用关键字EXTERNAL和LOCATION创建不存储在默认位置中的表,其中LOCATION指定了表存在HDFS上的位置。外部表在LOCATION已经存在数据时会派上用场,当删除一个EXTERNAL表时,表中的数据不会在文件系统删除
。
现在HDFS存在/user/Hadoop/iis/input/iis.log文件,在该位置上创建外部表:
hive> create external table item(log string) location '/data/input';
hive> select * from users;
可以看到,Hive将HDFS上的数据直接加载到了表中了。
3. 临时表
表只对当前session有效,session退出后,表自动删除。
CREATE TEMPORARY TABLE IF NOT EXISTS employee ( eid int, name String, salary String, destination String);
insert into employee values(1,'lihaonan','100.3','test')
0: jdbc:hive2://192.168.71.130:10000> select * from employee;
OK
+---------------+----------------+------------------+-----------------------+
| employee.eid | employee.name | employee.salary | employee.destination |
+---------------+----------------+------------------+-----------------------+
| 1 | lihaonan | 100.3 | test |
+---------------+----------------+------------------+-----------------------+
1 row selected (0.5 seconds)
- LIKE创建表
用Like创建表的语法为:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
LIKE existing_table_or_view_name
[LOCATION hdfs_path];
Like语法可以精确地根据现存表的定义定义目标表(不复制数据),如:
创建一个新表,结构与其他一样
hive> create table 新表名 like 原表名;
Hive-0.8.0版本及之后的版本,CREATE TABLE LIKE view_name采用视图的schema创建表,并使用默认的SerDe和文件格式。
SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。
示例:
create table emp like employee;
- create-table-as-select
可以使用create-table-as-select (CTAS)语句创建表并加载查询结果到表中。该语句的操作是原子性,即直到所有查询结果被加载到表中之前,表对于其他用户是不可见的。所以其他用户要么看见带完整查询结果的表,要么根本看不见表。
CTAS有CREATE和SELECT两部分,SELECT部分可以是任何被Hive支持的select语句,CREATE采用SELECT部分的schema并且创建带有其它表属性如SerDe和存储格式的目标表
。如果SELECT部分没有指定所查询列的别名,目标表的列名将自动分配为_col0, _col1, 和 _col2
等,否则按照别名命名目标表的列名。CTAS有几个限制:
目标表不能是分区表
目标表不能是外部表
create external table temp as select * from employee;
目标表不能是list bucketing表
正确示例:
create table temp as select * from employee;
(三)修改表
基本语法:
声明接受任意属性,我们希望在一个表中修改以下语法。
ALTER TABLE name RENAME TO new_name
ALTER TABLE name ADD COLUMNS (col_spec[, col_spec ...])
ALTER TABLE name DROP [COLUMN] column_name
ALTER TABLE name CHANGE column_name new_name new_type
ALTER TABLE name REPLACE COLUMNS (col_spec[, col_spec ...])
- 重命名表
Rename To… 语句
重命名表,把 employee 修改为 emp。
ALTER TABLE employee RENAME TO emp;
- 改变列名/类型/位置/注释
语法:
ALTER TABLE table_name CHANGE
[CLOUMN] col_old_name col_new_name column_type
[CONMMENT col_conmment]
[FIRST|AFTER column_name];
这个命令可以修改表的列名,数据类型,列注释和列所在的位置,FIRST将列放在第一列,AFTER col_name将列放在col_name后面一列。
数据的列名和列数据类型:
# 改变列名
ALTER TABLE employee CHANGE name ename String;
# 改变数据类型
ALTER TABLE employee CHANGE salary salary Double;
- 增加/更新列
基本语法:
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [CONMMENT col_comment], ...);
ADD COLUMNS允许用户在当前列的末尾,分区列之前添加新的列,REPLACE COLUMNS允许用户更新列,更新的过程是先删除当前的列,然后在加入新的列。注:只有在使用native的SerDE时才可以这么做。
增加了一个列名dept在employee表。
ALTER TABLE employee ADD COLUMNS (dept STRING COMMENT 'Department name');
- 增加表的属性
# 设置字段分隔属性为逗号
alter table emp set serdeproperties('field.delim'=',');
- 修改表文件格式和组织
修改表的文件格式
ALTER TABLE table_name SET FILEFORMAT file_format;
ALTER TABLE table_name CLUSTERED BY (col_name, col_name, ...)
[SORTED By (col_name, ...)] INTO num_buckets BUCKETS;
上面两个命令都修改了表的物理属性。
(四)删除表
语法如下:
DROP TABLE [IF EXISTS] table_name;
以下查询删除一个名为 employee 的表:
DROP TABLE IF EXISTS employee;
当对一个表进行Drop操作时,不仅会删除表中的数据还会删除表的元数据。如果HDFS配置了Trash,那么删除的数据会移动到.Trash/当前目录下,元数据则会彻底丢失。当删除EXTERNAL表时,表中的数据不会从文件系统中删除,也即文件系统中的数据不会随着EXTERNAL表的删除而删除。当删除被视图应用的表时,不会提示警告信息(视图不再有效,必须被另行删除或者被用户重建)。从Hive-0.7.0开始,DROP操作在表不存在时返回错误,除非使用了IF EXISTS或者配置参数hive.exec.drop.ignorenonexistent被设置为true。
(五)分区表
就是在系统上建立文件夹,把分类数据放在不同文件夹下面,加快查询速度。
分区是表的部分列的集合,可以为频繁使用的数据建立分区,这样查找分区中的数据时就不需要扫描全表,这对于提高查找效率很有帮助.
Hive组织表到分区。它是将一个表到基于分区列,如日期,城市和部门的值相关方式。使用分区,很容易对数据进行部分查询。
表或分区是细分成桶,以提供额外的结构,可以使用更高效的查询的数据。桶的工作是基于表的一些列的散列函数值。
一个名为employee表包含雇员数据,如 id, name, dept 和yoj (即入职年份)。假设需要检索所有在2012年加入,查询搜索整个表所需的信息员工的详细信息。但是,如果用年份分区雇员数据并将其存储在一个单独的文件,它减少了查询处理时间。
1. 添加分区
可以通过添加分区表改变所述表。假设我们有一个表叫employee ,拥有如 Id, Name, Salary, Designation, Dept, 和 yoj等字段。
语法:
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec
[LOCATION 'location1'] partition_spec [LOCATION 'location2'] ...;
partition_spec:
: (p_column = p_col_value, p_column = p_col_value, ...)
以下查询用于将分区添加到employee表。
hive> ALTER TABLE employee ADD PARTITION (year=’2013’) location '/2012/part2012';
一个表可以有一个或者多个分区列,Hive将会为分区列上的每个不同的值组合创建单独的数据目录。分区列是虚拟列,要避免分区列名和数据列名相同,可以基于分区列进行查询。
hive> create table people(name string, age int, birthday date, telephone string, address string) partitioned by(name string, age int);
FAILED: SemanticException [Error 10035]: Column repeated in partitioning columns
上面出现的错误是因为分区列和数据列名称相同了,此时要么修改数据列名要么修改分区列名。
hive> create table people(name string, age int, birthday date, telephone string, address string) partitioned by(department string, sex string, howOld int);
建立分区后,会在相应的表目录下建立以分区名命名的目录,目录下是分区的数据。
注意:表中的列不能和partition中的列重合了。
2. 静态分区
Hive分区是在创建表的时候用Partitioned by 关键字定义的,但要注意,Partitioned by子句中定义的列是表中正式的列,但是Hive下的数据文件中并不包含这些列,因为它们是目录名。
create table par_tab (name string,nation string) partitioned by (sex string) row format delimited fields terminated by ',';
1) 导入数据:
准备本地数据文件par_tab.txt,内容 “名字/国籍”,将以性别(sex)作为分区:
把数据插入到表(其实load操作相当于把文件移动到HDFS的Hive目录下):
hive> load data local inpath '/root/par_tab.txt' into table par_tab partition (sex='man');
查询:
hive> select * from par_tab;
徐魁元,china
梁 胜,america
陈 杰,china
张文凯,china
王凯月,japan
尹懋宁,japan
查看par_tab目录结构:
hive> dfs -lsr /user/hive/warehouse/par_tab;
再插入另一个数据文件数据,如文件:
刘丽丽,china
衣 洁,china
hive> load data local inpath '/root/par_tab_wm.txt' into table par_tab partition (sex='woman');
最后查看两次插入的结果,包含了man和woman:
hive> select * from par_tab;
因为分区列是表实际定义的列,所以查询分区数据时:
hive> select * from par_tab where sex='woman';
查看分区内容:
hive> desc par_tab;
2) 多个分区
创建一张静态分区表par_tab_muilt,多个分区(性别+日期):
hive> create table par_tab_muilt (name string, nation string) partitioned by (sex string,dt string) row format delimited fields terminated by ',' ;
导入数据:
hive> load data local inpath '/root/par_tab.txt' into table par_tab_muilt partition (sex='man',dt='2017-03-29');
hive> dfs -lsr /user/hive/warehouse/par_tab_muilt;
新建表的时候定义的分区顺序,决定了文件目录顺序(谁是父目录谁是子目录),正因为有了这个层级关系,当我们查询所有man的时候,man以下的所有日期下的数据都会被查出来。如果只查询日期分区,但父目录sex=man和sex=woman都有该日期的数据,那么Hive会对输入路径进行修剪,从而只扫描日期分区,性别分区不作过滤(即查询结果包含了所有性别)。
2. 动态分区
根据查询得到的数据动态分配到分区里。其实动态分区与静态分区区别就是不指定分区目录,由系统自己选择。
1)启动动态分区功能
hive> set hive.exec.dynamic.partition=true;
假设已有一张表par_tab,前两列是名称name和国籍nation,后两列是分区列,性别sex和日期dt:
hive> select * from par_tab_muilt;
梁 胜 america man 2017-03-29
陈 杰 china man 2017-03-29
张文凯 china man 2017-03-29
王凯月 japan man 2017-03-29
尹懋宁 japan man 2017-03-29
徐魁元 china man 2017-03-29
把这张表的内容直接插入到另一张表par_dnm中,并实现sex为静态分区,dt动态分区(不指定到底是哪日,让系统自己分配决定)。
2)创建动态分区
把这张表的内容直接插入到另一张表par_dnm中,并实现sex为静态分区,dt动态分区(不指定到底是哪日,让系统自己分配决定)。
现在我把这张表的内容直接插入到另一张表par_dnm中,并实现sex为静态分区,dt动态分区(不指定到底是哪日,让系统自己分配决定);
hive> insert overwrite table par_dnm partition(sex='man',dt)
> select name, nation, dt from par_tab_muilt;
插入后看下目录结构,再查看分区数。
hive> show partitions par_dnm;
注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区。
动态分区可以允许所有的分区列都是动态分区列,但是要首先设置一个参数hive.exec.dynamic.partition.mode :
hive> set hive.exec.dynamic.partition.mode;
hive.exec.dynamic.partition.mode=strict
它的默认值是strick,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。
所以我们要设置:
hive> set hive.exec.dynamic.partition.mode=nostrick;
3. 查看分区结构
hive> show partitions 表名;
4. 重命名分区
语法
ALTER TABLE table_name PARTITION 原分区 RENAME TO PARTITION 新分区;
以下查询用来命名一个分区:
hive> ALTER TABLE employee PARTITION (year=’1203’)
> RENAME TO PARTITION (Yoj=’1203’);
5. 删除分区
删除分区:
ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec, PARTITION partition_spec,...;
以下查询是用来删除分区:
hive> ALTER TABLE employee DROP [IF EXISTS] PARTITION (year=’1203’);
(六)桶表
桶表是对数据进行哈希取值,然后放到不同文件中存储。
数据加载到桶表时,会对字段取hash值,然后与桶的数量取模。把数据放到对应的文件中。
物理上,每个桶就是表(或分区)目录里的一个文件,一个作业产生的桶(输出文件)和reduce任务个数相同。
可以把表或分区组织成桶,桶是按行分开组织特定字段,每个桶对应一个reduce操作。在建立桶之前,需要设置“hive.enforce.bucketing”属性为true,使Hive能够识别桶。
作用:
桶表专门用于抽样查询,是很专业性的,不是日常用来存储数据的表,需要抽样查询时,才创建和使用桶表。
- 启用桶
hive>set hive.enforce.bucketing=true;
hive>set hive.enforce.bucketing;
- 创建桶
hive>create table btest2(id int,name string) clustered by(id) into 3 buckets
row format delimited fields terminated by '\t';
向桶中插入数据,这里按照用户id分了三个桶,在插入数据时对应三个reduce操作,输出三个文件。
hive>insert overwrite table btest2 select * from userinfo;
查看数据仓库下的桶目录,三个桶对应三个目录。
hive>dfs –ls /user/hive/warehouse/btest2;
Hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。
hive>dfs –cat /user/hive/warehouse/btest2/*0_0;
hive>dfs –cat /user/hive/warehouse/btest2/*1_0;
hive>dfs –cat /user/hive/warehouse/btest2/*2_0;
分桶可以获得比分区更高的查询效率,同时分桶也便于对全部数据进行采样处理。
hive>select * from btest2 tablesample(bucket 1 out of 3 on id);
- 插入数据
insert table 桶表名 select * from 表名;
请不要使用Load data插入数据,因为使用load data,没有启动mapreduce对数据进行哈希取值,只是简单的原样导入,没有起到抽样查询的目的。
(七)截断表
基本语法:
TRUNCATE TABLE table_name [PARTITION partition_spec];
partition_spec:
: (partition_col = partition_col_value, partition_col = partiton_col_value,
当进行truncate操作时将会从一个表或者分区中删除所有的行,用户可以通过指定partition_spec删除多个分区,省略partition_spec将会删除表中的所有分区。
truncate 不能删除外部表!因为外部表里的数据并不是存放在Hive Meta store中.
truncate table 表名;
二、数据类型
1. 列类型
1)字符类型:
字符串类型的数据类型可以使用单引号('')或双引号("")来指定。它包含两个数据类型:VARCHAR和CHAR。Hive遵循C-类型的转义字符。
各种CHAR数据类型:
数据类型 | 长度 |
---|---|
VARCHAR | 1 to 65355 |
CHAR | 255 |
STRING |
2)日期类型:
日期
DATE值在年/月/日的格式形式描述 {{YYYY-MM-DD}}.
转换类型 | 结果 |
---|---|
cast(date as date) | Same date value |
cast(date as string) | The year/month/day represented by the Date is formatted as a string in the form ‘YYYY-MM-DD’. |
cast(date as timestamp) | A timestamp value is generated corresponding to midnight of the year/month/day of the date value, based on the local timezone. |
cast(string as date) | If the string is in the form ‘YYYY-MM-DD’, then a date value corresponding to that year/month/day is returned. If the string value does not match this formate, then NULL is returned. |
cast(timestamp as date) | The year/month/day of the timestamp is determined, based on the local timezone, and returned as a date value. |
时间戳(timestamp)
它支持传统的UNIX时间戳可选纳秒的精度。它支持的java.sql.Timestamp格式“YYYY-MM-DD HH:MM:SS.fffffffff”和格式“YYYY-MM-DD HH:MM:ss.ffffffffff”。
支持传统的UNIX时间戳和可选的纳秒精度。
- 支持的转化:
- 整数数字类型:以秒为单位解释为UNIX时间戳
- 浮点数值类型:以秒为单位解释为UNIX时间戳,带小数精度
- 字符串:符合JDBC java.sql.Timestamp格式“YYYY-MM-DD HH:MM:SS.fffffffff”(9位小数位精度)
3)联合类型:
联合是异类的数据类型的集合。可以使用联合创建的一个实例。语法和示例如下:
UNIONTYPE<int, double, array<string>, struct<a:int,b:string>>
{0:1}
{1:2.0}
{2:["three","four"]}
{3:{"a":5,"b":"five"}}
{2:["six","seven"]}
{3:{"a":8,"b":"eight"}}
{0:9}
{1:10.0}
4) 数值类型
整型
默认情况下,整数型为INT型,当数字大于INT型的范围时,会自动解释执行为BIGINT
,或者使用以下后缀进行说明。
类型 | 后缀 | 例子 |
---|---|---|
TINYINT | Y | 100Y |
SMALLINT | S | 100S |
BIGINT | L | 100L |
大于BIGINT的数值,需要使用BD后缀以及Decimal(38,0)来处理。
select CAST(18446744073709001000BD AS DECIMAL(38,0)) from dual limit 1;
Hive的小数型是基于Java BigDecimal做的, BigDecimal在java中用于表示任意精度的小数类型。所有常规数字运算(例如+, - ,*,/)和相关的UDFs(例如Floor,Ceil,Round等等)都使用和支持Decimal。你可以将Decimal和其他数值型互相转换,且Decimal支持科学计数法和非科学计数法。因此,无论您的数据集是否包含如4.004E + 3(科学记数法)或4004(非科学记数法)或两者的组合的数据,可以使用Decimal。
从Hive 0.13开始,用户可以使用DECIMAL(precision, scale) 语法在创建表时来定义Decimal数据类型的precision和scale。 如果未指定precision,则默认为10。如果未指定scale,它将默认为0(无小数位)。
5) 使用示例
# 创建员工表:
create table employees(name string,sex char(10),age int,salary float,address varchar(50));
OK
No rows affected (0.682 seconds)
# 创建部门表:
create table deptarment(id int,deptname string,joindate date,bonus decimal(10,2));
OK
No rows affected (0.182 seconds)
6) 类型转换函数
# 创建虚表
create table dual(dummy string);
# 必须插入一条记录,否则查不到结果
insert into dual values('1');
cast() 转换函数
对于Date类型的数据,只能在Date、Timestamp以及String之间进行转换。下表将进行详细的说明:
有效的转换 | 结果 |
---|---|
cast(date as date) | 返回date类型 |
cast(timestamp as date) | timestamp中的年/月/日的值是依赖与当地的时区,结果返回date类型 |
cast(string as date) | 如果string是YYYY-MM-DD格式的,则相应的年/月/日的date类型的数据将会返回;但如果string不是YYYY-MM-DD格式的,结果则会返回NULL。 |
cast(date as timestamp) | 基于当地的时区,生成一个对应date的年/月/日的时间戳值 |
cast(date as string) | date所代表的年/月/日时间将会转换成YYYY-MM-DD的字符串。 |
字符串转为float:
0: jdbc:hive2://192.168.71.130:10000> select cast(salary as float) from employee;
OK
+---------+
| salary |
+---------+
| 100.3 |
+---------+
1 row selected (0.307 seconds)
7) Null 值
缺少值通过特殊值 - NULL表示。
2. 复杂类型
复杂类型包括ARRAY,MAP,STRUCT,UNION,这些复杂类型是由基础类型组成的。
ARRAY:ARRAY类型是由一系列相同数据类型的元素组成,这些元素可以通过下标来访问。比如有一个ARRAY类型的变量fruits,它是由['apple','orange','mango']组成,那么我们可以通过fruits[1]来访问元素orange,因为ARRAY类型的下标是从0开始的;
MAP
:MAP包含key->value键值对,可以通过key来访问元素。比如”userlist”是一个map类型,其中username是key,password是value;那么我们可以通过userlist['username']来得到这个用户对应的password;
STRUCT
:STRUCT可以包含不同数据类型的元素。这些元素可以通过”点语法”的方式来得到所需要的元素,比如user是一个STRUCT类型,那么可以通过user.address得到这个用户的地址。
UNION
: UNIONTYPE,他是从Hive 0.7.0开始支持的。
1). 数组
在Hive 数组与在Java中使用的方法相同。
Syntax: ARRAY<data_type>
ARRAY是具有相关同类型和名称的变量的集合['John','Doe'] 如:Array(['John','Doe'] )
2). 映射
映射在Hive类似于Java的映射。
Syntax: MAP<primitive_type, data_type>
MAP是一组键值对集合 字段名[last]获取值 如:map('first','Join','last','Doe')
3). 结构体
在Hive结构体类似于使用复杂的数据。
Syntax: STRUCT<col_name : data_type [COMMENT col_comment], ...>
STRUCT列类型为struct{first STRING,last STRING} 如: struct('john','Doe')
4). 示例
name --雇员名,salary --雇员薪水,subordinates --下属员工,deductions --五险一金,个税等,address --雇员的住址
hive> CREATE TABLE employees(name string,salary float,subordinates array<string>,deductions map<string,float>,address struct<street:string,city:string,state:string,zip:int>);
一个雇员表详细信心存储在一张表中,在RDBMS中则可能存在某个字段的信息存储在另外一张表,通过主外键或查询条件进行连接后获取结果。这里就可以通过一些集合数据类型进行处理了。
三、hive的文件格式
TEXTFILE //文本,默认值
SEQUENCEFILE // 二进制序列文件
RCFILE //列式存储格式文件 Hive0.6以后开始支持
ORC //列式存储格式文件,比RCFILE有更高的压缩比和读写效率,Hive0.11以后开始支持
PARQUET //列出存储格式文件,Hive0.13以后开始支持
四、常见问题:
- 分区常见问题
指定location加载不到数据:
指定了表的location但是select不出来数据,而目录确实存在hdfs上。
一个分区一个分区的添加,问题出现的原因是表没有添加到分区,,也就是没有注册,因为数据有可能是之前添加好的再创建表。
检查是否存在分区:
hive> show partitions 表;
表指定location的时候,他只是把表的路径指定一个存储位置,原来有的数据他并不知道,之后再添加的数据他知道,就像是注册一下,以前的东西并没有注册,他不知道里面有数据。
msck repair table 表名;
命令就是把location里面的数据都注册一遍,包括已经注册过的。
网友评论