这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

Apache Hadoop 集成

与 Vertica 一样,Apache™ Hadoop™ 使用一个节点群集进行分布式处理。最让人感兴趣的主要组件是 HDFS,也就是 Hadoop 分布式文件系统。

您可以通过多种方式将 Vertica 与 HDFS 结合使用:

  • 您可以将 HDFS 数据导入到本地存储的 ROS 文件中。

  • 您可以使用外部表访问相应位置的 HDFS 数据。您可以自己定义表或从 Hadoop 组件 Hive 获取架构信息。

  • 您可以将 HDFS 用作 ROS 文件的存储位置。

  • 您可以从 Vertica 导出数据,与其他使用 Hadoop 列式格式的 Hadoop 组件共享。有关详细信息,请参阅文件导出

Hadoop 文件路径在 webhdfshdfs URL 方案中表示为 URL。有关使用这些方案的详细信息,请参阅HDFS 文件系统

Hadoop 发行版

Vertica 可与 Hortonworks、Cloudera 和 MapR 推出的 Hadoop 发行版配合使用。请参阅Hadoop 集成了解受支持的特定版本。

如果您使用 Cloudera,则可以使用 Cloudera Manager 管理您的 Vertica 群集。请参阅与 Cloudera Manager 集成

如果您使用的是 MapR,请参阅集成 Vertica 与 Hadoop 的 MapR 发行版

WebHDFS 要求

默认情况下,如果您在 hdfs 方案中使用 URL,Vertica 会将其视为 webhdfs。如果您改用(已弃用的)LibHDFS++ 库,您必须仍然有可用的 WebHDFS 服务。LibHDFS++ 不支持某些 WebHDFS 功能,例如加密区域、线路加密或写入,并在需要时回退到 WebHDFS。

对于某些用途(例如 Eon 模式公共存储),您必须直接使用带有 webhdfs 方案的 WebHDFS。

1 - 群集布局

Vertica 支持两种用于 Hadoop 集成的群集架构。您使用的架构会影响您对与 HDFS 集成的决策。这些选项也可能受到许可条款的限制。

  • 您可以将 Vertica 共置于部分或全部 Hadoop 节点。然后,Vertica 可以充分利用数据局部性。

  • 您可以构建一个独立于 Hadoop 群集的 Vertica 群集。在此配置中,Vertica 可以充分利用各个节点;不与 Hadoop 共享资源。

无论采用哪种体系结构,如果您使用 hdfs 方案读取 ORC 或 Parquet 文件,就必须做一些额外的配置。请参阅配置 HDFS 访问

1.1 - 共置群集

使用共置群集时,Vertica 安装在部分或全部 Hadoop 节点上。如下图所示,除所有 Hadoop 节点使用的公用网络以外,Vertica 节点还使用专用网络:

您可以选择将 Vertica 置于全部或仅部分 Hadoop 节点上。如果要使用 HDFS 存储位置,您应该使用至少三个 Vertica 节点(企业模式数据库中的 K-safety 的最小数)。

使用更多 Vertica 节点可以提高性能,因为查询所需的 HDFS 数据更可能是节点的本地数据。

您可以将 Hadoop 和 Vertica 群集置于单个机架内,或者跨许多个机架和节点。如果您不在每个节点上共置 Vertica,则可以通过将其共置在每个机架中的至少一个节点上来提高性能。请参阅配置机架位置

通常情况下,Hadoop 和 Vertica 共同使用整个节点。由于这种配置使用共享节点,您必须在配置中解决这些节点上的潜在资源争用。有关详细信息,请参阅为共置群集配置 Hadoop。无需对仅 Hadoop 的节点做任何更改。

硬件建议

Hadoop 群集常常不具有完全相同的预配要求或硬件配置。但是,根据常规硬件和操作系统要求和建议中推荐的最佳实践标准,Vertica 节点的大小和功能应该相当。

由于 Hadoop 群集的规格并不总能满足这些标准,Vertica 建议针对 Hadoop 群集中的 Vertica 节点采用以下规格。

1.2 - 为共置群集配置 Hadoop

如果让 Vertica 共置于任何 HDFS 节点,那么有一些额外的配置要求。

Hadoop 配置参数

为获得最佳性能,请使用指定的最小值设置以下参数:

WebHDFS

Hadoop 有两种服务可为 HDFS 提供 Web 访问权限:

  • WebHDFS

  • httpFS

对于 Vertica,您必须使用 WebHDFS 服务。

YARN

YARN 服务在较新版本的 Hadoop 中提供。它为 Hadoop 群集执行资源管理。将 Vertica 共置于由 YARN 管理的 Hadoop 节点时,您必须在 YARN 中进行一些更改。

Vertica 建议在共享节点上为 Vertica 留出至少 16GB 的内存。预留更多内存将带来性能提升。如何执行此操作取决于您的 Hadoop 发行版:

  • 如果您使用 Hortonworks,创建一个 "Vertica" 节点标签,然后将其分配给运行 Vertica 的节点。

  • 如果您使用 Cloudera,请启用并配置静态服务池。

有关详细信息,请查阅 Hadoop 发行版的文档。或者,您可以禁用共享节点上的 YARN。

Hadoop Balancer

Hadoop Balancer 可在整个 HDFS 范围内重新分配数据块。此功能对于许多 Hadoop 服务都非常有用。但对于 Vertica 而言,此功能可能会在某些条件下降低性能。

如果您使用 HDFS 存储位置,Hadoop Load Balancer 可能会将数据从正在对其进行操作的 Vertica 节点上移走,从而降低性能。如果 Vertica 没有在所有 Hadoop 节点上运行,读取 ORC 或 Parquet 文件时也有可能发生这种情况。(如果您使用独立的 Vertica 和 Hadoop 群集,所有 Hadoop 访问均通过网络实现,而且性能成本不太明显。)

为了避免在整个 HDFS 群集内进行不必要的数据块移动,请考虑将 Vertica 节点排除在再平衡以外。请参阅 Hadoop 文档,以了解如何执行此操作。

复制因子

默认情况下,HDFS 存储每个数据块的三个副本。Vertica 通常会被设置为通过 K-Safety 存储每个数据项的两个副本。因此,将复制因子降低到 2 不但可以节省空间,还能提供数据保护。

要降低 HDFS 存储的副本数量,请按照对 HDFS 存储位置进行故障排除中的说明,设置 HadoopFSReplication。

用于非 HDFS 用途的磁盘空间

您还需要为非 HDFS 用途留出一些磁盘空间。要使用 Ambari 预留磁盘空间,将 dfs.datanode.du.reserved 设置为 hdfs-site.xml 配置文件中的一个值。

设置此参数可为 Vertica 需要的非 HDFS 文件保留空间。

1.3 - 配置机架位置

如果可能,在规划查询时,Vertica 会自动使用与包含数据的 HDFS 节点共置的数据库节点。将查询执行移到更靠近数据的位置可以减少网络延迟并提高性能。这种称为节点定位的行为不需要额外的配置。

当 Vertica 仅共置于 HDFS 节点的子集上时,有时没有与数据共置的数据库节点。但是,如果查询使用同一机架中的数据库节点,性能通常会更好。如果配置了有关 Hadoop 机架结构的信息,Vertica 会尝试使用与要查询的数据位于同一机架中的数据库节点。

例如,下图说明了具有三个机架的 Hadoop 群集,每个机架包含三个数据节点。(典型的生产系统在每个机架上会有更多的数据节点。)在每个机架中,Vertica 共置于一个节点上。

如果您配置了机架位置,则 Vertica 使用 db01 查询 dn1、dn2 或 dn3 上的数据,使用 db02 和 db03 分别查询 rack2 和 rack3 上的数据。因为 HDFS 会复制数据,所以任何给定的数据块都可以存在于多个机架中。例如,如果在 dn2、dn3 和 dn6 上复制数据块,Vertica 将使用 db01 或 db02 来查询它。

Hadoop 组件是机架感知的,因此描述机架结构的配置文件已经存在于 Hadoop 群集中。要在 Vertica 中使用此信息,请配置描述此机架结构的故障组。Vertica 在查询计划中使用故障组。

配置故障组

Vertica 使用 容错组 来描述物理群集布局。由于您的数据库节点共置在 HDFS 节点上,因此 Vertica 可以使用有关 HDFS 群集物理布局的信息。

Hadoop 将其群集布局数据存储在 HADOOP_CONF_DIR 中的拓扑映射文件中。在 HortonWorks 上,该文件通常命名为 topology_mappings.data。在 Cloudera 上,它通常命名为 topology.map。使用此文件中的数据为故障组脚本创建输入文件。有关此文件格式的详细信息,请参阅创建容错组输入文件

以下是前面说明的群集的拓扑映射文件示例:

[network_topology]
dn1.example.com=/rack1
10.20.41.51=/rack1
dn2.example.com=/rack1
10.20.41.52=/rack1
dn3.example.com=/rack1
10.20.41.53=/rack1
dn4.example.com=/rack2
10.20.41.71=/rack2
dn5.example.com=/rack2
10.20.41.72=/rack2
dn6.example.com=/rack2
10.20.41.73=/rack2
dn7.example.com=/rack3
10.20.41.91=/rack3
dn8.example.com=/rack3
10.20.41.92=/rack3
dn9.example.com=/rack3
10.20.41.93=/rack3

根据这些数据,您可以创建以下输入文件来描述该群集的 Vertica 子集:

/rack1 /rack2 /rack3
/rack1 = db01
/rack2 = db02
/rack3 = db03

此输入文件告知 Vertica 数据库节点 "db01" 在 rack1 上,"db02" 在 rack2 上,"db03" 在 rack3 上。在创建此文件时,忽略那些不是 Vertica 节点的 Hadoop 数据节点。

创建输入文件后,运行故障组工具:

$ python /opt/vertica/scripts/fault_group_ddl_generator.py dbName input_file > fault_group_ddl.sql

此脚本的输出是创建故障组的 SQL 文件。按照创建容错组中的说明执行。

您可以使用以下语句查看新的故障组:

=> SELECT member_name,node_address,parent_name FROM fault_groups
INNER JOIN nodes ON member_name=node_name ORDER BY parent_name;

 member_name  | node_address  | parent_name
-------------------------+--------------+-------------
db01          | 10.20.41.51   | /rack1
db02          | 10.20.41.71   | /rack2
db03          | 10.20.41.91   | /rack3

(3 rows)

使用多层机架

Hadoop 群集可以使用多层机架。例如,/west/rack-w1、/west/rack-2 和 /west/rack-w3 可能由一个数据中心提供服务,而 /east/rack-e1、/east/rack-e2 和 /east /rack-e3 由另一个数据中心提供服务。对故障组脚本输入文件中的条目使用以下格式:

/west /east
/west = /rack-w1 /rack-w2 /rack-w3
/east = /rack-e1 /rack-e2 /rack-e3
/rack-w1 = db01
/rack-w2 = db02
/rack-w3 = db03
/rack-e1 = db04
/rack-e2 = db05
/rack-e3 = db06

不要使用完整的机架路径(例如 /west/rack-w1)创建条目。

审核结果

要查看机架位置可以加载多少数据,请在查询中使用 EXPLAIN 并在输出中查找如下语句:

100% of ORC data including co-located data can be loaded with rack locality.

1.4 - 单独的群集

对于单独的群集,Vertica 群集和 Hadoop 群集不共享节点。您应当在两个群集之间使用高带宽网络连接。

下图说明了分置群集的配置:

网络

网络是任何配置良好的群集的关键性能组件。当 Vertica 将数据存储到 HDFS 时,它可以通过网络写入和读取数据。

图中所示的布局需要两个网络,而添加第三个网络也能带来好处:

  • 数据库专用网络:Vertica 使用专用网络进行命令与控制和在各节点之间移动数据,以支持其数据库功能。在某些网络中,命令与控制和数据传递会拆分到两个网络。

  • 数据库/Hadoop 共享网络:每个 Vertica 节点必须能够连接到每个 Hadoop 数据节点和 NameNode。Hadoop 的最佳实践通常需要为 Hadoop 群集提供专用网络。这并不是一项技术要求,但专用网络可以提高 Hadoop 的性能。Vertica 和 Hadoop 应该共享专用 Hadoop 网络。

  • 可选客户端网络:外部客户端可以通过客户端网络访问群集网络。这并不是一项绝对需求,但使用支持通过客户端连接到 Vertica 或 Hadoop 的第三个网络能够提高性能。如果配置不支持客户端网络,那么客户端连接应使用共享网络。

Hadoop 配置参数

为获得最佳性能,请使用指定的最小值设置以下参数:

2 - 配置 HDFS 访问

Vertica 使用 Hadoop 群集配置中的信息来支持读取数据(COPY 或外部表)。在 Eon 模式下,它还使用此信息来访问 HDFS 上的公共存储。因此,Vertica 节点必须有权访问某些 Hadoop 配置文件。

对于使用 Kerberos 身份验证的共置群集和单独群集,请按照为 Kerberos 身份验证配置 Vertica中的说明为 Kerberos 配置 Vertica。

Vertica 需要访问所有名称节点和数据节点上的 WebHDFS 服务和端口。有关 WebHDFS 端口的详细信息,请参阅 Cloudera 文档中的 HDFS 端口

访问 Hadoop 配置文件

您的 Vertica 节点需要访问某些 Hadoop 配置文件:

  • 如果 Vertica 共置于 HDFS 节点上,那么这些配置文件已经存在。
  • 如果 Vertica 在单独的群集上运行,您必须将所需文件复制到所有数据库节点。实现这一目标的一个简单方法是,将 Vertica 节点配置为 Hadoop 的边缘节点。客户端应用程序在边缘节点上运行;从 Hadoop 的角度来看,Vertica 是一个客户端应用程序。您可以使用 Ambari 或 Cloudera Manager 配置边缘节点。有关详细信息,请参阅 Hadoop 供应商的文档。

验证 HadoopConfDir 配置参数的值(请参阅Hadoop 参数)是否包含一个包括 core-site.xmlhdfs-site.xml 文件的目录。如果您未设置值,Vertica 会在 /etc/hadoop/conf 中查找文件。对于所有 Vertica 用户,该目录由运行 Vertica 服务器进程的 Linux 用户访问。

Vertica 使用这些配置文件中定义的多个属性。这些属性列在 HDFS 文件系统 中。

使用具有高可用性 NameNode 的群集

如果您的 Hadoop 群集使用高可用性 (HA) 名称节点,请验证 dfs.nameservices 参数和各个名称节点是否在 hdfs-site.xml 中定义。

使用多个 Hadoop 群集

在某些情况下,Vertica 群集需要访问多个 HDFS 群集。例如,您的企业可能对不同的区域使用单独的 HDFS 群集,或者您可能需要来自测试和部署群集的数据。

要支持多个群集,请执行以下步骤:

  1. 将所有 HDFS 群集的配置文件复制到您的数据库节点。您可以将复制的文件放置在 Vertica 可读的任何位置。但是,作为最佳实践,您应将它们全部放在同一个目录树中,每个 HDFS 群集有一个子目录。所有数据库节点上的位置必须相同。

  2. 设置 HadoopConfDir 配置参数。该值是一个以冒号分隔的路径,其中包含所有 HDFS 群集的目录。

  3. 创建外部表或复制数据时,在 URL 中使用显式名称节点或名称服务。不要使用 hdfs:///,因为它可能不明确。有关 URL 的详细信息,请参阅 HDFS 文件系统

Vertica 直接连接到名称节点或名称服务;它不以其他方式区分 HDFS 群集。因此,HDFS 名称节点和名称服务的名称必须是全局唯一的。

验证配置

使用 VERIFY_HADOOP_CONF_DIR 函数验证 Vertica 是否可以在 HadoopConfDir 中找到配置文件。

使用 HDFS_CLUSTER_CONFIG_CHECK 函数通过 hdfs 方案测试访问。

有关测试配置的详细信息,请参阅验证 HDFS 配置

更新配置文件

如果您在启动 Vertica 后更新配置文件,请使用下面的语句对其进行刷新:

=> SELECT CLEAR_HDFS_CACHES();

CLEAR_HDFS_CACHES 函数还刷新有关在高可用性 (HA) Hadoop 群集中哪个名称节点处于活动状态的信息。因此,调用此函数后的第一次请求很慢,因为与名称节点的初始连接可能需要 15 秒以上。

2.1 - 验证 HDFS 配置

使用 EXTERNAL_CONFIG_CHECK 函数可测试对 HDFS 的访问。此函数调用其他几个函数。如果您更喜欢测试单个组件,或者如果某些测试不适用于您的配置,则可以单独调用这些函数。例如,如果您不使用 HCatalog 连接器,则不需要调用该函数。函数为:

