Impala源代码分析(3)-backend查询执行过程
这篇文章主要介绍impala-backend是怎么执行一个SQL Query的。 在Impala中SQL Query的入口函数是: void ImpalaServer::query(QueryHandle query_handle, const Query query) 生成一个QueryExecState伴随这个SQL执行的生命周期,代表正在执行的这个SQL; 调用E
这篇文章主要介绍impala-backend是怎么执行一个SQL Query的。
在Impala中SQL Query的入口函数是:
void ImpalaServer::query(QueryHandle& query_handle, const Query& query)
- 生成一个QueryExecState伴随这个SQL执行的生命周期,代表正在执行的这个SQL;
- 调用Execute函数启动执行流程;
- 启动一个Wait线程等待结果。
这个Execute()函数首先是通过JNI向impala-fe请求SQL解析和执行计划生成(已经在上一篇文章中讲了这个过程),得到该Query对应的TExecRequest对象,交由impala-backend执行。
从下面这个函数开始backend执行,同时开始fragment status report。
Status ImpalaServer::QueryExecState::Exec(TExecRequest* exec_request)
因为我们知道在impala里面,一个Query是分配到多个节点执行的,我们把其中负责分配和协调这个Query执行的组件叫Coordinator;参与这个Query执行的每个节点叫backend instance,每个backend instance上面会执行一个或者多个PlanFragment。那么每个Query就对应一个Coordinator对象和多个backend instance,同时Coordinator中的query_profile_ 变量是用来统计这个query的执行的整个profile的。
Coordinator
这里首先生成Coordinator用于协调这个Query的执行,然后调用
Status?Coordinator::Exec(
const TUniqueId& query_id, TQueryExecRequest* request,
const TQueryOptions& query_options)
启动异步的执行过程:说白了这个Coordinator就是老板,把活(PlanFragment)都给各个下属(backend instance)安排好了,发出去,然后自己下班走人了,才不会等着下属干完了才走呢。因为老板早就安排好自己的秘书(ImpalaServer::Wait())去盯着结果呢。
这个函数里面最重要的两个步骤:
- ComputeScanRangeAssignment(*request);
- ComputeFragmentExecParams(*request);
其中ComputeScanRangeAssignment(const TQueryExecRequest& exec_request)?用于填充std::vector
typedef boost::unordered_map
另外一个函数ComputeFragmentExecParams?(const TQueryExecRequest& exec_request)?用于填充std::vector
- Status Coordinator::ComputeFragmentHosts(const TQueryExecRequest& exec_request):为每个PlanFragment找到执行所在的backend instance。如果一个PlanFragment是UNPARTITIONED,那么就在这个Coordinator所在的host上运行;如果一个PlanFragment含有ScanNode,那么就调度这个PlanFragment到HDFS/HBase数据块所在的那些DataNodes上,也就是这些DataNodes就成为了执行这个Query的backend instance。
- 计算TQueryExecRequest.fragments中每个PlanFragment会在哪些hosts上得到执行,填充到fragment_exec_params_ 中。
- 依次给每个PlanFragment执行的每个host分配一个instance_id。
- 填充每个?FragmentExecParams?的destinations(即Data Sink的目的地PlanFragment)和per_exch_num_senders(这个ExchangeNode会接收来自多少个PlanFragment的数据)
回到Coordinator::Exec()函数中,下面就该把各个PlanFragment分配干活了。
- 如果有Coordinator PlanFragment,那么先new PlanFragmentExecutor()生成这个PlanFragment所对应的PlanFragmentExecutor。然后填充其对应的TExecPlanFragmentParams。
- 下面是个双层循环:外层遍历PlanFragment,内层遍历backend instance,生成与每个instance关联的BackendExecState(主要是生成TExecPlanFragmentParams用于Coordinator与多个backend instance交互时的参数),并加入backend_exec_states_列表,用于Coordinator对所有的backend instance执行状况的管理。然后向每个instance发起RPC请求开始执行,请求协议是ImpalaInternalService:: ExecPlanFragment(TExecPlanFragmentParams)
Status fragments_exec_status = ParallelExecutor::Exec(
bind
reinterpret_cast
num_hosts);
每个Coordinator,PlanFragmentExecutor和ExecNode都会有一个RuntimeProfile,所有的RuntimeProfile会构成树状结构来记录每个执行节点的执行过程中的信息。
在Coordinator有个成员变量boost::scoped_ptr
每个Coordinator还有个aggregate_profile_专门负责aggregate相关的profile。
PlanFragmentExecutor和ExecNode
无论是在Coordinator端还是在backend instance端执行的PlanFragment都是由一个PlanFragmentExecutor控制的。下面我们看看PlanFragment在backend instance是怎么执行的?
在RPC的server端调用了ImpalaServer::ExecPlanFragment()->ImpalaServer::StartPlanFragmentExecution()
生成FragmentExecState里面含有一个PlanFragmentExecutor。那么下面就是分析PlanFragmentExecutor怎么控制Query的执行的了。
- FragmentExecState::Prepare()调用PlanFragmentExecutor::Prepare()
- FragmentExecState::Exec()调用PlanFragmentExecutor::Open(),这个是PlanFragment执行的主循环,block直到该PlanFragment执行结束。
真正控制PlanFragment执行的是PlanFragmentExecutor,主要由Prepare()/Open()/GetNext()/Close()这几个函数组成。
1,? PlanFragmentExecutor::Prepare(TExecPlanFragmentParams):准备执行,主要流程如下:
- 设定这个query能够使用的内存mem_limit;
- DescriptorTbl::Create():初始化descriptor table;
- ExecNode::CreateTree():生成执行树的结构(父子关系)。执行树由ExecNode组成,每一个ExecNode也提供了Prepare(), Open(), GetNext()函数。后面执行ExecNode::Prepare/Open/GenNext /EvalConjuncts/Close函数都是按照这个树状结构递归下去的。初始化完成后,PlanFragmentExecutor ::plan_指向了执行树的根节点。在这棵树中,root节点被最后执行,叶子节点被最先执行;
- 设置该PlanFragment的Exchange Node会接收来自多少个sender的数据;
- 调用plan_->Prepare():从根节点开始递归初始化执行树,主要是初始化runtime_profile等统计信息和conjuncts的LLVM本地代码生成 (adding functions to the LlvmCodeGen object);
- 如果使用本地代码生成,调用runtime_state_->llvm_codegen()->OptimizedModule()进行优化;
- 把所有的ScanNode对应的Scan Range映射到file/offset/length;
- DataSink::CreateDataSink();
- set up profile counter;
- 生成RowBatch用于存储结果。
2,PlanFragmentExecutor::Open()
先是start the profile-reporting thread,然后调用OpenInternal()
(1)???? 调用plan_->Open()沿着生成的ExecNode执行树依次调用ExecNode:: Open()
下面以HdfsScanNode::Open()为例说明:
- 调用DiskIoMgr:: RegisterReader初始化与HDFS的连接hdfs_connection_;
- 把要读取的File 和Split加入HdfsScanNode的队列queued_ranges_中;
- 调用HdfsScanNode::DiskThread驱动HdfsScanNode::StartNewScannerThread()->HdfsScanNode::ScannerThread->HdfsScanner:: ProcessSplit()去读取数据(目前一个scanner thread只能读取一个scan range);
- 调用IssueQueuedRanges()把上面加入queued_ranges_中的预读取Range发送给DiskIoMgr。由于上一步中已经启动了disk thread,所以就可以读取数据了。
(2)???? 如果当前这个PlanFragmen有sink,那么需要把这个PlanFragment要发给其他PF的数据都发出去。在发出去之前肯定得获取要发的东西吧,调用PlanFragmentExecutor ::GetNextInternal()从上到下递归调用执行树的ExecNode::GetNext()获取执行结果。
上面说到对于ExecNode::Open()不同种类的ExecNode的逻辑是不一样的,对于GetNext()也是一样的,可以参考下HdfsScanNode::GetNext()或者HashJoinNode::GetNext()看看具体是怎么获取查询结果的。
3,? PlanFragmentExecutor::GextNext(RowBatch** batch)
显示触发执行树的ExecNode::GetNext()函数获取查询结果。当其标记PlanFragmentExecutor::done_==true时,则表明所有数据已经被处理完,该PlanFragmentExecutor可以退出了。
至此,impala-backend也分析完了。总的来说impala在执行过程中和MapReduce及Hive的不同可以概括为一拉一推。
- 在MapReduce中,Map的输出结果要等着Reduce去拉;而impala中各个PlanFragment执行结束之后DataSink是推送到其他PlanFragment的。这样能更加有效利用带宽,加快Job执行速度。
- 在Hive中,逻辑上下游节点是由上游节点推送给下游节点的;而impala中是下游节点通过递归调用GetNext()向上游节点拉取的。
原文地址:Impala源代码分析(3)-backend查询执行过程, 感谢原作者分享。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Linux에서 컬 버전을 업데이트하려면 다음 단계를 따르세요. 현재 컬 버전을 확인하세요. 먼저 현재 시스템에 설치된 컬 버전을 확인해야 합니다. 터미널을 열고 다음 명령을 실행합니다. 컬 --version 이 명령은 현재 컬 버전 정보를 표시합니다. 사용 가능한 컬 버전 확인: 컬을 업데이트하기 전에 사용 가능한 최신 버전을 확인해야 합니다. 최신 버전의 컬을 찾으려면 컬의 공식 웹사이트(curl.haxx.se)나 관련 소프트웨어 소스를 방문하세요. 컬 소스 코드 다운로드: 컬 또는 브라우저를 사용하여 선택한 컬 버전의 소스 코드 파일(일반적으로 .tar.gz 또는 .tar.bz2)을 다운로드합니다.

