Hive内部表与外部表区别,数据导入与数据读取方式小结

时间:2021-05-24 06:39:14

原文地址:http://blog.csdn.net/shekey92/article/details/47661051,转载请注明地址。

创建一个外部表:

使用'|'作为分隔符,‘\n’回车作为换行符,指定数据仓库地址

hive> CREATE EXTERNAL TABLE rdcuser (
> id int,
> name string,
> password string
> )
> row format delimited fields terminated by '|'
> LINES TERMINATED BY '\n'
> stored as textfile
> location '/linyu/hivetest/';
OK
Time taken: 0.651 seconds


Hive每创建一个表都会在hive.metastore.warehouse.dir指向的目录下以表名创建一个文件夹,所有属于这个表的数据都存放在这个文件夹里面。如果不指定仓库地址,Hive每创建一个表都会在hive.metastore.warehouse.dir指向的目录下以表名创建一个文件夹,所有属于这个表的数据都存放在这个文件夹里面。

可以切换到mysql查看该表的仓库地址:

mysql> use hivemeta;       //hive在mysql的元数据库

mysql> select * from tbls;

+--------+-------------+-------+------------------+-------+-----------+-------+----------+
| TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER | RETENTION | SD_ID | TBL_NAME |
+--------+-------------+-------+------------------+-------+-----------+-------+----------+
| 11 | 1439456346 | 1 | 0 | root | 0 | 11 | rdcuser |
+--------+-------------+-------+------------------+-------+-----------+-------+----------+


mysql> select * from sds;

+-------+------------------------------------------+------------------------------------+
| SD_ID | INPUT_FORMAT | LOCATION |
+-------+------------------------------------------+------------------------------------+
| 11 | org.apache.hadoop.mapred.TextInputFormat | hdfs://dmp-nn-1:8020/linyu/hivetest|
+-------+------------------------------------------+------------------------------------+

 

查看该目录:

hive> dfs -ls /linyu/hivetest;

hive>

发现这个目录现在为空。

新建hivedata1.txt,

内容为:

1|a|b
2|aa|bb

使用load把本地文件导入到表中:

注意:使用local表示从本地导入,使用的是复制操作,原文件保留,没有local,表示从hdfs文件系统导入,使用的是剪切操作,原目录下的文件将被移除。

hive> load data local inpath '/hivedata1.txt' into table rdcuser;
Copying data from file:/hivedata1.txt
Copying file: file:/hivedata1.txt
Loading data to table default.rdcuser
Table default.rdcuser stats: [numFiles=0, numRows=0, totalSize=0, rawDataSize=0]
OK
Time taken: 1.241 seconds

再次查看该目录:

hive> dfs -ls /linyu/hivetest;

Found 1 items
-rwxr-xr-x 3 root supergroup 13 2015-08-14 14:59 /linyu/hivetest/hivedata1.txt

该目录下已经出现此文件,表示数据已经导入到表中。

hive> select * from rdcuser;

OK
1 a b
2 aa bb
Time taken: 0.504 seconds, Fetched: 2 row(s)

原来,hive的load操作,其实就是把数据文件移动到对应的表目录下。

那么,如果我们不是用load操作,而是直接手动把文件复制到目录下会怎么样呢?如果文件的格式与表结构不同,又会如何?

继续试验:

新建hivedata2.txt,此文件使用了','作为分隔符(建表时使用的是'|')

3,aaa,bbb
4,aaaa,bbbb

新建hivedata3.txt,此文件的数据长短与列定义不符

5|aaaaa|bbbbb|ccccc
6|aaaaaa

手动上传:

# hadoop fs -put /hivedata2.txt /linyu/hivetest

# hadoop fs -put /hivedata3.txt /linyu/hivetest

再次查看该目录:

hive> dfs -ls /linyu/hivetest;

Found 3 items
-rwxr-xr-x 3 root supergroup 13 2015-08-14 14:59 /linyu/hivetest/hivedata1.txt
-rw-r--r-- 3 root supergroup 21 2015-08-14 15:12 /linyu/hivetest/hivedata2.txt
-rw-r--r-- 3 root supergroup 28 2015-08-14 15:12 /linyu/hivetest/hivedata3.txt

