外部表和内部表
不管是外部表还是内部表,location为默认值的话,创建表的时候都会在数据库文件夹下产生和表同名的文件夹。内部表删除,文件夹和文件夹下的数据都会删除。外部表不会。
mysql> select * from DBS;
+-------+-----------------------+---------------------------------------------------------+------------+------------+------------+
| DB_ID | DESC | DB_LOCATION_URI | NAME | OWNER_NAME | OWNER_TYPE |
+-------+-----------------------+---------------------------------------------------------+------------+------------+------------+
| 1 | Default Hive database | hdfs://hadoop000:8020/user/hive/warehouse | default | public | ROLE |
| 2 | NULL | hdfs://hadoop000:8020/user/hive/warehouse/test_db.db | test_db | hadoop | USER |
| 6 | NULL | hdfs://hadoop000:8020/user/hive/warehouse/enterprise.db | enterprise | hadoop | USER |
| 11 | NULL | hdfs://hadoop000:8020/user/hive/warehouse/sogou.db | sogou | hadoop | USER |
| 16 | NULL | hdfs://hadoop000:8020/user/hive/warehouse/car.db | car | hadoop | USER |
| 22 | NULL | hdfs://hadoop000:8020/user/hive/warehouse/weibo.db | weibo | hadoop | USER |
+-------+-----------------------+---------------------------------------------------------+------------+------------+------------+
6 rows in set (0.00 sec)
location为自己指定的话,不会产生和表同名的文件夹。
实际开发,一般用外部表,因为可以进行数据共享,并且删除表不会删除数据。
external 和 location是搭配使用的,因为不同的外部表可以共用指定location的一份数据,不能使用默认的location,不然一个表就会产生一个文件夹,比较麻烦。
create external table customer_1(
name string,
age int,
sex string,
native string
)
row format delimited
fields terminated by '\t'
location '/data/customer_1';
mysql> select * from TBLS;
| TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER | RETENTION | SD_ID | TBL_NAME | TBL_TYPE | VIEW_EXPANDED_TEXT | VIEW_ORIGINAL_TEXT |
| 2 | 1583675306 | 2 | 0 | hadoop | 0 | 2 | helloworld | MANAGED_TABLE | NULL | NULL |
| 12 | 1596515822 | 6 | 0 | hadoop | 0 | 12 | employee | MANAGED_TABLE | NULL | NULL |
| 18 | 1596541763 | 6 | 0 | hadoop | 0 | 18 | product_2 | EXTERNAL_TABLE | NULL | NULL |
| 20 | 1596542579 | 6 | 0 | hadoop | 0 | 20 | product_1 | EXTERNAL_TABLE | NULL | NULL
删除hive表就是删除 TBLS 表中的一行元数据。
分区和分桶
Hive Load语句不会在加载数据的时候做任何转换工作,而是纯粹的把数据文件复制/移动到Hive表对应的地址。所以load操作只能争对静态分区。
hive> create external table consumer_patition_2(
> name string,
> age int
> )
> partitioned by (sex string, native string)
> row format delimited
> fields terminated by '\t'
> location '/data/customer_2';
静态分区,所load的文件中只能有name和age两列,并且在命令后面指定partition。
动态分区,则需要进行insert overwrite操作,则要运行mapreduce 。
先构建有四列不分区的表,再将这个表导入到分区表中。
hive> insert overwrite table consumer_patition_2 partition(sex, native) select name,age,sex,native from customer_1;
[hadoop@hadoop000 ~]$ hadoop fs -ls /data/customer_2
Found 2 items
drwxr-xr-x - hadoop supergroup 0 2021-02-08 17:36 /data/customer_2/sex=man
drwxr-xr-x - hadoop supergroup 0 2021-02-08 17:36 /data/customer_2/sex=women
[hadoop@hadoop000 sbin]$ hadoop fs -ls /data/customer_2/sex=man/native=GanSu
Found 1 items
-rwxr-xr-x 1 hadoop supergroup 37 2021-02-08 17:36 /data/customer_2/sex=man/native=GanSu/000000_0
会产生分级文件夹,一层分区就是一层文件夹,两层分区就是两层文件夹。
分桶是将一个文件按照某列哈希取余的方法拆成很多文件。
创造表的时候就指定分几个桶。
load命令无效,也需要进行insert overwrite操作,则要运行mapreduce 。
000000_0文件
本来helloworld表下有hive_table.data,里面有三行数据。
1 zhangsan
2 lisi
3 wangwu
执行insert into语句,会运行MR。
hive> insert into helloworld values (4,"zhulian");
表下多了一个000000_0文件。
[hadoop@hadoop000 ~]$ hadoop fs -ls /user/hive/warehouse/test_db.db/helloworld
Found 2 items
-rwxr-xr-x 1 hadoop supergroup 10 2021-02-08 16:06 /user/hive/warehouse/test_db.db/helloworld/000000_0
-rwxr-xr-x 1 hadoop supergroup 27 2020-03-08 21:52 /user/hive/warehouse/test_db.db/helloworld/hive_table.data
[hadoop@hadoop000 ~]$ hadoop fs -cat /user/hive/warehouse/test_db.db/helloworld/000000_0
4 zhulian
hive> select * from helloworld;
OK
4 zhulian
1 zhangsan
2 lisi
3 wangwu
Time taken: 0.062 seconds, Fetched: 4 row(s)