表操作

Create:表创建

Create Table 用于在 Hive 中创建表,其语法如下所示,注意,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]

譬如当我们希望创建如下的包含 Employee 新的表时,数据格式和域如下:

Sr.No Field Name Data Type
1 Eid int
2 Name String
3 Salary Float
4 Designation string
然后如下的语句会指定该表的注释、不同的域的分隔符、不同的行的分隔符,以及存储的文件类型:
COMMENT ‘Employee details’
FIELDS TERMINATED BY ‘\t’
LINES TERMINATED BY ‘\n’
STORED IN TEXT FILE

然后完整的创建语句为:

hive> CREATE TABLE IF NOT EXISTS employee ( eid int, name String,
salary String, destination String)
COMMENT ‘Employee details’
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘\t’
LINES TERMINATED BY ‘\n’
STORED AS TEXTFILE;

如果你添加了IF NOT EXISTS选项,Hive 会在表存在的情况下忽略掉创建,在成功执行该语句之后,你会得到如下的响应:

OK
Time taken: 5.905 seconds
hive>

Java Programming

import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.DriverManager;

public class HiveCreateTable {
   private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";

   public static void main(String[] args) throws SQLException {

      // Register driver and create driver instance
      Class.forName(driverName);

      // get connection
      Connection con = DriverManager.getConnection("jdbc:hive://localhost:10000/userdb", "", "");

      // create statement
      Statement stmt = con.createStatement();

      // execute statement
      stmt.executeQuery("CREATE TABLE IF NOT EXISTS "
         +" employee ( eid int, name String, "
         +" salary String, destignation String)"
         +" COMMENT ‘Employee details’"
         +" ROW FORMAT DELIMITED"
         +" FIELDS TERMINATED BY ‘\t’"
         +" LINES TERMINATED BY ‘\n’"
         +" STORED AS TEXTFILE;");

      System.out.println(“ Table employee created.”);
      con.close();
   }
}

内表 VS 外表

Hive 默认创建的表为内部表,内部表与外部表的区别可以归纳为:

  • 在导入数据到外部表,数据并没有移动到自己的数据仓库目录下(如果指定了 location 的话),也就是说外部表中的数据并不是由它自己来管理的!而内部表则不一样;
  • 在删除内部表的时候,Hive 将会把属于表的元数据和数据全部删掉;而删除外部表的时候,Hive 仅仅删除外部表的元数据,数据是不会删除的!
  • 在创建内部表或外部表时加上 location 的效果是一样的,只不过表目录的位置不同而已,加上 partition 用法也一样,只不过表目录下会有分区目录而已,load data local inpath 直接把本地文件系统的数据上传到 hdfs 上,有 location 上传到 location 指定的位置上,没有的话上传到 hive 默认配置的数据仓库中。

内表

(1)创建不带分区的内表 首先创建一个表,注意,Hive 创建成功的表即使你输入的是大写,也会被转化为小写:

create table innertable(id int,name string) row format delimited fields terminated by '|';

然后我们从 HDFS 上加载数据:

load data inpath 'hdfs://master:9000/user/root/test/innerTable' into table innertable;

查看 HDFS 上/user/root/test/innerTable,发现文件价 innerTable 还在,但是里面的文件已经不在了。去哪了,去 innertable 表中了。然后删除刚刚创建的表:

drop table innertable;

到 HDFS 上看一下 innertable 文件夹及其中的文件都没有了。去哪了,删除表的时候删除了。 (2)带分区的内表 使用如下命令创建表:

create table inner_table_with_p(id int,name string) partitioned by (part_num int);
#从HDFS加载数据
load data inpath 'hdfs://master:9000/user/root/test/innerTable/part1' into table inner_table_with_p partition(part_num=1)(文件夹inner_table_with_p出现子文件夹part_num=1,innerTable中 part1消失);
load data inpath 'hdfs://master:9000/user/root/test/innerTable/part2' into table inner_table_with_p partition(part_num=2)(文件夹inner_table_with_p出现子文件夹part_num=2,innerTable中 part2消失);

