[一起学Hive]—Hive中的数据库(Database)和表(Table)

本文详细介绍Hive中的数据库和表的基本概念,包括Hive如何组织数据、数据库和表的创建、修改及删除操作,以及内部表和外部表的区别。

在 前面的文章 中,介绍了可以把Hive当成一个“数据库”,它也具备传统数据库的数据单元,数据库(Database/Schema)和表(Table)。

本文介绍一下Hive中的数据库(Database/Schema)和表(Table)的基础知识,由于篇幅原因,这里只是一些常用的、基础的。

二、Hive的数据库和表

先看一张草图:

Hive结构

从图上可以看出,Hive作为一个“数据库”,在结构上积极向传统数据库看齐,也分数据库(Schema),每个数据库下面有各自的表组成。

1.  Hive在HDFS上的默认存储路径

Hive的数据都是存储在HDFS上的,默认有一个根目录,在hive-site.xml中,由参数 hive.metastore.warehouse.dir 指定。默认值为/user/hive/warehouse.

2.  Hive中的数据库(Database)

  • 进入Hive命令行,执行 show databases; 命令,可以列出hive中的所有数据库,默认有一个default数据库,进入Hive-Cli之后,即到default数据库下。
  • 使用 use databasename; 可以切换到某个数据库下,同mysql;
hive> show databases;
OK
default
lxw1234
usergroup_mdmp
userservice_mdmp
Time taken: 0.442 seconds, Fetched: 4 row(s)
hive> use lxw1234;
OK
Time taken: 0.023 seconds
hive>
  • Hive 中的数据库在HDFS 上的存储路径为 :

${hive.metastore.warehouse.dir}/databasename.db

比如,名为lxw1234的数据库存储路径为:

/user/hive/warehouse/lxw1234.db

  • 创建Hive 数据库

使用HDFS超级用户,进入Hive-Cli,语法为:

CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];

比如,创建名为lxw1234的数据库:

CREATE DATABASE IF NOT EXISTS lxw1234
COMMENT 'lxw的大数据田地-lxw1234.com'
localtion 'hdfs://namenode/user/lxw1234/lxw1234.db/';

创建时候可以指定数据库在HDFS上的存储位置。

注意:使用HDFS超级用户创建数据库后,该数据库在HDFS上的存储路径的属主为超级用户,如果该数据库是为某个或者某些用户使用的,则需要修改路径属主,或者在Hive中进行授权。

  • 修改数据库

修改数据库属性:

ALTER (DATABASE|SCHEMA) database_name

SET DBPROPERTIES (property_name=property_value, …);

修改数据库属主:

ALTER (DATABASE|SCHEMA) database_name

SET OWNER [USER|ROLE] user_or_role;

  • 删除数据库

DROP (DATABASE|SCHEMA) [IF EXISTS] database_name

[RESTRICT|CASCADE];

默认情况下,Hive不允许删除一个里面有表存在的数据库,如果想删除数据库,要么先将 数据库中的表全部删除,要么可以使用CASCADE关键字,使用该关键字后,Hive会自己将数据库下的表全部删除。RESTRICT关键字就是默认情 况,即如果有表存在,则不允许删除数据库。

3.  Hive中的表(Table)

3.1 查看所有的表

进入Hive-Cli,使用use databasename;切换到数据库之后,执行show tables; 即可查看该数据库下所有的表:

hive> show tables;
OK
lxw1
lxw1234
table1
t_site_log

3.2 表的存储路径

默认情况下,表的存储路径为:

${hive.metastore.warehouse.dir}/databasename.db/tablename/

可以使用 desc formatted tablename; 命令查看表的详细信息,其中包括了存储路径:

Location:               hdfs://cdh5/hivedata/warehouse/lxw1234.db/lxw1234

3.3 内部表和外部表

Hive中的表分为内部表(MANAGED_TABLE)和外部表(EXTERNAL_TABLE)。

  • 内部表和外部表最大的区别

内部表DROP时候 会删除 HDFS上的数据;

外部表DROP时候 不会删除 HDFS上的数据;

  • 内部表适用场景:

Hive中间表、结果表、一般不需要从外部(如本地文件、HDFS上load数据)的情况。

  • 外部表适用场景:

源表,需要定期将外部数据映射到表中。

  • 我们的使用场景:

每天将收集到的网站日志定期流入HDFS文本文件,一天一个目录;

在Hive中建立外部表作为源表,通过添加分区的方式,将每天HDFS上的原始日志映射到外部表的天分区中;

在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT进入内部表。

3.4 创建表

创建表的语法选项特别多,这里只列出常用的选项。

其他请参见Hive官方文档:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable

以一个例子来说吧:

CREATE EXTERNAL TABLE t_lxw1234 (

id INT,

ip STRING COMMENT ‘访问者IP’,

avg_view_depth DECIMAL(5,1),

bounce_rate DECIMAL(6,5)

) COMMENT ‘lxw的大数据田地-lxw1234.com’

PARTITIONED BY (day STRING)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY ‘,’

