Developer Guide

代码组织和简要架构

Introduction

Hive 有 3 个主要组成部分:

  • 序列化器/反序列化器(trunk/serde)-此组件具有框架库,允许用户为自己的数据格式开发序列化器和反序列化器。该组件还包含一些内置的序列化/反序列化系列。

  • MetaStore(中继/元存储)-此组件实现元数据服务器,该元数据服务器用于保存有关仓库中表和分区的所有信息。

  • 查询处理器(trunk/ql)-该组件实现了将 SQL 转换为 map/reduce 作业图的处理框架以及执行按依赖 Sequences 运行这些作业的执行时间框架。

除了这些主要组件之外,Hive 还包含许多其他组件。这些如下:

  • 命令行界面(trunk/cli)-此组件具有 Hive 命令行界面使用的所有 Java 代码。

  • Hive 服务器(中继/服务)-此组件实现了其他 Client 端(例如 JDBC 驱动程序)可以用来与 Hive 进行通信的所有 API。

  • 通用(trunk/common)-此组件包含其余代码所需的通用基础结构。当前,它包含用于 ManagementHive 配置并将 Hive 配置(HiveConf)传递给所有其他代码组件的所有 Java 源代码。

  • AntUtil(主体/Ant)-此组件包含构建基础结构所使用的某些 ant 任务的实现。

  • 脚本(trunk/bin)-此组件包含分发中提供的所有脚本,包括运行 Hive CLI 的脚本(bin/hive)。

以下顶级目录包含帮助程序库,打包的配置文件等:

  • trunk/conf-此目录包含打包的 hive-default.xml 和 hive-site.xml。

  • trunk/data-此目录包含在 Hive 测试中使用的一些数据集和配置。

  • trunk/ivy-此目录包含构建基础架构用来 Management 对不同 Hadoop 版本的依赖关系的 Ivy 文件。

  • trunk/lib-此目录包含 Hive 所需的运行时库。

  • trunk/testlibs-此目录包含构建基础结构中 JUnit 目标使用的 junit.jar。

  • trunk/testutils (Deprecated)

Hive SerDe

什么是 SerDe?

  • SerDe 是“序列化器和反序列化器”的缩写。

  • Hive 使用 SerDe(和 FileFormat)读取和写入表行。

  • HDFS 文件-> InputFileFormat-><key, value>->反序列化器->行对象

  • 行对象->序列化程序-><key, value>-> OutputFileFormat-> HDFS 文件

请注意,“键”部分在读取时会被忽略,而在写入时始终是常数。基本上行对象存储在“值”中。

Hive 的一项原则是 Hive 不拥有 HDFS 文件格式。用户应该能够使用其他工具直接读取 Hive 表中的 HDFS 文件,或者使用其他工具直接写入可以通过“ CREATE EXTERNAL TABLE”加载到 Hive 中或通过“ LOAD DATA INPATH”加载到 Hive 中的 HDFS 文件。 ”,将文件移到 Hive 的表目录中。

请注意,org.apache.hadoop.hive.serde 是已弃用的旧 SerDe 库。请查看 org.apache.hadoop.hive.serde2 以获取最新版本。

Hive 当前使用以下 FileFormat 类读取和写入 HDFS 文件:

  • TextInputFormat/HiveIgnoreKeyTextOutputFormat:这 2 个类以纯文本文件格式读取/写入数据。

  • SequenceFileInputFormat/SequenceFileOutputFormat:这 2 个类以 Hadoop SequenceFile 格式读取/写入数据。

Hive 当前使用这些 SerDe 类来序列化和反序列化数据:

  • MetadataTypedColumnsetSerDe:此 SerDe 用于读取/写入定界记录,例如 CSV,制表符分隔的 Control-A 分隔的记录(对不起,尚不支持引用)。

  • LazySimpleSerDe:此 SerDe 可用于读取与 MetadataTypedColumnsetSerDe 和 TCTLSeparatedProtocol 相同的数据格式,但是,它以惰性方式创建对象,从而提供了更好的性能。从Hive 0.14.0开始,它还支持具有指定编码字符集的读/写数据,例如:

ALTER TABLE person SET SERDEPROPERTIES ('serialization.encoding'='GBK');

如果将配置属性hive.lazysimple.extended_boolean_literal设置为true(Hive 0.14.0及更高版本),则 LazySimpleSerDe 可以将“ T”,“ t”,“ F”,“ f”,“ 1”和“ 0”视为扩展的合法布尔 Literals。默认值为false,这意味着仅将'TRUE'和'FALSE'视为合法的布尔 Literals。

  • ThriftSerDe:此 SerDe 用于读取/写入 Thrift 序列化的对象。 Thrift 对象的类文件必须首先加载。

  • DynamicSerDe:此 SerDe 还读取/写入 Thrift 序列化的对象,但是它了解 Thrift DDL,因此可以在运行时提供对象的架构。它还支持许多不同的协议,包括 TBinaryProtocol,TJSONProtocol,TCTLSeparatedProtocol(将数据写入分隔 Logging)。

Also:

  • 对于 JSON 文件,在 Hive 0.12.0 中添加了JsonSerDe。对于 0.12.0 之前的版本,Amazon SerDe 可在s3://elasticmapreduce/samples/hive-ads/libs/jsonserde.jar获得。

  • 在 Hive 0.9.1 中添加了Avro SerDe。从 Hive 0.14.0 开始,其规范由 STORED AS AVRO 子句隐含。

  • Hive 0.11.0 中添加了ORC文件格式的 SerDe。

  • 通过 Hive 0.10 中的插件添加了Parquet的 SerDe,并在 Hive 0.13.0 中本地添加了。

  • 在 Hive 0.14 中添加了CSV的 SerDe。

有关 Importing 和输出处理的详细信息,请参见SerDe。另请参见HCatalog manual中的Storage Formats,包括JSON SerDe 的 CTAS 问题。有关如何使用自定义或本机 SerDe 创建表的信息,请参见行格式,存储格式和 SerDe

如何编写自己的 SerDe

  • 在大多数情况下,用户希望编写反序列化程序而不是 SerDe,因为用户只想读取自己的数据格式而不是写入数据格式。

  • 例如,RegexDeserializer 将使用配置参数“ regex”以及可能的列名称列表对数据进行反序列化(请参见 serde2.MetadataTypedColumnsetSerDe)。有关详细信息,请参见 serde2/Deserializer.java。

  • 如果您的 SerDe 支持 DDL(基本上是带有参数化列和列类型的 SerDe),则您可能想实现基于 DynamicSerDe 的协议,而不是从头开始编写 SerDe。原因是该框架通过“ Thrift DDL”格式将 DDL 传递给 SerDe,并且编写“ Thrift DDL”解析器并非易事。

  • 有关示例,请参见下面的SerDe-如何添加新的 SerDe

关于 SerDe 的一些重要点:

  • SerDe(而不是 DDL)定义表模式。一些 SerDe 实现使用 DDL 进行配置,但是 SerDe 也可以覆盖它。

  • 列类型可以是任意嵌套的数组,Map 和结构。

  • ObjectInspector 的回调设计允许使用 CASE/IF 或使用复杂或嵌套类型时进行延迟反序列化。

ObjectInspector

Hive 使用 ObjectInspector 来分析行对象的内部结构以及各个列的结构。

ObjectInspector 提供了一种访问复杂对象的统一方法,这些对象可以以多种格式存储在内存中,包括:

  • Java 类的实例(Thrift 或本机 Java)

  • 一个标准的 Java 对象(我们使用 java.util.List 表示 Struct 和 Array,并使用 java.util.Map 表示 Map)

  • 惰性初始化的对象(例如,存储在单个 Java 字符串对象中的字符串字段的 Struct,每个字段的起始偏移量)

一个复杂的对象可以由一对 ObjectInspector 和 Java Object 表示。 ObjectInspector 不仅告诉我们对象的结构,而且还提供了访问对象内部字段的方法。

注意:Apache Hive 建议创建用于与自定义 SerDes 一起使用的自定义 ObjectInspector,除了用于序列化的常规构造函数外,还应具有无参数的构造函数。有关更多详细信息,请参见HIVE-5380

