hive基础介绍

3 篇文章 0 订阅
1 篇文章 0 订阅

HIVE

CREATE TABLE

CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name    -- (Note: TEMPORARY available in Hive 0.14.0 and later)
  [(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]
  [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]
  [SKEWED BY (col_name, col_name, ...)                  -- (Note: Available in Hive 0.10.0 and later)]
     ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
     [STORED AS DIRECTORIES]
  [
   [ROW FORMAT row_format] 
   [STORED AS file_format]
     | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)]  -- (Note: Available in Hive 0.6.0 and later)
  ]
  [LOCATION hdfs_path]
  [TBLPROPERTIES (property_name=property_value, ...)]   -- (Note: Available in Hive 0.6.0 and later)
  [AS select_statement];   -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
 
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
  LIKE existing_table_or_view_name
  [LOCATION hdfs_path];
 
data_type
  : primitive_type
  | array_type
  | map_type
  | struct_type
  | union_type  -- (Note: Available in Hive 0.7.0 and later)
 
primitive_type
  : TINYINT
  | SMALLINT
  | INT
  | BIGINT
  | BOOLEAN
  | FLOAT
  | DOUBLE
  | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
  | STRING
  | BINARY      -- (Note: Available in Hive 0.8.0 and later)
  | TIMESTAMP   -- (Note: Available in Hive 0.8.0 and later)
  | DECIMAL     -- (Note: Available in Hive 0.11.0 and later)
  | DECIMAL(precision, scale)  -- (Note: Available in Hive 0.13.0 and later)
  | DATE        -- (Note: Available in Hive 0.12.0 and later)
  | VARCHAR     -- (Note: Available in Hive 0.12.0 and later)
  | CHAR        -- (Note: Available in Hive 0.13.0 and later)
 
array_type
  : ARRAY < data_type >
 
map_type
  : MAP < primitive_type, data_type >
 
struct_type
  : STRUCT < col_name : data_type [COMMENT col_comment], ...>
 
union_type
   : UNIONTYPE < data_type, data_type, ... >  -- (Note: Available in Hive 0.7.0 and later)
 
row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]   -- (Note: Available in Hive 0.13 and later)
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
 
file_format:
  : SEQUENCEFILE
  | TEXTFILE    -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE      -- (Note: Available in Hive 0.6.0 and later)
  | ORC         -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET     -- (Note: Available in Hive 0.13.0 and later)
  | AVRO        -- (Note: Available in Hive 0.14.0 and later)
  | JSONFILE    -- (Note: Available in Hive 4.0.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
 
column_constraint_specification:
  : [ PRIMARY KEY|UNIQUE|NOT NULL|DEFAULT [default_value]|CHECK  [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]
 
default_value:
  : [ LITERAL|CURRENT_USER()|CURRENT_DATE()|CURRENT_TIMESTAMP()|NULL ] 
 
constraint_specification:
  : [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name, ...) DISABLE NOVALIDATE 
    [, CONSTRAINT constraint_name UNIQUE (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]

INSERT

Standard syntax:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
 
Hive extension (multiple inserts):
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2]
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...;
FROM from_statement
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2]
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2] ...;
 
Hive extension (dynamic partition inserts):
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;

动态分区插入

在动态分区插入中,用户可以提供部分分区规范,这意味着只需在partition子句中指定分区列名列表。列值是可选的。如果给定一个分区列值,我们称其为静态分区,否则为动态分区。每个动态分区列都有一个来自select语句的相应输入列。这意味着动态分区的创建由输入列的值决定。动态分区列必须在SELECT语句的列中最后指定,并且按照它们在partition()子句中出现的顺序指定。在Hive 3.0.0 (Hive -19083)中,不需要指定动态分区列。如果没有指定分区规范,则Hive将自动生成分区规范。

KeyDefaultDesc
hive.error.on.empty.partitionfalse如果动态分区插入生成空结果,是否抛出异常
hive.exec.dynamic.partitiontrue需要设置为true才能启用动态分区插入
hive.exec.dynamic.partition.modestrict在严格模式下,用户必须指定至少一个静态分区,以防用户意外地覆盖所有分区,在非严格模式下,所有分区都允许是动态的
hive.exec.max.created.files100000MapReduce作业中所有映射器/还原器创建的HDFS文件的最大数量
hive.exec.max.dynamic.partitions1000允许创建的动态分区的最大总数
hive.exec.max.dynamic.partitions.pernode100在每个mapper/reducer节点中允许创建的最大动态分区数

hive写入数据到文件系统

目录可以是一个完整的URI。如果没有指定scheme或authority, Hive将使用来自指定Namenode URI的hadoop配置变量fs.default.name的scheme和authority。

如果使用了LOCAL关键字,Hive将把数据写到本地文件系统的目录中。

写入文件系统的数据被序列化为文本,列以^A分隔,行以换行符分隔。如果其中任何列不是原始类型,那么这些列将被序列化为JSON格式。

SQL插入表