load data inpath ‘hdfs://master:9000/user/root/test/innerTable/part3’ into table inner_table_with_p partition(part_num=3)(文件夹 inner_table_with_p 出现子文件夹 part_num=3,innerTable 中 part3 消失);#删除分区 alter table inner_table_with_p drop partition(part_num=1);(part_num=1 对应分区文件夹本删除)
#删除表 drop table inner_table_with_p;(HDFS 上 inner_table_with_p 文件夹被删除)

外表

(1)不带分区的外表 创建表 create external table outer_table(id int,name string) row format delimited fields terminated by ‘|’; (hive 仓储目录中出现 outer_table)
加载数据 load data inpath ‘/user/root/test/outerTable/outer’ into table outer_table;(outer_table 中出现子文件 outer,outerTable 中 outer 消失)
删除表 drop table outer_table; (outer_table 及子文件 outer 依然存在,因为这是外表) (2)带分区的外表 创建表 create external table outer_table_with_p(id int,name string) partitioned by (part_num int) row format delimited fields terminated by ‘|’; (hive 仓储目录中出现 outer_table_with_p)
加载数据 load data inpath ‘/user/root/test/outerTable/part1’ into table outer_table_with_p partiton(part_num=1); (outer_table_with_p 中出现子文件夹 part_num=1) load data inpath ‘/user/root/test/outerTable/part2’ into table outer_table_with_p partition(part_num=2);(outer_table_with_p 中出现子文件夹 part_num=2) load data inpath ‘/user/root/test/outerTable/part3’ into table outer_table_with_p partition(part_num=3);(outer_table_with_p 中出现子文件夹 part_num=3)
删除分区 alter table outer_table_with_p drop partition(part_num=1);(HDFS 上分区文件依旧存在)
删除表
drop table outer_table_with_p;(HDFS 上对应数据依旧存在)

Partition:表分区

在 Hive Select 查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。有时候只需要扫描表中关心的一部分数据,因此建表时引入了 partition 概念。分区表指的是在创建表时指定的 partition 的分区空间。Hive 可以对数据按照某列或者某些列进行分区管理,所谓分区我们可以拿下面的例子进行解释。当前互联网应用每天都要存储大量的日志文件,几 G、几十 G 甚至更大都是有可能。存储日志,其中必然有个属性是日志产生的日期。在产生分区时,就可以按照日志产生的日期列进行划分。把每一天的日志当作一个分区。将数据组织成分区,主要可以提高数据的查询速度。至于用户存储的每一条记录到底放到哪个分区,由用户决定。即用户在加载数据的时候必须显示的指定该部分数据放到哪个分区。创建表分区的语法格式为:

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]

分区创建

单分区

  • 创建一个分区表,以 ds 为分区列:
create table invites (id int, name string) partitioned by (ds string) row format delimited fields terminated by 't' stored as textfile;
  • 将数据添加到时间为 2013-08-16 这个分区中:
load data local inpath '/home/hadoop/Desktop/data.txt' overwrite into table invites partition (ds='2013-08-16');
  • 将数据添加到时间为 2013-08-20 这个分区中:
load data local inpath '/home/hadoop/Desktop/data.txt' overwrite into table invites partition (ds='2013-08-20');
  • 从一个分区中查询数据:
select * from invites where ds ='2013-08-12';
  • 往一个分区表的某一个分区中添加数据:
insert overwrite table invites partition (ds='2013-08-12') select id,max(name) from test group by id;

可以查看分区的具体情况,使用命令:

hadoop fs -ls /home/hive/warehouse/invites

或者:

show partitions tablename;

Bucket:桶

对于每一个表(table)或者分区,Hive 可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive 也是针对某一列进行桶的组织。Hive 采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。把表(或者分区)组织成桶(Bucket)有两个理由:

  • 获得更高的查询处理效率。桶为表加上了额外的结 构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如 JOIN 操作。对于 JOIN 操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行 JOIN 操 作就可以,可以大大较少 JOIN 的数据量。
  • 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

多分区

双分区建表语句:create table day_hour_table (id int, content string) partitioned by (dt string, hour string);双分区表,按天和小时分区,在表结构中新增加了 dt 和 hour 两列。

Drop:表删除

上一页
下一页