From 74c068c1666ff20670d73c5995c639fc311cd2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Sat, 27 Apr 2019 10:26:39 +0800 Subject: [PATCH] Hive --- README.md | 15 +- notes/HiveShell基本使用.md | 0 notes/Hive分区表和分桶表.md | 171 ++++++++++++++++++ notes/Hive常用DDL操作.md | 114 +++++++++++- ...件格式.md => Hive核心概念讲解.md} | 17 +- pictures/HashMap-HashTable.png | Bin 0 -> 29477 bytes pictures/hive-hadoop-bucket.png | Bin 0 -> 38701 bytes pictures/hive-hadoop-mapreducer.png | Bin 0 -> 55714 bytes pictures/hive-hadoop-partitation.png | Bin 0 -> 57351 bytes 9 files changed, 303 insertions(+), 14 deletions(-) create mode 100644 notes/HiveShell基本使用.md create mode 100644 notes/Hive分区表和分桶表.md rename notes/{Hive数据类型和文件格式.md => Hive核心概念讲解.md} (84%) create mode 100644 pictures/HashMap-HashTable.png create mode 100644 pictures/hive-hadoop-bucket.png create mode 100644 pictures/hive-hadoop-mapreducer.png create mode 100644 pictures/hive-hadoop-partitation.png diff --git a/README.md b/README.md index 2b14c53..c383d6b 100644 --- a/README.md +++ b/README.md @@ -58,14 +58,15 @@ ## 二、Hive -1. [数据仓库Hive](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive.md) +1. [数据仓库Hive简介](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive.md) 2. [Linux环境下Hive的安装部署](https://github.com/heibaiying/BigData-Notes/blob/master/notes/installation/Linux%E7%8E%AF%E5%A2%83%E4%B8%8BHive%E7%9A%84%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2.md) -3. Hive shell基本使用 -4. Hive 数据类型和文件格式 -5. Hive 常用 DDL操作 -6. Hive 数据查询 -7. Hive 视图和索引 -8. Hive 模式设计 +3. [Hive Shell基本使用](https://github.com/heibaiying/BigData-Notes/blob/master/notes/HiveShell基本使用.md) +4. [Hive 核心概念讲解](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive核心概念讲解.md) +5. [Hive 分区表和分桶表](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive分区表和分桶表.md) +6. [Hive 常用DDL操作](https://github.com/heibaiying/BigData-Notes/blob/master/notes/Hive常用DDL操作.md) +7. Hive 数据查询 +8. Hive 视图和索引 +9. Hive 模式设计 ## 三、Spark diff --git a/notes/HiveShell基本使用.md b/notes/HiveShell基本使用.md new file mode 100644 index 0000000..e69de29 diff --git a/notes/Hive分区表和分桶表.md b/notes/Hive分区表和分桶表.md new file mode 100644 index 0000000..e9f898b --- /dev/null +++ b/notes/Hive分区表和分桶表.md @@ -0,0 +1,171 @@ +# Hive分区表和分桶表 + + + + +## 一、分区表 + +### 1.1 概念 + +Hive中的表表现为HDFS上的某个目录,在查询数据时候,默认都会对全表进行扫描,这样时间和性能的消耗都非常大。 + +**分区表现为HDFS上表目录的子目录**,数据按照分区存储在子目录中。如果查询的`where`字句的中包含分区条件,则直接从该分区去查找,而不是扫描整个表目录,合理的分区设计可以极大提高查询速度和性能。 + +>这里说明一下分区表并Hive独有的概念,实际上这个概念非常常见。比如在我们常用的Oracle数据库中,当表中的数据量不断增大,查询数据的速度就会下降,这时也可以对表进行分区。表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据存放到多个表空间(物理文件上),这样查询数据时,就不必要每次都扫描整张表,从而提升查询性能。 + +### 1.2 使用场景 + +通常,在管理大型生产数据集的时候都需要进行分区,比如在日志文件分析的项目中,通过按天进行分区,从而保证数据的细粒度划分,使得查询性能得以提升。 + +### 1.3 创建分区表 + +在Hive中可以使用`PARTITIONED BY`子句创建分区表。表可以包含一个或多个分区列,程序会为分区列中的每个不同值组合创建单独的数据目录。下面的我们创建一张雇员表作为测试: + +```shell + CREATE EXTERNAL TABLE emp_partition( + empno INT, + ename STRING, + job STRING, + mgr INT, + hiredate TIMESTAMP, + sal DECIMAL(7,2), + comm DECIMAL(7,2) + ) + PARTITIONED BY (deptno INT) -- 按照部门编号进行分区 + ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t" + LOCATION '/hive/emp_partition'; +``` + +### 1.4 加载数据到分区表 + +加载数据到分区表时候必须要指定数据所处的分区。 + +```shell +# 加载部门编号为20的数据到表中 +LOAD DATA LOCAL INPATH "/usr/file/emp20.txt" OVERWRITE INTO TABLE emp_partition PARTITION (deptno=20) +# 加载部门编号为30的数据到表中 +LOAD DATA LOCAL INPATH "/usr/file/emp30.txt" OVERWRITE INTO TABLE emp_partition PARTITION (deptno=30) +``` + +### 1.5 查看分区目录 + +这时候我们直接查看表目录,可以看到表目录下存在两个目录,分别是`deptno=20`和`deptno=30`,这就是分区目录,分区目录下才是我们加载的数据文件。 + +```shell +# hadoop fs -ls hdfs://hadoop001:8020/hive/emp_partition/ +``` + +这时候当你的查询语句的`where`包含`deptno=20`,则就去对应的分区目录下进行查找,而不用扫描全表。 + +
+ + + +## 二、分桶表 + +### 1.1 简介 + +分区提供了一个隔离数据和优化查询的可行方案,但是并非所有的数据集都可以形成合理的分区,分区的数量也不是越多越好,过多的分区条件可能会导致很多分区上并没有数据。同时Hive会限制动态分区可以创建的最大分区数,用来避免过多分区文件的产生而对文件系统的处理能力产生负担。鉴于以上原因,Hive还提供了一种更加细粒度的数据拆分方案:分桶表(bucket Table)。 + +分桶表会将指定列的值进行哈希散列,并对bucket(桶数量)取余,然后存储到对应的bucket(桶)中。 + +### 1.2 理解分桶表 + +单从概念上理解分桶表可能会比较晦涩,其实和分区一样,分桶这个概念同样不是Hive独有的,实际上对于Java开发人员而言,这可能是一个每天都会用到的概念,因为Hive中的分桶概念和Java数据结构中的HashMap的分桶概念是一致的。 + +在HashMap中,当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket(桶)位置,最后将键值对存储在对应桶的链表结构中,链表达到一定阈值后会转换为红黑树(JDK1.8+)。下图为HashMap的数据结构图: + +
+ +> 图片引用自:[HashMap vs. Hashtable](http://www.itcuties.com/java/hashmap-hashtable/) + +### 1.3 创建分桶表 + +在Hive中,我们可以通过`CLUSTERED BY`指定分桶列,并通过`SORTED BY`指定桶中数据排序参考列。下面为分桶表的建表语句示例: + +```sql + CREATE EXTERNAL TABLE emp_bucket( + empno INT, + ename STRING, + job STRING, + mgr INT, + hiredate TIMESTAMP, + sal DECIMAL(7,2), + comm DECIMAL(7,2), + deptno INT) + CLUSTERED BY(empno) SORTED BY(empno ASC) INTO 4 BUCKETS --按照员工编号散列到四个bucket中 + ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t" + LOCATION '/hive/emp_bucket'; +``` + +### 1.4 加载数据到分桶表 + +这里直接使用`Load`语句向分桶表加载数据,数据时可以加载成功的,但是数据并不会分桶。 + +这是由于分桶的实质是对指定字段做了hash散列然后存放到对应文件中,这意味着向分桶表中插入数据是必然要通过MapReduce,且Reducer的数量必须等于分桶的数量。由于以上原因,分桶表的数据通常只能使用CTAS(CREATE TABLE AS SELECT)方式插入,因为CTAS操作会触发MapReduce。加载数据步骤如下: + +#### 1. 设置强制分桶 + +```sql +set hive.enforce.bucketing = true; --Hive 2.x不需要这一步 +``` + +需要在插入分桶的时候hash, **也就是说向分桶表中插入数据的时候必然要执行一次MAPREDUCE,** + +在Hive 0.x and 1.x版本,必须使用设置`hive.enforce.bucketing = true`,表示强制分桶,允许程序根据表结构自动选择正确数量的Reducer和cluster by column来进行分桶。 + +#### 2. CTAS导入数据 + +```sql +INSERT INTO TABLE emp_bucket SELECT * FROM emp; --这里的emp表就是一张普通的雇员表 +``` + +可以从执行日志看到CTAS触发MapReduce操作,且Reducer数量和建表时候指定bucket数量一致: + +
+ +### 1.5 查看分桶文件 + +bucket(桶)本质上就是表目录下的具体文件: + +
+ + + +## 三、分区表和分桶表结合使用 + +分区表和分桶表的本质都是将数据按照不同粒度进行拆分,从而使得在查询时候不必扫描全表,只需要扫描对应的分区或分桶,从而提升查询效率。两者可以结合起来使用,从而保证表数据在不同粒度上都能得到合理的拆分。下面是Hive官方给出的示例: + +```sql +CREATE TABLE page_view_bucketed( + viewTime INT, + userid BIGINT, + page_url STRING, + referrer_url STRING, + ip STRING ) + PARTITIONED BY(dt STRING) + CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS + ROW FORMAT DELIMITED + FIELDS TERMINATED BY '\001' + COLLECTION ITEMS TERMINATED BY '\002' + MAP KEYS TERMINATED BY '\003' + STORED AS SEQUENCEFILE; +``` + +此时导入数据时候也需要指定分区: + +```shell +INSERT OVERWRITE page_view_bucketed +PARTITION (dt='2009-02-25') +SELECT * FROM page_view WHERE dt='2009-02-25'; +``` + + + +## 参考资料 + +1. [LanguageManual DDL BucketedTables](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL+BucketedTables) \ No newline at end of file diff --git a/notes/Hive常用DDL操作.md b/notes/Hive常用DDL操作.md index a9b63e4..fa111aa 100644 --- a/notes/Hive常用DDL操作.md +++ b/notes/Hive常用DDL操作.md @@ -59,9 +59,10 @@ DESC DATABASE EXTENDED hive_test; ```sql DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE]; ---默认行为是RESTRICT,如果数据库中存在表则删除失败。要想删除库及其中的表,可以使用CASCADE级联删除。 ``` ++ 默认行为是RESTRICT,如果数据库中存在表则删除失败。要想删除库及其中的表,可以使用CASCADE级联删除。 + 示例: ```sql @@ -156,8 +157,8 @@ CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- mgr INT, hiredate TIMESTAMP, sal DECIMAL(7,2), - comm DECIMAL(7,2) - ) + comm DECIMAL(7,2), + deptno INT) CLUSTERED BY(empno) SORTED BY(empno ASC) INTO 4 BUCKETS --按照员工编号散列到四个bucket中 ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t" LOCATION '/hive/emp_bucket'; @@ -165,6 +166,8 @@ CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- ### 2.6 倾斜表 +通过指定一个或者多个列经常出现的值(严重偏斜),Hive会自动将涉及到这些值的数据拆分为单独的文件。在查询时,如果涉及到倾斜值,它就直接从独立文件中获取数据,而不是扫描所有文件,这使得性能得到提升。 + ```sql CREATE EXTERNAL TABLE emp_skewed( empno INT, @@ -175,7 +178,7 @@ CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- sal DECIMAL(7,2), comm DECIMAL(7,2) ) - SKEWED BY (empno) ON (66,88,100) --指定数据倾斜 + SKEWED BY (empno) ON (66,88,100) --指定empno的倾斜值66,88,100 ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t" LOCATION '/hive/emp_skewed'; ``` @@ -314,5 +317,106 @@ ALTER TABLE emp_temp ADD COLUMNS (address STRING COMMENT 'home address'); -### 3.4 修改分区 +## 四、清空表/删除表 + +### 4.1 清空表 + +语法: + +```sql +-- 清空整个表或表指定分区中的数据 +TRUNCATE TABLE table_name [PARTITION (partition_column = partition_col_value, partition_column = partition_col_value, ...)]; +``` + ++ 目前只有内部表才能执行TRUNCATE操作,外部表执行时会抛出异常`Cannot truncate non-managed table XXXX`。 + +示例: + +```sql +TRUNCATE TABLE emp_mgt_ptn PARTITION (deptno=20); +``` + + + +### 4.2 删除表 + +语法: + +```sql +DROP TABLE [IF EXISTS] table_name [PURGE]; +``` + ++ 内部表:不仅会删除表的元数据,同时会删除HDFS上的数据; ++ 外部表:只会删除表的元数据,不会删除HDFS上的数据; ++ 删除视图引用的表时,不会给出警告(但视图已经无效了,必须由用户删除或重新创建)。 + +示例: + +```sql +`DROP TABLE [IF EXISTS] table_name [PURGE]; ` +``` + + + +## 五、其他命令 + +### 5.1 Describe + +查看数据库: + +```sql +DESCRIBE|Desc DATABASE [EXTENDED] db_name; --EXTENDED 是否显示额外属性 +``` + +查看表: + +```sql +DESCRIBE|Desc [EXTENDED|FORMATTED] table_name --FORMATTED 以友好的展现方式查看表详情 +``` + + + +### 5.2 Show + +**1. 查看数据库列表** + +```sql +-- 语法 +SHOW (DATABASES|SCHEMAS) [LIKE 'identifier_with_wildcards']; + +-- 示例: +SHOW DATABASES like 'hive*'; +``` + +LIKE子句允许使用正则表达式进行过滤,Show语句当中的LIKE子句只支持`*`(通配符)和`|`(条件或)两个符号。例如'employees','emp *','emp * | * ees',所有这些都将匹配名为'employees'的数据库。 + +**2. 查看表的列表** + +```sql +-- 语法 +SHOW TABLES [IN database_name] ['identifier_with_wildcards']; + +-- 示例 +SHOW TABLES IN default; +``` + +**3. 查看视图列表** + +```sql +SHOW VIEWS [IN/FROM database_name] [LIKE 'pattern_with_wildcards']; --仅支持Hive 2.2.0 + +``` + +**4. 查看表的分区列表** + +```sql +SHOW PARTITIONS table_name; +``` + +**5. 查看表/视图的创建语句** + +```sql +SHOW CREATE TABLE ([db_name.]table_name|view_name); +``` + + diff --git a/notes/Hive数据类型和文件格式.md b/notes/Hive核心概念讲解.md similarity index 84% rename from notes/Hive数据类型和文件格式.md rename to notes/Hive核心概念讲解.md index 5f18345..7f5fad8 100644 --- a/notes/Hive数据类型和文件格式.md +++ b/notes/Hive核心概念讲解.md @@ -1,4 +1,4 @@ -# Hive数据类型和文件格式 +# Hive基本概念讲解