VALUES子句中列出的每一行都插入到表tablename中。

必须为表中的每一列提供值。目前还不支持允许用户仅向某些列插入值的标准SQL语法。为了模拟标准SQL,可以为用户不希望赋值的列提供空值。

支持动态分区的方式与INSERT…SELECT相同。

如果要插入的表支持ACID,并且使用了支持ACID的事务管理器,则成功完成后将自动提交此操作。

Hive不支持复杂类型的文字(array,map,struct,union),所以不可能在INSERT INTO…值的条款。这意味着用户不能使用insert into…将数据插入到复杂数据类型列中。值子句。

CREATE TABLE students (name VARCHAR(64), age INT, gpa DECIMAL(3, 2))
  CLUSTERED BY (age) INTO 2 BUCKETS STORED AS ORC;
 
INSERT INTO TABLE students
  VALUES ('fred flintstone', 35, 1.28), ('barney rubble', 32, 2.32);
 
 
CREATE TABLE pageviews (userid VARCHAR(64), link STRING, came_from STRING)
  PARTITIONED BY (datestamp STRING) CLUSTERED BY (userid) INTO 256 BUCKETS STORED AS ORC;
 
INSERT INTO TABLE pageviews PARTITION (datestamp = '2014-09-23')
  VALUES ('jsmith', 'mail.com', 'sports.com'), ('jdoe', 'mail.com', null);
 
INSERT INTO TABLE pageviews PARTITION (datestamp)
  VALUES ('tjohnson', 'sports.com', 'finance.com', '2014-09-23'), ('tlee', 'finance.com', null, '2014-09-21');
  
INSERT INTO TABLE pageviews
  VALUES ('tjohnson', 'sports.com', 'finance.com', '2014-09-23'), ('tlee', 'finance.com', null, '2014-09-21');

UPDATE

引用的列必须是正在更新的表的列。

分配的值必须是Hive在select子句中支持的表达式。因此,支持算术运算符、udf、强制类型转换、文本等。不支持子查询。只更新与WHERE子句匹配的行。无法更新分区列。无法更新Bucketing列。

UPDATE tablename SET column = value [, column = value ...] [WHERE expression]

DELETE

只删除where字句匹配到的条件

MERGE

Merge允许基于与源表连接的结果在目标表上执行操作。

性能报告

SQL标准要求,如果ON子句中source中的一行与target中的一行匹配的行多于一行,则会引发错误。这种检查的计算开销很大,可能会严重影响MERGE语句的总体运行时间。hive.merge.cardinality.check=false如果禁用了检查,但该语句具有这样的交叉连接效果,则可能导致数据损坏。

1、2或3(如有从句);每种类型最多1个:更新/删除/插入。

WHEN NOT MATCHED必须是最后一个WHEN子句。

如果同时存在UPDATE和DELETE子句,则语句中的第一个必须包含[和<布尔表达式>]。

对合并操作将关闭向量化。这是自动的,不需要用户操作。非删除操作不受影响。仍然可以使用向量化查询已删除数据的表。

MERGE INTO <target table> AS T USING <source expression/table> AS S
ON <boolean expression1>
WHEN MATCHED [AND <boolean expression2>] THEN UPDATE SET <set clause list>
WHEN MATCHED [AND <boolean expression3>] THEN DELETE
WHEN NOT MATCHED [AND <boolean expression4>] THEN INSERT VALUES<value list>

ManagerTable vs ExternalTable

ManagerTable数据被附加到Hive实体。每当改变一个实体(例如删除一个表),数据也被改变(在这种情况下,数据被删除)。这与传统RDBMS非常相似,在传统RDBMS中,也不需要自己管理数据文件,而是使用基于sql的访问来实现这一点。而externalTable,hive不管理其数据,即hive通过SQL删除表后,外表的表结构被删除,但数据是依然存在的。

表特征

  • ARCHIVE/UNARCHIVE/TRUNCATE/MERGE/CONCATENATE只适用于托管表

  • DROP删除托管表的数据,而仅删除外部表的元数据

  • ACID/Transactional只适用于受管表

  • 查询结果缓存仅适用于受管表

  • 只允许在外部表上使用依赖约束

  • 一些物化视图特性只能在托管表上工作

ManagerTable

一个托管表存储在hive.metastore.warehouse.dir路径属性,默认情况下在类似于/user/hive/warehouse/databasename.db/tablename/的文件夹路径中。在表创建期间,location属性可以覆盖默认位置。如果删除了一个托管表或分区,则会删除与该表或分区关联的数据和元数据。如果未指定清除选项,则在定义的持续时间内将数据移动到垃圾文件夹。

当Hive应该管理表的生命周期,或者在生成临时表时,使用托管表。

ExternalTable

外部表描述外部文件的metadata/schema。外部表文件可以由Hive之外的进程访问和管理。外部表可以访问存储在源中的数据,比如Azure存储卷(ASV)或远程HDFS位置。如果外部表的结构或分区被更改,可以使用MSCK REPAIR table table_name语句刷新元数据信息。

