原文地址: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,转载请注明地址。