要运行所有测试,请调用 EXTERNAL_CONFIG_CHECK(不带实参):

=> SELECT EXTERNAL_CONFIG_CHECK();

要仅测试某些权限、名称服务或 Hive 架构,请传递单个字符串实参。格式是“键=值”对的逗号分隔列表,其中键为 "authority"、"nameservice" 和 "schema"。值传递给所有子函数;有关如何解释值的详细信息,请参阅这些参考页面。

以下示例仅测试名为 "ns1" 的名称服务的配置:

=> SELECT EXTERNAL_CONFIG_CHECK('nameservice=ns1');

2.2 - 排除 HDFS 数据读取故障

访问 HDFS 中的数据时,可能会遇到以下问题。

使用 [web]hdfs:/// 的查询显示意外结果

如果您使用 /// 简写查询外部表并看到意外结果(例如测试群集中的生产数据),请验证 HadoopConfDir 是否设置为您期望的值。HadoopConfDir 配置参数定义了用于搜索 Vertica 解析文件位置所需的 Hadoop 配置文件的路径。HadoopConfDir 参数可以在会话级别设置,覆盖数据库中设置的永久值。

要调试 /// URL 的问题,请尝试将 URL 替换为使用显式名称服务或名称节点的 URL。如果显式 URL 有效,则问题在于简写的解析。如果显式 URL 也没有按预期工作,则问题出在其他地方(例如您的名称服务)。

使用 HA 时查询需要很长时间才能运行

HDFS 中的高可用性名称节点功能允许名称节点故障转移到备用名称节点。dfs.client.failover.max.attempts 配置参数(在 hdfs-site.xml 中)指定故障转移时尝试的次数。如果未设置此参数,Vertica 将使用默认值 4。在达到最大故障转移尝试次数后,Vertica 会断定 HDFS 群集不可用并中止操作。Vertica 使用 dfs.client.failover.sleep.base.millisdfs.client.failover.sleep.max.millis 参数来决定重试之间的等待时间。典型范围是 500 毫秒到 15 秒,连续重试的等待时间更长。

另一个参数 ipc.client.connect.retry.interval 指定尝试之间的等待时间,典型值为 10 到 20 秒。

Cloudera 和 Hortonworks 都提供可自动生成配置文件的工具。这些工具可能将最大故障转移尝试次数设置为更高的数(50 或 100)。如果 HDFS 群集不可用(所有名称节点都无法访问),Vertica 可能会在尝试连接时出现长时间挂起(几分钟到几小时)。

QUERY_EVENTS 系统表记录了故障转移尝试。以下示例展示了如何查询此表以查找这些事件:

=> SELECT event_category, event_type, event_description, operator_name,
   event_details, count(event_type) AS count
   FROM query_events
   WHERE event_type ilike 'WEBHDFS FAILOVER RETRY'
   GROUP BY event_category, event_type, event_description, operator_name, event_details;
-[ RECORD 1 ]-----+---------------------------------------
event_category    | EXECUTION
event_type        | WEBHDFS FAILOVER RETRY
event_description | WebHDFS Namenode failover and retry.
operator_name     | WebHDFS FileSystem
event_details     | WebHDFS request failed on ns
count             | 4

您可以等待 Vertica 完成或中止连接,或者将 dfs.client.failover.max.attempts 参数设置为较低的值。

使用 LibHDFS++ 时出现 WebHDFS 错误

创建外部表或者加载数据并使用 hdfs 方案时,您可能会看到 WebHDFS 失败的错误消息。此类错误消息表明,Vertica 无法使用 hdfs 方案并已回退到 webhdfs,但并不表明 WebHDFS 的配置不正确。

首先验证 HadoopConfDir 配置参数的值(可以在会话级别设置该参数)。然后,验证找到的 HDFS 配置文件是否具有适用于 Hadoop 群集的正确 WebHDFS 配置。有关使用这些文件的信息,请参阅配置 HDFS 访问。有关 WebHDFS 配置的信息,请参阅 Hadoop 文档。

Vertica 在名称节点上施加了过多负载 (LibHDFS++)

当包括 Vertica 在内的客户端需要定位数据时,大型 HDFS 群集有时会在名称节点上遇到繁重的负载。如果您的名称节点对此负载敏感并且您使用的是 LibHDFS++,则可以指示 Vertica 将有关块位置的元数据分发到其节点,这样它们就不必经常联系名称节点。在没有争用名称节点的部署中,分发此元数据可能会降低数据库性能。产生这种性能影响的原因是数据必须是序列化和分布式的。

如果保护名称节点免受负载比查询性能更重要,请将 EnableHDFSBlockInfoCache 配置参数设置为 1 (true)。通常这适用于名称节点争用已经成为问题的大型 HDFS 群集。

此设置适用于通过 LibHDFS++(hdfs 方案)进行的访问。有些时候,LibHDFS++ 会退回到不使用此设置的 WebHDFS。如果您启用了此设置,而仍然看到 Vertica 名称节点上的流量很高,请查看 QUERY_EVENTS 系统表中的 LibHDFS++ UNSUPPORTED OPERATION 事件。

Kerberos 身份验证错误

如果 Hadoop 频繁使票证过期,即使票证有效,Kerberos 身份验证也可能失败。身份验证也可能由于 Hadoop 和 Vertica 节点之间的时钟偏差而失败。有关详细信息,请参阅Kerberos 身份验证故障排除

3 - 访问已进行 Kerberize 的 HDFS 数据

如果您的 Hortonworks 或 Cloudera Hadoop 群集使用 Kerberos 身份验证来限制对 HDFS 的访问,则必须授予 Vertica 访问权限。如果您对 Vertica 数据库使用 Kerberos 身份验证,并且数据库用户具有 HDFS 访问权限,则可以将 Vertica 配置为使用相同的主体进行身份验证。但是,并非所有 Hadoop 管理员都希望向所有数据库用户授予访问权限,他们更愿意以其他方式管理访问权限。此外,并非所有 Vertica 数据库都使用 Kerberos。

Vertica 提供以下选项来访问已进行 Kerberize 的 Hadoop 群集:

  • 使用 Vertica Kerberos 主体。

  • 将 Hadoop 代理用户与 Vertica 用户结合使用。

  • 使用用户指定的委托令牌来授予对 HDFS 的访问权限。委托令牌由 Hadoop 群集颁发。

代理用户和委托令牌都使用会话参数来管理身份。使用这些方法中的任何一种时,Vertica 都不需要进行 Kerberize。

Vertica 不支持将 Kerberos 用于 MapR。

要测试您的 Kerberos 配置,请参阅验证 HDFS 配置

3.1 - 将 Kerberos 与 Vertica 结合使用

如果您将 Kerberos 用于 Vertica 群集并且您的主体有权访问 HDFS,则您可以将 Vertica 配置为对 HDFS 使用相同的凭据。

Vertica 以下面两种方式执行 Hadoop 的身份验证,而这两种方式需要不同的配置:

  • 用户身份验证 — 代表用户,通过传递用户现有的 Kerberos 凭据实现。此方法也称为用户模拟。代表特定用户执行的操作(例如执行查询)通常使用用户身份验证。

  • Vertica 身份验证 — 代表访问 ROS 数据或编录的系统进程,通过使用存储在 keytab 文件中的特殊 Kerberos 凭据实现。

Vertica 可以与多个 Kerberos 领域进行交互。要配置多个领域,请参阅多领域支持

Vertica 会尝试在 Hadoop 令牌过期之前自动刷新它们。请参阅令牌过期

用户身份验证

要将 Vertica 与 Kerberos 和 Hadoop 配合使用,客户端用户首先要通过 Hadoop 群集使用的一台 Kerberos 服务器(密钥分发中心或 KDC)的身份验证。例如,用户可能会运行 kinit 或登录到 Active Directory。

通过 Kerberos 服务器身份验证的用户会收到 Kerberos 票证。在客户端会话开始时,Vertica 会自动检索此票证。然后,Vertica 使用此票证获取 Hadoop 令牌,Hadoop 使用该令牌授予访问权限。Vertica 使用此令牌访问 HDFS,例如在代表用户执行查询时。当令牌过期时,Vertica 会自动更新它,并在必要时更新 Kerberos 票证。

用户必须已获得 HDFS 中相关文件的访问权限。此权限将在 Vertica 首次读取 HDFS 数据时接受检查。

如果在领域之间建立了适当的跨领域信任,Vertica 可以使用多个 KDC 服务于多个 Kerberos 领域。

Vertica 身份验证

自动进程(例如 Tuple Mover 或访问 Eon 模式公共存储的进程)不会像用户那样登录。相反,Vertica 使用存储在每个数据库节点上的 keytab 文件中的特殊身份(主体)。(这种方法也用于使用 Kerberos 但不使用 Hadoop 的 Vertica 群集。)配置 keytab 文件后,Vertica 会使用驻留在该文件中的主体自动获取和维护 Kerberos 票证,这与客户端场景中的情况非常相似。在这种情况下,客户端不与 Kerberos 交互。

每个 Vertica 节点均使用其自己的主体;将节点名称纳入主体名称是很常见的。您可以给每个节点均创建一个 keytab 文件,其中仅包含该节点的主体;或者您可以创建包含所有主体的单个 keytab 文件,并将该文件分发到所有节点。无论采用哪种方法,节点均使用其主体获取 Kerberos 票据,并随后使用该票据获取 Hadoop 令牌。

创建 HDFS 存储位置时,Vertica 使用 keytab 文件中的主体,而不是发出 CREATE LOCATION 语句的用户的主体。HCatalog 连接器有时会使用 keytab 文件中的主体,这取决于 Hive 如何对用户进行身份验证。

配置用户和 keytab 文件

如果您尚未针对 Vertica 配置 Kerberos 身份验证,请遵循为 Kerberos 身份验证配置 Vertica中的指示。对于 Hadoop 集成特别重要:

  1. 每个节点创建一个 Kerberos 主体。

  2. 将 keytab 文件放在每个数据库节点上的相同位置,并将配置参数 KerberosKeytabFile 设置为该位置。

  3. 将 KerberosServiceName 设置为主体的名称。(请参阅通知 Vertica 有关 Kerberos 主体的信息。)

如果您使用的是 HCatalog 连接器,请按照 HCatalog 连接器文档的配置安全性中的其他步骤操作。

如果您使用的是 HDFS 存储位置,请向所有节点主体授予将用作存储位置的 HDFS 目录的读写权限。

3.2 - 代理用户和委托令牌

向单个 Vertica 用户授予 HDFS 访问权限的另一种方法是直接或通过代理用户使用委托令牌。在此配置中,Vertica 代表其他一些 (Hadoop) 用户访问 HDFS。Hadoop 用户根本不需要是 Vertica 用户。

在 Vertica 中,您可以指定 Hadoop 用户的名称以代表 (doAs) 执行操作,也可以直接使用从 HDFS 获得的 Kerberos 委托令牌(自带您的委托令牌)。在 doAs 案例中,Vertica 为该用户获取委托令牌,因此这两种方法最终都使用委托令牌来访问 HDFS 中的文件。

使用 HadoopImpersonationConfig 会话参数以指定用于 HDFS 访问的用户或委托令牌。每个会话可以使用不同的用户,并且可以使用 doAs 或委托令牌。HadoopImpersonationConfig 的值是一组 JSON 对象。

要使用任一类型的委托令牌(更具体地说,当设置 HadoopImpersonationConfig 时),您必须通过 WebHDFS 访问 HDFS。

3.2.1 - 用户模拟 (doAs)

您可以使用用户模拟从 Vertica 访问 HDFS 群集中的数据。这种方法称为 "doAs"(表示 "do As"),因为 Vertica 使用单个代理用户代表另一个 (Hadoop) 用户。模拟的 Hadoop 用户不需要是 Vertica 用户。

在下图中,Alice 是 Hadoop 用户,但不是 Vertica 用户。她以代理用户 vertica-etl 的身份连接到 Vertica。在她的会话中,Vertica 代表 doAs 用户 (Alice) 获得一个委托令牌 (DT),并使用该委托令牌访问 HDFS。

您可以使用带有或不带 Kerberos 的 doAs,只要 HDFS 和 Vertica 匹配即可。如果 HDFS 使用 Kerberos,那么 Vertica 也必须使用 Kerberos。

用户配置

Hadoop 管理员必须创建一个代理用户并允许其代表其他用户访问 HDFS。在 core-site.xml 中设置值,如下例所示:

<name>hadoop.proxyuser.vertica-etl.users</name>
<value>*</value>
<name>hadoop.proxyuser.vertica-etl.hosts</name>
<value>*</value>

在 Vertica 中,创建相应的用户。

会话配置

要代表 Hadoop 用户发出请求,首先设置 HadoopImpersonationConfig 会话参数以指定用户和 HDFS 群集。Vertica 将以该用户身份访问 HDFS,直到会话结束或您更改参数为止。

此会话参数的值是 JSON 对象的集合。每个对象指定一个 HDFS 群集和一个 Hadoop 用户。对于群集,您可以指定名称服务或单个名称节点。如果您使用的是 HA 名称节点,则必须使用名称服务或指定所有名称节点。 HadoopImpersonationConfig 格式 描述了完整的 JSON 语法。

以下示例显示了代表两个不同用户的访问权限。用户 "stephanie" 和 "bob" 是 Hadoop 用户,而不是 Vertica 用户。"vertica-etl" 是 Vertica 用户。


$ vsql -U vertica-etl

=> ALTER SESSION SET
   HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"stephanie"}]';
=> COPY nation FROM 'webhdfs:///user/stephanie/nation.dat';

=> ALTER SESSION SET
   HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"bob"}, {"authority":"hadoop2:50070", "doAs":"rob"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';

Vertica 使用从名称节点获取的 Hadoop 委托令牌来模拟 Hadoop 用户。在长时间运行的会话中,令牌可能会过期。Vertica 会尝试自动更新令牌;请参阅令牌过期

测试配置

您可以使用 HADOOP_IMPERSONATION_CONFIG_CHECK 函数测试 HDFS 委托令牌,使用 HCATALOGCONNECTOR_CONFIG_CHECK 测试 HCatalog 连接器委托令牌。

3.2.2 - 自带您的委托令牌

您可以为 Vertica 提供一个 Hadoop 委托令牌以供使用,而不是创建代理用户并授予其访问 HDFS 以与 doAs 一起使用的权限。您必须从 Hadoop 名称节点获取此委托令牌。在此模型中,安全性完全在 Hadoop 端处理,Vertica 只传递一个令牌。Vertica 可能会或可能不会进行 Kerberize。

典型的工作流是:

  • 在 ETL 前端,用户提交查询。

  • ETL 系统使用身份验证和授权服务验证用户是否有足够的权限来运行查询。

  • ETL 系统从名称节点为用户请求一个委托令牌。

  • ETL 系统与 Vertica 建立客户端连接,为会话设置委托令牌,然后运行查询。

使用委托令牌时,客户端可以作为任何 Vertica 用户进行连接。不需要代理用户。

在下图中,Bob 有一个 Hadoop 颁发的委托令牌。他连接到 Vertica,Vertica 使用该委托令牌访问 HDFS 中的文件。

会话配置

设置 HadoopImpersonationConfig 会话参数以指定委托令牌和 HDFS 群集。Vertica 将使用该委托令牌访问 HDFS,直到会话结束、令牌过期或您更改参数为止。

此会话参数的值是 JSON 对象的集合。每个对象指定一个 WebHDFS 格式的委托令牌(“令牌”)和一个 HDFS 名称服务或名称节点。 HadoopImpersonationConfig 格式 描述了完整的 JSON 语法。

以下示例显示了代表两个不同用户的访问权限。用户 "stephanie" 和 "bob" 是 Hadoop 用户,而不是 Vertica 用户。"dbuser1" 是没有特殊权限的 Vertica 用户。

$ vsql -U dbuser1

=> ALTER SESSION SET
   HadoopImpersonationConfig ='[{"authority":"hadoop1:50070","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/stephanie/nation.dat';

=> ALTER SESSION SET
   HadoopImpersonationConfig ='[{"authority":"hadoop1:50070","token":"HgADdG9tA3RvbQCKAWDXJgAoigFg-zKEKI4gaI4BmhRoOUpq_jPxrVhZ1NSMnodAQnhUthJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';

您可以使用 WebHDFS REST API 获取委托令牌:

$ curl -s --noproxy "*" --negotiate -u: -X GET "http://hadoop1:50070/webhdfs/v1/?op=GETDELEGATIONTOKEN"

Vertica 不会也不能在授权令牌到期时更新它们。您必须保持会话短于令牌生命周期,或实施更新方案。

委托令牌和 HCatalog 连接器

HiveServer2 对委派令牌使用不同的格式。因此,要使用 HCatalog 连接器,您必须设置两个委托令牌,一个用于往常用途(授权),一个用于 HiveServer2(架构)。HCatalog 连接器使用架构令牌访问元数据,使用授权令牌访问数据。架构名称与您在 CREATE HCATALOG SCHEMA 中指定的 Hive 架构相同。以下示例显示了如何使用这两个委托令牌。

$ vsql -U dbuser1

-- set delegation token for user and HiveServer2
=> ALTER SESSION SET
   HadoopImpersonationConfig='[
     {"nameservice":"hadoopNS","token":"JQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"},
     {"schema":"access","token":"UwAHcmVsZWFzZQdyZWxlYXNlL2hpdmUvZW5nLWc5LTEwMC52ZXJ0aWNhY29ycC5jb21AVkVSVElDQUNPUlAuQ09NigFhUkmyTooBYXZWNk4BjgETFKN2xPURn19Yq9tf-0nekoD51TZvFUhJVkVfREVMRUdBVElPTl9UT0tFThZoaXZlc2VydmVyMkNsaWVudFRva2Vu"}]';