如果文件已经存在或位于远程位置,则使用外部表,并且即使删除表,这些文件也应该保留。

Storage Format

格式描述
STORED AS TEXTFILE存储为纯文本文件。TEXTFILE是默认的文件格式,除非配置参数hive.default.fileformat有不同的设置。
使用DELIMITED子句读取带分隔符的文件。
通过使用“ESCAPED BY”子句(例如使用“\”转义)启用分隔符的转义

如果要处理可以包含这些分隔符字符的数据,则需要转义。
还可以使用’NULL DEFINED AS’子句指定自定义空格式(默认为’\N’)。
STORED BY以非本机表格式存储。创建或链接到非本机表,例如HBaseDruidAccumulo支持的表。有关此选项的更多信息. 请参见 StorageHandlers
STORED AS SEQUENCEFILE存储为压缩序列文件。
STORED AS RCFILE存储为记录柱状文件格式。
STORED AS PARQUET对于Hive 0.13.0及以后的parquet存储格式,存储为parquet格式;
使用行格式SERDE…存储为INPUTFORMAT…OUTPUTFORMAT语法
STORED AS ORC存储为ORC文件格式。支持ACID事务和基于成本的优化器(CBO)。stores列级元数据。
STORED AS JSONFILEStored as Json file format in Hive 4.0.0 and later.
STORED AS AVROStored as Avro format in Hive 0.14.0 and later (see Avro SerDe).
INPUTFORMAT and OUTPUTFORMAT在file_format中指定相应的名称InputFormat 和 OutputFormat class 作为字符串文字。例如,‘org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat’.
对于LZO压缩,要使用的值是
‘INPUTFORMAT “com.hadoop.mapred.DeprecatedLzoTextInputFormat”
OUTPUTFORMAT org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat"’
hive常用数据格式说明

ORC:优化的行柱状(ORC)文件格式提供了一种高效的方式来存储Hive数据。它被设计用来克服其他Hive文件格式的限制。使用ORC文件可以提高Hive读取、写入和处理数据时的性能。

例如,与RCFile格式相比,ORC文件格式有很多优点,例如:

  • 单个文件作为每个任务的输出,这减少了NameNode的负载

  • 支持Hive类型,包括日期时间、十进制和复杂类型(结构、列表、映射和联合)

  • 存储在文件中的轻量级索引

  • 跳过没有通过谓词筛选的行组

  • 查找给定的行

  • 基于数据类型的块模式压缩

  • 整数列的运行长度编码

  • 字符串列的字典编码

  • 使用单独的记录器并发读取同一文件

  • 能力分裂文件没有扫描标记

  • 限制读写所需的内存量

  • 使用协议缓冲区存储的元数据,允许添加和删除字段

ORC文件包含称为条带的行数据组,以及文件页脚中的辅助信息。在文件的末尾,一个postscript保存压缩参数和压缩页脚的大小。默认的条带大小是250mb。大条带大小允许从HDFS进行大的、高效的读取。文件页脚包含文件中的条带列表、每个条带的行数和每个列的数据类型。它还包含列级聚合计数、最小值、最大值和总和。

下图演示了ORC文件结构:

img

条纹结构

如图所示,ORC文件中的每个条带保存索引数据、行数据和条带页脚。

条纹页脚包含流位置的目录。行数据用于表扫描。

索引数据包括每列的最小值和最大值以及每列中的行位置。(也可以包括一个位域或bloom过滤器。)行索引项提供了偏移量,允许查找解压缩块中的正确压缩块和字节。注意,ORC索引仅用于条纹和行组的选择,而不是用于回答查询。

使用相对频繁的行索引条目可以在条带中跳过行,以便快速读取,尽管条带很大。默认情况下,可以跳过10,000行。

有了基于过滤器谓词跳过大量行集的能力,您可以根据辅助键对表进行排序,从而大大减少执行时间。例如,如果主分区是事务日期,则可以按状态、邮政编码和姓氏对表进行排序。然后,查找一个区域的记录将跳过所有其他区域的记录。

ORC规范中给出了该格式的完整规范。

KeyDefaultNotes
orc.compressZLIB高级压缩( NONE, ZLIB, SNAPPY)
orc.compress.size262,144每个压缩块中的字节数
orc.stripe.size67,108,864每个条带中的字节数
orc.row.index.stride10,000索引项之间的行数(必须是>= 1000)
orc.create.indextrue是否创建行索引
orc.bloom.filter.columns“”应为其创建bloom过滤器的列名列表,以逗号分隔
orc.bloom.filter.fpp0.05bloom filter的正概率(必须>0.0和<1.0)

整数列序列化

整型列在两个流中序列化。

  • 当前位流:是值非空?

  • 数据流:整数流

整数数据序列化的方式,利用了数字的公共分布:

  • 整数使用变宽编码进行编码,对于小整数,这种编码具有更少的字节。

  • 重复值按运行长度进行编码。

  • 在范围内(-128到127)相差一个常数的值被编码为运行长度。

