Presto CLI学习

1. 序言

  • 作为Presto的客户端之一,Presto CLI是一个基于终端的交互式shell,对应presto源码中的presto-cli模块

  • Presto CLI的本质是一个self-executing jar —— presto-cli-version-executable.jar,就像一个普通的UNIX可执行文件

  • 因此,可以像下面这样使用presto cli

    ./presto --server localhost:8080 --user adhoc_user --catalog hive
    
  • Presto CLI依赖Presto client向Presto server提交查询,获取查询执行进度、执行结果等。

  • Presto使用Master-Slave架构,对外提供服务的接口都在coordinator中,上面的描述可以改写为:Pressto client向coordinator提交查询

  • 笔者认为,在学习Presto CLI前,了解Presto client与coordinator之间如何进行HTTP通信是极有必要的

  • 官网有Presto Client的相关文档:Presto Client REST API,本文对Presto client的介绍也会参考该文档,并辅以Presto 0.279的源码

1.1 StatementClientV1.advance()方法,获取下一批查询结果(简称response)

  • 成功创建StatementClientV1后,上层调用者将根据StatementClientV1的状态,决定是否发起更多的请求以获取查询结果
  • 注意: 查询结果是广义的,它包括查询执行进度执行结果

response为查询执行进度

  • response中的QueryResults.data为null,只有查询的状态信息(QueryResults.stats)
    client.currentData().getData() != null
    
  • 此时,上层调用会打印执行进度,并继续调用StatementClientV1.advance()方法获取下一批查询结果
  • 例如,非交互式查询下的presto.cli.Query.processInitialStatusUpdates()方法,则负责获取并打印执行进度
    private void processInitialStatusUpdates(WarningsPrinter warningsPrinter)
    {
        while (client.isRunning() && (client.currentData().getData() == null)) {
            warningsPrinter.print(client.currentStatusInfo().getWarnings(), true, false);
            client.advance();
        }
        ... // 其他代码省略
    }
    

response为查询执行结果

  • response中的QueryResults.data不为null,这时可以进入执行结果打印阶段

  • presto.cli.Query.renderResults()方法负责查询结果的打印,该方法最终将调用OutputHandler.processRows()方法构建并打印行数据

  • 由于QueryResults.data中可能只是部分执行结果,可能还需要多次调用advance()方法获取剩余的执行结果

    public void processRows(StatementClient client)
            throws IOException
    {
        while (client.isRunning()) {
            Iterable<List<Object>> data = client.currentData().getData();
            if (data != null) {
                for (List<Object> row : data) {
                    processRow(unmodifiableList(row)); // 超过MAX_BUFFERED_ROWS(10_000)则刷新输出
                }
            }
    
            // 超过MAX_BUFFER_TIME,也会刷新输出
            if (nanosSince(bufferStart).compareTo(MAX_BUFFER_TIME) >= 0) {
                flush(false);
            }
    
            // 访问nextUri,获取新的执行结果
            client.advance();
        }
    }
    

1.2 关于nextUri

  • new StatementClientV1()时,以POST方式向/v1/statement接口发送查询请求,这时只是提交一个查询
  • 因为查询具有lazy execution特征,需要以GET方式、多次访问response中的nextUri,才能触发查询的执行、获取查询执行进度以及查询结果
  • advance()方法就是访问nextUri的关键方法,每次访问nexrUri都将返回一个response;若response中的nexrUri为null,说明查询结束
  • nextUri不停变化,意味着查询处于不同的阶段,如/v1/statement/queued//v1/statement/executing/
  • 具体的nextUri的变化,可以参考之前的博客《结合Presto CLI,Presto Client学习》的4.3小节

2. 取消正在运行的查询

Presto CLI学习_第1张图片 # 3. 非交互式查询的执行流程 Presto CLI学习_第2张图片 # 4. 交互式查询的执行流程 Presto CLI学习_第3张图片 # 5. 单个查询的执行流程 Presto CLI学习_第4张图片

你可能感兴趣的:(presto)