HIVE 随谈(hive操作create,alter等)

2023-12-09 04:08
文章标签 操作 hive create alter 随谈

本文主要是介绍HIVE 随谈(hive操作create,alter等),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Hive 的官方文档中对查询语言有了很详细的描述,请参考:http://wiki.apache.org/hadoop/Hive/LanguageManual ,本文的内容大部分翻译自该页面,期间加入了一些在使用过程中需要注意到的事项。

Create Table

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name[(col_name data_type [COMMENT col_comment], ...)][COMMENT table_comment][PARTITIONED BY (col_name data_type[COMMENT col_comment], ...)][CLUSTERED BY (col_name, col_name, ...)[SORTED BY (col_name [ASC|DESC], ...)]INTO num_buckets BUCKETS][ROW FORMAT row_format][STORED AS file_format][LOCATION hdfs_path]

CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXIST 选项来忽略这个异常。

EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

LIKE 允许用户复制现有的表结构,但是不复制数据。

用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive 通过 SerDe 确定表的具体的列的数据。

如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCE 。

有分区的表可以在创建的时候使用 PARTITIONED BY 语句。一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下。而且,表和分区都可以对某个列进行CLUSTERED BY 操作,将若干个列放入一个桶(bucket)中。也可以利用SORT BY 对数据进行排序。这样可以为特定应用提高性能。

表名和列名不区分大小写,SerDe 和属性名区分大小写。表和列的注释是字符串。

Drop Table

删除一个内部表的同时会同时删除表的元数据和数据。删除一个外部表,只删除元数据而保留数据。

Alter Table

Alter table 语句允许用户改变现有表的结构。用户可以增加列/分区,改变serde,增加表和 serde 熟悉,表本身重命名。

Add Partitions

ALTER TABLE table_name ADDpartition_spec [ LOCATION 'location1' ]partition_spec [ LOCATION 'location2' ] ...partition_spec:: PARTITION (partition_col = partition_col_value,partition_col = partiton_col_value, ...)

用户可以用 ALTER TABLE ADD PARTITION 来向一个表中增加分区。当分区名是字符串时加引号。

  ALTER TABLE page_view ADDPARTITION (dt='2008-08-08', country='us')location '/path/to/us/part080808'PARTITION (dt='2008-08-09', country='us')location '/path/to/us/part080809';

DROP PARTITION

ALTER TABLE table_name DROPpartition_spec, partition_spec,...

用户可以用 ALTER TABLE DROP PARTITION 来删除分区。分区的元数据和数据将被一并删除。

ALTER TABLE page_viewDROP PARTITION (dt='2008-08-08', country='us');

RENAME TABLE

ALTER TABLE table_name RENAME TO new_table_name

这个命令可以让用户为表更名。数据所在的位置和分区名并不改变。换而言之,老的表名并未“释放”,对老表的更改会改变新表的数据。

ChangeColumn Name/Type/Position/Comment

ALTER TABLE table_name CHANGE [COLUMN]col_old_name col_new_name column_type[COMMENT col_comment][FIRST|AFTER column_name]

这个命令可以允许用户修改一个列的名称、数据类型、注释或者位置。

比如:

CREATE TABLE test_change (a int, b int,c int);

ALTER TABLE test_changeCHANGE a a1 INT; 将 a 列的名字改为 a1.

ALTER TABLE test_changeCHANGE a a1 STRING AFTER b; 将 a 列的名字改为 a1,a 列的数据类型改为 string,并将它放置在列 b 之后。新的表结构为: b int, a1 string,c int.

ALTER TABLE test_changeCHANGE b b1 INT FIRST; 会将 b 列的名字修改为 b1, 并将它放在第一列。新表的结构为: b1 int, a string,c int.

注意:对列的改变只会修改 Hive 的元数据,而不会改变实际数据。用户应该确定保证元数据定义和实际数据结构的一致性。

Add/Replace Columns

ALTER TABLE table_name ADD|REPLACECOLUMNS (col_name data_type [COMMENT col_comment], ...)

ADD COLUMNS 允许用户在当前列的末尾增加新的列,但是在分区列之前。

REPLACE COLUMNS 删除以后的列,加入新的列。只有在使用 native 的 SerDE(DynamicSerDe or MetadataTypeColumnsetSerDe)的时候才可以这么做。