本机 SerDes 的注册

Hive 0.14起,已为本地 Hive SerDes 引入了注册机制。这样可以在CreateTable语句中动态地绑定“ STORED AS”关键字,以代替\ {SerDe, InputFormat, and OutputFormat}规范的三 Tuples。

通过此注册机制添加了以下 Map:

SyntaxEquivalent
储存为 AVRO /

储存为 Files
ROW FORMAT SERDE
````+43+

+46+``+47+`` `'`
````+55+
+58+`` ' |
|存储为 RCFILE | STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.RCFileInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.RCFileOutputFormat'|
|存储为序列文件| STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.SequenceFileInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.mapred.SequenceFileOutputFormat'|
|存储为文本文件| STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'|

要使用 STORED AS 关键字添加新的本机 SerDe,请按照下列步骤操作:

MetaStore

MetaStore 包含有关表,分区和数据库的元数据。在计划生成过程中,查询处理器将使用它。

  • Metastore Server-这是 Thrift 服务器(在 metastore/if/hive_metastore.if 中定义的接口),为来自 Client 端的元数据请求提供服务。它委派了基础元数据存储和包含数据的 Hadoop 文件系统中的大多数请求。

  • 对象存储-对象存储类处理对存储在 SQL 存储中的实际元数据的访问。当前的实现使用基于 JDA 规范的 JPOX ORM 解决方案。它可以与 JPOX 支持的任何数据库一起使用。可以通过实现接口 MetaStore 来添加新的元存储(基于文件或基于 xml)。 FileStore 是 Metastore 的较旧版本的部分实现,该版本可能很快就会弃用。

  • MetastoreClient-metastore/src 中有 python,java,php ThriftClient。 Java 生成的 Client 端由 HiveMetaStoreClient 扩展,该模块由查询处理器(ql/metadta)使用。这是所有其他 Hive 组件的主要界面。

Query Processor

以下是 Hive 查询处理器的主要组件:

  • 解析和语义分析(ql/parse)-该组件包含用于解析 SQL,将其转换为抽象语法树,将抽象语法树转换为操作员计划,最后将操作员计划转换为由驱动程序执行的有向图的有向图的代码.java。

  • Optimizer(ql/optimizer)-此组件包含一些基于规则的简单优化,例如从 Hive 查询处理器在将 SQL 转换为一系列 map/reduce 任务时执行的表扫描(列修剪)中修剪未引用的列。

  • 计划组件(ql/plan)-该组件包含类(称为 Descriptors),编译器(解析器,SemanticAnalysis 和 Optimizer)使用这些类将信息传递给执行代码所使用的运算符树。

  • 元数据层(ql /元数据)-查询处理器使用此组件与 MetaStore 进行接口,以检索有关表,分区和表的列的信息。编译器使用此信息将 SQL 编译为一系列 map/reduce 任务。

  • Map/Reduce 执行引擎(ql/exec)-此组件包含所有查询运算符和用于从 map/reduce 任务中调用这些运算符的框架。

  • Hive 的 Hadoop 记录读取器,Importing 和输出格式化程序(ql/io)-该组件包含 Hive 向 Hadoop Job 注册的记录读取器以及 Importing,输出格式化器。

  • 会话数(ql/session)-Hive 的基本会话实施。

  • 类型接口(ql/typeinfo)-此组件提供从 MetaStore 和 SerDes 检索的表列的所有类型信息。

  • Hive 函数框架(ql/udf)-Hive 运算符,函数和集合函数的框架和实现。该组件还包含用户可以实现以创建用户定义的功能的接口。

  • 工具(ql/tools)-查询处理框架提供的一些简单工具。当前,该组件包含沿袭工具的实现,该沿袭工具可以解析查询并显示查询的源表和目标表。

Compiler

Parser

TypeChecking

Semantic Analysis

Plan generation

Task generation

Execution Engine

Plan

Operators

UDF 和 UDAF

可以在此Hive 解剖滑板中找到有关 Hive 查询处理器的有用概述。

编译并运行 Hive

Ant to Maven