-- uses HiveServer2 token to get metadata
=> CREATE HCATALOG SCHEMA access WITH hcatalog_schema 'access';

-- uses both tokens
=> SELECT * FROM access.t1;

--uses only HiveServer2 token
=> SELECT * FROM hcatalog_tables;

HiveServer2 不像 WebHDFS 那样为委派令牌提供 REST API。请参阅获取 HiveServer2 委托令牌了解一些提示。

测试配置

您可以使用 HADOOP_IMPERSONATION_CONFIG_CHECK 函数测试 HDFS 委托令牌,使用 HCATALOGCONNECTOR_CONFIG_CHECK 测试 HCatalog 连接器委托令牌。

3.2.3 - 获取 HiveServer2 委托令牌

要使用 HiveServer2 访问 Hive 元数据,您需要一个特殊的委托令牌。(请参阅自带您的委托令牌。)与授予 HDFS(数据)委托令牌的 REST API 不同,HiveServer2 不提供获取此令牌的简单方法。

以下实用程序代码显示了获取此令牌的方法。您需要为自己的群集修改此代码;特别是,更改 connectURL 静态的值。

import java.io.FileWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.shims.Utils;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hive.jdbc.HiveConnection;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class JDBCTest {
  public static final String driverName = "org.apache.hive.jdbc.HiveDriver";
  public static String connectURL = "jdbc:hive2://node2.cluster0.example.com:2181,node1.cluster0.example.com:2181,node3.cluster0.example.com:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2";
  public static String schemaName = "hcat";
  public static String verticaUser = "condor";
  public static String proxyUser = "condor-2";
  public static String krb5conf = "/home/server/kerberos/krb5.conf";
  public static String realm = "EXAMPLE.COM";
  public static String keytab = "/home/server/kerberos/kt.keytab";

  public static void main(String[] args) {
    if (args.length < 7) {
      System.out.println(
          "Usage: JDBCTest <jdbc_url> <hive_schema> <kerberized_user> <proxy_user> <krb5_conf> <krb_realm> <krb_keytab>");
      System.exit(1);
    }
    connectURL = args[0];
    schemaName = args[1];
    verticaUser = args[2];
    proxyUser = args[3];
    krb5conf = args[4];
    realm = args[5];
    keytab = args[6];

    System.out.println("connectURL: " + connectURL);
    System.out.println("schemaName: " + schemaName);
    System.out.println("verticaUser: " + verticaUser);
    System.out.println("proxyUser: " + proxyUser);
    System.out.println("krb5conf: " + krb5conf);
    System.out.println("realm: " + realm);
    System.out.println("keytab: " + keytab);
    try {
      Class.forName("org.apache.hive.jdbc.HiveDriver");
      System.out.println("Found HiveServer2 JDBC driver");
    } catch (ClassNotFoundException e) {
      System.out.println("Couldn't find HiveServer2 JDBC driver");
    }
    try {
      Configuration conf = new Configuration();
      System.setProperty("java.security.krb5.conf", krb5conf);
      conf.set("hadoop.security.authentication", "kerberos");
      UserGroupInformation.setConfiguration(conf);
      dtTest();
    } catch (Throwable e) {
      Writer stackString = new StringWriter();
      e.printStackTrace(new PrintWriter(stackString));
      System.out.println(e);
      System.out.printf("Error occurred when connecting to HiveServer2 with [%s]: %s\n%s\n",
          new Object[] { connectURL, e.getMessage(), stackString.toString() });
    }
  }

  private static void dtTest() throws Exception {
    UserGroupInformation user = UserGroupInformation.loginUserFromKeytabAndReturnUGI(verticaUser + "@" + realm, keytab);
    user.doAs(new PrivilegedExceptionAction() {
      public Void run() throws Exception {
        System.out.println("In doas: " + UserGroupInformation.getLoginUser());
        Connection con = DriverManager.getConnection(JDBCTest.connectURL);
        System.out.println("Connected to HiveServer2");
        JDBCTest.showUser(con);
        System.out.println("Getting delegation token for user");
        String token = ((HiveConnection) con).getDelegationToken(JDBCTest.proxyUser, "hive/_HOST@" + JDBCTest.realm);
        System.out.println("Got token: " + token);
        System.out.println("Closing original connection");
        con.close();

        System.out.println("Setting delegation token in UGI");
        Utils.setTokenStr(Utils.getUGI(), token, "hiveserver2ClientToken");
        con = DriverManager.getConnection(JDBCTest.connectURL + ";auth=delegationToken");
        System.out.println("Connected to HiveServer2 with delegation token");
        JDBCTest.showUser(con);
        con.close();

        JDBCTest.writeDTJSON(token);

        return null;
      }
    });
  }

  private static void showUser(Connection con) throws Exception {
    String sql = "select current_user()";
    Statement stmt = con.createStatement();
    ResultSet res = stmt.executeQuery(sql);
    StringBuilder result = new StringBuilder();
    while (res.next()) {
      result.append(res.getString(1));
    }
    System.out.println("\tcurrent_user: " + result.toString());
  }

  private static void writeDTJSON(String token) {
    JSONArray arr = new JSONArray();
    JSONObject obj = new JSONObject();
    obj.put("schema", schemaName);
    obj.put("token", token);
    arr.add(obj);
    try {
      FileWriter fileWriter = new FileWriter("hcat_delegation.json");
      fileWriter.write(arr.toJSONString());
      fileWriter.flush();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

以下是一个调用及其输出的示例:

$ java -cp hs2token.jar JDBCTest 'jdbc:hive2://test.example.com:10000/default;principal=hive/_HOST@EXAMPLE.COM' "default" "testuser" "test" "/etc/krb5.conf" "EXAMPLE.COM" "/test/testuser.keytab"
connectURL: jdbc:hive2://test.example.com:10000/default;principal=hive/_HOST@EXAMPLE.COM
schemaName: default
verticaUser: testuser
proxyUser: test
krb5conf: /etc/krb5.conf
realm: EXAMPLE.COM
keytab: /test/testuser.keytab
Found HiveServer2 JDBC driver
log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
In doas: testuser@EXAMPLE.COM (auth:KERBEROS)
Connected to HiveServer2
        current_user: testuser
Getting delegation token for user
Got token: JQAEdGVzdARoaXZlB3JlbGVhc2WKAWgvBOwzigFoUxFwMwKOAgMUHfqJ5ma7_27LiePN8C7MxJ682bsVSElWRV9ERUxFR0FUSU9OX1RPS0VOFmhpdmVzZXJ2ZXIyQ2xpZW50VG9rZW4
Closing original connection
Setting delegation token in UGI
Connected to HiveServer2 with delegation token
        current_user: testuser

3.2.4 - HadoopImpersonationConfig 格式

HadoopImpersonationConfig 会话参数的值是由一个或多个 JSON 对象组成的集合。每个对象为一个 Hadoop 目标描述一个 doAs 用户或委托令牌。您必须使用 WebHDFS 而不是 LibHDFS++,才能使用模拟。

语法

[ { ("doAs" | "token"): value,
    ("nameservice" | "authority" | "schema"): value} [,...]
]

属性

示例

在以下 doAs 示例中,Bob 是 Hadoop 用户,vertica-etl 是已进行 Kerberize 的代理用户。

$ kinit vertica-etl -kt /home/dbadmin/vertica-etl.keytab
$ vsql -U vertica-etl

=> ALTER SESSION SET
   HadoopImpersonationConfig = '[{"nameservice":"hadoopNS", "doAs":"Bob"}]';
=> COPY nation FROM 'webhdfs:///user/bob/nation.dat';

在以下示例中,当前 Vertica 用户(无论是谁)使用 Hadoop 委托令牌。此令牌属于 Alice,但您从未在此处指定用户名。相反,您使用它从 Hadoop 获取委托令牌。

$ vsql -U dbuser1

=> ALTER SESSION SET
   HadoopImpersonationConfig ='[{"nameservice":"hadoopNS","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"}]';
=> COPY nation FROM 'webhdfs:///user/alice/nation.dat';

在以下示例中,"authority" 指定不使用高可用性的 Hadoop 群集上的(单个)名称节点。

$ vsql -U dbuser1

=> ALTER SESSION SET
   HadoopImpersonationConfig ='[{"authority":"hadoop1:50070", "doAs":"Stephanie"}]';
=> COPY nation FROM 'webhdfs://hadoop1:50070/user/stephanie/nation.dat';

要访问 Hive 中的数据,您需要指定两个委托令牌。第一个用于名称服务或授权,像往常一样进行数据访问。第二个用于架构的 HiveServer2 元数据。HiveServer2 需要 WebHDFS 格式的委托令牌。架构名称是您使用 CREATE HCATALOG SCHEMA 指定的 Hive 架构。

$ vsql -U dbuser1

-- set delegation token for user and HiveServer2
=> ALTER SESSION SET
   HadoopImpersonationConfig='[
     {"nameservice":"hadoopNS","token":"JQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"},
     {"schema":"access","token":"UwAHcmVsZWFzZQdyZWxlYXNlL2hpdmUvZW5nLWc5LTEwMC52ZXJ0aWNhY29ycC5jb21AVkVSVElDQUNPUlAuQ09NigFhUkmyTooBYXZWNk4BjgETFKN2xPURn19Yq9tf-0nekoD51TZvFUhJVkVfREVMRUdBVElPTl9UT0tFThZoaXZlc2VydmVyMkNsaWVudFRva2Vu"}]';

-- uses HiveServer2 token to get metadata
=> CREATE HCATALOG SCHEMA access WITH hcatalog_schema 'access';

-- uses both tokens
=> SELECT * FROM access.t1;

--uses only HiveServer2 token
=> SELECT * FROM hcatalog_tables;

HadoopImpersonationConfig 集合中的每个对象都指定与一个 Hadoop 群集的连接。您可以添加任意数量的连接,包括添加与多个 Hadoop 群集的连接。以下示例显示了两个不同 Hadoop 群集的委托令牌。Vertica 在连接时为每个群集使用正确的令牌。

$ vsql -U dbuser1

=> ALTER SESSION SET
   HadoopImpersonationConfig ='[
    {"nameservice":"productionNS","token":"JAAGZGJldGwxBmRiZXRsMQCKAWDXJgB9igFg-zKEfY4gao4BmhSJYtXiWqrhBHbbUn4VScNg58HWQxJXRUJIREZTIGRlbGVnYXRpb24RMTAuMjAuMTAwLjU0OjgwMjA"},
    {"nameservice":"testNS", "token":"HQAHcmVsZWFzZQdyZWxlYXNlAIoBYVJKrYSKAWF2VzGEjgmzj_IUCIrI9b8Dqu6awFTHk5nC-fHB8xsSV0VCSERGUyBkZWxlZ2F0aW9uETEwLjIwLjQyLjEwOTo4MDIw"}]';

=> COPY clicks FROM 'webhdfs://productionNS/data/clickstream.dat';
=> COPY testclicks FROM 'webhdfs://testNS/data/clickstream.dat';

3.3 - 令牌过期

Vertica 在使用 Kerberos 票证 (将 Kerberos 与 Vertica 结合使用) 或 doAs (用户模拟 (doAs)) 时使用 Hadoop 令牌。Vertica 会尝试在 Hadoop 令牌过期前自动刷新 Hadoop 令牌,不过如果您愿意,您还可以设置最低刷新频率。使用 HadoopFSTokenRefreshFrequency 配置参数以秒为单位指定频率:

=> ALTER DATABASE exampledb SET HadoopFSTokenRefreshFrequency = '86400';

如果令牌的当前年限大于此参数中指定的值,Vertica 将在访问 HDFS 中存储的数据前刷新令牌。

Vertica 不会刷新委托令牌 (自带您的委托令牌)。

4 - 使用 HDFS 存储位置

Vertica 以原生格式 ROS 将数据存储在存储位置。您可以将存储位置放在本地 Linux 文件系统或 HDFS 中。如果您将存储位置放在 HDFS 中,则必须在 HDFS 中执行额外的配置才能管理它们。这些是 Vertica 中对管理存储位置备份/还原的要求的补充。

如果您使用 HDFS 存储位置,则在启动 Vertica 时 HDFS 数据必须可用。HDFS 群集必须可以运行,且 ROS 文件必须存在。如果您已移动数据文件,或者它们已损坏,或者 HDFS 群集没有响应,则 Vertica 无法启动。

4.1 - 用于备份和还原的 Hadoop 配置

如果您的 Vertica 群集使用 HDFS 上的存储位置,并且您希望能够使用 vbr 备份和还原这些存储位置,则必须在 HDFS 中启用快照。

Vertica 备份脚本使用 HDFS 的快照功能创建 HDFS 存储位置备份。在 HDFS 可以生成快照之前,目录必须允许快照功能。只有 Hadoop 超级用户可以启用目录上的快照功能。如果数据库管理员同样是 Hadoop 超级用户,则 Vertica 可以自动启用快照功能。

如果 HDFS 不安全,以下说明适用于数据库管理员帐户,通常为 dbadmin。如果 HDFS 使用 Kerberos 安全性,以下说明适用于 Vertica keytab 文件中存储的主体,通常为 vertica。下面的说明使用“数据库帐户”一词指代此用户。

我们建议您让数据库管理员或主体成为 Hadoop 超级用户。如果您无法做到这一点,则必须先启用目录上的快照功能,然后再对其进行配置,以供 Vertica 使用。

让 Vertica 数据库管理员帐户成为超级用户所需执行的步骤取决于您正在使用的 Hadoop 发行版。有关详细信息,请查阅 Hadoop 发行版的文档。

手动启用目录的快照功能

如果不能向数据库帐户授予超级用户身份,您可以转而手动启用各个目录的快照功能。请使用以下命令:

$ hdfs dfsadmin -allowSnapshot path

针对每个节点上的每个目录发出此命令。每当您将新节点添加到 HDFS 群集时,请记得执行此操作。

可生成快照的嵌套目录不受支持,因此您无法通过启用父目录的快照功能来自动启用子目录的快照功能。而必须为每个目录分别启用该功能。

Kerberos 的附加要求

如果 HDFS 使用 Kerberos,那么除了授予 keytab 主体访问权限以外,您还必须授予 Vertica 对某些 Hadoop 配置文件的访问权限。请参阅配置 Kerberos

测试数据库帐户使 HDFS 目录可生成快照的能力

使数据库帐户成为 Hadoop 超级用户后,验证该帐户能否将目录设置为可生成快照:

  1. 以数据库帐户的身份(默认为 dbadmin)登录到 Hadoop 群集。

  2. 在 HDFS 中确定一个可供数据库管理员创建目录的位置。通常情况下,可以使用 /tmp 目录。使用以下命令创建一个测试 HDFS 目录:

    $ hdfs dfs -mkdir /path/testdir
    
  3. 使用以下命令使测试目录可以生成快照:

    $ hdfs dfsadmin -allowSnapshot /path/testdir
    

下面的示例演示了如何创建 HDFS 目录并使其可以生成快照:

$ hdfs dfs -mkdir /tmp/snaptest
$ hdfs dfsadmin -allowSnapshot /tmp/snaptest
Allowing snaphot on /tmp/snaptest succeeded

4.2 - 移除 HDFS 存储位置

移除 HDFS 存储位置的步骤与移除标准存储位置的步骤类似:

  1. 通过使用 SET_OBJECT_STORAGE_POLICY 更改每个对象的存储位置,从 HDFS 存储位置移除任何现有数据。或者,您可以使用 CLEAR_OBJECT_STORAGE_POLICY。由于 Tuple Mover 不经常运行,请将 enforce-storage-move 参数设置为 true 以立即进行更改。

  2. 使用 RETIRE_LOCATION,在定义了该存储位置的每个主机上停用该位置。将 enforce-storage-move 设置为 true

  3. 使用 DROP_LOCATION 删除每个节点上的位置。

  4. 可以选择将快照和文件从该存储位置的 HDFS 目录中移除。

  5. 执行完整的数据库备份。

有关更改存储策略、更改使用、停用位置和删除位置的详细信息,请参阅管理存储位置

从 HDFS 移除存储位置文件

删除 HDFS 存储位置不会自动清理存储该位置文件的 HDFS 目录。也不会删除备份该位置时创建的任何数据文件快照。这些文件不但占用 HDFS 上的磁盘空间,还使该目录无法再次用作 HDFS 存储位置。Vertica 无法在包含现有文件或子目录的目录中创建存储位置。

您必须登录到 Hadoop 群集,才能将文件从 HDFS 中删除。一个替代方案是,使用一些其他的 HDFS 文件管理工具。

移除备份快照

如果您试图移除具有快照的目录,HDFS 将返回以下错误:

$ hdfs dfs -rm -r -f -skipTrash /user/dbadmin/v_vmart_node0001
rm: The directory /user/dbadmin/v_vmart_node0001 cannot be deleted since
/user/dbadmin/v_vmart_node0001 is snapshottable and already has snapshots

作为备份过程的一部分,Vertica 备份脚本将创建 HDFS 存储位置的快照。如果制作了 HDFS 存储位置的备份,您必须在删除目录之前删除快照。

HDFS 将快照存储在名为 .snapshot 的子目录中。您可以使用标准的 HDFS ls 命令列出目录中的快照。

$ hdfs dfs -ls /user/dbadmin/v_vmart_node0001/.snapshot
Found 1 items
drwxrwx---   - dbadmin supergroup          0 2014-09-02 10:13 /user/dbadmin/v_vmart_node0001/.snapshot/s20140902-101358.629

要删除快照,请使用以下命令:

$ hdfs dfs -removeSnapshot directory snapshotname

下面的示例演示了用于删除上个示例中显示的快照的命令:

$ hdfs dfs -deleteSnapshot /user/dbadmin/v_vmart_node0001 s20140902-101358.629

您必须将每个快照从群集中各个主机的目录中删除。删除快照后,您就可以删除存储位置中的目录。

有关管理和移除快照的详细信息,请参阅 Apache 的 HDFS 快照文档

移除存储位置目录

您可以通过下列任一方法,删除保存存储位置数据的目录:

  • 使用 HDFS 文件管理器删除目录。请参阅 Hadoop 发行版的文档,以确定其是否提供文件管理器。

  • 使用数据库管理员帐户登录到 Hadoop 名称节点,然后使用 HDFS 的 rmr 命令删除目录。有关详细信息,请参阅 Apache 的文件系统 Shell 指南

下面的示例从 Linux 命令行使用 HDFS rmr 命令,来删除 HDFS 存储位置目录 /user/dbamin 中剩余的目录。它使用 -skipTrash 标志来强制立即删除这些文件:

$ hdfsp dfs -ls /user/dbadmin
Found 3 items
drwxrwx---   - dbadmin supergroup          0 2014-08-29 15:11 /user/dbadmin/v_vmart_node0001
drwxrwx---   - dbadmin supergroup          0 2014-08-29 15:11 /user/dbadmin/v_vmart_node0002
drwxrwx---   - dbadmin supergroup          0 2014-08-29 15:11 /user/dbadmin/v_vmart_node0003

$ hdfs dfs -rmr -skipTrash /user/dbadmin/*
Deleted /user/dbadmin/v_vmart_node0001
Deleted /user/dbadmin/v_vmart_node0002
Deleted /user/dbadmin/v_vmart_node0003

5 - 使用 HCatalog 连接器

Vertica HCatalog 连接器允许您像访问原生 Vertica 表内数据那样,访问存储在 Apache 的 Hive 数据仓库软件中的数据。

如果您的文件是 Optimized Columnar Row (ORC) 或 Parquet 格式且不使用复杂类型,HCatalog 连接器将创建外部表并使用 ORC 或 Parquet 读取器,而不是使用 Java SerDe。有关这些读取器的详细信息,请参阅 ORCPARQUET

HCatalog 连接器执行谓词下推以提高查询性能。HCatalog 连接器将谓词评估移动到更接近数据的位置,而不是读取整个网络的所有数据来评估查询。谓词下推适用于 Hive 分区修剪、ORC 带区修剪和 Parquet 行组修剪。HCatalog 连接器支持以下谓词的谓词下推:>、>=、=、<>、<=、<。

5.1 - 概述

要使用 HCatalog 连接器,您必须了解几个 Hadoop 组件:

  • Apache Hive 允许您按照与查询关系数据库中所存数据相同的方式,查询 Hadoop 分布式文件系统 (HDFS) 中存储的数据。Hive 在后台使用一组序列化程序和反序列化程序 (SerDe) 类,从 HDFS 中存储的文件中提取数据并将其分解成列和行。每个 SerDe 均以特定的格式处理数据文件。例如,一个 SerDe 从以逗号分隔的数据文件中提取数据,另一个 SerDe 则可解释以 JSON 格式存储的数据。

  • Apache HCatalog 是 Hadoop 生态系统的一个组件,可向其他 Hadoop 组件(如 Pig)提供 Hive 元数据。

  • HiveServer2 通过 JDBC 使 HCatalog 和 Hive 数据可用。通过它,客户端可以请求检索 Hive 中存储的数据以及有关 Hive 架构的信息。HiveServer2 可以使用授权服务(Sentry 或 Ranger)。HiverServer2 可以使用 Hive LLAP (Live Long And Process)。

Vertica HCatalog 连接器让您可以透明地访问可通过 HiveServer2 获得的数据。您可以使用该连接器来定义 Vertica 中与 Hive 数据库或架构相对应的架构。当您在此架构内查询数据时,HCatalog 连接器可以透明地从 Hadoop 中提取数据,并将该数据格式化为表格数据。Vertica 支持授权服务和 Hive LLAP。

HCatalog 连接功能

HCatalog 连接器允许您使用 Vertica 原生 SQL 语法查询 Hive 中存储的数据。其部分主要特性有:

  • HCatalog 连接器始终反映 Hive 中存储的数据的当前状态。

  • HCatalog 连接器利用 Vertica 和 Hadoop 的并行特性来处理 Hive 数据。其结果是,通过 HCatalog 连接器查询数据通常比直接通过 Hive 查询数据速度更快。

  • 由于 Vertica 执行数据的提取和解析,HCatalog 连接器不会明显增加 Hadoop 群集上的负载。

  • 您可以像使用原生 Vertica 数据那样,使用通过 HCatalog 连接器查询的数据。例如,您可以执行能够联接 HCatalog 架构中的表数据与本地表数据的查询。

HCatalog 连接器注意事项

使用 HCatalog 连接器时,要牢记以下几点:

  • Hive 的数据存储在分布式文件系统中的平面文件内,每次查询 Hive 数据都必须对其进行读取和反序列化。这种反序列化会导致 Hive 的性能远慢于 Vertica。要读取数据,HCatalog 连接器必须执行与 Hive 相同的流程。因此,使用 HCatalog 连接器查询 Hive 中存储的数据比查询本地 Vertica 表要慢得多。如果需要对 Hive 中存储的数据执行广泛的分析,您应该考虑将其加载到 Vertica 中。Vertica 优化后,通过 HCatalog 连接器查询数据通常比直接通过 Hive 查询数据更快。

  • 如果 Hive 使用 Kerberos 安全性,则 HCatalog 连接器默认在查询中使用查询用户的凭据。如果 Hive 使用 Sentry 或 Ranger 来强制实施安全性,则您必须通过将 EnableHCatImpersonation 设置为 0 在 Vertica 中禁用这种查询行为,或者授予用户对 HDFS 中基础数据的访问权限。(Sentry 支持 ACL 同步自动授予访问权限。)或者,您可以为数据和元数据访问指定委托令牌。请参阅配置安全性

  • Hive 支持 Vertica 不支持的复杂数据类型,如 list、map 和 struct。包含这些数据类型的列将转换成以 JSON 表示的数据类型,并存储为 VARCHAR。请参阅从 Hive 到 Vertica 的数据类型转换

5.2 - HCatalog 连接器工作原理

规划访问 Hive 表中数据的查询时,启动程序节点上的 Vertica HCatalog 连接器将联系 Hadoop 群集中的 HiveServer2(或 WebHCat),以确定该表是否存在。如果该表存在,连接器将从元存储数据库检索该表的元数据,以便查询规划可以继续。查询执行时,Vertica 群集中的所有节点直接从 HDFS 检索完成查询所必需的数据。然后,它们使用 Hive SerDe 类提取数据,以便查询可以执行。访问 ORC 或 Parquet 格式的数据时,HCatalog 连接器使用 Vertica 的内部读取器(而不是 Hive SerDe 类)来处理这些格式。

这种方法利用了 Vertica 和 Hadoop 的并行性。此外,HCatalog 连接器还通过直接执行数据检索和提取,降低了查询对 Hadoop 群集的影响。

对于采用 Optimized Columnar Row (ORC) 或 Parquet 格式且不使用复杂类型的文件,HCatalog 连接器将创建外部表并使用 ORC 或 Parquet 读取器,而不是使用 Java SerDe。如果 Hive 在写入数据时使用自定义 Hive 分区位置,您可以指示这些读取器访问该位置。默认情况下,系统会关闭这些额外的检查以提高性能。

5.3 - HCatalog 连接器要求

您的 Vertica 和 Hadoop 安装必须满足以下要求,才可以使用 HCatalog 连接器。

Vertica 要求

群集中的所有节点均须安装 Java 虚拟机 (JVM)。您必须使用 Hadoop 群集所用的相同 Java 版本。请参阅在 Vertica 群集上安装 Java 运行时

您还必须将使用 Hadoop 和 Hive 分发的特定库添加到 Vertica 安装目录。请参阅为 HCatalog 配置 Vertica

Hadoop 要求

您的 Hadoop 群集必须满足几项要求才能与 Vertica Connector for HCatalog 一起正常操作:

  • 必须已安装 Hive、HiveServer2 和 HCatalog 并且正在运行。有关详细信息,请参阅 Apache 的 HCatalog 页面。

  • HiveServer2 服务器以及用于存储 HCatalog 数据的所有 HDFS 节点必须能够直接从 Vertica 数据库中的所有主机中访问。验证用于分离 Hadoop 群集和 Vertica 群集的任何防火墙是否会传递 HiveServer2、metastore 数据库和 HDFS 流量。

  • 您要查询的数据必须位于内部或外部 Hive 表中。

  • 如果您要查询的表使用一个非标准 SerDe,则必须将 SerDe 的类安装在 Vertica 群集上,然后才能查询数据。请参阅使用非标准 SerDes

5.4 - 在 Vertica 群集上安装 Java 运行时

HCatalog 连接器需要 64 位 Java 虚拟机 (JVM)。此 JVM 必须支持 Java 6 或更高版本,还必须与 Hadoop 节点上安装的 JVM 同属一个版本。

在 Vertica 群集上安装 Java 分为两步:

  1. 在群集中的所有主机上安装 Java 运行时。

  2. 设置 JavaBinaryForUDx 配置参数,让 Vertica 了解 Java 可执行文件的位置。

对于基于 Java 的功能,Vertica 要求使用 64 位 Java 6(Java 版本 1.6)或更高版本 Java 运行时。Vertica 支持 Oracle 或 OpenJDK 中的运行时。您可以选择安装 Java 运行时环境 (JRE) 或者 Java 开发工具包 (JDK),因为 JDK 还包括 JRE。

许多 Linux 分发版都含有一个 OpenJDK 运行时包。有关安装和配置 OpenJDK 的信息,请参阅您的 Linux 分发版的文档。

要安装 Oracle Java 运行时,请参阅 Java Standard Edition (SE) 下载页。您通常需要以 root 身份运行安装包才能安装它。有关说明,请参阅下载页。

如果已经在每台主机上安装了 JVM,请确保 java 命令位于搜索路径中,而且通过运行以下命令来调用正确的 JVM:

$ java -version

此命令的输出类似如下内容:

java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

设置 JavaBinaryForUDx 配置参数

JavaBinaryForUDx 配置参数可以让 Vertica 了解到执行 Java UDx 的 JRE 的位置。在群集中的所有节点上安装 JRE 后,请将此参数设置为 Java 可执行文件的绝对路径。您可以使用 Java 安装程序创建的符号链接(例如 /usr/bin/java)。如果 Java 可执行文件位于 shell 搜索路径中,您可以从 Linux 命令行 shell 中运行以下命令来获得 Java 可执行文件的路径。

$ which java
/usr/bin/java

如果 java 命令不在 shell 搜索路径中,请使用 JRE 安装目录中的 Java 可执行文件路径。假设您已在 /usr/java/default 中安装了 JRE(Oracle 提供的安装包会在此安装 Java 1.6 JRE)。在此情况下,Java 可执行文件为 /usr/java/default/bin/java

要设置配置参数,您可以 数据库超级用户身份执行以下语句:

=> ALTER DATABASE DEFAULT SET PARAMETER JavaBinaryForUDx = '/usr/bin/java';

有关设置配置参数的详细信息,请参阅 ALTER DATABASE

要查看配置参数的当前设置,请查询 CONFIGURATION_PARAMETERS 系统表:

=> \x
Expanded display is on.
=> SELECT * FROM CONFIGURATION_PARAMETERS WHERE parameter_name = 'JavaBinaryForUDx';
-[ RECORD 1 ]-----------------+----------------------------------------------------------
node_name                     | ALL
parameter_name                | JavaBinaryForUDx
current_value                 | /usr/bin/java
default_value                 |
change_under_support_guidance | f
change_requires_restart       | f
description                   | Path to the java binary for executing UDx written in Java

设置配置参数后,Vertica 可以在群集中的每个节点上查找 Java 可执行文件。

5.5 - 为 HCatalog 配置 Vertica

在使用 HCatalog 连接器之前,您必须将特定的 Hadoop 和 Hive 库添加到您的 Vertica 安装中。您还必须复制指定各项连接属性的 Hadoop 配置文件。Vertica 使用这些配置文件中的值创建自己到 Hadoop 的连接。

您只需在群集中的一个节点上执行这些更改。完成此操作后,您就可以安装 HCatalog 连接器。

复制 Hadoop 库和配置文件

Vertica 提供一个工具(即 hcatUtil)来从 Hadoop 收集所需的文件。此工具可将选中的库和 XML 配置文件从 Hadoop 群集复制到 Vertica 群集。此工具可能还需要其他库的访问权限:

  • 如果您打算用 Hive 查询使用 Snappy 压缩的文件,您需要 Snappy 本机库 libhadoop*.so 和 libsnappy*.so 的访问权限。

  • 如果您打算用 Hive 查询使用 LZO 压缩的文件,您需要 hadoop-lzo-*.jarlibgplcompression.so* 库的访问权限。您还必须在 core-site.xml 中编辑 io.compression.codecs 属性以包括 com.hadoop.compression.lzo.LzopCodec

  • 如果您打算将 JSON SerDe 用于 Hive 表,您需要其库的访问权限。这是指您用于配置 Hive 的同一个库;例如:

    hive> add jar /home/release/json-serde-1.3-jar-with-dependencies.jar;
    
    
    
    hive> create external table nationjson (id int,name string,rank int,text string)
          ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
          LOCATION '/user/release/vt/nationjson';
    
  • 如果您要使用任何其他库,而这些库并非所有受支持的 Hadoop 版本的标准配置,则您需要这些库的访问权限。

如果上述任何情况适用于您,请执行下列操作之一:

  • 将路径加入您指定为 --hcatLibPath 的值的路径中,或者

  • 将文件复制到一个已在该路径上的目录。

如果 Vertica 并未共置于 Hadoop 节点上,您应该执行以下操作:

  1. 将 /opt/vertica/packages/hcat/tools/hcatUtil 复制到一个 Hadoop 节点并在那里运行它,指定一个临时的输出目录。您的 Hadoop、HIVE 和 HCatalog 库路径可能不同。在较新版本的 Hadoop 中,HCatalog 目录通常是 HIVE 目录下的子目录,Cloudera 会为配置文件的每个修订版创建一个新目录。将您环境中的值用于以下命令:

    hcatUtil --copyJars
          --hadoopHiveHome="$HADOOP_HOME/lib;$HIVE_HOME/lib;/hcatalog/dist/share"
           --hadoopHiveConfPath="$HADOOP_CONF_DIR;$HIVE_CONF_DIR;$WEBHCAT_CONF_DIR"
          --hcatLibPath="/tmp/hadoop-files"
    

    如果您使用 Hive LLAP,请指定 hive2 目录。

  2. 验证所有必要的文件已复制:

    hcatUtil --verifyJars --hcatLibPath=/tmp/hadoop-files
    
  3. 将该输出目录(本示例中为 /tmp/hadoop-files)复制到您在安装 HCatalog 连接器时将连接到的 Vertica 节点上的 /opt/vertica/packages/hcat/lib。如果您要更新 Vertica 群集以使用新的 Hadoop 群集(或新版本的 Hadoop),请先移除 /opt/vertica/packages/hcat/lib 中除 vertica-hcatalogudl.jar 以外的所有 JAR 文件。

  4. 验证所有必要的文件已复制:

    hcatUtil --verifyJars --hcatLibPath=/opt/vertica/packages/hcat
    

如果 Vertica 共置于部分或全部 Hadoop 节点上,您可以在共享节点上以一个步骤完成此操作。Hadoop、HIVE 和 HCatalog 的 lib 路径可能有所不同;将您环境中的值用于以下命令:

hcatUtil --copyJars
      --hadoopHiveHome="$HADOOP_HOME/lib;$HIVE_HOME/lib;/hcatalog/dist/share"
      --hadoopHiveConfPath="$HADOOP_CONF_DIR;$HIVE_CONF_DIR;$WEBHCAT_CONF_DIR"
      --hcatLibPath="/opt/vertica/packages/hcat/lib"

hcatUtil 脚本具有以下参数:

复制并验证这些文件后,安装 HCatalog 连接器。

安装 HCatalog 连接器

在您将 hcatUtil 中的文件复制到的同一节点上,通过运行 install.sql 脚本安装 HCatalog 连接器。此脚本驻留在 HCatalog 采集器安装路径下的 ddl/ 文件夹中。此脚本将创建库、VHCatSource 和 VHCatParser。

现在,您可以按照使用 HCatalog 连接器定义架构中的介绍,创建指向现有 Hadoop 服务的 HCatalog 架构参数。

升级到新版本的 Vertica

升级到新版本的 Vertica 后,请执行以下步骤:

  1. 使用 uninstall.sql 脚本卸载 HCatalog 连接器。此脚本驻留在 HCatalog 采集器安装路径下的 ddl/ 文件夹中。
  2. 删除 hcatLibPath 目录中除 vertica-hcatalogudl.jar 之外的内容。
  3. 重新运行 hcatUtil。
  4. 使用 install.sql 脚本重新安装 HCatalog 连接器。

有关升级 Vertica 的详细信息,请参阅升级 Vertica

Hadoop 列式文件格式的其他选项

读取 Hadoop 的列式文件格式(ORC 或 Parquet)时,HCatalog 连接器将尝试使用内置读取器。这样做时,它默认使用 WebHDFS。您可以使用已弃用的 LibHDFS++ 库,方法是使用 hdfs URI 方案且使用 ALTER DATABASE 将 HDFSUseWebHDFS 设置为 0。此设置适用于所有 HDFS 访问,而不仅仅是 HCatalog 连接器。

无论哪种情况,您都必须执行配置 HDFS 访问中描述的配置。

5.6 - 配置安全性

您可以使用访问已进行 Kerberize 的 HDFS 数据中描述的任何安全选项来访问 Hive 数据。本主题描述了使用 HCatalog 连接器时特别需要的其他步骤。

如果您在 Vertica 中使用 Kerberos,则 HCatalog 连接器可以使用授权服务(Sentry 或 Ranger)。如果您使用委托令牌,则必须自己管理授权。

Kerberos

您可以在 Vertica 中使用 Kerberos,如将 Kerberos 与 Vertica 结合使用中所述。

如何配置 HCatalog 连接器取决于 Hive 如何管理授权。

  • 如果 Hive 使用 Sentry 来管理授权,并且如果 Sentry 使用 ACL 同步,则 HCatalog 连接器必须以当前用户身份访问 HDFS。验证 EnableHCatImpersonation 配置参数是否设置为 1(默认值)。ACL 同步自动为授权用户提供对底层 HDFS 文件的读取访问权限。

  • 如果 Hive 在没有 ACL 同步的情况下使用 Sentry,则 HCatalog 连接器必须作为 Vertica 主体访问 HDFS 数据。(用户仍然可以正常验证和访问元数据。)将 EnableHCatImpersonation 配置参数设置为 0。Vertica 主体必须具有对底层 HDFS 文件的读取访问权限。

  • 如果 Hive 使用 Ranger 来管理授权,并且 Vertica 用户对底层 HDFS 文件具有读取访问权限,则您可以使用用户模拟。验证 EnableHCatImpersonation 配置参数是否设置为 1(默认值)。相反,您可以禁用用户模拟并授予 Vertica 主体对 HDFS 文件的读取访问权限。

  • 如果 Hive 使用 Sentry 或 Ranger,则 HCatalog 连接器必须使用 HiveServer2(默认设置)。WebHCat 不支持授权服务。

  • 如果 Hive 不使用授权服务,或者如果您使用 WebHCat 而不是 HiveServer2 连接到 Hive,则 HCatalog 连接器以当前用户身份访问 Hive。验证 EnableHCatImpersonation 是否设置为 1。所有用户都必须具有对底层 HDFS 文件的读取访问权限。

此外,请确保在 Hadoop 配置文件(在大多数发行版中为 core-site.xml)中启用所有的 Hadoop 组件,以模拟 Vertica 用户。要做到这一点,最简单的方法是,使用通配符为所有主机上和所有组中的所有用户设置 proxyuser 属性。有关说明,请查阅您的 Hadoop 文档。确保在运行 hcatUtil 之前设置此属性(请参阅为 HCatalog 配置 Vertica)。

委托令牌

您可以将委托令牌用于会话,如自带您的委托令牌中所述。使用 HCatalog 连接器时,您指定两个委托令牌,一个用于数据,一个用于元数据。元数据令牌与 Hive 架构相关联。有关如何指定这两个委托令牌的信息,请参阅 HadoopImpersonationConfig 格式

验证安全配置

要验证 HCatalog 连接器是否可以访问 Hive 数据,请使用 HCATALOGCONNECTOR_CONFIG_CHECK 函数。

有关测试配置的详细信息,请参阅验证 HDFS 配置

5.7 - 使用 HCatalog 连接器定义架构

设置 HCatalog 连接器后,您可以用它来定义 Vertica 数据库中的架构,以访问 Hive 数据库中的表。您可以使用 CREATE HCATALOG SCHEMA 语句定义架构。

创建架构时,您必须提供要在 Vertica 中定义的架构名称。其它参数为可选参数。如果您不提供值,Vertica 将使用默认值。Vertica 从 HDFS 配置文件中读取一些默认值;请参阅配置参数

要创建架构,您必须具有对所有 Hive 数据的读取访问权限。验证创建架构的用户是否已直接或通过授权服务(如 Sentry 或 Ranger)被授予访问权限。dbadmin 用户没有自动的特殊权限。

创建架构后,您可以使用 ALTER HCATALOG SCHEMA 语句更改多个参数。

定义架构后,您可以按照与查询原生 Vertica 表相同的方式,查询 Hive 数据仓库中的数据。下面的示例演示了,如何创建 HCatalog 架构并随后查询几个系统表以检查新架构的内容。有关这些表的详细信息,请参阅查看 Hive 架构和表元数据

=> CREATE HCATALOG SCHEMA hcat WITH HOSTNAME='hcathost' PORT=9083
   HCATALOG_SCHEMA='default' HIVESERVER2_HOSTNAME='hs.example.com'
   SSL_CONFIG='/etc/hadoop/conf/ssl-client.xml' HCATALOG_USER='admin';
CREATE SCHEMA
=> \x
Expanded display is on.

=> SELECT * FROM v_catalog.hcatalog_schemata;
-[ RECORD 1 ]----------------+-------------------------------------------
schema_id                    | 45035996273748224
schema_name                  | hcat
schema_owner_id              | 45035996273704962
schema_owner                 | admin
create_time                  | 2017-12-05 14:43:03.353404-05
hostname                     | hcathost
port                         | -1
hiveserver2_hostname         | hs.example.com
webservice_hostname          |
webservice_port              | 50111
webhdfs_address              | hs.example.com:50070
hcatalog_schema_name         | default
ssl_config                   | /etc/hadoop/conf/ssl-client.xml
hcatalog_user_name           | admin
hcatalog_connection_timeout  | -1
hcatalog_slow_transfer_limit | -1
hcatalog_slow_transfer_time  | -1
custom_partitions            | f

=> SELECT * FROM v_catalog.hcatalog_table_list;
-[ RECORD 1 ]------+------------------
table_schema_id    | 45035996273748224
table_schema       | hcat
hcatalog_schema    | default
table_name         | nation
hcatalog_user_name | admin
-[ RECORD 2 ]------+------------------
table_schema_id    | 45035996273748224
table_schema       | hcat
hcatalog_schema    | default
table_name         | raw
hcatalog_user_name | admin
-[ RECORD 3 ]------+------------------
table_schema_id    | 45035996273748224
table_schema       | hcat
hcatalog_schema    | default
table_name         | raw_rcfile
hcatalog_user_name | admin
-[ RECORD 4 ]------+------------------
table_schema_id    | 45035996273748224
table_schema       | hcat
hcatalog_schema    | default
table_name         | raw_sequence
hcatalog_user_name | admin

配置参数

如果您在创建架构时未覆盖这些值,HCatalog 连接器将使用 Hadoop 配置文件中的以下值。

使用分区数据

Hive 支持对数据进行分区,如下例所示:

hive> create table users (name varchar(64), address string, city varchar(64))
    partitioned by (state varchar(64)) stored as orc;

Vertica 利用元数据(ORC 和 Parquet)中提供的格式的分区信息。查询可以完全跳过不相关的分区(分区修剪),Vertica 不需要实体化分区列。有关如何在 Vertica 中使用分区的详细信息,请参阅分区文件路径。有关如何在 Hive 中创建兼容分区的详细信息,请参阅适用于 Vertica 集成的 Hive 入门知识

默认情况下,Hive 将分区信息存储在表定义的路径下,可能成为 Hive 本地的信息。但是,Hive 用户也可以选择将分区信息存储在其他位置,例如 S3 等共享位置,如下例所示:

hive> alter table users add partition (state='MA')
    location 's3a://DataLake/partitions/users/state=MA';

因此,在查询执行期间,Vertica 必须查询 Hive 以获取表分区信息的位置。

由于额外的 Hive 查询可能很昂贵,因此 Vertica 默认仅在 Hive 的默认位置查找分区信息。如果您的 Hive 表指定了自定义位置,请使用 CUSTOM_PARTITIONS 参数:

=> CREATE HCATALOG SCHEMA hcat WITH HOSTNAME='hcathost' PORT=9083
    HCATALOG_SCHEMA='default' HIVESERVER2_HOSTNAME='hs.example.com'
    SSL_CONFIG='/etc/hadoop/conf/ssl-client.xml' HCATALOG_USER='admin'
    CUSTOM_PARTITIONS='yes';

Vertica 可以访问 S3 和 S3a 方案中的分区位置,不支持 S3n 方案。

HIVE_CUSTOM_PARTITIONS_ACCESSED 系统表记录了查询中使用的所有自定义分区位置。

将 HCatalog 连接器与 WebHCat 一起使用

默认情况下,HCatalog 连接器使用 HiveServer2 访问 Hive 数据。如果您改用 WebHCat,请在创建架构之前将 HCatalogConnectorUseHiveServer2 配置参数设置为 0,如下例所示。

=> ALTER DATABASE DEFAULT SET PARAMETER HCatalogConnectorUseHiveServer2 = 0;
=> CREATE HCATALOG SCHEMA hcat WITH WEBSERVICE_HOSTNAME='webhcat.example.com';

如果您之前使用过 WebHCat,则可以通过将配置参数设置为 1 并使用 ALTER HCATALOG SCHEMA 设置 HIVESERVER2_HOSTNAME 来切换到使用 HiveServer2。您不需要移除 WebHCat 值;HCatalog 连接器使用 HCatalogConnectorUseHiveServer2 的值来确定要使用的参数。

5.8 - 使用 HCatalog 连接器查询 Hive 表

定义 HCatalog 架构后,您就可以通过在查询中使用该架构名称,来查询 Hive 数据库中的数据。

=> SELECT * from hcat.messages limit 10;
 messageid |   userid   |        time         |             message
-----------+------------+---------------------+----------------------------------
         1 | nPfQ1ayhi  | 2013-10-29 00:10:43 | hymenaeos cursus lorem Suspendis
         2 | N7svORIoZ  | 2013-10-29 00:21:27 | Fusce ad sem vehicula morbi
         3 | 4VvzN3d    | 2013-10-29 00:32:11 | porta Vivamus condimentum
         4 | heojkmTmc  | 2013-10-29 00:42:55 | lectus quis imperdiet
         5 | coROws3OF  | 2013-10-29 00:53:39 | sit eleifend tempus a aliquam mauri
         6 | oDRP1i     | 2013-10-29 01:04:23 | risus facilisis sollicitudin sceler
         7 | AU7a9Kp    | 2013-10-29 01:15:07 | turpis vehicula tortor
         8 | ZJWg185DkZ | 2013-10-29 01:25:51 | sapien adipiscing eget Aliquam tor
         9 | E7ipAsYC3  | 2013-10-29 01:36:35 | varius Cum iaculis metus
        10 | kStCv      | 2013-10-29 01:47:19 | aliquam libero nascetur Cum mal
(10 rows)

由于您通过 HCatalog 连接器访问的表的行为就像 Vertica 表一样,您可以执行同时使用 Hive 数据和原生 Vertica 数据的操作,如 join:

=> SELECT u.FirstName, u.LastName, d.time, d.Message from UserData u
-> JOIN hcat.messages d ON u.UserID = d.UserID LIMIT 10;
FirstName | LastName |        time         |                  Message
----------+----------+---------------------+-----------------------------------
Whitney   | Kerr     | 2013-10-29 00:10:43 | hymenaeos cursus lorem Suspendis
Troy      | Oneal    | 2013-10-29 00:32:11 | porta Vivamus condimentum
Renee     | Coleman  | 2013-10-29 00:42:55 | lectus quis imperdiet
Fay       | Moss     | 2013-10-29 00:53:39 | sit eleifend tempus a aliquam mauri
Dominique | Cabrera  | 2013-10-29 01:15:07 | turpis vehicula tortor
Mohammad  | Eaton    | 2013-10-29 00:21:27 | Fusce ad sem vehicula morbi
Cade      | Barr     | 2013-10-29 01:25:51 | sapien adipiscing eget Aliquam tor
Oprah     | Mcmillan | 2013-10-29 01:36:35 | varius Cum iaculis metus
Astra     | Sherman  | 2013-10-29 01:58:03 | dignissim odio Pellentesque primis
Chelsea   | Malone   | 2013-10-29 02:08:47 | pede tempor dignissim Sed luctus
(10 rows)

5.9 - 查看 Hive 架构和表元数据

使用 Hive 时,您可以通过执行用 HiveQL(Hive 版本的 SQL)编写的语句(如 SHOW TABLES),访问架构和表元数据。使用 HCatalog 连接器时,您可以通过几个 Vertica 系统表,获取 Hive 数据库中表的元数据。

您可以通过 HCatalog 连接器访问四个包含表元数据的系统表:

  • HCATALOG_SCHEMATA 列出使用 HCatalog 连接器定义的所有架构。

  • HCATALOG_TABLE_LIST 包含使用 HCatalog 连接器定义的所有架构中所有可用表的概览。此表仅显示查询表的用户可以访问的表。针对使用 HCatalog 连接器定义的每个架构均调用一次 HiveServer2 即可检索此表中的信息,这意味着查询此表时的开销非常小。

  • HCATALOG_TABLES 包含比 HCATALOG_TABLE_LIST 更深入的信息。

  • HCATALOG_COLUMNS 列出通过 HCatalog 连接器获得的所有表中所有列的元数据。至于 HCATALOG_TABLES,查询此表会导致对每个表均调用一次 HiveServer2,因此可能需要花费一段时间才能完成。

下面的示例演示了,如何查询包含通过 HCatalog 连接器获取的表元数据的系统表。

=> CREATE HCATALOG SCHEMA hcat WITH hostname='hcathost'
-> HCATALOG_SCHEMA='default' HCATALOG_DB='default' HCATALOG_USER='hcatuser';
CREATE SCHEMA
=> SELECT * FROM HCATALOG_SCHEMATA;
-[ RECORD 1 ]--------+-----------------------------
schema_id            | 45035996273864536
schema_name          | hcat
schema_owner_id      | 45035996273704962
schema_owner         | dbadmin
create_time          | 2013-11-05 10:19:54.70965-05
hostname             | hcathost
port                 | 9083
webservice_hostname  | hcathost
webservice_port      | 50111
hcatalog_schema_name | default
hcatalog_user_name   | hcatuser
metastore_db_name    | hivemetastoredb

=> SELECT * FROM HCATALOG_TABLE_LIST;
-[ RECORD 1 ]------+------------------
table_schema_id    | 45035996273864536
table_schema       | hcat
hcatalog_schema    | default
table_name         | hcatalogtypes
hcatalog_user_name | hcatuser
-[ RECORD 2 ]------+------------------
table_schema_id    | 45035996273864536
table_schema       | hcat
hcatalog_schema    | default
table_name         | tweets
hcatalog_user_name | hcatuser
-[ RECORD 3 ]------+------------------
table_schema_id    | 45035996273864536
table_schema       | hcat
hcatalog_schema    | default
table_name         | messages
hcatalog_user_name | hcatuser
-[ RECORD 4 ]------+------------------
table_schema_id    | 45035996273864536
table_schema       | hcat
hcatalog_schema    | default
table_name         | msgjson
hcatalog_user_name | hcatuser

=> -- Get detailed description of a specific table
=> SELECT * FROM HCATALOG_TABLES WHERE table_name = 'msgjson';
-[ RECORD 1 ]---------+-----------------------------------------------------------
table_schema_id       | 45035996273864536
table_schema          | hcat
hcatalog_schema       | default
table_name            | msgjson
hcatalog_user_name    | hcatuser
min_file_size_bytes   |
total_number_files    | 10
location              | hdfs://hive.example.com:8020/user/exampleuser/msgjson
last_update_time      |
output_format         | org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
last_access_time      |
max_file_size_bytes   |
is_partitioned        | f
partition_expression  |
table_owner           |
input_format          | org.apache.hadoop.mapred.TextInputFormat
total_file_size_bytes | 453534
hcatalog_group        |
permission            |

=> -- Get list of columns in a specific table
=> SELECT * FROM HCATALOG_COLUMNS WHERE table_name = 'hcatalogtypes'
-> ORDER BY ordinal_position;
-[ RECORD 1 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | intcol
hcatalog_data_type       | int
data_type                | int
data_type_id             | 6
data_type_length         | 8
character_maximum_length |
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 1
-[ RECORD 2 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | floatcol
hcatalog_data_type       | float
data_type                | float
data_type_id             | 7
data_type_length         | 8
character_maximum_length |
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 2
-[ RECORD 3 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | doublecol
hcatalog_data_type       | double
data_type                | float
data_type_id             | 7
data_type_length         | 8
character_maximum_length |
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 3
-[ RECORD 4 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | charcol
hcatalog_data_type       | string
data_type                | varchar(65000)
data_type_id             | 9
data_type_length         | 65000
character_maximum_length | 65000
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 4
-[ RECORD 5 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | varcharcol
hcatalog_data_type       | string
data_type                | varchar(65000)
data_type_id             | 9
data_type_length         | 65000
character_maximum_length | 65000
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 5
-[ RECORD 6 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | boolcol
hcatalog_data_type       | boolean
data_type                | boolean
data_type_id             | 5
data_type_length         | 1
character_maximum_length |
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 6
-[ RECORD 7 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | timestampcol
hcatalog_data_type       | string
data_type                | varchar(65000)
data_type_id             | 9
data_type_length         | 65000
character_maximum_length | 65000
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 7
-[ RECORD 8 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | varbincol
hcatalog_data_type       | binary
data_type                | varbinary(65000)
data_type_id             | 17
data_type_length         | 65000
character_maximum_length | 65000
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 8
-[ RECORD 9 ]------------+-----------------
table_schema             | hcat
hcatalog_schema          | default
table_name               | hcatalogtypes
is_partition_column      | f
column_name              | bincol
hcatalog_data_type       | binary
data_type                | varbinary(65000)
data_type_id             | 17
data_type_length         | 65000
character_maximum_length | 65000
numeric_precision        |
numeric_scale            |
datetime_precision       |
interval_precision       |
ordinal_position         | 9

5.10 - 将 HCatalog 架构或表与局部架构或表同步

由于 Hive 的性能问题,从 HCatalog 架构查询数据可能会很慢。当您希望检查 Hive 数据库中表的结构时,这一缓慢的性能可能特别令人头疼。从 Hive 获取此信息需要您使用 HCatalog 连接器查询 HCatalog 架构的元数据。

为了避免这一性能问题,您可以使用 SYNC_WITH_HCATALOG_SCHEMA 函数,在 Vertica 架构内创建 HCatalog 架构元数据的快照。您将向此函数提供:预先存在的 Vertica 架构(通常是通过 CREATE HCATALOG SCHEMA 创建的那个架构)的名称以及一个通过 HCatalog 连接器获得的 Hive 架构。您必须在 Vertica 中拥有写入数据的权限,在 Hive 和 HDFS 中拥有读取数据的权限。

此函数将在 Vertica 架构内创建一个外部表集,而您随后可将该外部表集用于检查 Hive 数据库内表的结构。由于 Vertica 架构中的元数据是本地的,因此查询计划要快得多。您还可以使用标准 Vertica 语句和系统表查询来检查 HCatalog 架构中 Hive 表的结构。

当 SYNC_WITH_HCATALOG_SCHEMA 在 Vertica 中创建表时,它会使 Hive 的 STRING 和 BINARY 类型与 Vertica 的 VARCHAR(65000) 和 VARBINARY(65000) 类型相匹配。在以下两种情况下,您可能会希望使用 ALTER TABLE SET DATA TYPE 来更改这些长度:

  • 如果 Hive 中的值大于 65000 字节,增加其大小并使用 LONG VARCHAR 或 LONG VARBINARY,以免数据被截断。如果 Hive 字符串使用多字节编码,您必须增加 Vertica 的大小,以免数据被截断。需要执行这一步骤的原因是,Hive 按字符计算字符串长度,而 Vertica 按字节计算长度。

  • 如果 Hive 中的值远小于 65000 字节,减少其大小,以节约 Vertica 的内存。

Vertica 架构只不过是 HCatalog 架构元数据的一个快照。在您调用 SYNC_WITH_HCATALOG_SCHEMA 之后,Vertica 不会使用本地架构将后来的更改同步到 HCatalog 架构。您可以再次调用此函数,将本地架构重新同步到 HCatalog 架构。如果您更改了列数据类型,您将需要重复这些更改,因为此函数将创建新的外部表。

默认情况下,SYNC_WITH_HCATALOG_SCHEMA 不会删除出现在本地架构中、但未出现在 HCatalog 架构中的表。因此,此函数调用后,本地架构将不反映自上次调用以来 Hive 数据库中已删除的表。您可以通过以下方式更改此行为:提供可选的第三个布尔参数,让函数删除本地架构中无法与 HCatalog 架构中的表对应的任何表。

您可以使用 SYNC_WITH_HCATALOG_SCHEMA_TABLE 同步个别表,而无需同步整个架构。如果 Vertica 中已经存在该表,此函数会将其覆盖。如果 HCatalog 架构中找不到该表,此函数将返回错误。在所有其他方面,此函数的表现与 SYNC_WITH_HCATALOG_SCHEMA 相同。

如果更改任何 HCatalog 连接器配置参数 (Hadoop 参数) 的设置,则必须再次调用此函数。

示例

下面的示例演示了如何调用 SYNC_WITH_HCATALOG_SCHEMA,将 Vertica 中的 HCatalog 架构与 Hive 中的元数据同步。由于函数直接同步 HCatalog 架构,而不是将其他架构与 HCatalog 架构同步,两个参数都是相同的。

=> CREATE HCATALOG SCHEMA hcat WITH hostname='hcathost' HCATALOG_SCHEMA='default'
   HCATALOG_USER='hcatuser';
CREATE SCHEMA
=> SELECT sync_with_hcatalog_schema('hcat', 'hcat');
sync_with_hcatalog_schema
----------------------------------------
Schema hcat synchronized with hcat
tables in hcat = 56
tables altered in hcat = 0
tables created in hcat = 56
stale tables in hcat = 0
table changes erred in hcat = 0
(1 row)

=> -- Use vsql's \d command to describe a table in the synced schema

=> \d hcat.messages
List of Fields by Tables
  Schema   |   Table  | Column  |      Type      | Size  | Default | Not Null | Primary Key | Foreign Key
-----------+----------+---------+----------------+-------+---------+----------+-------------+-------------
hcat       | messages | id      | int            |     8 |         | f        | f           |
hcat       | messages | userid  | varchar(65000) | 65000 |         | f        | f           |
hcat       | messages | "time"  | varchar(65000) | 65000 |         | f        | f           |
hcat       | messages | message | varchar(65000) | 65000 |         | f        | f           |
(4 rows)

此示例演示了如何与使用 CREATE HCATALOG SCHEMA 创建的架构同步。此外,与使用 CREATE SCHEMA 创建的架构同步亦可获得支持。

将本地架构与 HCatalog 架构同步后,您可在该本地架构中查询表。然而,在同步后的架构中查询表并未比直接查询 HCatalog 架构快很多,因为 SYNC_WITH_HCATALOG_SCHEMA 仅复制 HCatalog 架构的元数据。表中的数据仍要使用 HCatalog 连接器进行检索。

5.11 - 从 Hive 到 Vertica 的数据类型转换

Hive 识别的数据类型与 Vertica 识别的数据类型不同。下表列出了 HCatalog 连接器如何将 Hive 数据类型转换为与 Vertica 兼容的数据类型。

Hive 和 Vertica 之间的数据宽度处理差异

HCatalog 连接器依靠 Hive SerDe 类从 HDFS 上的文件中提取数据。因此,从这些文件中读取的数据须遵从 Hive 的数据宽度限制。例如,假定 SerDe 将 INT 列的一个值解析成大于 232-1 的值(32 位整数的最大值)。在这种情况下,即使该值适合 Vertica 的 64 位 INTEGER 列也会被拒绝,因为它不属于 Hive 的 32 位 INT。

Hive 以字符为单位测量 CHAR 和 VARCHAR 的长度,而 Vertica 以字节为单位测量其长度。因此,如果使用多字节编码(如 Unicode),文本可能会在 Vertica 中被截断。

值经过解析并转换成 Vertica 数据类型后,会被视为原生数据。比较分别在 Hive 和 Vertica 中运行完全相同的查询所得的结果时,这种处理可能会导致一些混乱。例如,如果您的查询添加两个 INT 值,得到一个大于 232-1 的值,该值会溢出其 32 位 INT 数据类型,导致 Hive 返回错误。而使用 HCatalog 连接器在 Vertica 中运行具有相同数据的相同查询时,该值很可能仍然属于 Vertica 的 64 位 int 值。因此,该添加成功并返回一个值。

5.12 - 使用非标准 SerDes

Hive 将其数据存储在 Hadoop 分布式文件系统 (HDFS) 内的非结构化平面文件中。执行 Hive 查询时,它将使用一组序列化程序和反序列化程序 (SerDe) 类,来提取这些平面文件中的数据,并将其组织成一个关系数据库表。要想让 Hive 能够从文件中提取数据,它必须具备可以解析文件中所含数据的 SerDe。在 Hive 中创建表时,您可以选择要用于该表数据的 SerDe。

Hive 拥有一组标准的 SerDe,它们能够处理多种格式的数据,比如分隔数据和使用正则表达式提取的数据。您还可以使用第三方或自定义的 SerDe,让 Hive 处理以其他文件格式存储的数据。例如,一些常用的第三方 SerDe 能够处理以 JSON 格式存储的数据。

HCatalog 连接器直接从 HDFS 提取文件段,然后使用 Hive 的 SerDe 类从文件段中提取数据。此连接器包括 Hive 的所有标准 SerDe 类,因此可以处理 Hive 本机支持的任何文件中存储的数据。如想查询使用自定义 SerDe 的 Hive 表中的数据,您必须先在 Vertica 群集上安装 SerDe 类。

确定您需要的 SerDe

如您拥有 Hive 命令行的访问权限,就可以使用 Hive 的 SHOW CREATE TABLE 语句,确定表要使用哪种 SerDe。此语句显示了重新创建表所需的 HiveQL 语句。例如:

hive> SHOW CREATE TABLE msgjson;
OK
CREATE EXTERNAL TABLE msgjson(
messageid int COMMENT 'from deserializer',
userid string COMMENT 'from deserializer',
time string COMMENT 'from deserializer',
message string COMMENT 'from deserializer')
ROW FORMAT SERDE
'org.apache.hadoop.hive.contrib.serde2.JsonSerde'
STORED AS INPUTFORMAT
'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
'hdfs://hivehost.example.com:8020/user/exampleuser/msgjson'
TBLPROPERTIES (
'transient_lastDdlTime'='1384194521')
Time taken: 0.167 seconds

在此示例中,ROW FORMAT SERDE 表明一个特殊的 SerDe 已用于解析数据文件。下一行则表明,该 SerDe 类命名为 org.apache.hadoop.hive.contrib.serde2.JsonSerde。您必须为 HCatalog 连接器提供此 SerDe 类的副本,以便其可以从此表中读取数据。

您还可以通过查询使用自定义 SerDe 的表,来弄清楚您需要哪种 SerDe 类。此查询将失败并生成错误消息,其中包含解析表中数据所需的 SerDe 类名称。在下面的示例中,错误消息中指定缺失 SerDe 类的部分以粗体显示。

=> SELECT * FROM hcat.jsontable;
ERROR 3399:  Failure in UDx RPC call InvokePlanUDL(): Error in User Defined
Object [VHCatSource], error code: 0
com.vertica.sdk.UdfException: Error message is [
org.apache.hcatalog.common.HCatException : 2004 : HCatOutputFormat not
initialized, setOutput has to be called. Cause : java.io.IOException:
java.lang.RuntimeException:
MetaException(message:org.apache.hadoop.hive.serde2.SerDeException
SerDe com.cloudera.hive.serde.JSONSerDe does not exist) ] HINT If error
message is not descriptive or local, may be we cannot read metadata from hive
metastore service thrift://hcathost:9083 or HDFS namenode (check
UDxLogs/UDxFencedProcessesJava.log in the catalog directory for more information)
at com.vertica.hcatalogudl.HCatalogSplitsNoOpSourceFactory
.plan(HCatalogSplitsNoOpSourceFactory.java:98)
at com.vertica.udxfence.UDxExecContext.planUDSource(UDxExecContext.java:898)
. . .

在 Vertica 群集上安装 SerDe

要获取 HCatalog 连接器需要的 SerDe 类文件,您通常有两种选择:

  • 找到 SerDe 的安装文件,然后将其复制到 Vertica 群集。例如,您可从 Google Code 和 GitHub 等网站获取数个第三方 JSON SerDe。您可能会找到与 Hive 群集上安装的文件相匹配的 SerDe。如果是这样,那么请下载程序包,并将其复制到 Vertica 群集。

  • 将 JAR 文件从 Hive 服务器直接复制到您的 Vertica 群集。SerDe JAR 文件的位置取决于您的 Hive 安装。在某些系统上,它们可能位于 /usr/lib/hive/lib 中。

无论您从哪里得到文件,请将其复制到 Vertica 群集中各节点上的 /opt/vertica/packages/hcat/lib 目录中。

5.13 - 排除 HCatalog 连接器故障

使用 HCatalog 连接器时,可能会遇到以下问题。

连接错误

在定义架构和查询架构时,HCatalog 连接器都可能遇到错误。出现哪种类型的错误要看哪些 CREATE HCATALOG SCHEMA 参数是不正确的。假设您针对元存储数据库设置的参数不正确,但针对 HiveServer2 设置了正确的参数。在这种情况下,与 HCatalog 相关的系统表查询会成功,而在 HCatalog 架构上进行的查询会失败。下面的示例演示了如何使用正确的默认 HiveServer2 信息创建 HCatalog 架构。但元存储数据库的端口号是不正确的。

=> CREATE HCATALOG SCHEMA hcat2 WITH hostname='hcathost'
-> HCATALOG_SCHEMA='default' HCATALOG_USER='hive' PORT=1234;
CREATE SCHEMA
=> SELECT * FROM HCATALOG_TABLE_LIST;
-[ RECORD 1 ]------+---------------------
table_schema_id    | 45035996273864536
table_schema       | hcat2
hcatalog_schema    | default
table_name         | test
hcatalog_user_name | hive

=> SELECT * FROM hcat2.test;
ERROR 3399:  Failure in UDx RPC call InvokePlanUDL(): Error in User Defined
 Object [VHCatSource], error code: 0
com.vertica.sdk.UdfException: Error message is [
org.apache.hcatalog.common.HCatException : 2004 : HCatOutputFormat not
initialized, setOutput has to be called. Cause : java.io.IOException:
MetaException(message:Could not connect to meta store using any of the URIs
provided. Most recent failure: org.apache.thrift.transport.TTransportException:
java.net.ConnectException:
Connection refused
at org.apache.thrift.transport.TSocket.open(TSocket.java:185)
at org.apache.hadoop.hive.metastore.HiveMetaStoreClient.open(
HiveMetaStoreClient.java:277)
. . .

要解决这些问题,您必须删除并重新创建架构,或更改架构以更正参数。如果问题仍然存在,请确定 Vertica 群集和 Hadoop 群集之间是否存在连接性问题。此类问题可能包括能够阻止一个或多个 Vertica 主机联系 HiveServer2、元存储或 HDFS 主机的防火墙。

查询数据时 UDx 发生故障:错误 3399

查询数据(而不是架构信息等元数据)时,您可能会看到错误消息。伴随该消息的出现,日志中可能会记录一个 ClassNotFoundException。发生这种情况的原因可能如下:

  • 您在 Hadoop 和 Vertica 节点上使用的 Java 版本不同。在这种情况下,您需要对其中之一进行更改,使其与另一个相匹配。

  • 您还没有使用 hcatUtil 将所有的 Hadoop 和 Hive 库以及配置文件复制到 Vertica;或者您运行了 hcatutil,然后更改了您的 Hadoop 或 Hive 版本。

  • 您将 Vertica 升级到了新版本,而没有重新运行 hcatutil 并重新安装 HCatalog 连接器。

  • 您使用的 Hadoop 版本依赖于一个必须手动复制的第三方库。

  • 您要读取使用 LZO 压缩的文件,但还没有复制库或设置 core-site.xml 中的 io.compression.codecs 属性。

  • 您要从 Hive 读取 Parquet 数据,且多个列在表中已经存在一些数据之后被添加到表中。添加列不会更新现有数据,Hive 提供并由 HCatalog 连接器使用的 ParquetSerDe 无法处理这种情况。此错误是由于 Hive 中的限制造成的,并且没有解决方法。

  • 查询花费的时间太长并且即将超时。如果这是一个常见问题,您可以增加 UDxFencedBlockTimeout 配置参数的值。请参阅常规参数

如果您未曾复制库或配置 LZO 压缩,请遵循为 HCatalog 配置 Vertica 中的说明。

如果您从 Hadoop 复制的 Hive jar 文件过期,您可能会看到像下面这样的错误消息。

ERROR 3399: Failure in UDx RPC call InvokePlanUDL(): Error in User Defined Object [VHCatSource],
error code: 0 Error message is [ Found interface org.apache.hadoop.mapreduce.JobContext, but
class was expected ]
HINT hive metastore service is thrift://localhost:13433 (check UDxLogs/UDxFencedProcessesJava.log
in the catalog directory for more information)

此错误通常指示 hive-hcatalog-core jar 出现问题。请确保您拥有此文件的最新副本。请记住,如果重新运行 hcatUtil,您还需要重新创建 HCatalog 架构。

您可能还会看到不同形式的此错误:

ERROR 3399: Failure in UDx RPC call InvokePlanUDL(): Error in User Defined Object [VHCatSource],
error code: 0 Error message is [ javax/servlet/Filter ]

即使 hcatUtil 报告您的库都是最新的,您仍可能收到此错误的报告。部分 Hadoop 版本会使用 javax.servlet.Filter 类所在的库,但该库通常情况下并非 Hadoop 安装的直接组成部分。如果您看到提及此类的错误,请在 Hadoop 节点上找到 servlet-api-*.jar,然后将其复制到所有数据库节点上的 hcat/lib 目录。如果您在 Hadoop 节点上找不到它,请通过互联网查找并下载。(这种情况很少见。)库的版本必须为 2.3 或更高版本。

将该 jar 文件复制到 hcat/lib 目录后,请按照为 HCatalog 配置 Vertica 中的说明,重新安装 HCatalog 连接器。

查询数据时发生身份验证错误

您可能已经使用 CREATE HCATALOG SCHEMA 成功创建了架构,但在查询时出现如下错误:

=> SELECT * FROM hcat.clickdata;
ERROR 6776:  Failed to glob [hdfs:///user/hive/warehouse/click-*.parquet]
because of error: hdfs:///user/hive/warehouse/click-12214.parquet: statAll failed;
error: AuthenticationFailed

如果 Hive 使用授权服务,您可能会看到此错误。如果 HDFS 中底层文件的权限与授权服务中的权限匹配,则 Vertica 在访问该数据时必须使用用户模拟。要启用用户模拟,请将 EnableHCatImpersonation 配置参数设置为 1。

Vertica 使用数据库主体访问 HDFS。因此,如果 EnableHCatImpersonation 为 0,则 Vertica 数据库主体必须有权访问 HDFS 上 Hive 仓库内的数据。如果无权访问,您可能会看到以下错误:

=> SELECT * FROM hcat.salesdata;
ERROR 6776:  Failed to glob [vertica-hdfs:///hive/warehouse/sales/*/*]
because of error: vertica-hdfs:///hive/warehouse/sales/: listStat failed;
error: Permission denied: user=vertica, access=EXECUTE, inode="/hive/warehouse/sales":hdfs:hdfs:d---------