STORED AS textfile

LOCATION ‘hdfs://cdh5/tmp/lxw1234/';

  • 关键字 EXTERNAL :

表示该表为外部表,如果不指定EXTERNAL关键字,则表示内部表

  • 关键字 COMMENT

为表和列添加注释

  • 关键字 PARTITIONED BY

表示该表为分区表,分区字段为day,类型为string

  • 关键字 ROW FORMAT DELIMITED

指定表的分隔符,通常后面要与以下关键字连用:

FIELDS TERMINATED BY ‘,’ //指定每行中字段分隔符为逗号

LINES TERMINATED BY ‘\n’ //指定行分隔符

COLLECTION ITEMS TERMINATED BY ‘,’ //指定集合中元素之间的分隔符

MAP KEYS TERMINATED BY ‘:’ //指定数据中Map类型的Key与Value之间的分隔符

举个例子:

create table score(name string, score map<string,int>)

ROW FORMAT DELIMITED

FIELDS TERMINATED BY ‘\t’

COLLECTION ITEMS TERMINATED BY ‘,’

MAP KEYS TERMINATED BY ‘:';

要加载的文本数据为:

biansutao ‘数学':80,’语文':89,’英语':95

jobs ‘语文':60,’数学':80,’英语':99

  • 关键字 STORED AS

指定表在HDFS上的文件存储格式,可选的文件存储格式有:

TEXTFILE //文本,默认值

SEQUENCEFILE // 二进制序列文件

RCFILE //列式存储格式文件 Hive0.6以后开始支持

ORC //列式存储格式文件,比RCFILE有更高的压缩比和读写效率,Hive0.11以后开始支持

PARQUET //列出存储格式文件,Hive0.13以后开始支持

  • 关键词 LOCATION

指定表在HDFS上的存储位置。

Hive相关文章(持续更新) :

一起学Hive系列

Hive分析函数系列

Hive索引

hive优化之——控制hive任务中的map数和reduce数