12306 티켓 예매 앱의 최신 버전을 다운로드하세요. 모두가 매우 만족하는 여행 티켓 구매 소프트웨어입니다. 소프트웨어에서 제공되는 다양한 티켓 소스가 있어 매우 편리합니다. - 실명인증으로 온라인 구매가 가능합니다. 모든 사용자가 쉽게 여행티켓과 항공권을 구매하고 다양한 할인 혜택을 누릴 수 있습니다. 또한 사전에 예약하고 티켓을 얻을 수도 있습니다. 호텔을 예약하거나 차량으로 픽업 및 하차할 수도 있습니다. 한 번의 클릭으로 원하는 곳으로 이동하고 티켓을 구매할 수 있어 여행이 더욱 간편해지고 편리해집니다. 모든 사람의 여행 경험이 더욱 편안해졌습니다. 이제 편집자가 온라인으로 자세히 설명합니다. 12306명의 사용자에게 과거 티켓 구매 기록을 볼 수 있는 방법을 제공합니다. 1. 철도 12306을 열고 오른쪽 하단의 My를 클릭한 후 My Order를 클릭합니다. 2. 주문 페이지에서 Paid를 클릭합니다. 3. 유료페이지에서

Xuexin.com에서 내 학업 자격을 어떻게 확인하나요? Xuexin.com에서 학업 자격을 확인할 수 있습니다. 많은 사용자가 Xuexin.com에서 학업 자격을 확인하는 방법을 모릅니다. 다음으로 편집자는 Xuexin.com에서 학업 자격을 확인하는 방법에 대한 그래픽 튜토리얼을 제공합니다. 유저들이 와서 구경해 보세요! Xuexin.com 사용 튜토리얼: Xuexin.com에서 학업 자격을 확인하는 방법 1. Xuexin.com 입구: https://www.chsi.com.cn/ 2. 웹사이트 쿼리: 1단계: Xuexin.com 주소를 클릭합니다. 위의 홈페이지에 들어가려면 [교육 쿼리]를 클릭합니다. 2단계: 최신 웹페이지에서 아래 그림의 화살표와 같이 [쿼리]를 클릭합니다. 3단계: 새 페이지에서 [학점 파일에 로그인]을 클릭합니다. 4단계: 로그인 페이지에서 정보를 입력하고 [로그인]을 클릭합니다.

