怎么理解Impala元数据

技术怎么理解Impala元数据本篇文章给大家分享的是有关怎么理解Impala元数据,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。背景Impala是一个高性能

本文是关于如何理解Impala元数据的。边肖觉得很实用,所以分享给大家学习。希望你看完这篇文章能有所收获。让我们和边肖一起看看。

背景

Impala是一款高性能的OLAP查询引擎。与其他SQL-on-Hadoop的ROLAP解决方案如Presto、SparkSQL不同,Impala缓存元数据(Metadata/Catalog),因此在进行查询计划生成时不再依赖外部系统(如Hive、HDFS、Kudu),可以实现毫秒级的生成时间。此外,缓存元数据还可以大大降低底层系统主节点(Hive Metastore、HDFS NameNode、Kudu Master)的负载。

然而事物总是有两面性,元数据缓存给Impala的系统设计带来了极大的复杂性。一方面在功能上,为了维护缓存的正确性,引入了两个Impala特有的SQL语句:Invalidate Metadata和Refresh,此外还引入了查询选项SYNC_DDL。这些都使得用户参与到缓存的维护中。另一方面,在架构设计中,有许多与元数据相关的复杂设计,如元数据的增量传播、缓存一致性的维护等。

当数据仓库规模较大时,Impala的元数据设计暴露出很多问题,比如大表的元数据加载和刷新时间极长,元数据的广播会被DDL阻塞,导致广播延迟较大,元数据缓存会导致节点Full GC或OOM等。因此,Impala的元数据设计一直在演进,最新进展主要集中在Fetch-on-demand协调器的设计上(也称为本地目录模式、catalog-v2等)。).

Impala Server简介

Impala集群由一个目录服务器(Catalogd)、一个状态存储服务器(Statestored)和几个Impala守护进程(Impalad)组成。Catalogd主要负责元数据获取和DDL执行,Statestored主要负责消息/元数据广播,Impalad主要负责查询接收和执行。

怎么理解Impala元数据

Impalad可以配置为三种模式:仅协调器、仅执行器或协调器和执行器(默认)。协调者角色中的Impalad负责接收查询、生成计划、调度查询等。Impalad在Executor角色中负责读取和计算数据。默认情况下,每个黑斑羚既是协调者又是执行者。生产环境建议角色应该分开,即每个Impalad要么是协调者,要么是执行者,可以1:50的比例进行配置。更多详情请参考官方文件[1]。

Impala元数据的构成

Impala的元数据缓存在每个协调员角色的catalogd和Impala中。catalog d中的缓存是最新的,每个协调器都会在Catalogd中缓存一份元数据的副本,如下图所示,元数据由Catalogd从外部系统获取,通过Statestored传播给各个协调器。

怎么理解Impala元数据

元数据缓存主要由Java代码实现,主要代码在FE中。还有一些由C实现的代码,主要处理FE和BE之间的交互以及元数据的广播。在代码中,Catalogd和Coordinator (Impalad)中相同的元数据管理逻辑被提取并放在Catalog.java,Catalogd中的实现是CatalogServiceCatalog.java,Coordinator中的实现是ImpaladCatalog.java。

目录是一个层次结构,第一层是从数据库名称到数据库的映射,第二层是每个数据库下的函数映射和表映射:

目录

| - dbCache_=MapString,Db

| - functions_=MapString,ListFunction

|-tablecache _=catalogobjectcachetablefunctions _ map中的值是函数列表,主要表示同名函数的不同重载。TableCache_由CatalogObjectCache维护。CatalogObjectCache封装了一个ConcurrentHashMap,并增加了版本管理的逻辑,比如避免较低版本的更新覆盖较高版本的缓存,跟踪所有缓存的版本。

号等。这些版本管理逻辑在Impalad中尤其重要。我们在后续的文章中会详细介绍。

Table 在代码里有五个具体的子类:HdfsTable、KuduTable、HBaseTable、View、IncompleteTable、DataSourceTable。前4个都比较直白,解释下最后两个:

  • IncompleteTable 表示未加载元数据的表或视图(View)。Catalogd 启动时,为了减少启动时间,只加载了所有表的表名,每个表用IncompleteTable来表示。如果执行了INVALIDATE METADATA,则表的元数据也会被清空,其表现就是回置成了IncompleteTable。IncompleteTable可能代表一个视图,但这在元数据未加载时是无法确定的。因此在HUE等可视化界面中使用Impala时,常常会看到一个View是用Table的图标表示的,但一旦有被使用过,就又变回成了View的图标。

  • DataSourceTable 属于external data source的实现,这块没有任何文档提及,因为一直处于实验状态。其初衷是提供一个Java接口来自定义外部数据源,只需要实现 prepare、open、getNext、close 这几个接口。具体可参考代码里的 EchoDataSource 和 AllTypesDataSource。