<think>我们正在处理Hive中将数据库A中的迁移到另一个数据库的需求。在Hive中,没有直接的“迁移”命令,但可以通过以下步骤实现: 1. 在目标数据库创建相同的结构(可以使用CREATE TABLE ... LIKE) 2. 将数据从原插入到目标(使用INSERT OVERWRITE或INSERT INTO) 3. 删除原(如果需要) 但是,如果很多,手动操作会很麻烦。我们可以编写脚本自动完成。 另外,Hive的元数据存储在关系型数据库中(如MySQL),直接修改元数据也是一种方法,但风险较大,一般不建议,因为容易导致元数据不一致。 因此,推荐使用第一种方法:通过脚本来迁移。 步骤: 1. 获取数据库A的所有名。 2. 对于每个: a. 在目标数据库中创建相同结构的(使用LIKE语法)。 b. 将数据从原插入到目标。 注意:如果是外部,还需要考虑数据位置的问题。如果是内部,数据位置由Hive管理。 另外,如果两个数据库在同一个Hive实例中,可以使用以下方式: 但是,如果很多,我们可以生成一个脚本。 示例脚本(HiveQL): 假设源数据库名为`db_a`,目标数据库名为`db_b`。 步骤1:生成创建的语句并执行 步骤2:生成插入数据的语句并执行 我们可以使用Hive的`SHOW TABLES IN db_a`来获取所有,然后使用`DESCRIBE FORMATTED db_a.table`来获取结构,但这样比较复杂。 更简单的方法:使用`SHOW CREATE TABLE`来获取创建的语句,然后替换数据库名。 例如: ``` SHOW TABLES IN db_a; ``` 将返回所有名,然后对于每个: ``` SHOW CREATE TABLE db_a.table_name; ``` 将输出创建的语句,然后将语句中的`db_a`替换为`db_b`,并执行。 然后插入数据: ``` INSERT OVERWRITE TABLE db_b.table_name SELECT * FROM db_a.table_name; ``` 但是,如果有分区,那么需要处理分区。另外,如果数据量很大,插入操作可能会很慢。 对于分区,我们可以使用动态分区插入来优化。 因此,完整的迁移脚本需要根据的类型(是否分区)来调整。 由于操作涉及大量数据,建议在非高峰时段进行。 另外,如果两个数据库不在同一个Hive实例中,那么可能需要先导出数据到外部存储(如HDFS),然后再导入到目标实例。 但是,问题中并没有提到跨实例,我们假设在同一个Hive实例中。 下面是一个Shell脚本的示例,用于生成迁移脚本: 生成建语句的脚本: ```bash #!/bin/bash # 设置源数据库目标数据库 SRC_DB="db_a" TGT_DB="db_b" # 获取所有 tables=$(hive -e "USE $SRC_DB; SHOW TABLES;") # 生成建语句文件 hive -e "USE $SRC_DB; SHOW TABLES;" | while read table do # 获取建语句并替换数据库hive -e "SHOW CREATE TABLE ${SRC_DB}.${table};" | sed "s/$SRC_DB\./$TGT_DB./g" | sed "s/^CREATE TABLE /CREATE TABLE IF NOT EXISTS /g" > create_table_${table}.sql # 执行建语句 hive -f create_table_${table}.sql done ``` 生成数据插入语句并执行: ```bash #!/bin/bash SRC_DB="db_a" TGT_DB="db_b" tables=$(hive -e "USE $SRC_DB; SHOW TABLES;") for table in $tables do # 插入数据,使用OVERWRITE覆盖目标 hive -e "INSERT OVERWRITE TABLE ${TGT_DB}.${table} SELECT * FROM ${SRC_DB}.${table};" done ``` 注意:上面的脚本是简化版,实际中需要考虑分区、桶、事务等复杂情况,以及错误处理。 另外,如果有分区,那么上面的插入语句可能会因为动态分区设置而失败。因此,在插入前需要设置动态分区模式: ``` set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict; ``` 如果数据量非常大,可以考虑使用distcp复制底层HDFS数据,然后修复元数据。但这种方法只适用于内部,且需要知道的数据位置。 步骤: 1. 创建目标(同上) 2. 使用distcp将HDFS上的源数据目录复制到目标数据目录 3. 使用MSCK REPAIR TABLE修复分区(如果是分区) 例如: ``` hadoop distcp hdfs:///user/hive/warehouse/db_a.db/table hdfs:///user/hive/warehouse/db_b.db/table ``` 然后对于分区,执行: ``` MSCK REPAIR TABLE db_b.table; ``` 这种方法更快,但同样需要谨慎操作。 综上所述,根据具体情况选择方法。 由于用户没有提供更多细节,我们给出一般方法。 相关问题: 1. 在Hive中迁移时,如何处理分区? 2. 如何批量修改Hive的存储位置? 3. 使用distcp迁移Hive数据时需要注意什么?</think>### Hive 数据库迁移方法 在 Hive 中将数据库 A 的迁移到数据库 B 可以通过以下两种主要方法实现: #### 方法 1:使用 `CREATE TABLE AS SELECT`(推荐) ```sql -- 步骤 1:在目标数据库创建新并复制数据 USE database_b; CREATE TABLE table_name STORED AS ORC -- 指定存储格式(需与原一致) AS SELECT * FROM database_a.table_name; -- 步骤 2:验证数据行数 SELECT COUNT(*) FROM database_b.table_name; SELECT COUNT(*) FROM database_a.table_name; -- 应相同 ``` **优点**: ✅ 自动处理结构数据迁移 ✅ 兼容分区、外部等复杂结构 ✅ 可转换存储格式(如 TEXT 转 ORC) **缺点**: ⏱️ 大数据集时耗时较长 #### 方法 2:元数据库直接修改(高风险) ```sql -- 仅适用于相同存储格式的紧急迁移 UPDATE TBLS SET DB_ID = (SELECT DB_ID FROM DBS WHERE NAME = 'database_b') WHERE TBL_NAME = 'table_name' AND DB_ID = (SELECT DB_ID FROM DBS WHERE NAME = 'database_a'); ``` **注意**: ⚠️ 需访问 Hive数据库(如 MySQL) ⚠️ 必须保持路径不变 ⚠️ 需同步更新分区元数据(`PARTITIONS` ) **风险**: ❌ 元数据不一致可能导致查询失败 ❌ 需停止 Hive 服务操作 --- ### 最佳实践建议 1. **分区处理** 动态分区迁移需添加配置: ```sql SET hive.exec.dynamic.partition=true; SET hive.exec.dynamic.partition.mode=nonstrict; CREATE TABLE database_b.part_table PARTITIONED BY (dt STRING) AS SELECT * FROM database_a.part_table; ``` 2. **外部迁移** 需保持数据位置不变: ```sql CREATE EXTERNAL TABLE database_b.ext_table(...) LOCATION 'hdfs:///path/to/existing/data' ``` 3. **批量迁移脚本** ```bash # 生成迁移脚本 hive -e "USE database_a; SHOW TABLES;" | awk '{print "CREATE TABLE database_b."$1" AS SELECT * FROM database_a."$1";"}' > migrate.hql # 执行迁移 hive -f migrate.hql ``` 4. **数据验证** 推荐使用 `CHECKSUM` 对比: ```sql SELECT SUM(CRC32(*)) FROM database_a.table; SELECT SUM(CRC32(*)) FROM database_b.table; -- 值应相同 ``` --- ### 注意事项 1. 权限配置:迁移后需在 Ranger 重新配置级权限[^1] 2. 存储空间:确保 HDFS 有足够空间容纳副本 3. 事务:需在迁移前关闭事务 (`SET hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager`) 4. 视图迁移:视图需手动重建,`CREATE VIEW` 不支持跨库引用 > **关键提示**:对于 TB 级大,建议使用 `INSERT OVERWRITE DIRECTORY` 配合 HDFS DistCp 进行迁移,可减少 30-50% 时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值