此错误消息中的 URL 方案已从 hdfs 更改为 vertica-hdfs。这是一个内部方案,在 Vertica 之外的 URL 中无效。在 HDFS 中指定路径时不能使用此方案。

Hive 和 Vertica 查询的结果不一致

有些时候,通过 HCatalog 连接器在 Hive 和 Vertica 上运行相同的查询可能会返回不同的结果。这个问题有几种常见原因。

这种差异往往由 Hive 和 Vertica 支持的数据类型不同导致。有关受支持的数据类型的详细信息,请参阅从 Hive 到 Vertica 的数据类型转换

如果 Hive 字符串的值在 Vertica 中被截断,这可能是由 Hive 中的多字节字符编码导致的。Hive 以字符为单位报告字符串长度,而 Vertica 则以字节为单位记录该长度。对于 Unicode 等两字节编码,您需要在 Vertica 中将列大小增加一倍以避免其被截断。

如果 Hive 表使用除字符串以外的其他类型的分区列,也有可能会产生差异。

如果 Hive 表将分区数据存储在自定义位置而不是默认位置,且您在创建 Vertica 架构时未指定 CUSTOM_PARTITIONS 参数,您将看到不同的查询结果。请参阅使用分区数据。此外,即使使用自定义分区,Vertica 和 Hive 之间也存在差异:

  • 如果自定义分区在查询时不可用,则 Hive 将忽略它并返回其余结果。Vertica 报告错误。

  • 如果在创建表后在 Hive 中更改分区以使用自定义位置,则 Hive 仅从新位置读取数据,而 Vertica 从默认位置和新位置读取数据。

  • 如果分区值与其对应的目录名称不一致,Hive 将使用其元数据中的值,而 Vertica 使用目录名称中的值。