Alter Table Properties

ALTER TABLE table_name SET TBLPROPERTIES table_properties
table_properties:: (property_name = property_value, property_name = property_value, ... )

用户可以用这个命令向表中增加 metadata,目前 last_modified_user,last_modified_time 属性都是由 Hive 自动管理的。用户可以向列表中增加自己的属性。可以使用 DESCRIBE EXTENDED TABLE 来获得这些信息。

Add Serde Properties

ALTER TABLE table_nameSET SERDE serde_class_name[WITH SERDEPROPERTIES serde_properties]ALTER TABLE table_nameSET SERDEPROPERTIES serde_propertiesserde_properties:: (property_name = property_value,property_name = property_value, ... )

这个命令允许用户向 SerDe 对象增加用户定义的元数据。Hive 为了序列化和反序列化数据,将会初始化 SerDe 属性,并将属性传给表的 SerDe。如此,用户可以为自定义的 SerDe 存储属性。

Alter Table File Format and Organization

ALTER TABLE table_name SET FILEFORMAT file_format
ALTER TABLE table_name CLUSTERED BY (col_name, col_name, ...)[SORTED BY (col_name, ...)] INTO num_buckets BUCKETS

这个命令修改了表的物理存储属性。

Loading files into table

当数据被加载至表中时,不会对数据进行任何转换。Load 操作只是将数据复制/移动至 Hive 表对应的位置。

Syntax:

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE]INTO TABLE tablename[PARTITION (partcol1=val1, partcol2=val2 ...)]

Synopsis:

Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。

  • filepath 可以是:
    • 相对路径,例如:project/data1
    • 绝对路径,例如: /user/hive/project/data1
    • 包含模式的完整 URI,例如:hdfs://namenode:9000/user/hive/project/data1
  • 加载的目标可以是一个表或者分区。如果表包含分区,必须指定每一个分区的分区名。
  • filepath 可以引用一个文件(这种情况下,Hive 会将文件移动到表所对应的目录中)或者是一个目录(在这种情况下,Hive 会将目录中的所有文件移动至表所对应的目录中)。
  • 如果指定了 LOCAL,那么:
    • load 命令会去查找本地文件系统中的 filepath。如果发现是相对路径,则路径会被解释为相对于当前用户的当前路径。用户也可以为本地文件指定一个完整的 URI,比如:file:///user/hive/project/data1.
    • load 命令会将 filepath 中的文件复制到目标文件系统中。目标文件系统由表的位置属性决定。被复制的数据文件移动到表的数据对应的位置。
  • 如果没有指定 LOCAL 关键字,如果 filepath 指向的是一个完整的 URI,hive 会直接使用这个 URI。 否则:
    • 如果没有指定 schema 或者 authority,Hive 会使用在 hadoop 配置文件中定义的 schema 和 authority,fs.default.name 指定了 Namenode 的 URI。
    • 如果路径不是绝对的,Hive 相对于 /user/ 进行解释。
    • Hive 会将 filepath 中指定的文件内容移动到 table (或者 partition)所指定的路径中。
  • 如果使用了 OVERWRITE 关键字,则目标表(或者分区)中的内容(如果有)会被删除,然后再将 filepath 指向的文件/目录中的内容添加到表/分区中。
  • 如果目标表(分区)已经有一个文件,并且文件名和 filepath 中的文件名冲突,那么现有的文件会被新文件所替代。

SELECT

Syntax

SELECT [ALL | DISTINCT] select_expr, select_expr, ...FROM table_reference[WHERE where_condition][GROUP BY col_list][CLUSTER BY col_list| [DISTRIBUTE BY col_list][SORT BY col_list]]
[LIMIT number]
  • 一个SELECT语句可以是一个union查询或一个子查询的一部分。
  • table_reference是查询的输入,可以是一个普通表、一个视图、一个join或一个子查询
  • 简单查询。例如,下面这一语句从t1表中查询所有列的信息。
SELECT * FROM t1

WHERE Clause

where condition 是一个布尔表达式。例如,下面的查询语句只返回销售记录大于 10,且归属地属于美国的销售代表。Hive 不支持在WHERE 子句中的 IN,EXIST 或子查询。

SELECT * FROM sales WHERE amount > 10 AND region = "US"

ALL and DISTINCT Clauses

