Impala前端代码分析

1 概述

前端代码使用java。感觉使用java的原因是,本身语法分析不会占用太多时间,毫秒级可以完成,不是性能瓶颈。而且语法分析的代码通常比较复杂,逻辑较多,如果再自己管理内存的话,会影响开发效率。

Impala通过jni调用前端java代码,前后端数据传递采用thrift格式。

前端的代码主要包括以下几个功能:

  • 将用户提交的query转换成语法树,这个通过jflex和cup完成(hive使用的是antlr)
  • 语法分析
  • 生成执行计划
  • 在编译中访问元数据

2 语法分析和ParseNode

ParseNode定义了一个接口。jflex和cup分析完的语法树中,每一个节点都实现了这个接口。语法分析就是在这个ParseNode组成的树中进行的。

ParseNode的实现和继承关系如下:

  • Expr (表达式)

    • Predicate (谓词,出现在where语句中)

      • BetweenPredicate
      • BinaryPredicate (=, !=, <=, >=, <, >)
      • CompoundPredicate (&&, ||, !)
      • InPredicate
      • IsNullPredicate
      • LikePredicate
      • LiteralPredicate
        • BoolLiteral
        • DateLiteral
        • FloatLiteral
        • IntLiteral
        • NullLiteral
        • StringLiteral
    • AggregateExpr (count, min, max, distince, sum, avg)
    • ArithmeticExpr (*, /, %, DIV, +, -, &, |, ^, ~)
    • CaseExpr
    • CastExpr
    • FunctionCallExpr
    • LiteralExpr
    • TimestampArithmeticExpr
  • QueryStmt
    • SelectStmt
    • UnionStmt
  • InsertStmt
  • ShowDbStmt
  • ShowTablesStmt
  • DescribeStmt
  • UseStmt
  • TableRef
    • BaseTableRef
    • InlineViewTableRef (alias)

其中,Expr继承了TreeNode类,可以组成一个求值树。而其他ParseNode虽然没有继承TreeNode,但也都有类似的数据结构。可以访问孩子节点。这样ParseNode就组成了一颗语法树。

语法分析阶段主要进行了一些基本的语法检查,类型检查,并抽取一些信息,放到Analyzer类中,例如alias映射表等等。

3 Analyzer

Analyzer是语法分析的一个产出。Analyzer用于收集某一个QureyBlock内的信息。类似Hive中的QB类。

其主要成员变量包括:

  • DescriptorTable descTbl;
  • Catalog catalog;
  • String defaultDb;
  • IdGenerator<ExprId> conjunctIdGenerator;
  • Analyzer parentAnalyzer;
  • Map<String, TupleDescriptor> aliasMap;
  • Map<String, SlotDescriptor> slotRefMap;
  • Map<ExprId, Predicate> conjuncts;
  • Map<TupleId, List<ExprId> > tuplePredicates;
  • Map<SlotId, List<ExprId> > slotPredicates;
  • Map<TupleId, List<ExprId> > eqJoinConjuncts;
  • Set<ExprId> assignedConjuncts;
  • Map<TupleId, TableRef> outerJoinedTupleIds;
  • Map<TableRef, List<ExprId> > conjunctsByOjClouse;
  • Map<ExprId, TableRef> ojClouseByConjunct;
  • Set<ExprId> whereClauseConjuncts;

4 生成执行计划和Planner

Planner负责将分析后的语法树转换成执行计划,即PlanFragments。

Planner的入口函数是Planner::createPlanFragments()。其主要流程如下:

  • createSinglePlan:

    根据语法分析的结果,遍历并生成一个逻辑执行计划树。树中的节点是PlanNode。树的根节点是最后被执行的节点。

  • createPlanFragments:

    将生成的执行计划切割成多个PlanFragment。这个过程类似Hive中将执行计划分割成多个MapRed阶段。目前Impala划分阶段的规则是:如果遇到ScanNode, HashJoinNode, MergeNode, AggregationNode, SortNode,则产生一个新的PlanFragment。每一个PlanFragment之间通过ExchangeNode相连。ExchangeNode在运行时中会负责跨Impalad的数据传输。

  • computeMemLayout:

    对于输入表,计算在内存中的layout。主要目的是为了计算一条记录在内存中会占用多少字节(由TupleDescriptor描述),以及每一个字段在内存中如何分布(由SlotDescriptor描述)。