接下来我们重点介绍下前三个的元数据构成。

HdfsTable

HdfsTable 代表一张底层存储为 HDFS 的 Hive 表。无分区表的元数据比较简单,少了各个分区对应的元数据。这里以分区表为例,其元数据如图所示:

怎么理解Impala元数据

其中 msTable 和 msPartition 表示 HMS API 里返回的对象:

org.apache.hadoop.hive.metastore.api.Tableorg.apache.hadoop.hive.metastore.api.Partition

HdfsPartition 代表一个分区的元数据,其一大部分内容是 HDFS 文件和块的信息。图中的 FileDescriptor 和 BlockDescriptor,就是从 HDFS API 里返回的 FileStatus 和 BlockLocation 对象抽取数据后生成的。为了节省空间,实际缓存的并不是上图展示的 FileDescriptor 和 FileBlock。IMPALA-4029 引入了 FlatBuffer 来压缩 FileDescriptor 和 FileBlock。FlatBuffer 的好处是不需要像 protobuf 或 thrift 一样做序列化和反序列化,但却可以直接访问对象里的内容,同时带来了一定的压缩比。更多关于 FlatBuffer 参见文末文档 [2].

HdfsPartition 的另一大部分内容是增量统计信息,缓存的是deflate算法压缩后的数据,具体详见:PartitionStatsUtil#partStatsFromCompressedBytes()。解压之后是一个 TPartitionStats 对象,主要包含了各列在该partition里的统计信息,每列的统计信息用一个 TIntermediateColumnStats 表示:

struct TIntermediateColumnStats {
 1: optional binary intermediate_ndv // NDV HLL 计算的中间结果
 2: optional bool is_ndv_encoded     // HLL中间结果是否有用 RLE 压缩
 3: optional i64 num_nulls           // 该列在该分区的 NULL 数目
 4: optional i32 max_width           // 该列在该分区的最大长度
 5: optional double avg_width        // 该列在该分区的平均长度
 6: optional i64 num_rows            // 该分区行数,用于聚集HLL中间结果
}

关于 Impala 里 ndv() 的实现,可参考 be/src/exprs/aggregate-functions-ir.cc 中的 HllInit()、HllUpdate()、HllMerge()、HllFinalEstimate() 的逻辑。ndv 的中间结果用一个string表示,长度为 1024。在传输时一般会用 RLE (Run Length Encoding) 压缩。

Impala的统计信息受限于Hive(因为要保存在Hive Metastore中),目前并没有统计数值类型列的最大最小、平均值等信息。这块有个古老的 JIRA: IMPALA-2416,目前还没有进展。

一个HDFS分区表的元数据在各种压缩后,在内存中的大小约为

分区数*2048 + 分区数*列数*400 + 文件数*500 + 块数目*150

实际应用中要降低大表的元数据大小,就需要在分区数、列数、文件数、块数目上寻求优化的空间。其中 2048、400、500、150 这些数都是各对象压缩大小的估计值,"分区数 * 列数 * 200" 指的是增量统计信息的大小,如果表的统计信息是非增量的,即一直用 Compute Stats 来统计,则不需要这部分。实际应用中很少直接对大表做 Compute Stats,因为执行时间可能很长,一般都是使用 Compute Incremental Stats,因此这部分的内存占用不可忽略。

KuduTable

HdfsTable 代表一张底层存储为 Kudu 的 Hive 表。Impala 缓存的 Kudu 元数据特别有限:

  • msTable: HMS API 返回的 Table 对象,主要是 Hive 中的元数据

  • TableStats: HMS 中存的统计信息,主要是各列统计信息和整张表的行数等

  • kuduTableName: Kudu 存储中的实际表名,该名字可以跟 Hive 中的表名不同。

  • kuduMasters: Kudu 集群的 master 列表

  • primaryKeyColumnNames: Kudu 表的主键列

  • partitions: Kudu 表的分区信息

  • kuduSchema: Kudu API 返回的 Schema 信息

关于分区信息,只缓存了分区的列是哪些,以及 hash 分区的分区数,并没有缓存 Range 分区的各个 Range 是什么,因此在用 SHOW CREATE TABLE 语句时,看到的 range partition 信息只包含了列名。比如下面这个例子,"Partition by range(id)" 部分的各个 range 被省略了:

Query: show create table functional_kudu.dimtbl
+-------------------------------------------------------------------------------------------------------------------------------------------+
| result                                                                                                                                    |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| CREATE TABLE functional_kudu.dimtbl (                                                                                                     |
|   id BIGINT NOT NULL ENCODING AUTO_ENCODING COMPRESSION DEFAULT_COMPRESSION,                                                              |
|   name STRING NULL ENCODING AUTO_ENCODING COMPRESSION DEFAULT_COMPRESSION,                                                                |
|   zip INT NULL ENCODING AUTO_ENCODING COMPRESSION DEFAULT_COMPRESSION,                                                                    |
|   PRIMARY KEY (id)                                                                                                                        |
| )                                                                                                                                         |
| PARTITION BY RANGE (id) (...)                                                                                                             |
| STORED AS KUDU                                                                                                                            |
| TBLPROPERTIES ('STATS_GENERATED'='TASK', 'impala.lastComputeStatsTime'='1573922577', 'kudu.master_addresses'='localhost', 'numRows'='10') |
+-------------------------------------------------------------------------------------------------------------------------------------------+

如果需要查看具体有哪些 range 分区,还是需要用 SHOW RANGE PARTITIONS 语句,Impala 会从 Kudu 中获取结果来返回,然而还是不会缓存这些 range 信息。

Query: show range partitions functional_kudu.dimtbl
+-----------------------+
| RANGE (id)            |
+-----------------------+
| VALUES < 1004         |
| 1004 <= VALUES < 1008 |
| VALUES >= 1008        |
+-----------------------+
Fetched 3 row(s) in 0.07s

这块个人觉得还有很多工作可做,比如把 range 分区的分界点缓存下来后,可以用来优化 Insert 语句,提升批量导入 Kudu 的性能(IMPALA-7751)。另外关于更细节的信息如每个 kudu tablet 的复本位置,kudu tserver 地址等都是没有缓存的,利用这些信息实际也能做很多优化,欢迎大家一起来参与开发!

HBaseTable

Impala 对 HBase 的支持始于对 Hive 的兼容(Hive 可以读 HBase 的数据),但目前已经处于维护状态,社区不再在这方面投入精力。一方面是 Kudu 更适合替代 HBase 来做 OLAP,另一方面是 Impala 也不适合太高并发的 DML 操作。

HBaseTable 代表底层存储为 HBase 的 Hive 表,缓存了 HMS 中的 Table 定义和表的大小(行数)这些基本的统计信息,另外也缓存了底层 HBase 表的所有列族名。

总结

Impala 缓存了外部系统(Hive、HDFS、Kudu等)的元数据,主要目的是让查询计划生成阶段不再需要跟外部系统交互。元数据统一由Catalogd向外部系统获得,并通过Statestored广播给所有Coordinator。

生成查询计划需要哪些元数据,哪些元数据就会被缓存下来:

  • Table: Schema(表名、字段名、字段类型、分区字段等)、各列统计信息

    • HdfsTable: 分区目录、文件路径、文件分块及复本位置、各分区的增量统计信息

    • KuduTable: 分区列及分区类型(Hash、Range)

    • HBaseTable: 各列族名

    • View: 具体的查询语句

以上就是怎么理解Impala元数据,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/112504.html

(0)

相关推荐

  • PHP 5中echo和print语句怎么用

    技术PHP 5中echo和print语句怎么用这篇文章主要介绍了PHP 5中echo和print语句怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。P

    攻略 2021年11月25日
  • android项目一般用到哪些开源库(android开源库分类及使用方法)

    技术实用的Android开源库有哪些这篇文章主要为大家展示了“实用的Android开源库有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“实用的Android开源库有哪些”

    攻略 2021年12月24日
  • iptables使用教程(iptables使用)

    技术iptables怎么使用本篇内容主要讲解“iptables怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“iptables怎么使用”吧! 实战1 服务器禁止pin

    攻略 2021年12月21日
  • 为您的物联网系统选择合适的数据库的4个步骤分别是什么

    技术为您的物联网系统选择合适的数据库的4个步骤分别是什么本篇文章为大家展示了为您的物联网系统选择合适的数据库的4个步骤分别是什么,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。为物

    攻略 2021年12月2日
  • vue生命周期多少个钩子函数(vue生命周期和钩子函数的区别)

    技术Vue生命周期中的八个钩子函数相机是怎样的Vue生命周期中的八个钩子函数相机是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、beforeCre

    攻略 2021年12月16日
  • 如何实现对Samba UAF和内存泄漏漏洞的分析

    技术怎么实现Samba UAF和内存泄露漏洞的分析怎么实现Samba UAF和内存泄露漏洞的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。0x00 事件

    攻略 2021年12月22日