使用ALL和DISTINCT选项区分对重复记录的处理。默认是ALL,表示查询所有记录。DISTINCT表示去掉重复的记录。

hive> SELECT col1, col2 FROM t11 31 31 42 5
hive> SELECT DISTINCT col1, col2 FROM t11 31 42 5
hive> SELECT DISTINCT col1 FROM t112

基于Partition的查询

一般 SELECT 查询会扫描整个表(除非是为了抽样查询)。但是如果一个表使用 PARTITIONED BY 子句建表,查询就可以利用分区剪枝(input pruning)的特性,只扫描一个表中它关心的那一部分。Hive 当前的实现是,只有分区断言出现在离 FROM 子句最近的那个WHERE 子句中,才会启用分区剪枝。例如,如果 page_views 表使用 date 列分区,以下语句只会读取分区为‘2008-03-01’的数据。

 SELECT page_views.*FROM page_viewsWHERE page_views.date >= '2008-03-01'AND page_views.date <= '2008-03-31';

HAVING Clause

Hive 现在不支持 HAVING 子句。可以将 HAVING 子句转化为一个字查询,例如:

SELECT col1 FROM t1 GROUP BY col1 HAVING SUM(col2) > 10

可以用以下查询来表达:

SELECT col1 FROM (SELECT col1, SUM(col2) AS col2sumFROM t1 GROUP BY col1) t2WHERE t2.col2sum > 10

LIMIT Clause

Limit 可以限制查询的记录数。查询的结果是随机选择的。下面的查询语句从 t1 表中随机查询5条记录:

SELECT * FROM t1 LIMIT 5

Top k 查询。下面的查询语句查询销售记录最大的 5 个销售代表。

SET mapred.reduce.tasks = 1SELECT * FROM sales SORT BY amount DESC LIMIT 5

REGEX Column Specification

SELECT 语句可以使用正则表达式做列选择,下面的语句查询除了 ds 和 hr 之外的所有列:

SELECT `(ds|hr)?+.+` FROM sales

Join

Syntax

join_table:table_reference JOIN table_factor [join_condition]| table_reference {LEFT|RIGHT|FULL} [OUTER]JOIN table_reference join_condition| table_reference LEFT SEMI JOINtable_reference join_conditiontable_reference:table_factor| join_tabletable_factor:tbl_name [alias]| table_subquery alias| ( table_references )join_condition:ON equality_expression ( AND equality_expression )*equality_expression:expression = expression

Hive 只支持等值连接(equality joins)、外连接(outer joins)和(left semi joins???)。Hive 不支持所有非等值的连接,因为非等值连接非常难转化到 map/reduce 任务。另外,Hive 支持多于 2 个表的连接。

写 join 查询时,需要注意几个关键点:
1. 只支持等值join,例如:

  SELECT a.* FROM a JOIN b ON (a.id = b.id)SELECT a.* FROM a JOIN bON (a.id = b.id AND a.department = b.department)

是正确的,然而:

  SELECT a.* FROM a JOIN b ON (a.id  b.id)

是错误的。

2. 可以 join 多于 2 个表,例如

  SELECT a.val, b.val, c.val FROM a JOIN bON (a.key = b.key1) JOIN c ON (c.key = b.key2)

如果join中多个表的 join key 是同一个,则 join 会被转化为单个 map/reduce 任务,例如:

  SELECT a.val, b.val, c.val FROM a JOIN bON (a.key = b.key1) JOIN cON (c.key = b.key1)

被转化为单个 map/reduce 任务,因为 join 中只使用了 b.key1 作为 join key。

SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1)JOIN c ON (c.key = b.key2)

而这一 join 被转化为 2 个 map/reduce 任务。因为 b.key1 用于第一次 join 条件,而 b.key2 用于第二次 join。

join 时,每次 map/reduce 任务的逻辑是这样的:reducer 会缓存 join 序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统。这一实现有助于在 reduce 端减少内存的使用量。实践中,应该把最大的那个表写在最后(否则会因为缓存浪费大量内存)。例如:

 SELECT a.val, b.val, c.val FROM aJOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)

所有表都使用同一个 join key(使用 1 次 map/reduce 任务计算)。Reduce 端会缓存 a 表和 b 表的记录,然后每次取得一个c 表的记录就计算一次 join 结果,类似的还有:

  SELECT a.val, b.val, c.val FROM aJOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)