最后PlanFragments就会成为物理执行计划,转成thrift后返回给前端。

5 Catalog

Impala直接使用了Hive的HiveMeteStoreClient类,用于访问元数据。这就意味着,必须还要启动一个HiveMetaStore进程,用于提供元数据服务。目前Catalog默认采用lazy模式,只在需要时加载database和table对象。

Catalog主要在语法分析阶段使用,用于获取Hive元数据,目前在Planner中没有使用Catalog。

Impala学习–Impala后端代码分析

1 代码结构

  • service: 连接前端,并接受client的请求
  • runtime: 运行时需要的类,包括coordinator, datastream, mem-pool, tuple等
  • exec: ExecNode,执行节点
  • expr: 表达式求值
  • transport: Thrift SASL: Simple Authentication and Security Layer
  • statestore: 调度,nameservice,资源池
  • codegen: 代码生成

2 StateStore

StateStore是一个C/S结构的信息订阅服务,在Impala里面,主要用于管理当前集群的membership状态,并用于调度和发现故障进程。StateStore是一个独立的进程,每一各impalad会建立一个或多个于StateStore的连接。

StateStore提供四个接口:

  • RegisterService:向某个服务进行注册,就是加入并成为这个服务的成员
  • UnregisterService:取消在某个服务的注册
  • RegisterSubscription:订阅某一各服务的成员信息
  • UnregisterSubscription:取消对某个服务成员信息的注册

StateStore会通过心跳来检查已经注册的成员是否还活着,判断条件可以是心跳超时,连续丢失n个心跳。StateStore定期向subscriber更新其所订阅服务的成员信息。目前的更新策略是全量更新,未来会考虑增量更新。通常在Impala集群中只存在一个服务,每个impalad都会注册这个服务。注册服务后,这个impalad就可以对其他impalad可见,这样就可以接受其他impalad发来的任务。

3 Scheduler

Coordinator在得到执行计划后,通过Scheduler得到可以执行的后端,并向这些后端发送执行命令

Scheduler提供两个接口

  • GetHosts:提供一组访问数据所在的机器地址,返回一组和数据尽量接近的机器地址
  • GetAllKnownHosts:返回所有还存活的机器地址。

SimpleScheduler是目前唯一的Scheduler的实现。Coordinator通过调用SimpleScheduler的GetHosts方法,调度和远端任务分配。在GetHosts方法中,采用的算法是:优先寻找已经和数据位置相同的后端,如果没有相同的,则采用roud-robin算法。目前SimpleScheduler没有考虑机器实时的负载情况。返回的后端数目取决于输入数据分布的机器数目。

4 impalad启动流程

  • 初始化LLVM,hdfs,jni,hbase,前端
  • 启动ImpalaServer
  • 启动thriftserver,接受thrift请求
  • 启动ExecEnv
    • 启动webserver
    • 启动SubscriptionManager
    • 启动Scheduler
      • 向StateStore订阅,并注册回调函数SimpleScheduler::UpdateMembership,用于调度时提供当前可用的后端
  • SubscriptionManager::RegisterService
    • StateStore检查service是否存在,如果不存在,则建立一个新的service_instance
    • 检查客户端是否存在于这个service_instance的membership中,如果不存在,则添加一个
  • SubscriptionMangaer::RegisterSubscription
    • StateStore添加一个Subscriber,订阅这个service的membership,并注册回调函数MembershipCallback
    • 当有update回调时,更新impala-server的membership状态,用于failure detector

Impalad启动后,就可以接受query请求,也可以接受其他impalad的请求,执行一个PlanFragment。

5 Coordinator

负责执行一组PlanFragments。同时负责响应client的请求。coordinator fragment在本地执行,其他发送到远程的impalad执行。coordinator同时监控整个执行状态。