MySQL과 PL/SQL은 각각 관계형 데이터베이스와 절차적 언어의 특성을 나타내는 서로 다른 두 가지 데이터베이스 관리 시스템입니다. 이 기사에서는 구체적인 코드 예제를 통해 MySQL과 PL/SQL 간의 유사점과 차이점을 비교합니다. MySQL은 SQL(구조적 쿼리 언어)을 사용하여 데이터베이스를 관리하고 운영하는 인기 있는 관계형 데이터베이스 관리 시스템입니다. PL/SQL은 Oracle 데이터베이스 고유의 절차적 언어로 저장 프로시저, 트리거, 함수 등의 데이터베이스 개체를 작성하는 데 사용됩니다. 같은

애플 휴대폰을 이용하여 개통일을 확인하고 싶다면 휴대폰에 있는 일련번호를 통해 확인하는 것이 가장 좋은 방법이며, 애플 공식 홈페이지를 방문하여 컴퓨터에 연결한 후 세 번째 다운로드를 통해 확인할 수도 있습니다. - 그것을 확인하는 파티 소프트웨어. Apple 휴대폰의 활성화 날짜를 확인하는 방법은 무엇입니까? 답변: 일련번호 쿼리, Apple 공식 웹사이트 쿼리, 컴퓨터 쿼리, 타사 소프트웨어 쿼리 1. 사용자가 휴대폰의 일련번호를 아는 것이 가장 좋습니다. 설정, 일반, 이 기기 정보를 열어 일련번호를 확인할 수 있습니다. 2. 일련번호를 이용하면 휴대폰 개통일뿐만 아니라 휴대폰 버전, 휴대폰 원산지, 휴대폰 공장일 등을 확인할 수 있습니다. 3. 사용자는 Apple의 공식 웹 사이트를 방문하여 기술 지원을 찾고, 페이지 하단의 서비스 및 수리 열을 찾아 거기에서 iPhone 활성화 정보를 확인합니다. 4. 사용자