hive> select * from rdcuser;

OK
1 a b
2 aa bb
NULL NULL NULL
NULL NULL NULL
5 aaaaa bbbbb
6 aaaaaa NULL
Time taken: 1.566 seconds, Fetched: 6 row(s)


我们发现,所有三个文件都以表内数据的形式被查出来,而不存在建表分隔符的数据全部被标识为NULL,而长度超过表字段数的数据被遗弃,不足的补NULL。

至此我们已经大致了解了hive外部表的数据的存储与读取方式。

再试试内部表:

hive> CREATE TABLE rdcuser2 (
> id int,
> name string,
> password string
> )
> row format delimited fields terminated by '|'
> LINES TERMINATED BY '\n'
> stored as textfile;
OK


由于没有指定存储位置,数据会被存储到上文所述的默认位置:由于没有指定存储位置,数据会被存储到上文所述的默认位置。

 

在看看元数据:

mysql> select * from tbls;

+--------+-------------+-------+------------------+-------+-----------+-------+----------+
| TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER | RETENTION | SD_ID | TBL_NAME |
+--------+-------------+-------+------------------+-------+-----------+-------+----------+
| 11 | 1439456346 | 1 | 0 | root | 0 | 11 | rdcuser |
| 18 | 1439451526 | 1 | 0 | root | 0 | 18 | rdcuser2 |
+--------+-------------+-------+------------------+-------+-----------+-------+----------+


mysql> select * from sds;

+-------+------------------------------------------+-------------------------------------------------+
| SD_ID | INPUT_FORMAT | LOCATION |
+-------+------------------------------------------+-------------------------------------------------+
| 11 | org.apache.hadoop.mapred.TextInputFormat | hdfs://dmp-nn-1:8020/linyu/hivetest |
| 18 | org.apache.hadoop.mapred.TextInputFormat | hdfs://dmp-nn-1:8020/user/hive/warehouse/rdcuser|
+-------+------------------------------------------+-------------------------------------------------+

 

重复上述步骤,来导入数据,我们会发现,内部表与外部表的数据存储、读取方式是相同的,无非就是往对应的hdfs目录复制文件,再以定义的表结构来读取数据。过程不再赘述。

那么,内部表和外部表的区别在哪里?

 

我们再删除表试试。

 

先删除外部表:

hive> drop table rdcuser;

OK
Time taken: 6.054 seconds

 

再删除内部表:

hive> drop table rdcuser2;

Moved: 'hdfs://dmp-nn-1:8020/user/hive/warehouse/rdcuser2' to trash at: hdfs://dmp-nn-1:8020/user/root/.Trash/Current
OK
Time taken: 5.822 seconds


很明显,从命令行返回的过程,删除内部表多了一步:将该表数据仓库移除到回收站中(若未开启回收机制,将被直接删除)

眼见为实,我们再查看一下对应的目录:

hive> dfs -ls /linyu/hivetest;

Found 3 items
-rwxr-xr-x 3 root supergroup 13 2015-08-14 14:59 /linyu/hivetest/hivedata1.txt
-rw-r--r-- 3 root supergroup 21 2015-08-14 15:12 /linyu/hivetest/hivedata2.txt
-rw-r--r-- 3 root supergroup 28 2015-08-14 15:12 /linyu/hivetest/hivedata3.txt
hive> dfs -ls /user/hive/warehouse/rdcuser2;

外部表的三个数据文件依然健在。

 

hive> dfs -ls /user/hive/warehouse/rdcuser2;

ls: `/user/hive/warehouse/rdcuser2': No such file or directory
Command failed with exit code = 1
Query returned non-zero code: 1, cause: null

内部表目录已经人去楼空。

在看看元数据:

mysql> select * from tbls;

Empty set (0.00 sec)

mysql> select * from sds;

Empty set (0.00 sec)

 

总结:

1.hive无论是内部表还是外部表,无非就是往对应的hdfs目录复制文件,再以定义的表结构来读取数据。

2.hive删除内部表时,会连同数据文件、元数据一起删除,而外部表仅删除表里的元数据,数据文件不会删除。

 

原文地址:http://blog.csdn.net/shekey92/article/details/47661051,转载请注明地址。