Exec()函数是其最主要的函数,简要介绍一下这个函数中的流程::

  • ComputeFragementExecParams():

    • ComputeFragmentHosts():对于每一个Fragment,根据输入数据所在的节点,调用Scheduler的GetHosts方法,得到每个阶段在那些后端上执行
    • 对于每一个Fragment,计算其ExchangeNode的参数
  • ComputeScanRangeAssignment():计算每一个后端应该扫描多少数据。
  • executor_ = new PlanFragmentExecutor()创建一个新的PlanFragmentExecutor。
  • executor_->Prepare()
  • 对于每一各fragment,对于每一个远程后端,调用ExecRemoteFragment。
  • ProgressUpdater:定期更新状态。

6 ExecNode

所有ExecNode的父类。主要方法有Prepare(), Open(), GetNext(), Close(), CreateTree()ExecNode是真正在Impalad上处理数据的类,包括hash-join,聚合,scan等等。多个ExecNode组成了一颗执行树。root节点被最后执行,叶子节点被最先执行。

Impala中的执行顺序和Hive中相反。在Impala中,采用拖的方式,而Hive中采用推的方式。Impala中,执行入口是根节点的Open方法。Open方法会调用孩子节点的Open方法和GetNext方法。

主要数据结构包括:

  • ObjectPool* pool_
  • vector<Expr*> conjuncts_
  • vector<ExecNode*> children_
  • RowDescriptor row_descriptor_

主要函数包括:

  • Prepare()在Open前被调用。code generation
  • Open()在GetNext前被调用,准备工作。调用孩子节点的GetNext()
  • GetNext()返回一组row,并标记eos
  • EvalConjuncts()对所有表达式进行求值,并返回布尔结果

7 PlanFragmentExecutor

执行一个PlanFragment。包括初始化和清理。清理包括释放资源,关闭data stream。每一个Executor会有一个callback,用于汇报执行状态。

最主要的有三个函数,分别是:

  • Status Prepare(TExecPlanFragmentParams):准备执行,主要流程如下:

    • DescriptorTbl::Create():初始化descriptor table.
    • ExecNode::CreateTree():初始化执行树。执行树由ExecNode组成。每一个ExecNode也提供了Prepare(), Open(), GetNext()三个函数。初始化完成后,plan_指向了执行树的根节点。
    • plan_->Prepare():初始化执行树
    • 如果可以使用代码生成,则调用runtime_state_->llvm_codegen()->OptimizedModule()进行优化
    • set scan ranges
    • set up sink, if required
    • set up profile counter
  • Status Open():开始执行,并启动一个独立的线程向coordinator汇报状态:
    • plan_->Open()从根节点开始调用Open函数,开始执行。
    • if has sink: sink_->Send()如果有写回操作,例如query中包含insert语句,则主动将计算结果推送到hdfs或hbase中。
  • Status GetNext(RowBatch)用于触发执行树的GetNext函数。当GetNext返回done时,则表明所有数据已经被处理完,Executor可以退出了。

Impala学习--Impala前端代码分析,Impala后端代码分析的更多相关文章

  1. 基于数据库的代码自动生成工具,生成JavaBean、生成数据库文档、生成前后端代码等(v6.0.0版)

    TableGo v6.0.0 版震撼发布,此次版本更新如下: 1.UI界面大改版,组件大调整,提升界面功能的可扩展性. 2.新增BeautyEye主题,界面更加清新美观,也可以通过配置切换到原生Jav ...

  2. 【impala学习之一】impala

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 CM5.4 一.ImpalaImpala是基于Hive的大数 ...

  3. impala学习笔记

    impala学习笔记 -- 建库 CREATE DATABASE IF NOT EXISTS database_name; -- 在HDFS文件系统中创建数据库,需要指定要创建数据库的位置. CREA ...

  4. 通过java代码进行impala和kudu的对接

    对于impala而言,开发人员是可以通过JDBC连接impala的,有了JDBC,开发人员可以通过impala来间接操作kudu: maven导包: <!-- https://mvnreposi ...

  5. 【impala学习之二】impala 使用

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 CM5.4 一.Impala shell 1.进入impal ...

  6. Vue实现多文件上传功能(前端 + 后端代码)

    本人业余前端开发,因为公司(很坑)觉得我很牛逼,所以让我前后端一起玩,无奈的我只能磕磕碰碰的研究起了vue. 开发项目的时候,用到文件上传的功能很常见,包括单文件上传和多文件上传,上传各种类型的文件. ...

  7. impala与hive的比较以及impala的有缺点

    最近读的几篇关于impala的文章,这篇良心不错:https://www.biaodianfu.com/impala.html(本文截取部分内容) Impala是Cloudera公司主导开发的新型查询 ...

  8. node.js接收前端上传的文件并保存到其他位置+后端代码支持进度条

    一:直接上传文件,放入body里 1.前端代码 <input type="file" onchange="sendFiles(this.files)"&g ...

  9. 【Java学习笔记之十七】Java中普通代码块,构造代码块,静态代码块区别及代码示例分析

    //执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 //普通代码块:在 ...

  10. 前端代码质量保障之代码review

    经验丰富的程序员和一般程序员之间的最大区别,不仅体现在解决问题的能力上, 还体现在日常代码的风格上.掌握一门技术可能需要几月,甚至几周就够了. 好的习惯风格养成却需数年. 团队成员之间需要合作,代码需 ...