从版本0.13开始,Hive 使用 Maven 而不是 Ant 进行构建。以下说明不是最新的。

有关更新的说明,请参见Hive 开发人员常见问题解答

Hive 可以针对不同版本的 Hadoop 进行编译。

Default Mode

从源树的根:

ant package

将使 Hive 可以针对 Hadoop 0.19.0 版进行编译。注意:

  • Hive 使用 Ivy 下载 hadoop-0.19.0 发行版。但是,一旦下载,它就会被缓存并且不会多次下载。

  • 这将在 build/dist(相对于源根目录)中创建一个分发目录,从该目录可以启动 Hive。此分发仅应用于执行针对 Hadoop 分支 0.19 的查询。 (Hive 对 Hadoop 版本的次要版本不敏感)。

Advanced Mode

  • 可以使用以下命令指定自定义分发目录:
ant -Dtarget.dir=<my-install-dir> package
  • 可以通过使用(以 0.17.1 为例)指定除 0.19.0 之外的 Hadoop 版本:
ant -Dhadoop.version=0.17.1 package
  • 还可以针对 Hadoop 树的自定义版本进行编译(仅 0.4 版及更高版本)。如果在运行 Ivy 时遇到问题(例如在断开模式下),但是 Hadoop 树可用时,这也很有用。这可以通过指定要使用的 Hadoop 源树的根来完成,例如:
ant -Dhadoop.root=~/src/hadoop-19/build/hadoop-0.19.2-dev -Dhadoop.version=0.19.2-dev

note that:

  • Hive 的构建脚本假定hadoop.root指向通过在 Hadoop 中运行 ant 软件包而创建的 Hadoop 分发树。

  • hadoop.version必须与用于构建 Hadoop 的版本匹配。

在此特定示例中,~/src/hadoop-19是 Hadoop 19 分支的签出,该分支使用0.19.2-dev作为默认版本,并默认在build/hadoop-0.19.2-dev中创建分发目录。

从命令行使用“ $HIVE_HOME/bin/hive”运行 Hive,其中$HIVE_HOME通常是 Hive 存储库顶级目录下的build/dist

$ build/dist/bin/hive

如果 Hive 在运行时失败,请尝试使用“ ant very-clean package”删除 Ivy 缓存,然后再进行重建。

在没有 Hadoop 群集的情况下运行 Hive

From Thejas:

export HIVE_OPTS='--hiveconf mapred.job.tracker=local --hiveconffs.default.name=file:///tmp \
    --hiveconf hive.metastore.warehouse.dir=file:///tmp/warehouse \
    --hiveconf javax.jdo.option.ConnectionURL=jdbc:derby:;databaseName=/tmp/metastore_db;create=true'

然后,您可以运行“ build/dist/bin/hive”,它将对您的本地文件系统起作用。

单元测试和调试

单元测试的布局

Hive 使用JUnit进行单元测试。 Hive 的 3 个主要组件中的每一个在相应的 src/test 目录中都有其单元测试实现,例如 trunk/metastore/src/test 具有 metastore 的所有单元测试,trunk/serde/src/test 具有 serde 的所有单元测试,trunk/ql/src/test 具有查询处理器的所有单元测试。 Metastore 和 Serde 单元测试提供了 JUnit 的 TestCase 实现。另一方面,查询处理器测试是使用 Velocity 生成的。 trunk/ql/src/test 下包含这些测试和相应结果的主目录如下:

  • Test Queries:

  • querys/clientnegative-此目录包含否定测试用例的查询文件(.q 文件)。它们通过 CLI 类运行,因此可以测试整个查询处理器堆栈。

    • querys/clientpositive-此目录包含肯定测试用例的查询文件(.q 文件)。 Thesre 通过 CLI 类运行,因此测试了整个查询处理器堆栈。

    • qureies/positive(将不推荐使用)-此目录包含编译器的肯定测试用例的查询文件(.q 文件)。这些仅测试编译器,而不运行执行代码。

    • querys/negative(将不建议使用)-此目录包含针对编译器的否定测试用例的查询文件(.q 文件)。这些仅测试编译器,而不运行执行代码。

  • Test Results:

  • 结果/Client 端阴性-查询/Client 端阴性中查询的预期结果。

    • 结果/Client 端肯定-查询/Client 端肯定中的查询的预期结果。

    • 结果/编译器/错误-查询/负数中查询的预期结果。

    • results/compiler/parse-查询/肯定中查询的预期抽象语法树输出。

    • 结果/编译器/计划-查询/肯定查询的预期查询计划。

  • 生成测试的速度模板:

  • templates/TestCliDriver.vm-从查询/Client 端阳性生成测试。

    • templates/TestNegativeCliDriver.vm-从查询/Client 端阴性生成测试。

    • templates/TestParse.vm-从查询/正生成测试。

    • templates/TestParseNegative.vm-从查询/负数生成测试。