变宽编码基于谷歌的协议缓冲区,并使用高位来表示该字节是否为最后的,较低的7位来编码数据。为了对负数进行编码,使用了锯齿编码,其中0、-1、1、-2和2分别映射为0、1、2、3、4和5。

每组数字都是这样编码的:

  • 如果第一个字节(b0)为负数:

    • 后面跟着可变长度的整数。
  • 如果第一个字节(b0)为正:

    • 它表示b0 + 3个重复整数

    • 在每次重复之间添加第二个字节(-128到+127)

    • 1变长整数。

在运行长度编码中,第一个字节指定运行长度以及值是文本还是重复。复制可以步进-128到+128。运行长度编码使用原buf样式的可变长度整数。

序列化字符串列

字符串列的序列化使用字典来形成惟一的列值。对字典进行排序是为了加快谓词过滤和提高压缩比。

字符串列被序列化为四个流。

  1. 当前位流:是值非空?
  2. 字典数据:字符串的字节
  3. 字典长度:每个条目的长度
  4. 行数据:行值

字典长度和行值都是运行长度编码的整数流。

压缩

流使用编解码器进行压缩,编解码器被指定为该表中所有流的表属性。为了优化内存使用,压缩是在生成每个块时逐步进行的。可以跳过压缩块,而无需首先进行解压以进行扫描。流中的位置由块的起始位置和到块的偏移量表示。

编解码器可以是Snappy、Zlib或none。

查看ORC文件的详细信息及描述
0: jdbc:hive2://192.168.1.128:10000/test> show create table t02_trans;
+----------------------------------------------------+
|                   createtab_stmt                   |
+----------------------------------------------------+
| CREATE TABLE `t02_trans`(                          |
|   `c1` string,                                     |
|   `c2` string,                                     |
|   `c3` string)                                     |
| PARTITIONED BY (                                   |
|   `dt` string)                                     |
| CLUSTERED BY (                                     |
|   c1)                                              |
| INTO 3 BUCKETS                                     |
| ROW FORMAT SERDE                                   |
|   'org.apache.hadoop.hive.ql.io.orc.OrcSerde'      |
| STORED AS INPUTFORMAT                              |
|   'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'  |
| OUTPUTFORMAT                                       |
|   'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat' |
| LOCATION                                           |
|   'hdfs://192.168.1.128:9000/user/hive/warehouse/test.db/t02_trans' |
| TBLPROPERTIES (                                    |
|   'transactional'='true',                          |
|   'transient_lastDdlTime'='1595413357')            |
+----------------------------------------------------+
20 rows selected (0.153 seconds)


0: jdbc:hive2://192.168.1.128:10000/test> dfs -ls /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123;
+----------------------------------------------------+
|                     DFS Output                     |
+----------------------------------------------------+
| Found 3 items                                      |
| -rw-r--r--   1 hive supergroup       2770 2020-07-22 23:58 /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00000 |
| -rw-r--r--   1 hive supergroup       2998 2020-07-22 23:58 /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00001 |
| -rw-r--r--   1 hive supergroup       2895 2020-07-22 23:58 /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00002 |


-- 这里桶文件即ORC文件,通过hive --orcfiledump /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00000进行对ORC文件的分析,可以看到ORC文件的详细信息

====================================================================================================
hive --orcfiledump /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00001
====================================================================================================
Processing data file /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00001 [length: 2998]
Structure for /user/hive/warehouse/test.db/t02_trans/dt=2020-07-22/base_0000123/bucket_00001
File Version: 0.12 with ORC_135
Rows: 43
Compression: ZLIB
Compression size: 262144
Type: struct<operation:int,originalTransaction:bigint,bucket:int,rowId:bigint,currentTransaction:bigint,row:struct<c1:string,c2:string,c3:string>>

Stripe Statistics:
  Stripe 1:
    Column 0: count: 43 hasNull: false
    Column 1: count: 43 hasNull: false min: 0 max: 0 sum: 0
    Column 2: count: 43 hasNull: false min: 1 max: 122 sum: 2429
    Column 3: count: 43 hasNull: false min: 1 max: 1 sum: 43
    Column 4: count: 43 hasNull: false min: 0 max: 0 sum: 0
    Column 5: count: 43 hasNull: false min: 1 max: 122 sum: 2429
    Column 6: count: 43 hasNull: false
    Column 7: count: 43 hasNull: false min: 0.28193786335955884 max: x5EqVVpK31tjlbOZm0ej sum: 857
    Column 8: count: 43 hasNull: false min: 0.011835947052477924 max: 0.9905895912412243 sum: 787
    Column 9: count: 43 hasNull: false min: 05696f6db5fdbceb325d00ecff8283d4 max: ec4e7c9410ace886d93889f7f57a90d3 sum: 1376