这里用了 2 次 map/reduce 任务。第一次缓存 a 表,用 b 表序列化;第二次缓存第一次 map/reduce 任务的结果,然后用c 表序列化。

LEFT,RIGHT 和 FULL OUTER 关键字用于处理 join 中空记录的情况,例如:

  SELECT a.val, b.val FROM a LEFT OUTERJOIN b ON (a.key=b.key)

对应所有 a 表中的记录都有一条记录输出。输出的结果应该是 a.val, b.val,当 a.key=b.key 时,而当 b.key 中找不到等值的 a.key 记录时也会输出 a.val, NULL。“FROM a LEFT OUTER JOIN b”这句一定要写在同一行——意思是 a 表在 b 表的左边,所以 a 表中的所有记录都被保留了;“a RIGHT OUTER JOIN b”会保留所有 b 表的记录。OUTER JOIN 语义应该是遵循标准 SQL spec的。

Join 发生在 WHERE 子句之前。如果你想限制 join 的输出,应该在 WHERE 子句中写过滤条件——或是在 join 子句中写。这里面一个容易混淆的问题是表分区的情况:

  SELECT a.val, b.val FROM aLEFT OUTER JOIN b ON (a.key=b.key)WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

会 join a 表到 b 表(OUTER JOIN),列出 a.val 和 b.val 的记录。WHERE 从句中可以使用其他列作为过滤条件。但是,如前所述,如果 b 表中找不到对应 a 表的记录,b 表的所有列都会列出 NULL,包括 ds 列。也就是说,join 会过滤 b 表中不能找到匹配 a 表 join key 的所有记录。这样的话,LEFT OUTER 就使得查询结果与 WHERE 子句无关了。解决的办法是在 OUTER JOIN 时使用以下语法:

  SELECT a.val, b.val FROM a LEFT OUTER JOIN bON (a.key=b.key ANDb.ds='2009-07-07' ANDa.ds='2009-07-07')

这一查询的结果是预先在 join 阶段过滤过的,所以不会存在上述问题。这一逻辑也可以应用于 RIGHT 和 FULL 类型的 join 中。

Join 是不能交换位置的。无论是 LEFT 还是 RIGHT join,都是左连接的。

  SELECT a.val1, a.val2, b.val, c.valFROM aJOIN b ON (a.key = b.key)LEFT OUTER JOIN c ON (a.key = c.key)

先 join a 表到 b 表,丢弃掉所有 join key 中不匹配的记录,然后用这一中间结果和 c 表做 join。这一表述有一个不太明显的问题,就是当一个 key 在 a 表和c 表都存在,但是 b 表中不存在的时候:整个记录在第一次 join,即 a JOIN b 的时候都被丢掉了(包括a.val1,a.val2和a.key),然后我们再和c 表 join 的时候,如果c.key 与 a.key 或 b.key 相等,就会得到这样的结果:NULL, NULL, NULL,c.val。

LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现。Hive 当前没有实现 IN/EXISTS 子查询,所以你可以用 LEFT SEMI JOIN 重写你的子查询语句。LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行。

  SELECT a.key, a.valueFROM aWHERE a.key in(SELECT b.keyFROM B);

可以被重写为:

   SELECT a.key, a.valFROM a LEFT SEMI JOIN b on (a.key = b.key)

这篇关于HIVE 随谈(hive操作create,alter等)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/472414

相关文章

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字

MySQL——表操作

目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,接下来来看一下表的相关操作。 一、创建表 create

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

PHP7扩展开发之流操作

前言 啥是流操作?简单来讲就是对一些文件,网络的IO操作。PHP已经把这些IO操作,封装成流操作。这节,我们将使用PHP扩展实现一个目录遍历的功能。PHP示例代码如下: <?phpfunction list_dir($dir) {if (is_dir($dir) === false) {return;} $dh = opendir($dir);if ($dh == false) {ret

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity

mysql中导入txt文件数据的操作指令

1 表tt的格式:    CREATE TABLE `tt` (   `ind` int NOT NULL auto_increment,   `name` char(100) default NULL,   PRIMARY KEY  (`ind`)  )   2 文件d.txt的内容示例:  1,a  2,b  3,c