下面的示例说明了这些差异。Hive 中按状态列分区的表以下面的数据开头:

hive> select * from inventory;
+--------------+-----------------+-----------------+--+
| inventory.ID | inventory.quant | inventory.state |
+--------------+-----------------+-----------------+--+
| 2            | 300             | CA              |
| 4            | 400             | CA              |
| 5            | 500             | DC              |
| 1            | 100             | PA              |
| 2            | 200             | PA              |
+--------------+-----------------+-----------------+--+

然后,移动状态为 CA 的分区。该目录已经包含一些数据。请注意,查询现在会针对 CA 分区返回不同的结果。

hive> ALTER TABLE inventory PARTITION (state='CA') SET LOCATION 'hdfs:///partitions/inventory/state=MD';
hive> select * from inventory;
+--------------+-----------------+-----------------+--+
| inventory.ID | inventory.quant | inventory.state |
+--------------+-----------------+-----------------+--+
| 20           | 30000           | CA              |
| 40           | 40000           | CA              |
| 5            | 500             | DC              |
| 1            | 100             | PA              |
| 2            | 200             | PA              |
+--------------+-----------------+-----------------+--+
5 rows selected (0.399 seconds)

CA 分区已移至名为 state=MD 的目录。由于目录名称,Vertica 将前两行(新分区位置中的行)的状态报告为 MD。除了新位置之外,它还报告来自原始位置的 CA 值:

