(四)PrestoDB源码解析(二)

本文深入解析PrestoDB如何生成执行计划。用户通过JDBC或presto-cli提交SQL,经过Coordinator的StatementResource接口,SQLQueryManager进行词法和语法分析,然后在SqlQueryExecution的analyze阶段进行语义分析,获取字段信息,最后通过logicalPlanner生成并优化执行计划。
摘要由CSDN通过智能技术生成

(四)PrestoDB源码解析(二)

执行计划模块

概要

  1. PrestoDB对传入的SQL语句进行解析后将生成执行计划,本模块将解析PrestoDB如何生成执行计划。
  2. (a). 用户输入SQL语句,通过JDBC或者presto-cli客户端将SQL通过HTTP的形式传入Coordinator中的StatementResource接口的createQuery方法中,进入执行计划生成模块;
    (b).通过SQLQueryManager类的createQuery方法来实现完整的词法语法分析,通过sqlParser.createStatement方法来实现分析的,词法分析主要的作用是进行一些sql语句大小写,处理函数等词法解析,语法分析主要是形成一个该语句的所有方法的包装对象;
    ( c).通过Statement类型生成对应的工厂,在工厂中通过queryExecutionFactory.createQueryExecution方法中SqlQueryExecution类下的analyzer.analyze进行语义分析,语义分析的作用是得到该sql语句的一系列字段信息;
    (d).在createQueryExecution方法中SqlQueryExecution类下的logicalPlanner.plan(analysis)根据不同的类型进行执行计划的生成,并对执行计划进行优化和分段
  3. 整体流程在这里插入图片描述

源码

  1. 进入语法分析主入口:SqlQueryManager类(语法分析在此类中进行)
package com.facebook.presto.execution;

import com.facebook.presto.ExceededCpuLimitException;
import com.facebook.presto.Session;
.............

//语法分析入口
@ThreadSafe
public class SqlQueryManager
        implements QueryManager
{
    private static final Logger log = Logger.get(SqlQueryManager.class);

    private final QueryPreparer queryPreparer;

    private final EmbedVersion embedVersion;
    private final ExecutorService queryExecutor;
    private final ThreadPoolExecutorMBean queryExecutorMBean;
    private final ResourceGroupManager<?> resourceGroupManager;
    private final ClusterMemoryManager memoryManager;
    ...............

  1. 进入语法分析的主要方法:SqlQueryManager类的createQuery方法
   //分析词法和语法的方法
    @Override
    public ListenableFuture<?> createQuery(QueryId queryId, SessionContext sessionContext, String query)
    {
        QueryCreationFuture queryCreationFuture = new QueryCreationFuture();
        queryExecutor.submit(embedVersion.embedVersion(() -> {
            try {
                //进行词法和语法分析
                createQueryInternal(queryId, sessionContext, query, resourceGroupManager);
                queryCreationFuture.set(null);
            }
            catch (Throwable e) {
                queryCreationFuture.setException(e);
            }
        }));
        return queryCreationFuture;
    }
  1. 进入语法词法分析具体方法:createQueryInternal
private <C> void createQueryInternal(QueryId queryId, SessionContext sessionContext, String query, ResourceGroupManager<C> resourceGroupManager)
    {
        requireNonNull(queryId, "queryId is null");
        requireNonNull(sessionContext, "sessionFactory is null");
        requireNonNull(query, "query is null");
        checkArgument(!query.isEmpty(), "query must not be empty string");
        checkArgument(!queryTracker.tryGetQuery(queryId).isPresent(), "query %s already exists", queryId);

        Session session = null;
        SelectionContext<C> selectionContext = null;
        QueryExecution queryExecution;
        PreparedQuery preparedQuery;
        Optional<QueryType> queryType = Optional.empty();
        try {
            clusterSizeMonitor.verifyInitialMinimumWorkersRequirement();

            if (query.length() > maxQueryLength) {
                int queryLength = query.length();
                query = query.substring(0, maxQueryLength);
                throw new PrestoException(QUERY_TEXT_TOO_LARGE, format("Query text length (%s) exceeds the maximum length (%s)", queryLength, maxQueryLength));
            }

            // decode session
            session = sessionSupplier.createSession(queryId, sessionContext);

            WarningCollector warningCollector = warningCollectorFactory.create();

            // prepare query
            //分析词法和语法的方法
            preparedQuery = queryPreparer.prepareQuery(session, query, warningCollector);

            // select resource group
  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值