[17]-Console提交查询过程

本文详细介绍了Presto SQL查询的整个执行流程,包括客户端提交查询、查询解析、计划生成、任务分发及执行等多个阶段。通过深入剖析每个环节的工作原理和技术细节,帮助读者全面理解Presto的内部运作机制。

Console提交查询过程
Console::executeCommand()直接提交sql
Console::process(),包装Query,启动查询
QueryRunner::startQuery,启动查询

构造Query
Query query = queryRunner.startQuery(finalSql),来构建StatementClient  

StatementClient负责构造查询和获取结果与coordinator通信

构造请求
Request request = buildQueryRequest(session, query);
执行restful(/v1/statement)
JsonResponse<QueryResults> response = JsonResponse.execute(QUERY_RESULTS_CODEC, httpClient, request);
处理结果
processResponse(response.getHeaders(), response.getValue());

Query::分批拉数据
query.renderOutput(System.out, outputFormat, interactive)

第一种方式,动态刷屏分批拉数据
statusPrinter.printInitialStatusUpdates();
第二种方式,非动态拉取最终结果
waitForData();

共同点:
都是调获取结果,前面说了StatementClient负责构造查询和获取结果与coordinator通信
(/v1/statement/{queryId}/{token})
StatementClient::advance()
主要先获取分批nextUri,构造查询

以SQL查询为例看SQL执行(感谢引文博主,原文点击该链接)
下面的执行图引用自(presto 0.166概述),感谢

这里写图片描述

=====================================================================================================================================================
presto-cli:
  Presto.main():
    Console.run():
      Console.executeCommand():
        Console.process():
          QueryRunner.startQuery():
            QueryRunner.startInternalQuery():
              StatementClient.StatementClient():
                StatementClient.buildQueryRequest(): 构建 http 请求参数
                JsonResponse.execute(): 这里开始发送请求到 StatmentResource,并且会把 response 返回值转为 json,方便后续渲染
                StatementClient.processResponse(): 这里会直接尝试处理 query 响应,看看有没有返回
          Query.renderOutput(): 开始打印结果到控制台
            Query.renderQueryOutput(): 这里会根据是否是"交互"模式,来决定如何渲染输出结果. 这里只考虑以"交互"模式渲染结果.
              StatusPrinter.printInitialStatusUpdates():
                StatementClient.advance(): 这里会循环去发送 http 请求去 Coordinator 获取返回值
                  JsonResponse.execute(): 同上
=====================================================================================================================================================
presto-main: [Coordinator,Worker] 都是用这份代码
  StatementResource.createQuery(): 接收 cli 请求
    Query.create():
      Query.Query():
        SqlQueryManager.createQuery():
          QueryQueueManager.submit():
            SqlQueryExecution.start(): Async
              SqlQueryExecution.analyzeQuery(): 分析查询语句,生成查询计划
              SqlQueryExecution.planDistribution(): 分发查询计划到激活的节点
                SqlQueryScheduler.SqlQueryScheduler():
                SqlQueryScheduler.createStages(): 关键代码,创建 stage 树,并指定 StageScheduler. StageScheduler 有 4 个实现类,后续异步调用的时候,会使用 Jdk 的 BiFunction 方式来调用.
              SqlQueryScheduler.start(): 如果状态机显示查询未完成,则执行
                SqlQueryScheduler.schedule(): Async, 循环执行,直到 execution 完成.
                  stageSchedulers.get(stage.getStageId()).schedule(): 使用上述 StageScheduler 的实现类来分发 Task 到工作节点.
                    SqlStageExecution.scheduleTask(): 根据不同的 StageScheduler 实现,进入该方法的入口可能不一样,入口可能是[scheduleTask,scheduleSplits]
                      HttpRemoteTaskFactory.createRemoteTask(): 创建 http remote task
                      HttpRemoteTask.start(): 如果状态机显示查询未完成,则执行
                        HttpRemoteTask.scheduleUpdate():
                          HttpRemoteTask.sendUpdate(): Async,
                            HttpClient.executeAsync(): 发送请求到 TaskResource.createOrUpdateTask()
                              TaskResource.createOrUpdateTask(): 接收 Task 的 rest 接口
                                SqlTaskManager.updateTask():
                                  SqlTask.updateTask():
                                    SqlTaskExecutionFactory.create():
                                      SqlTaskExecution.createSqlTaskExecution():
                                        SqlTaskExecution.SqlTaskExecution(): [driverRunnerFactoriesWithSplitLifeCycle,driverRunnerFactoriesWithDriverGroupLifeCycle,driverRunnerFactoriesWithTaskLifeCycle] 比较重要
                                          TaskExecutor.addTask():
                                            List<TaskHandle>.add(): 填加 taskHandle 之后,不考虑返回值,sql 执行在 presto 能就告一段落了,会异步到 TaskExecutor 执行.
  TaskExecutor.start(): 该方法含有 @PostConstruct ,所以在 presto 启动时就会执行
    TaskExecutor.addRunnerThread():
      ExecutorService.execute():
        TaskRunner.run(): Asyc
          PrioritizedSplitRunner.take(): 该方法会阻塞,直到有值返回
          PrioritizedSplitRunner.process():
            DriverSplitRunner.processFor():
              Driver.processFor():
                Driver.processInternal():
                  Driver.processNewSources(): 更新 TaskResource
                  Opertator.getOutput(): 会根据不同的 sql 操作,得到不同的 Operator 实现类.然后根据实现,调用对应的 connector . 该方法返回的是一个 Page, Page 相当于一张 RDBMS 的表,只不过 Page 是列存储的. 获取 page 的时候,会根据 [Block 类型,文件格式]等,使用相应的 Loader 来 load 取数据.
                  Operator.addInput():  下一个 Operator 如果需要上一个 Operator 的输出,则会调用该方法
  StatementResource.asyncQueryResults(): 异步返回查询结果给 cli
    Query.waitForResults():
      Futures.transform(): 提供一个 function 和 executor 给 guava
        BoundedExecutor.execute(): 这个方法会由 guava 异步回调
          coreExecutor.execute(this::drainQueue): 这里会使用 JDK 的 Executor 来调度异步任务
            BoundedExecutor.drainQueue():
              queue.poll().run(): 这里执行的时候,意味着会执行 Futures.transform() 的 function 参数
                Query.getNextResult():
                  Query.getCachedResult(): 首先会尝试从缓存里去获取返回值
                    ExchangeClient.pollPage(): 从 ExchangeClient 中获取结果页
                      QueryResults.QueryResults(): 根据结果页生成 QueryResults 返回给 cli
=====================================================================================================================================================

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值