File Statistics:
  Column 0: count: 43 hasNull: false
  Column 1: count: 43 hasNull: false min: 0 max: 0 sum: 0
  Column 2: count: 43 hasNull: false min: 1 max: 122 sum: 2429
  Column 3: count: 43 hasNull: false min: 1 max: 1 sum: 43
  Column 4: count: 43 hasNull: false min: 0 max: 0 sum: 0
  Column 5: count: 43 hasNull: false min: 1 max: 122 sum: 2429
  Column 6: count: 43 hasNull: false
  Column 7: count: 43 hasNull: false min: 0.28193786335955884 max: x5EqVVpK31tjlbOZm0ej sum: 857
  Column 8: count: 43 hasNull: false min: 0.011835947052477924 max: 0.9905895912412243 sum: 787
  Column 9: count: 43 hasNull: false min: 05696f6db5fdbceb325d00ecff8283d4 max: ec4e7c9410ace886d93889f7f57a90d3 sum: 1376

Stripes:
  Stripe: offset: 3 data: 1909 rows: 43 tail: 103 index: 362
    Stream: column 0 section ROW_INDEX start: 3 length 11
    Stream: column 1 section ROW_INDEX start: 14 length 24
    Stream: column 2 section ROW_INDEX start: 38 length 26
    Stream: column 3 section ROW_INDEX start: 64 length 24
    Stream: column 4 section ROW_INDEX start: 88 length 24
    Stream: column 5 section ROW_INDEX start: 112 length 26
    Stream: column 6 section ROW_INDEX start: 138 length 11
    Stream: column 7 section ROW_INDEX start: 149 length 65
    Stream: column 8 section ROW_INDEX start: 214 length 64
    Stream: column 9 section ROW_INDEX start: 278 length 87
    Stream: column 1 section DATA start: 365 length 7
    Stream: column 2 section DATA start: 372 length 28
    Stream: column 3 section DATA start: 400 length 7
    Stream: column 4 section DATA start: 407 length 7
    Stream: column 5 section DATA start: 414 length 28
    Stream: column 7 section DATA start: 442 length 607
    Stream: column 7 section LENGTH start: 1049 length 11
    Stream: column 8 section DATA start: 1060 length 400
    Stream: column 8 section LENGTH start: 1460 length 39
    Stream: column 9 section DATA start: 1499 length 768
    Stream: column 9 section LENGTH start: 2267 length 7
    Encoding column 0: DIRECT
    Encoding column 1: DIRECT_V2
    Encoding column 2: DIRECT_V2
    Encoding column 3: DIRECT_V2
    Encoding column 4: DIRECT_V2
    Encoding column 5: DIRECT_V2
    Encoding column 6: DIRECT
    Encoding column 7: DIRECT_V2
    Encoding column 8: DIRECT_V2
    Encoding column 9: DIRECT_V2

File length: 2998 bytes
Padding length: 0 bytes
Padding ratio: 0%
ACID stats: inserts: 43 updates: 0 deletes: 0
___________________________________________________________________________________________________

Avro:

写入表到Avro文件

AvroSerde可以将任何Hive表序列化为Avro文件。这使它有效的任何hive类型到Avro转换器。为了向Avro文件写入一个表,您必须首先创建一个合适的Avro模式(除了在Hive 0.14.0及以后的版本中,如下所述)。当前不支持Create as select type语句。

对于不能直接转换的类型,有几项需要记住:

  • 可能为null的类型必须在Avro中定义为该类型和null的联合。未这样定义的字段中的null将在保存期间导致异常。不需要对Hive模式进行任何更改来支持这一点,因为Hive中的所有字段都可以为null。

  • Avro字节类型应该在Hive中定义为小整数的列表。AvroSerde将在保存过程中将这些转换为字节。

  • Avro固定类型应该在Hive中定义为微小整数的列表。AvroSerde会在保存过程中将这些内容转换为固定的内容。

  • Avro枚举类型应该在Hive中定义为字符串,因为Hive没有枚举的概念。确保表中只有有效的枚举值——试图保存未定义的枚举将导致异常。

  • Hive对于类型非常宽容:它将尝试将与所提供的列匹配的任何值存储在新表的等效列位置中。例如,没有对列名进行匹配。因此,查询编写器有责任确保目标列类型是正确的。如果它们不是,Avro可能会接受类型或抛出一个异常;这取决于类型的特定组合。

Hive归档文件

由于HDFS的设计,文件系统中的文件数量直接影响namenode中的内存消耗。虽然对于小型集群通常不是问题,但是当有5000 -1亿个文件时,内存使用可能会达到一台机器上可访问内存的限制。在这种情况下,文件越少越好。

使用Hadoop归档是减少分区中文件数量的一种方法。Hive内置支持将现有分区中的文件转换为Hadoop Archive (HAR),这样一个曾经包含100个文件的分区可以只占用3个文件(取决于设置)。但是,这样做的代价是,由于从HAR读取数据的额外开销,查询可能会变慢。

注意,归档并不压缩文件——HAR类似于Unix的tar命令。