=> SELECT * FROM hcat.inventory;
 ID | quant | state
----+----------+------
 20 | 30000 | MD
 40 | 40000 | MD
  2 | 300   | CA
  4 | 400   | CA
  1 | 100   | PA
  2 | 200   | PA
  5 | 500   | DC
(7 rows)

MapR 上的 HCatalog 连接器安装失败

如果您将 MapR 文件系统挂载为 NFS 挂载点,然后安装 HCatalog 连接器,则可能会失败并显示如下消息:

ROLLBACK 2929: Couldn't create new UDx side process,
failed to get UDx side process info from zygote: Broken pipe

这可能伴随着 dbLog 中的如下错误:

java.io.IOException: Couldn't get lock for /home/dbadmin/node02_catalog/UDxLogs/UDxFencedProcessesJava.log
    at java.util.logging.FileHandler.openFiles(FileHandler.java:389)
    at java.util.logging.FileHandler.<init>(FileHandler.java:287)
    at com.vertica.udxfence.UDxLogger.setup(UDxLogger.java:78)
    at com.vertica.udxfence.UDxSideProcess.go(UDxSideProcess.java:75)
    ...

如果您在创建 NFS 挂载点时将其锁定,则会出现此错误。锁定是默认设置。如果您使用 HCatalog 连接器并将 MapR 挂载为 NFS 挂载点,则必须使用 -o nolock 选项创建挂载点。例如:

sudo mount -o nolock -t nfs MaprCLDBserviceHostname:/mapr/ClusterName/vertica/$(hostname -f)/ vertica

您可以将 HCatalog 连接器与 MapR 一起使用,而无需挂载 MapR 文件系统。如果您挂载 MapR 文件系统,则必须在没有锁定的情况下执行此操作。

过多的查询延迟

网络问题或 HiveServer2 服务器上的高系统负载可能会在使用 HCatalog 连接器查询 Hive 数据库时导致长时间延迟。虽然 Vertica 不能解决这些问题,但您可以设置参数,限制 Vertica 在取消 HCatalog 架构上的查询之前等待多长时间。您可以使用 Vertica 配置参数在全局范围内设置这些参数。您还可以在 CREATE HCATALOG SCHEMA 语句中针对特定的 HCatalog 架构设置这些参数。这些特定设置将覆盖配置参数中的设置。

HCatConnectionTimeout 配置参数和 CREATE HCATALOG SCHEMA 语句的 HCATALOG_CONNECTION_TIMEOUT 参数控制 HCatalog 连接器在连接到 HiveServer2 服务器时等待多少秒。值为 0(配置参数的默认设置)是指无限期地等待。如果到此超时过去后,服务器仍然没有响应,HCatalog 连接器会断开连接并取消查询。如果您发现在 HCatalog 架构上执行的某些查询暂停时间过长,请尝试将此参数设置为一个超时值,这样查询就不会无限期挂起了。

HCatSlowTransferTime 配置参数和 CREATE HCATALOG SCHEMA 语句的 HCATALOG_SLOW_TRANSFER_TIME 参数指定 HCatlog 连接器在成功连接到服务器后等待数据的时间。指定时间过去后,HCatalog 连接器将确定来自服务器的数据传输速度是否达到了在 HCatSlowTransferLimit 配置参数中(或通过 CREATE HCATALOG SCHEMA 语句的 HCATALOG_SLOW_TRANSFER_LIMIT 参数)设置的值。如果没有达到,那么 HCatalog 连接器将终止连接并取消查询。

您可以设置这些参数,以取消运行非常缓慢但最终确实可以完成的查询。然而,导致查询延迟的原因通常是连接缓慢而不是无法建立连接。因此,请先尝试调整缓慢的传输速度设置。如果您发现导致问题的原因是连接永远都无法完成,您还可以将 Linux TCP 套接字超时调整为合适的值,而不是完全依赖于 HCatConnectionTimeout 参数。

SerDe 错误

如果您尝试查询使用非标准 SerDe 的 Hive 表,可能会发生错误。如果您尚未在 Vertica 群集上安装 SerDe JAR 文件,您将收到与以下示例中类似的错误消息:

=> SELECT * FROM hcat.jsontable;
ERROR 3399:  Failure in UDx RPC call InvokePlanUDL(): Error in User Defined
Object [VHCatSource], error code: 0
com.vertica.sdk.UdfException: Error message is [
org.apache.hcatalog.common.HCatException : 2004 : HCatOutputFormat not
initialized, setOutput has to be called. Cause : java.io.IOException:
java.lang.RuntimeException:
MetaException(message:org.apache.hadoop.hive.serde2.SerDeException
SerDe com.cloudera.hive.serde.JSONSerDe does not exist) ] HINT If error
message is not descriptive or local, may be we cannot read metadata from hive
metastore service thrift://hcathost:9083 or HDFS namenode (check
UDxLogs/UDxFencedProcessesJava.log in the catalog directory for more information)
at com.vertica.hcatalogudl.HCatalogSplitsNoOpSourceFactory
.plan(HCatalogSplitsNoOpSourceFactory.java:98)
at com.vertica.udxfence.UDxExecContext.planUDSource(UDxExecContext.java:898)
. . .

您可在错误消息中看到,出错的根本原因是缺少一个 SerDe 类(以粗体显示)。要解决此问题,请在 Vertica 群集上安装 SerDe 类。有关详细信息,请参阅使用非标准 SerDes

如果群集中仅一个或少量主机没有 SerDe 类,此错误可能会间歇性出现。

6 - 与 Cloudera Manager 集成

Hadoop 的 Cloudera 发行版包括 Cloudera Manager,这是一个用于管理 Hadoop 群集的基于 Web 的工具。Cloudera Manager 可以管理任何提供服务描述的服务,包括 Vertica。

您可以使用 Cloudera Manager 启动、停止和监控单个数据库节点或整个数据库。您可以管理共置的和单独的 Vertica 群集 — Cloudera 可以管理不属于 Hadoop 群集的节点上的服务。

您必须安装和配置您的 Vertica 数据库才能继续操作;您不能使用 Cloudera Manager 创建数据库。

安装服务

Cloudera 服务描述 (CSD) 文件描述了 Cloudera 可以管理的服务。Vertica CSD 位于数据库节点上的 /opt/vertica/share/CSD 中。

要安装 Vertica CSD,请执行以下步骤:

  1. 在 Vertica 节点上,按照 VerticaAPIKey 中的说明生成 API 密钥。您需要此密钥来完成 CSD 的安装。

  2. 在托管 Cloudera Manager 的 Hadoop 节点上,将 CSD 文件复制到 /opt/cloudera/csd。

  3. 重新启动 Cloudera Manager:

    $ service cloudera-scm-server restart
    
  4. 在 Web 浏览器中,转到 Cloudera Manager 并重新启动 Cloudera Management Service。

  5. 如果您的 Vertica 群集与 Hadoop 群集是分开的(非共置):使用 Cloudera Manager 为您的数据库节点添加主机。如果您的群集是共置的,请跳过此步骤。

  6. 使用 Cloudera Manager 添加 Vertica 服务。

  7. 在“角色分配 (Role Assignment)”页面上,选择作为数据库节点的主机。

  8. 在“配置 (Configuration)”页面上,为以下字段指定值:

    • 数据库名称

    • 代理端口(如果不确定,则接受默认值)

    • API 密钥

    • 运行时所使用的数据库用户身份(通常是 dbadmin)和密码

关于代理