제목: DreamWeaver CMS의 보조 디렉터리를 열 수 없는 이유와 해결 방법 분석 Dreamweaver CMS(DedeCMS)는 다양한 웹 사이트 구축에 널리 사용되는 강력한 오픈 소스 콘텐츠 관리 시스템입니다. 그러나 때로는 웹사이트를 구축하는 과정에서 보조 디렉토리를 열 수 없는 상황이 발생할 수 있으며, 이로 인해 웹사이트의 정상적인 작동에 문제가 발생할 수 있습니다. 이 기사에서는 보조 디렉터리를 열 수 없는 가능한 이유를 분석하고 이 문제를 해결하기 위한 구체적인 코드 예제를 제공합니다. 1. 예상 원인 분석: 의사 정적 규칙 구성 문제: 사용 중

Linux 커널은 소스 코드가 전용 코드 저장소에 저장되어 있는 오픈 소스 운영 체제 커널입니다. 이번 글에서는 리눅스 커널 소스코드의 저장 경로를 자세히 분석하고, 독자들의 이해를 돕기 위해 구체적인 코드 예시를 활용하겠습니다. 1. Linux 커널 소스 코드 저장 경로 Linux 커널 소스 코드는 linux라는 Git 저장소에 저장되어 있으며, 이 저장소는 [https://github.com/torvalds/linux](http://github.com/torvalds/linux)에서 호스팅됩니다.

포럼은 인터넷에서 가장 일반적인 웹사이트 형태 중 하나입니다. 포럼은 사용자에게 정보를 공유하고 토론을 교환할 수 있는 플랫폼을 제공합니다. Discuz는 일반적으로 사용되는 포럼 프로그램이며 많은 웹마스터들이 이미 이에 대해 매우 잘 알고 있다고 생각합니다. Discuz 포럼을 개발하고 관리하는 동안 분석이나 처리를 위해 데이터베이스의 데이터를 쿼리해야 하는 경우가 종종 있습니다. 이 글에서는 Discuz 데이터베이스의 위치를 쿼리하기 위한 몇 가지 팁을 공유하고 구체적인 코드 예제를 제공합니다. 먼저 Discuz의 데이터베이스 구조를 이해해야 합니다.