hive> set hive.archive.enabled=true;
hive> set hive.archive.har.parentdir.settable=true;
hive> set har.partfile.size=1099511627776;

参数说明:

  1. hive.archive.enabled.controls 是否启用存档操作。
  2. hive.archive.har.parentdir.settable 通知Hive在创建归档时是否可以设置父目录。在Hadoop的最新版本中,-p选项可以指定归档文件的根目录。例如,如果/dir1/dir2/file是以/dir1作为父目录归档的,那么生成的归档文件将包含目录结构dir2/file。在旧版本的Hadoop(2011年之前)中,这个选项是不可用的,因此必须配置Hive以适应这个限制。
  3. har.partfile.size 控制组成存档的文件的大小。归档文件将包含size_of_partition/ha .partfile。调整文件大小,四舍五入。较高的值意味着更少的文件,但是由于映射器的数量减少,将导致更长的归档时间。

归档使用方法:

设置好配置值后,可以使用命令对分区进行归档:

ALTER TABLE table_name ARCHIVE PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...)

ALTER TABLE srcpart ARCHIVE PARTITION(ds='2008-04-08', hr='12')

解档使用方法:

ALTER TABLE srcpart UNARCHIVE PARTITION(ds='2008-04-08', hr='12')

排序(Order, Sort, Cluster, and Distribute By)

Sort By / Order By

Hive支持排序,通过排序每个reducer对数据进行排序。“order by”和“sort by”之间的区别在于,前者保证输出中的总顺序,而后者仅保证reducer中的行顺序。如果有多个reducer,“sort by”可能会给出部分有序的最终结果。

注意:单个列的SORT BY和CLUSTER BY之间的区别可能会令人困惑。不同之处在于,按照字段按分区进行集群,如果有多个简化器分区,则按照随机进行排序,以便在各个简化器之间均匀地分布数据(和加载)。

Cluster By / Distribute By

Cluster By和Distribute By主要与Transform/Map-Reduce脚本一起使用。但是,如果需要为后续查询对查询的输出进行分区和排序,那么在SELECT语句中它是有用的。

Cluster By是Distribute By和Sort By的捷径。

Hive使用分布By中的列在减少器之间分布行。具有相同的Distribute By列的所有行都将使用同一个reducer。但是,Distribute By并不保证分布键的集群化或排序属性。

Hive Join 优化

优化改进

join的一侧适合在内存。在新的优化中:

  • 这一端作为散列表加载到内存中

  • 只需要扫描较大的表

  • 事实表占用内存更小

  • 星形架构连接

  • 提示在许多情况下不再需要。

  • 映射联接由优化器自动挑选。

Hive mapjoin

处理mapjoin的方法是将较小的表加载到内存中的散列映射中,并在流过较大表时将键与之匹配。

  • local work

    • 通过标准表扫描(包括过滤器和投影)从本地机器上的源读取记录
    • 在内存中构建哈希表
    • 将哈希表写入本地磁盘
    • 上传哈希表到dfs
    • 将散列表添加到分布式缓存
  • Map task

    • 将哈希表从本地磁盘(分布式缓存)读入内存

    • 根据哈希表匹配记录的键

    • combine匹配并写入输出

    • 没有reduce任务

预先实行限制