当您通过 Cloudera Manager 管理 Vertica 时,您实际上是在与 Vertica 代理进行交互,而不是直接与数据库交互。代理在所有数据库节点上运行并代表您与数据库交互。管理控制台使用相同的代理。大多数时候,这种额外的间接操作对您来说是透明的。

Cloudera 管理的服务包含一个或多个角色。在这种情况下,服务是 "Vertica",而单一角色是“Vertica 节点”。

可用操作

Cloudera Manager 显示两组操作。服务级别操作应用于所有节点上的服务,而角色级别操作仅应用于单个节点。

您可以在所有节点上执行以下服务级别操作:

  • 启动:启动代理和(如果尚未运行)数据库。

  • 停止:停止数据库和代理。

  • 重新启动:先调用“停止”,然后调用“启动”。

  • 添加角色实例:将新的数据库节点添加到 Cloudera Manager。节点必须已经是 Vertica 群集的一部分,并且主机必须已经为 Cloudera Manager 所知。

  • 进入维护模式:抑制由 Cloudera Manager 生成的运行状况警报。

  • 退出维护模式:恢复正常报告。

  • 更新内存池大小:从“静态服务池 (Static Service Pools)”配置页面应用内存池设置。

除添加角色实例之外,您可以在单个节点上将上述其余操作当作角色级别操作执行。

管理内存池

Cloudera Manager 允许您更改其管理的节点的资源分配,例如内存和 CPU。如果您使用的是共置群集,集中管理资源可以简化群集管理。如果您使用的是单独的 Hadoop 和 Vertica 群集,您可能倾向于按照管理数据库中所述单独管理 Vertica。

使用 Cloudera Manager“静态服务池 (Static Service Pools)”配置页面来配置资源分配。以 GB 为单位指定的“Vertica 内存池 (Vertica Memory Pool)”值是分配给每个节点上的数据库的最大内存量。如果配置页面包含“Cgroup 内存硬限制 (Cgroup Memory Hard Limit)”,则将其设置为与“Vertica 内存池 (Vertica Memory Pool)”相同的值。

设置这些值后,您可以使用“更新内存池大小”操作将该值应用到受管节点。此操作等效于 ALTER RESOURCE POOL GENERAL MAXMEMORYSIZE。在您执行此操作之前,“静态服务池 (Static Service Pools)”中的配置更改不会在 Vertica 中生效。

卸载服务

要卸载 Vertica CSD,请执行以下步骤:

  1. 停止 Vertica 服务,然后将其从 Cloudera Manager 中移除。

  2. 从 /opt/cloudera/csd 中移除 CSD 文件。

  3. 从命令行中,重新启动 Cloudera Manager 服务器。

  4. 在 Cloudera Manager 中,重新启动 Cloudera Management Service。

7 - 集成 Vertica 与 Hadoop 的 MapR 发行版

MapR 是 MapR Technologies 推出的一款 Apache Hadoop 发行版,它用自身的功能扩展了标准 Hadoop 组件。Vertica 可以通过以下方式与 MapR 集成:

  • 您可以通过 NFS 挂载点从 MapR 读取数据。将 MapR 文件系统挂载为 NFS 挂载点后,您可以使用 CREATE EXTERNAL TABLE AS COPYCOPY 来访问数据,就像它在本地文件系统上一样。此选项为读取数据提供了最佳性能。

  • 您可以使用 HCatalog 连接器来读取 Hive 数据。出于性能原因,请勿在 MapR 中将 HCatalog 连接器与 ORC 或 Parquet 数据一起使用。相反,应将 MapR 文件系统挂载为 NFS 挂载点并在不使用 Hive 架构的情况下创建外部表。有关读取 Hive 数据的详细信息,请参阅使用 HCatalog 连接器

  • 您可以使用原生 Vertica 格式 (ROS) 创建存储位置以将数据存储在 MapR 中。将 MapR 文件系统挂载为 NFS 挂载点,然后使用 CREATE LOCATION...ALL NODES SHARED 创建存储位置。(CREATE LOCATION 通常不支持 NFS 挂载点,但在 MapR 中支持它们。)

Hadoop 的其他 Vertica 集成不适用于 MapR。

有关将 MapR 文件系统挂载为 NFS 挂载点的信息,请参阅 MapR 网站上的 Accessing Data with NFS(使用 NFS 访问数据)和 Configuring Vertica Analytics Platform with MapR(使用 MapR 配置 Vertica Analytics Platform)。特别是,您必须配置 MapR 才能将 Vertica 添加为 MapR 服务。

示例

在以下示例中,MapR 文件系统已挂载为 /mapr。

以下语句从 ORC 数据创建外部表:

=> CREATE EXTERNAL TABLE t (a1 INT, a2 VARCHAR(20))
   AS COPY FROM '/mapr/data/file.orc' ORC;

以下语句从 Parquet 数据创建外部表并利用分区修剪(请参阅分区文件路径):

=> CREATE EXTERNAL TABLE t2 (id int, name varchar(50), created date, region varchar(50))
   AS COPY FROM '/mapr/*/*/*' PARTITION COLUMNS created, region PARQUET();

以下语句将 ORC 数据从 MapR 加载到 Vertica:

=> COPY t FROM '/mapr/data/*.orc' ON ANY NODE ORC;

以下语句在 MapR 文件系统中创建存储位置来保存 ROS 数据:

=> CREATE LOCATION '/mapr/my.cluster.com/data' SHARED USAGE 'DATA' LABEL 'maprfs';

=> SELECT ALTER_LOCATION_USE('/mapr/my.cluster.com/data', '', 'DATA');

8 - 适用于 Vertica 集成的 Hive 入门知识

您可以使用 Hive 导出数据以供 Vertica 使用。您在执行 Hive 导出时所做的决定会影响 Vertica 的性能。

调整 ORC 带区和 Parquet 行组

Vertica 可以读取任何 Hive 版本生成的 ORC 和 Parquet 文件。不过,较新的 Hive 版本在这些文件中存储了更多元数据。Hive 和 Vertica 都使用这些元数据来修剪值并仅读取所需的数据。使用最新的 Hive 版本以采用这些格式存储数据。ORC 和 Parquet 完全向前和向后兼容。要获得最佳性能,请使用 Hive 0.14 或更高版本。

ORC 格式将表拆分为称作“带区”的行分组,并在每个带区中存储列级元数据。Parquet 格式将表拆分为称作“行组”的行分组,并在每个行组中存储列级元数据。在谓词评估期间使用每个带区/行组的元数据来确定是否需要读取该带区中的值。大的带区通常会产生较好的性能,因此请将带区大小设置为至少 256M。

Hive 将 ORC 带区和 Parquet 行组写入 HDFS,HDFS 将数据存储在分布于多个物理数据节点的 HDFS 块中。访问 HDFS 块需要打开与相应数据节点的单独连接。最好确保 ORC 带区或 Parquet 行组不跨越多个 HDFS 块。为此,请将 HDFS 块大小设置为大于带区/行组大小。通常,将 HDFS 块大小设置为 512M 就足够了。

Hive 提供三种压缩选项:无、Snappy 和 Zlib。使用 Snappy 或 Zlib 压缩可减少存储和 I/O 消耗。通常,Snappy 的 CPU 密集度较低,但与 Zlib 相比可以产生更低的压缩率。

按排序顺序存储数据可以提高数据访问速度和谓词评估性能。根据表列在查询谓词中出现的可能性对其进行排序;应先对在比较或范围谓词中最常出现的列进行排序。

分区表是一种非常有用的数据组织技术。类似于按列对表进行排序,分区可以提高数据访问和谓词评估性能。Vertica 支持 Hive 样式的分区和分区修剪。

以下 Hive 语句创建带区大小为 256M 且采用 Zlib 压缩的 ORC 表:

hive> CREATE TABLE customer_visits (
        customer_id bigint,
        visit_num int,
        page_view_dt date)
    STORED AS ORC tblproperties("orc.compress"="ZLIB",
        "orc.stripe.size"="268435456");

以下语句创建带区大小为 256M 且采用 Zlib 压缩的 Parquet 表:

hive> CREATE TABLE customer_visits (
        customer_id bigint,
        visit_num int,
        page_view_dt date)
    STORED AS PARQUET tblproperties("parquet.compression"="ZLIB",
        "parquet.stripe.size"="268435456");

在 Hive 中创建排序文件

与 Vertica 不同,Hive 不会将表列存储在单独的文件中,并且不会为每个表创建具有不同排序顺序的多个投影。为了实现高效的数据访问和谓词下推,根据 Hive 表列在查询谓词中出现的可能性对它们进行排序。最常出现在比较或范围谓词中的列应排在前面。

可以使用 ORDER BY 或 SORT BY 关键字将数据按排序顺序插入 Hive 表。例如,要在 ORC 表 "customer_visit" 中插入具有相同列的另一个表 "visits" 中的数据,请在 INSERT INTO 命令中使用以下关键字:

hive> INSERT INTO TABLE customer_visits
        SELECT * from visits
        ORDER BY page_view_dt;
hive> INSERT INTO TABLE customer_visits
        SELECT * from visits
        SORT BY page_view_dt;

这两个关键字之间的区别在于 ORDER BY 通过使用单个 MapReduce reducer 填充表来保证整个表的全局排序。SORT BY 使用多个 reducer,这可能导致 ORC 或 Parquet 文件按指定列排序,而不能全局排序。使用靠后的关键字会增加加载文件所需的时间。

您可以结合聚类和排序来对表进行全局排序。以下表定义添加了一个提示,即数据插入到此表中,按 customer_id 分桶并按 page_view_dt 排序:

hive> CREATE TABLE customer_visits_bucketed (
        customer_id bigint,
        visit_num int,
        page_view_dt date)
    CLUSTERED BY (page_view_dt)
    SORTED BY (page_view_dt)INTO 10 BUCKETS
    STORED AS ORC;

将数据插入到表中时,必须显式指定聚类和排序列,如下例所示:

hive> INSERT INTO TABLE customer_visits_bucketed
    SELECT * from visits
    DISTRIBUTE BY page_view_dt
    SORT BY page_view_dt;

下面的语句是等效的:

hive> INSERT INTO TABLE customer_visits_bucketed
    SELECT * from visits
    CLUSTER BY page_view_dt;

上述两个命令都将数据插入到 customer_visits_bucketed 表中,并在 page_view_dt 列上全局排序。

对 Hive 表进行分区

Hive 中的表分区是一种用于数据分离和组织以及减少存储需求的有效技术。要在 Hive 中对表进行分区,请将其包含在 PARTITIONED BY 子句中:

hive> CREATE TABLE customer_visits (
        customer_id bigint,
        visit_num int)
    PARTITIONED BY (page_view_dt date)
    STORED AS ORC;

Hive 不实体化分区列。相反,它会创建以下形式的子目录:

path_to_table/partition_column_name=value/

查询表时,Hive 解析子目录名称以实体化分区列中的值。Hive 中的值实体化是从字符串到适当数据类型的简单转换。

将数据插入分区表需要指定分区列的值。以下示例创建两个分区子目录 "customer_visits/page_view_dt=2016-02-01" 和 "customer_visits/page_view_dt=2016-02-02":

hive> INSERT INTO TABLE customer_visits
    PARTITION (page_view_dt='2016-02-01')
    SELECT customer_id, visit_num from visits
    WHERE page_view_dt='2016-02-01'
    ORDER BY page_view_dt;

hive> INSERT INTO TABLE customer_visits
    PARTITION (page_view_dt='2016-02-02')
    SELECT customer_id, visit_num from visits
    WHERE page_view_dt='2016-02-02'
    ORDER BY page_view_dt;

每个目录都包含 ORC 文件,其中包含两列 customer_id 和 visit_num。

示例:已分区且排序的 ORC 表

假设您将数据存储在包含 customer_id、visit_num、page_view_dtm 这三列的 CSV 文件中:

1,123,2016-01-01
33,1,2016-02-01
2,57,2016-01-03
...

目标是创建以下 Hive 表:

hive> CREATE TABLE customer_visits (
            customer_id bigint,
            visit_num int)
    PARTITIONED BY (page_view_dt date)
    STORED AS ORC;

为此,请执行以下步骤:

  1. 将 CSV 文件复制或移动到 HDFS。

  2. 定义一个文本文件 Hive 表并将 CSV 文件复制到其中:

    hive> CREATE TABLE visits (
                customer_id bigint,
                visit_num int,
                page_view_dt date)
        ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
        STORED AS TEXTFILE;
    
    hive> LOAD DATA INPATH path_to_csv_files INTO TABLE visits;
    
  3. 对于 page_view_dt 中的每个唯一值,将数据插入目标表,同时将 page_view_dt 实体化为 page_view_dtm:

    hive> INSERT INTO TABLE customer_visits
            PARTITION (page_view_dt='2016-01-01')
            SELECT customer_id, visit_num FROM visits
            WHERE page_view_dt='2016-01-01'
            ORDER BY page_view_dt;
    ...
    

    此操作将 visits.customer_id 中的数据插入 customer_visits.customer_id,并将 visits.visit_num 中的数据插入 customer_visits.visit_num。这两列存储在生成的 ORC 文件中。同时,visits.page_view_dt 中的值用于为分区列 customer_visits.page_view_dt(该列不存储在 ORC 文件中)创建分区。

Hive 中的数据修改

Hive 非常适合读取大量的一次性写入数据。它的最佳用法是将数据批量加载到表中,并且从不修改数据。特别是,对于以 ORC 和 Parquet 格式存储的数据,这种使用模式会生成大型的全局(或几乎全局)排序文件。

定期向表中添加数据(称为“涓流式加载”)可能会产生许多小文件。这样做的缺点是 Vertica 在查询计划和执行期间必须访问更多文件。这些额外的访问可能会导致查询处理时间延长。主要的性能下降是因为 HDFS 上文件搜索次数的增加。

Hive 还可以在无需用户干预的情况下修改底层 ORC 或 Parquet 文件。例如,如果 Hive 表中有足够多的记录被修改或删除,Hive 会删除现有文件并用新创建的文件替换它们。Hive 还可以配置为自动将许多小文件合并为几个较大的文件。

在 Hive 中创建新表或修改现有表时,必须手动同步 Vertica 以使其保持最新。以下语句在 Hive 发生更改后同步 Vertica 架构 "hcat":

=> SELECT sync_with_hcatalog_schema('hcat_local', 'hcat');

Hive 中的架构演变

Hive 支持两种架构演变:

  1. 可以将新列添加到 Hive 中的现有表。Vertica 会自动处理这种架构演变。对于新列,旧记录将显示 NULL。
  2. 可以在 Hive 中修改表的列类型。Vertica 不支持这种架构演变。

下面的示例演示了通过新列进行的架构演变。在此示例中,hcat.parquet.txt 是具有以下值的文件:

-1|0.65|0.65|6|'b'
hive> create table hcat.parquet_tmp (a int, b float, c double, d int, e varchar(4))
      row format delimited fields terminated by '|' lines terminated by '\n';

hive> load data local inpath 'hcat.parquet.txt' overwrite into table
      hcat.parquet_tmp;

hive> create table hcat.parquet_evolve (a int) partitioned by (f int) stored as
      parquet;
hive> insert into table hcat.parquet_evolve partition (f=1) select a from
      hcat.parquet_tmp;
hive> alter table hcat.parquet_evolve add columns (b float);
hive> insert into table hcat.parquet_evolve partition (f=2) select a, b from
      hcat.parquet_tmp;
hive> alter table hcat.parquet_evolve add columns (c double);
hive> insert into table hcat.parquet_evolve partition (f=3) select a, b, c from
      hcat.parquet_tmp;
hive> alter table hcat.parquet_evolve add columns (d int);
hive> insert into table hcat.parquet_evolve partition (f=4) select a, b, c, d from
      hcat.parquet_tmp;
hive> alter table hcat.parquet_evolve add columns (e varchar(4));
hive> insert into table hcat.parquet_evolve partition (f=5) select a, b, c, d, e
      from hcat.parquet_tmp;
hive> insert into table hcat.parquet_evolve partition (f=6) select a, b, c, d, e
      from hcat.parquet_tmp;

=> SELECT * from hcat_local.parquet_evolve;

  a |         b         |  c   | d | e | f
----+-------------------+------+---+---+---
 -1 |                   |      |   |   | 1
 -1 | 0.649999976158142 |      |   |   | 2
 -1 | 0.649999976158142 | 0.65 |   |   | 3
 -1 | 0.649999976158142 | 0.65 | 6 |   | 4
 -1 | 0.649999976158142 | 0.65 | 6 | b | 5
 -1 | 0.649999976158142 | 0.65 | 6 | b | 6
(6 rows)