# 简介

Impala 是一个分布式,大规模并行处理数据库引擎。

  • 支持 SQL 实时查询
  • 由 Java 和 C++ 实现
  • 共享 Hive Metastore
  • 支持多种数据存储格式,如 Text、Parquet、Avro 等
  • 支持多种数据存储引擎,如 HDFS、KUDU、S3 等
  • 能够与 Hadoop 集成
  • ...

# Impala 架构

Impala 架构

  • impalad,部署在集群中的各个节点中,负责接受来自客户端进程的查询,并协调其在整个集群中的执行,以及执行其他 impalad 分配的单个查询片段。
    • Query Planner,负责解析客户端的 SQL 生成一个执行计划树 。
    • Query Coordinator,负责给其他 impalad 节点分发执行任务。
    • Query Exec Engine,负责执行被分配的查询片段。
  • statestored,部署在集群中的单个节点中,是 impala 的元数据发布订阅服务,负责将集群范围的元数据传播到所有 Impalad,同时收集集群中 impalad 的健康状况。
  • catalogd,部署在集群中的单个节点中,充当 Impala 的目录存储库和元数据访问网关。
  • cli,包括 Impala-shell、Hue 界面和 ODBC / JDBC 驱动程序。

# SQL 执行流程

  1. Client 向集群中的一个 impalad 发送 SQL 语句;
  2. Query Planner 解析这个 SQL 语句生成执行计划树;
  3. Query Coordinator 根据执行计划树向所有的 impalad 发送执行任务;
  4. Query Executor 执行被分配的查询片段;
  5. 查询结果返回给 Query Coordinator;
  6. 最后由 Query Coordinator 将结果汇总给 Client。

# 源码流程

# 生成并发送查询计划

——ImpalaServer::ExecuteStatement impala-hs2-server.cc
  ——ImpalaServer::Execute impala-server.cc
    ——ImpalaServer::ExecuteInternal impala-server.cc
      ——QueryDriver::RunFrontendPlanner query-driver.cc
        ——Frontend::GetExecRequest frontend.cc
          ——JniUtil::CallJniMethod jni-util.h
            ——JniFrontend::createExecRequest JniFrontend.java
              ——Frontend::createExecRequest Frontend.java
                ——Frontend::getTExecRequest Frontend.java
                  ——Frontend::doCreateExecRequest Frontend.java
                    ——Parser::parse Parser.java
                    ——AnalysisContext::analyzeAndAuthorize AnalysisContext.java
                    ——AnalysisContext::getPlannedExecRequest AnalysisContext.java
                      ——Frontend::createExecRequest Frontend.java
                        ——Planner::createPlans Planner.java
                          ——SingleNodePlanner::createSingleNodePlan SingleNodePlanner.java
                          ——DistributedPlanner::createPlanFragments DistributedPlanner.java
                        ——Planner::computeResourceReqs Planner.java
      ——ClientRequestState::Exec client-request-state.cc
        ——ClientRequestState::ExecAsyncQueryOrDmlRequest client-request-state.cc
          ——ClientRequestState::FinishExecQueryOrDmlRequest client-request-state.cc
            ——RemoteAdmissionControlClient::SubmitForAdmission remote-admission-control-client.cc
            ——Coordinator::Exec coordinator.cc
              ——Coordinator::StartBackendExec coordinator.cc
                ——Coordinator::BackendState::ExecAsync coordinator-backend-state.cc
                  ——ControlServiceProxy::ExecQueryFInstancesAsync control_service.proto

# 执行查询计划

——ControlService::ExecQueryFInstances control-service.cc
  ——QueryExecMgr::StartQuery query-exec-mgr.cc
    ——QueryExecMgr::ExecuteQueryHelper query-exec-mgr.cc
      ——QueryState::StartFInstances query-state.cc
        ——QueryState::ExecFInstance query-state.cc
          ——FragmentInstanceState::Exec fragment-instance-state.cc
            ——FragmentInstanceState::Prepare fragment-instance-state.cc
              ——ExecNode::CreateTree exec-node.cc
              ——ExecNode::Prepare() exec-node.cc
            ——FragmentInstanceState::Open fragment-instance-state.cc
              ——ExecNode::Open() exec-node.cc
            ——FragmentInstanceState::ExecInternal fragment-instance-state.cc
              ——ExecNode::GetNext() exec-node.cc
            ——FragmentInstanceState::Close fragment-instance-state.cc
              ——ExecNode::Close() exec-node.cc

# 查询计划

查询计划分为两阶段:

  • 单机查询计划
  • 分布式查询计划,尽量降级数据移动

# 例子

# sql

select
  *
from
  test_1
  join test_2 on test_1.id = test_2.id
order by
  test_1.name_1

# 查询计划

# 查询优化

# 多表连接查询

连接方式有两种:

  • broadcast,右表比左表小,右表会被发送到所有节点上
  • partitioned,左右表大小差不多,两表都会有一部分数据被发送到其他节点上
    连接方式的选择依赖于 compute stats 搜集的表的统计信息,straight_join 可以手动指定连接方式。

# 表统计信息

# compute stats

自动对表、分区及列进行信息统计。

# show table stats

表统计信息。

# show column stats

列统计信息。

# explain

输出查询执行的逻辑步骤。

# profile

输出最近执行的查询的详细信息。

# 代码结构

最主要关注 fe 和 be 部分。

# fe

├── cup 语法解析
├── java
│ └── org
│ └── apache
│ └── impala
│ ├── analysis,语义分析,例如检查表是否存在,列是否存在
│ ├── authentication,认证鉴权相关
│ ├── authorization,授权相关,例如 ranger、column、masking
│ ├── catalog,包含元数据操作的主类和各种数据库、表、分区的元数据实例类
│ ├── common,一些通用类,如 exception 相关
│ ├── compat
│ ├── extdatasource
│ ├── hive
│ ├── hooks
│ ├── planner,PlanNode、执行计划相关代码
│ ├── rewrite,表达式级别的改写优化,主要包括常量折叠、通用表达式提取、Between and 改下等
│ ├── service
│ └── util,一些工具类
└── jflex 词法解析

# be

├── benchmarks
├── catalog,元数据服务相关代码,与 statestore 交互,实现了 Thrift service
├── codegen,LLVM IR generation
├── common
├── exec,PlanNode 实现
├── experiments
├── exprs,Math、Date、String、Agg 等函数实现
├── gutil,google gutil 相关
├── kudu,引用的 kudu 的相关代码,例如 krpc
├── rpc,Rpc 协议相关代码
├── runtime,Coordinator 及查询运行时相关代码
├── scheduling,Admission control、调度相关
├── service,BE 对外服务接口相关代码,主函数 daemon-main 位于这个目录下
├── statestore,Statestore 相关
├── testutil
├── thirdparty,第三方依赖库
├── transport
├── udf,用户自定义函数相关代码
├── udf_samples
└── util,工具类相关

# 相关资料

  • official website: https://impala.apache.org/
  • repo: https://github.com/apache/impala
  • wiki: https://cwiki.apache.org/confluence/display/IMPALA/Impala+Home
  • doc: https://impala.apache.org/docs/build/html/topics/impala_intro.html
  • cloudera doc: https://docs.cloudera.com/documentation/enterprise/6/6.3/topics/impala.html