mapjoin操作符一次只能处理一个键;也就是说,它可以执行多表连接,但前提是所有表都在同一个键上连接。(典型的星型模式连接不属于这一类。)提示对于用户来说,正确应用提示很麻烦,自动转换也没有足够的逻辑来一致地预测MAPJOIN是否适合内存。一个mapjoin链不会合并成一个仅适用于Map的作业,除非查询被写成mapjoin(表、子查询(mapjoin(表、子查询…))的级联序列。自动转换永远不会产生一个单独的仅适用于Map的作业。每次运行查询时都必须生成mapjoin操作符的哈希表,这涉及到将所有数据下载到Hive客户机,以及上传生成的哈希表文件。

星形连接

Hive 0.11中的优化器增强主要关注于星型模式配置中所需的连接的有效处理。最初的工作仅限于星型模式连接,其中过滤和投射后的所有维度表同时适合内存。现在也实现了只有一部分维度表能装入内存的场景。

连接优化可以分为三个部分:

  • 当使用maphint时,在一个仅使用map的作业中执行操作符树中的mapjoin链。

  • 将优化扩展到自动转换情况(在优化时生成适当的备份计划)。

  • 完全在任务端生成内存中的散列表。

    下面的部分将描述这些优化器增强。

Hive事务

ACID代表数据库事务的四个特性:原子性(完全成功或失败),一致性(一旦应用程序执行一个操作,操作的结果是可见的在每个后续操作),隔离(由一个用户一个不完整的操作不会引起意想不到的副作用为其他用户),和持久性(一个操作完成后它将被保留下来即使面对机器或系统故障)。

在Hive 0.13之前,原子性、一致性和持久性都是在分区级别上提供的。可以通过打开一个可用的锁定机制(ZooKeeper或内存中)来提供隔离。通过在Hive 0.13中添加事务,现在可以在行级提供完整的ACID语义,这样一个应用程序可以添加行,而另一个应用程序可以从相同的分区读取,而不会相互干扰。

使用ACID语义的事务已经被添加到Hive中,以解决以下用例:

  • 数据流摄取。许多用户都有Apache Flume、Apache Storm或Apache Kafka这样的工具,他们使用这些工具将数据流传输到Hadoop集群中。虽然这些工具可以以每秒数百行或更多行的速度写入数据,但Hive只能每15分钟到1小时添加一次分区。添加分区通常会很快导致表中分区数量过多。这些工具可以将数据流传输到现有的分区中,但这会导致读取器进行脏读(即,在开始查询之后会看到写入的数据),并在目录中留下许多小文件,从而对NameNode造成压力。有了这个新功能,这个用例将得到支持,同时允许读者获得一致的数据视图,并避免过多的文件。

  • 缓慢变化维度。在典型的星型模式数据仓库中,维度表会随着时间缓慢变化。例如,零售商将开设新商店,需要将其添加到stores表中,或者现有商店可能更改其面积或其他跟踪特征。这些更改导致插入单个记录或更新记录(取决于所选择的策略)。从0.14开始,Hive就能够支持这一点。

  • 数据重述。有时收集的数据被发现是不正确的,需要纠正。或者,数据的第一个实例可能是一个近似值(90%的服务器报告),稍后提供完整的数据。或者,业务规则可能要求由于后续的事务而重复某些事务(例如,在购买之后,客户可能购买了会员资格,因此有权享受折扣价格,包括之前的购买)。或者,根据合同,用户可能需要在关系终止时删除其客户的数据。从Hive 0.14开始,可以通过插入、更新和删除来支持这些用例。

使用SQL MERGE语句进行批量更新。

限制

还不支持开始、提交和回滚。所有的语言操作都是自动提交的。

在第一个版本中只支持ORC文件格式。该特性的构建使得事务可以被任何存储格式使用,这些格式可以决定更新或删除如何应用于基本记录(基本上,这些记录有显式或隐式的行id),但到目前为止,集成工作只针对ORC完成。

默认情况下,事务被配置为off。要使用这些特性,表必须被封装起来。在同一个系统中不使用事务和ACID的表不需要桶。外部表不能成为ACID表,因为外部表上的更改超出了compactor的控制范围。

不允许从非ACID会话中读取/写入ACID表。换句话说,Hive事务管理器必须设置为org.apache.hadoop.hive.ql.lockmgr.DbTxnManager以便与ACID表一起工作。

此时,只支持快照级别隔离。当一个给定的查询开始时,将向它提供数据的一致快照。不支持脏读、提交读、可重复读或可序列化。通过引入BEGIN,目的是在事务持续期间支持快照隔离,而不仅仅是单个查询。可以根据用户请求添加其他隔离级别。

基础设计

HDFS不支持对文件的就地更改。当写入器附加到用户正在读取的文件时,它也不提供读取一致性。为了在HDFS之上提供这些特性,我们遵循了在其他数据仓库工具中使用的标准方法。表或分区的数据存储在一组基本文件中。新记录、更新和删除都存储在增量文件中。为修改表或分区的每个事务(或者对于流代理,如Flume或Storm,为每批事务)创建一组新的delta文件。在读取时,读取器合并基本文件和增量文件,在读取时应用任何更新和删除。

base目录和delta目录

以前,一个分区(或者一个未分区的表)的所有文件都位于一个目录中。通过这些更改,任何使用支持ACID的写器编写的分区(或表)都将有一个用于基本文件的目录和一个用于每组delta文件的目录。下面是未分区表“t”的情况:

hive> dfs -ls -R /user/hive/warehouse/t;
drwxr-xr-x   - ekoifman staff          0 2016-06-09 17:03 /user/hive/warehouse/t/base_0000022
-rw-r--r--   1 ekoifman staff        602 2016-06-09 17:03 /user/hive/warehouse/t/base_0000022/bucket_00000
drwxr-xr-x   - ekoifman staff          0 2016-06-09 17:06 /user/hive/warehouse/t/delta_0000023_0000023_0000
-rw-r--r--   1 ekoifman staff        611 2016-06-09 17:06 /user/hive/warehouse/t/delta_0000023_0000023_0000/bucket_00000
drwxr-xr-x   - ekoifman staff          0 2016-06-09 17:07 /user/hive/warehouse/t/delta_0000024_0000024_0000
-rw-r--r--   1 ekoifman staff        610 2016-06-09 17:07 /user/hive/warehouse/t/delta_0000024_0000024_0000/bucket_00000

Compactor

Compactor是一组运行在Metastore内部的后台进程来支持ACID系统。它由Initiator, Worker, Cleaner, AcidHouseKeeperService组成。

Delta文件合并

随着操作对表的修改,会创建越来越多的delta文件,需要压缩这些文件以保持足够的性能。压缩有两种类型,Minor压缩和Major压缩。

  • Minor压缩采用一组现有的增量文件,并将它们重写为每个bucket的单个增量文件。

  • Major压缩接受一个或多个delta文件和bucket的基本文件,并将它们重写为每个bucket的新基本文件。主要压实更昂贵,但更有效。

所有的压缩都是在后台完成的,并不阻止数据的并发读和写。压缩之后,系统将等待,直到旧文件的所有读取器都完成,然后删除旧文件。

Initiator角色

这个模块负责发现应该压缩哪些表或分区。这应该是启用在一个转移使用hive.compactor.initiator.on表单*有几个属性。下面“事务的新配置参数”表中的阀值,该阀值控制何时创建压缩任务以及执行哪种类型的压缩。每个压缩任务处理1个分区(如果该表未分区,则处理整个表)。如果给定分区的连续压缩失败数超过hive. compator .initiator. failure .compact .threshold,则该分区的自动压缩调度将停止。

Worker角色

每个Worker处理一个压缩任务。一个压缩是一个MapReduce作业,其名称如下:-compactor-.

.。每个worker将作业提交到集群(如果定义了,则通过hive.compactor.job.queue)并等待作业完成。thread决定每个转移的Worker数量。Hive仓库中的Worker总数决定了并发压缩的最大数量。

Cleaner角色

这个过程在压缩之后以及在确定不再需要delta文件之后删除它们。

AcidHouseKeeperService角色

该进程查找在hive.txn.timeout中未被处理的事务。超时即中止它们。系统假设一个客户端启动了一个停止心跳的事务,崩溃了,它锁定的资源应该被释放。

事务/锁管理器

添加了一个名为“事务管理器”的新逻辑实体,它合并了以前的“数据库/表/分区锁管理器”(hive.lock)概念。默认为org.apache.hadoop.hive.ql.lockmgr. zookeper . zookeeperhivelockmanager)。事务管理器现在另外负责管理事务锁。默认的DummyTxnManager模拟旧的Hive版本的行为:没有事务并且使用hivev .lock。属性创建表、分区和数据库的锁管理器。一个新添加的DbTxnManager用DbLockManager管理Hive metastore中的所有锁/事务(事务和锁在面对服务器故障时是持久的)。这意味着,当事务被启用时,ZooKeeper中先前的锁定行为将不再出现。为了避免客户端死亡并使事务或锁悬空,锁持有者和事务启动者定期向转移者发送一个心跳。如果在配置的时间内没有接收到心跳,则锁定或事务将中止。