正在运行单元测试

Ant to Maven

从版本0.13开始,Hive 使用 Maven 而不是 Ant 进行构建。以下说明不是最新的。

有关更新的说明,请参见Hive 开发人员常见问题解答

运行所有测试:

ant package test

运行所有肯定的测试查询:

ant test -Dtestcase=TestCliDriver

运行特定的阳性测试查询:

ant test -Dtestcase=TestCliDriver -Dqfile=groupby1.q

上面的测试产生以下文件:

  • build/ql/test/TEST-org.apache.hadoop.hive.cli.TestCliDriver.txt-测试的日志输出。这在检查测试失败时会很有帮助。

  • build/ql/test/logs/groupby1.q.out-测试的实际查询结果。作为测试的一部分,将该结果与预期结果进行比较。

运行与正则表达式匹配的单元测试集,例如 partition_wise_fileformat 测试 10-16:

ant test -Dtestcase=TestCliDriver -Dqfile_regex=partition_wise_fileformat1[0-6]

请注意,此选项与不带.q 后缀的测试的基本名称匹配。

显然,除非您先运行ant package,否则清除后 Hive 测试不会成功运行。不知道为什么 build.xml 不编码此依赖项。

添加新的单元测试

Ant to Maven

从版本0.13开始,Hive 使用 Maven 而不是 Ant 进行构建。以下说明不是最新的。

有关更新的说明,请参见Hive 开发人员常见问题解答。另请参见在 Hive 中添加新测试的提示如何贡献:添加单元测试

首先,在 ql/src/test/queries/clientpositive 中编写一个新的 myname.q。

然后,使用查询运行测试并覆盖结果(在添加新测试时很有用)。

ant test -Dtestcase=TestCliDriver -Dqfile=myname.q -Doverwrite=true

然后,我们可以通过以下方式创建补丁:

svn add ql/src/test/queries/clientpositive/myname.q ql/src/test/results/clientpositive/myname.q.out
svn diff > patch.txt

同样,要添加否定的 Client 端测试,请在 ql/src/test/queries/clientnegative 中编写一个新的查询 Importing 文件,然后运行相同的命令,这次将测试用例名称指定为 TestNegativeCliDriver 而不是 TestCliDriver。请注意,对于负面的 Client 端测试,可以在目录 ql/src/test/results/clientnegative 中找到使用覆盖标志创建的输出文件。

调试 Hive 代码

Hive 代码包括 Client 端代码(例如 HiveQL 的编译器,语义分析器和优化器)和服务器端代码(例如,operator/task/SerDe 实现)。Client 端和服务器端代码的调试不同,如下所述。

调试 Client 端代码

Client 端代码在本地计算机上运行,因此您可以像调试任何常规本地 Java 代码一样轻松地使用 Eclipse 对其进行调试。以下是调试单元测试中的代码的步骤。

  • 自上次运行ant clean以来,请确保已在 hive/metastore 中运行了ant model-jar,并且在 hive 中运行了ant gen-test

  • 要为 CLI 运行所有单元测试:

  • 打开 TestCliDriver.java

    • 单击运行->调试配置,选择 TestCliDriver,然后单击调试。
  • 要在 TestCliDriver.java 中运行一个测试:

  • 与以前一样,开始运行整个 TestCli 套件。

    • 完成设置并开始执行 JUnit 测试后,请停止测试执行。

    • 在“ JUnit”窗格中找到所需的测试,

    • 右键单击该测试,然后选择“调试”。