随机推荐

  1. SQL Server磁盘空间清理 【转】

    SQL Server在删除数据后,会重新利用这部分空间,所以如果不是空间紧张的情况下,可以不回收.回收一般先回收日志文件,因为这个回收速度非常快,可以短时间内清理出一部分可用空间.回收步骤: 1.查看 ...

  2. AWS 认证

    Data Analytics: 准备先Fundamental, 然后Udemy 上买课程,在看Exam Readiness, 然后小测试一下水平,看白皮书,最后不行就 Guru上再买课程 https: ...

  3. ZEGO 自研客户端配置管理系统 —— 云控

    一.常规客户端配置的弊端 客户端配置信息通常会通过一个静态文件进行管理,或存放在本地或者通过远程获取.存在本地最大的问题是不易更新,所以通常做法是通过远程获取. 我们通过两种常见的场景来看看静态文件管 ...

  4. TimesURL: 用于通用时间序列表征学习的自监督对比学习《TimesURL: Self-supervised Contrastive Learning for Universal Time Series Representation Learning》模型代码运行解析

    现在是2024年3月25日16:17,打算好好的跑一个模型的代码,之前都没有系统性的过一遍,打算拿这个模型的代码开刀,Go,环境和乱七八糟的已经配好了. 关于这篇论文,之前写了博客,里面也有Githu ...

  5. namespace hdk

    没有高精类,因为这玩意太占内存了,正在优化 demap Rander StringAddition_InFix string ordered_vector #include<bits/stdc+ ...

  6. Windows平台下安装与配置MySQL9

    要在Windows平台下安装MySQL,可以使用图行化的安装包.图形化的安装包提供了详细的安装向导,以便于用户一步一步地完成对MySQL的安装.本节将详细介绍使用图形化安装包安装MySQL的方法. 1 ...

  7. ARM SMMU的原理与IOMMU

    首先放一个社区iommupatch的网址:https://lore.kernel.org/linux-iommu/ 1: arm smmu的原理 1.1: smmu 基本知识 如上图所示,smmu 的 ...

  8. Ex-BSGS

    给定\(a,p,b\),求\(a^x\equiv b \pmod p\)的最小自然数\(x\) . 保证\(\sum \sqrt p \leq5\times 10^6\) 当\(a=p=b=0\)时, ...

  9. 【VMware VCF】更新 VCF 5.1 至 VCF 5.2 版本。

    VMware Cloud Foundation(VCF)是一个由众多产品(vSphere.vSAN 以及 NSX 等)所构成的 SDDC 解决方案,这些环境中的不同组件的生命周期统一由 SDDC Ma ...

  10. C# .netcore NPOI库 实现报表的列自适应删减

    实际需求:业务上的一个需求,数据库表A中的B字段存放的是该条数据的一些标签,标签存在两级[即一级标签和二级标签], 现在要是实现将这些标签统计到报表中,一级标签作为表头,二级标签作为填充值. 由于之前 ...