DbLockManger继续尝试获取锁的时间长度可以通过Hive .lock来控制。numretires hive.lock.sleep.between.retries。当DbLockManager无法获得一个锁(由于存在一个竞争的锁)时,它将退出并在一段时间后再次尝试。为了支持短时间运行的查询,同时又不让metastore负载过高,DbLockManager在每次重试之后都会将等待时间延长一倍。最初的后退时间为100ms,并以以下动作为上限:间歇、锁定、休息、间隔、重试。hive.lock.numretries是它重试给定锁请求的总次数。因此,获取锁的调用将阻塞的总时间(给定100次重试和60次睡眠时间)是(100ms + 200ms + 400ms +…+ 51200ms + 60s + 60s +…+ 60) = 91m:42s:300ms。

表属性

如果要在ACID写(插入、更新、删除)中使用一个表,那么必须在该表上设置表属性“transactional=true”,从Hive 0.14.0开始。注意,一旦一个表通过TBLPROPERTIES (“transactional”=“true”)被定义为ACID表,它就不能被转换回非ACID表。,不允许更改TBLPROPERTIES (“transactional”=“false”)。同时,hive.txn.manager必须设置为org.apache.hadoop.hive.ql.lockmgr。DbTxnManager或者在hive-site.xml中,或者在任何查询运行之前的会话开始。没有这些,插入将做在旧的风格;更新和删除将被禁止在HIVE-11716之前。因为HIVE-11716操作在没有DbTxnManager的ACID表是不允许的。但是,这并不适用于Hive 0.13.0。

如果表所有者不希望系统自动确定压缩时间,那么可以设置表属性"NO_AUTO_COMPACTION" .这将防止所有自动压缩。手动压缩仍然可以使用Alter Table/Partition Compact语句来完成。

在创建或修改表时,使用TBLPROPERTIES子句设置表属性,如Hive数据定义语言的Create Table和Alter Table属性部分所述。“transactional”和“NO_AUTO_COMPACTION”表属性在Hive release 0中区分大小写。x和1.0,但是从release 1.1.0 (HIVE-8308)开始它们就不区分大小写了。

它们可以在表级通过CREATE TABLE进行设置,在请求级通过ALTER TABLE/分区紧凑进行设置。它们用于覆盖仓库/表宽设置。例如,要重写MR属性以影响压缩作业,可以添加"compactor.=" 在CREATE TABLE语句或通过ALTER TABLE显式启动压缩时使用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值