调试服务器端代码

服务器端代码是分布式的,并且在 Hadoop 群集上运行,因此调试服务器端 Hive 代码有点复杂。除了使用 log4j 打印到日志文件外,还可以在单元测试(单机模式)下将调试器附加到其他 JVM。以下是有关如何在服务器端代码上进行调试的步骤。

  • 使用 javac.debug = on 编译 Hive 代码。在 Hive 结帐目录下:
> ant -Djavac.debug=on package

如果您已经在没有 javac.debug = on 的情况下构建了 Hive,则可以清除该构建,然后运行上述命令。

> ant clean  # not necessary if the first time to compile
    > ant -Djavac.debug=on package
  • 使用其他选项运行 ant test,以告诉正在运行 Hive 服务器端代码的 Java VMawait 调试器附加。首先定义一些方便的宏进行调试。您可以将其放在.bashrc 或.cshrc 中。
> export HIVE_DEBUG_PORT=8000
    > export HIVE_DEBUG="-Xdebug -Xrunjdwp:transport=dt_socket,address=${HIVE_DEBUG_PORT},server=y,suspend=y"

特别是 HIVE_DEBUG_PORT 是 JVM 正在侦听且调试器将附加到的端口号。然后如下运行单元测试:

> export HADOOP_OPTS=$HIVE_DEBUG
    > ant test -Dtestcase=TestCliDriver -Dqfile=<mytest>.q

单元测试将一直运行,直到显示:

[junit] Listening for transport dt_socket at address: 8000
  • 现在,您可以使用 jdb 附加到端口 8000 进行调试
> jdb -attach 8000

或者,如果您正在运行 Eclipse 并且已经导入了 Hive 项目,则可以使用 Eclipse 进行调试。在 Eclipse Run-> Debug Configurations 下,在左面板底部找到“ Remote Java Application”。应该已经有一个 MapRedTask 配置。如果没有这样的配置,则可以使用以下属性创建一个:

  • 名称:任何任务,例如 MapRedTask

    • 项目:您导入的 Hive 项目。

    • 连接类型:标准(socket 连接)

    • Connection Properties:

  • Host: localhost

    • Port: 8000
      然后单击“调试”按钮,Eclipse 将连接到侦听端口 8000 的 JVM,并 continue 运行直至结束。如果在点击“调试”按钮之前在源代码中定义了断点,它将在此处停止。其余与调试 Client 端 Hive 相同。

不使用 Ant 进行调试(Client 端和服务器端)

还有另一种无需通过 Ant 即可调试 Hive 代码的方法。
您需要安装 Hadoop 并将环境变量 HADOOP_HOME 设置为该变量。

> export HADOOP_HOME=<your hadoop home>

然后,启动 Hive:

>  ./build/dist/bin/hive --debug

然后,它的行为类似于 Debugging Hive 代码中概述的调试步骤。由于不需要编译 Hive 代码,因此速度更快,
并通过 Ant。它可以用于调试 Client 端 Hive 和服务器端 Hive。

如果要调试特定查询,请启动 Hive 并执行该查询之前所需的步骤。然后再次在调试中启动 Hive,以调试该查询。

>  ./build/dist/bin/hive
    >  perform steps before the query
>  ./build/dist/bin/hive --debug
    >  run the query

请注意,将使用本地文件系统,因此不会自动释放计算机上的空间(与通过 Ant 进行调试不同,在 Ant 中,在测试中创建的表会在测试结束时自动删除)。确保明确删除表,或从/ User/hive/warehouse 删除数据。

Pluggable interfaces

File Formats

请参阅Hive 用户组会议,2009 年 8 月 59-63 页。

SerDe-如何添加新的 SerDe

请参阅Hive 用户组会议,2009 年 8 月第 64-70 页。

Map-Reduce Scripts

请参阅Hive 用户组会议,2009 年 8 月第 71-73 页。

UDF 和 UDAF-如何添加新的 UDF 和 UDAF

请参阅Hive 用户组会议,2009 年 8 月 74-87 页。