Starrocks中的 Query Profile以及explain analyze及trace命令中的区别

背景

本文基于Starrocks 3.5.5
现有公司因为业务的不同,可能会更加关系单个SQL 的RT,因为如果一个SQL的RT比较大的话,影响的就是这个业务,从而影响收入,所以对于这方面我们就比较关心,
而最近在基于Starrocks做计算存储引擎的时候,遇到了一些问题。时间上超过了2秒,因此需要分析一下对应SQL的指标。
最直接的就是开启 Query Profile,比如说做一下配置:

SET enable_profile = true;
SET global big_query_profile_threshold = '1s';
SET runtime_profile_report_interval = 30;

这个在对应的UI界面(http://<fe_ip>:<fe_http_port>)就能看到Profile
当然还有ANALYZE PROFILE,explain analyzetrace命令,这里就来分析一下三者的差别, 其中以以下SQL为例:

SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA` WHERE SCHEMA_NAME = 'fin_config';

结论

  1. 开启Query Profile会得得到更多的明细信息,以及每个阶段所用的耗时,适合对该SQL的每个算子的各个指标全方位的分析
    此种方法会有BE端的信息更新过来,但是这个信息只存在内存,FE重启之后就不复存在。
  2. EXPLAIN ANALYZE 展示的是大概的查询执行计划执行信息,比如说 Summary和fragement
  3. ANALYZE PROFILE 展示的和explain analyze一样,但是指标比 explain analyze 更加丰富
  4. trace 展示的是某个局部指标,比如说 某个规则的耗时

对于每个方法所对应指标信息如下见下面的 其他

分析

开启Query Profile

通过访问http://<fe_ip>:<fe_http_port>/query_profile?query_id可以获取到对应的profile,
对应到Fe端是QueryProfileAction类接受请求:
QueryProfileAction 里有对应的 “/query_profile” Get请求

对应的Get方法response为executeGet方法:

String queryProfileStr = ProfileManager.getInstance().getProfile(queryId);
        if (queryProfileStr != null) {
            appendCopyButton(response.getContent());
            appendQueryProfile(response.getContent(), queryProfileStr);
            getPageFooter(response.getContent());
            writeResponse(request, response);

这里ProfileManager.getInstance().getProfile(queryId)会获取对应的 Profile.

runtimeProfile数据流

FrontendServiceImpl.reportExecStatus
    ||
    \/
DefaultCoordinator.updateFragmentExecStatus(params)
    ||
    \/
QueryRuntimeProfile.updateProfile(execState, params) // 这里会 runtime_profile_report_interval 判断
    ||
    \/
saveRunningProfile
    ||
    \/
ProfileManager.pushProfile(profilingPlan, profile);

这里会把 BE端 Fragment 实力的 运行指标都给返回给 FE端.

EXPLAIN ANALYZE

具体语法参考Simulate a query for Profile Analysis Using EXPLAIN ANALYZE
直接转到StarRocks.g4

queryStatement
    : (explainDesc | optimizerTrace) ? queryRelation outfile?;
...
explainDesc
    : (DESC | DESCRIBE | EXPLAIN) (LOGICAL | ANALYZE | VERBOSE | COSTS | SCHEDULER)?
    ;
...
optimizerTrace
    : TRACE (ALL | LOGS | TIMES | VALUES | REASON) identifier?
    ;

通过AstBuilder.visitQueryStatement 解析完后:

@Override
public ParseNode visitQueryStatement(StarRocksParser.QueryStatementContext context) {
    QueryRelation queryRelation = (QueryRelation) visit(context.queryRelation());
    QueryStatement queryStatement = new QueryStatement(queryRelation);
    if (context.outfile() != null) {
        queryStatement.setOutFileClause((OutFileClause) visit(context.outfile()));
    }

    if (context.explainDesc() != null) {
        queryStatement.setIsExplain(true, getExplainType(context.explainDesc()));
    }

    if (context.optimizerTrace() != null) {
        String module = "base";
        if (context.optimizerTrace().identifier() != null) {
            module = ((Identifier) visit(context.optimizerTrace().identifier())).getValue();
        }
        queryStatement.setIsTrace(getTraceMode(context.optimizerTrace()), module);
    }

    return queryStatement;
}

可以看到queryStatement.setIsExplain(true, getExplainType(context.explainDesc()))这个方法:

  public void setIsExplain(boolean isExplain, ExplainLevel explainLevel) {
        this.isExplain = isExplain;
        this.explainLevel = explainLevel;
    }

会把isExplain设置为true,
之后数据流会转到StmtExecutor.execute方法,最终会调用handleQueryStmt方法:

private void handleQueryStmt(ExecPlan execPlan) throws Exception {
        // Every time set no send flag and clean all data in buffer
        context.getMysqlChannel().reset();

        boolean isExplainAnalyze = parsedStmt.isExplain()
                && StatementBase.ExplainLevel.ANALYZE.equals(parsedStmt.getExplainLevel());
        boolean isSchedulerExplain = parsedStmt.isExplain()
                && StatementBase.ExplainLevel.SCHEDULER.equals(parsedStmt.getExplainLevel());
        boolean isOutfileQuery = (parsedStmt instanceof QueryStatement) && ((QueryStatement) parsedStmt).hasOutFileClause();
        if (isOutfileQuery) {
            Map<TableName, Table> tables = AnalyzerUtils.collectAllTable(parsedStmt);
            boolean hasTemporaryTable = tables.values().stream().anyMatch(t -> t.isTemporaryTable());
            if (hasTemporaryTable) {
                throw new SemanticException("temporary table doesn't support select outfile statement");
            }
        }
        boolean executeInFe = !isExplainAnalyze && !isSchedulerExplain && !isOutfileQuery
                && canExecuteInFe(context, execPlan.getPhysicalPlan());

        if (isExplainAnalyze) {
            context.getSessionVariable().setEnableProfile(true);
            context.getSessionVariable().setEnableAsyncProfile(false);
            context.getSessionVariable().setPipelineProfileLevel(1);
        } else if (isSchedulerExplain) {
            // Do nothing.
        } else if (parsedStmt.isExplain()) {
            String explainString = buildExplainString(execPlan, ResourceGroupClassifier.QueryType.SELECT,
                    parsedStmt.getExplainLevel());
            if (executeInFe) {
                explainString = "EXECUTE IN FE\n" + explainString;
            }
            handleExplainStmt(explainString);
            return;
        }
        ... 

        StatementBase queryStmt = parsedStmt;
        List<PlanFragment> fragments = execPlan.getFragments();
        List<ScanNode> scanNodes = execPlan.getScanNodes();
        TDescriptorTable descTable = execPlan.getDescTbl().toThrift();
        List<String> colNames = execPlan.getColNames();
        List<Expr> outputExprs = execPlan.getOutputExprs();

        if (executeInFe) {
            coord = new FeExecuteCoordinator(context, execPlan);
        } else {
            coord = getCoordinatorFactory().createQueryScheduler(context, fragments, scanNodes, descTable);
        }

        QeProcessorImpl.INSTANCE.registerQuery(context.getExecutionId(),
                new QeProcessorImpl.QueryInfo(context, originStmt.originStmt, coord));

        if (isSchedulerExplain) {
            coord.startSchedulingWithoutDeploy();
            handleExplainStmt(coord.getSchedulerExplain());
            return;
        }

        coord.exec();
        coord.setTopProfileSupplier(this::buildTopLevelProfile);
        coord.setExecPlan(execPlan);

对于 explain analyze 会进行如下配置:

 context.getSessionVariable().setEnableProfile(true);
 context.getSessionVariable().setEnableAsyncProfile(false);
 context.getSessionVariable().setPipelineProfileLevel(1);

且会走到 coord.exec();这里会有调度的部分,如以下:

 try (Timer timer = Tracers.watchScope(Tracers.Module.SCHEDULER, "Prepare")) {
            prepareExec();
        }

 try (Timer timer = Tracers.watchScope(Tracers.Module.SCHEDULER, "Deploy")) {
     deliverExecFragments(needDeploy);
 }

而在handleQueryStmt下后有finally的处理:

 else if (context.isProfileEnabled()) {
    isAsync = tryProcessProfileAsync(execPlan, i);
    if (parsedStmt.isExplain() &&
            StatementBase.ExplainLevel.ANALYZE.equals(parsedStmt.getExplainLevel())) {
        if (coord != null && coord.isShortCircuit()) {
            throw new UserException(
                    "short circuit point query doesn't suppot explain analyze stmt, " +
                            "you can set it off by using  set enable_short_circuit=false");
        }
        handleExplainStmt(ExplainAnalyzer.analyze(
                ProfilingExecPlan.buildFrom(execPlan), profile, null));
    }
 }

ExplainAnalyzer.analyze这里就是返回的Explain String

ANALYZE PROFILE

直接跳转到Starrocks.g4:

analyzeProfileStatement
    : ANALYZE PROFILE FROM string
    | ANALYZE PROFILE FROM string ',' INTEGER_VALUE (',' INTEGER_VALUE)*
    ;

之后到AstBuilder的如下方法:

@Override
public ParseNode visitAnalyzeProfileStatement(StarRocksParser.AnalyzeProfileStatementContext context) {
    StringLiteral stringLiteral = (StringLiteral) visit(context.string());
    List<Integer> planNodeIds = Lists.newArrayList();
    if (context.INTEGER_VALUE() != null) {
        planNodeIds = context.INTEGER_VALUE().stream()
                .map(ParseTree::getText)
                .map(Integer::parseInt)
                .collect(toList());
    }
    return new AnalyzeProfileStmt(stringLiteral.getStringValue(), planNodeIds, createPos(context));
}

之后再到StmtExecutor.handleAnalyzeProfileStmt方法:

private void handleAnalyzeProfileStmt() throws IOException, UserException {
        AnalyzeProfileStmt analyzeProfileStmt = (AnalyzeProfileStmt) parsedStmt;
        String queryId = analyzeProfileStmt.getQueryId();
        List<Integer> planNodeIds = analyzeProfileStmt.getPlanNodeIds();
        ProfileManager.ProfileElement profileElement = ProfileManager.getInstance().getProfileElement(queryId);
        Preconditions.checkNotNull(profileElement, "query not exists");
        // For short circuit query, 'ProfileElement#plan' is null
        if (profileElement.plan == null) {
            throw new UserException(
                    "short circuit point query doesn't suppot analyze profile stmt, " +
                            "you can set it off by using  set enable_short_circuit=false");
        }
        handleExplainStmt(ExplainAnalyzer.analyze(profileElement.plan,
                RuntimeProfileParser.parseFrom(CompressionUtils.gzipDecompressString(profileElement.profileContent)),
                planNodeIds));
    }

这里通过ProfileManager.getInstance().getProfileElement(queryId)获取到对应的profile,
之后再通过ExplainAnalyzer.analyze获取对应的explain string.

TRACE

具体语法参考query_trace_profile
EXPLAIN ANALYZE的逻辑一样,通过AstBuilder.visitQueryStatement 解析完后,走的是queryStatement.setIsTrace(getTraceMode(context.optimizerTrace()), module);这个逻辑:

 public void setIsTrace(Tracers.Mode mode, String module) {
        this.isExplain = true;
        this.traceMode = mode;
        this.traceModule = module;
    }

可以看到这里的isExplaintrue.
handleQueryStmt方法为:

} else if (parsedStmt.isExplain()) {
    String explainString = buildExplainString(execPlan, ResourceGroupClassifier.QueryType.SELECT,
            parsedStmt.getExplainLevel());
    if (executeInFe) {
        explainString = "EXECUTE IN FE\n" + explainString;
    }
    handleExplainStmt(explainString);
    return;
}

这里的buildExplainString方法,会根据tracemode来进行explain String的构建。

其他

  1. 开启Query Profile 指标

| Query:
  Summary:
     - Query ID: 135d8852-62fd-11f0-b356-00163e164034
     - Start Time: 2025-07-17 18:59:13
     - End Time: 2025-07-17 18:59:14
     - Total: 268ms
     - Query Type: Query
     - Query State: Finished
     - StarRocks Version: 3.3.5-6d81f75
     - User: sr_read_write
     - Default Db
     - Sql Statement: SELECT `COLUMN_NAME`, `DATA_TYPE`, `ORDINAL_POSITION`, `COLUMN_SIZE`, `DECIMAL_DIGITS`, `IS_NULLABLE`, `COLUMN_KEY`, `COLUMN_COMMENT` FROM `information_schema`.`COLUMNS` WHERE `TABLE_SCHEMA`='lendtrade' AND `TABLE_NAME`='tr_tran_proc_db_sub';
     - Variables: parallel_fragment_exec_instance_num=8,max_parallel_scan_instance_num=-1,pipeline_dop=0,enable_adaptive_sink_dop=true,enable_runtime_adaptive_dop=false,runtime_profile_report_interval=10,resource_group=default_wg
     - NonDefaultSessionVariables: {"sql_mode_v2":{"defaultValue":32,"actualValue":2097184},"big_query_profile_threshold":{"defaultValue":"0s","actualValue":"30s"},"character_set_results":{"defaultValue":"utf8","actualValue":"NULL"},"parallel_fragment_exec_instance_num":{"defaultValue":1,"actualValue":8},"enable_adaptive_sink_dop":{"defaultValue":false,"actualValue":true},"enable_profile":{"defaultValue":false,"actualValue":true}}
     - Collect Profile Time: 2ms
     - IsProfileAsync: true
  Planner:
     - -- Parser[1] 0
     - -- Total[1] 0
     -     -- Analyzer[1] 0
     -         -- Lock[1] 0
     -         -- AnalyzeDatabase[1] 0
     -         -- AnalyzeTemporaryTable[1] 0
     -         -- AnalyzeTable[1] 0
     -     -- Transformer[1] 0
     -     -- Optimizer[1] 0
     -         -- MVPreprocess[1] 0
     -             -- MVChooseCandidates[1] 0
     -             -- MVGenerateMvPlan[1] 0
     -             -- MVValidateMv[1] 0
     -             -- MVProcessWithView[1] 0
     -         -- MVTextRewrite[1] 0
     -         -- RuleBaseOptimize[1] 0
     -         -- CostBaseOptimize[1] 0
     -         -- PhysicalRewrite[1] 0
     -         -- PlanValidate[1] 0
     -             -- InputDependenciesChecker[1] 0
     -             -- TypeChecker[1] 0
     -             -- CTEUniqueChecker[1] 0
     -             -- ColumnReuseChecker[1] 0
     -     -- ExecPlanBuild[1] 0
     - -- Pending[1] 0
     - -- Prepare[1] 0
     - -- Deploy[1] 23ms
     -     -- DeployLockInternalTime[1] 23ms
     -         -- DeploySerializeConcurrencyTime[1] 0
     -         -- DeployStageByStageTime[3] 0
     -         -- DeployWaitTime[3] 23ms
     -             -- DeployAsyncSendTime[1] 0
     - DeployDataSize: 5803
    Reason:
  Execution:
     - Topology: {"rootId":1,"nodes":[{"id":1,"name":"PROJECT","properties":{"sinkIds":[],"displayMem":false},"children":[0]},{"id":0,"name":"SCHEMA_SCAN","properties":{"displayMem":false},"children":[]}]}
     - FrontendProfileMergeTime: 732.454us
     - QueryAllocatedMemoryUsage: 1015.680 KB
     - QueryCumulativeCpuTime: 11.169ms
     - QueryCumulativeNetworkTime: 0ns
     - QueryCumulativeOperatorTime: 240.565ms
     - QueryCumulativeScanTime: 229.352ms
     - QueryDeallocatedMemoryUsage: 840.773 KB
     - QueryExecutionWallTime: 257.617ms
     - QueryPeakMemoryUsagePerNode: 485.695 KB
     - QueryPeakScheduleTime: 42.480us
     - QuerySpillBytes: 0.000 B
     - QuerySumMemoryUsage: 485.695 KB
     - ResultDeliverTime: 0ns
    Fragment 0:
       - BackendAddresses: 172.17.172.252:9060
       - InstanceIds: 135d8852-62fd-11f0-b356-00163e164035
       - BackendNum: 1
       - BackendProfileMergeTime: 541.804us
       - FragmentInstancePrepareTime: 16.399ms
         - prepare-fragment-ctx: 922ns
         - prepare-pipeline-driver: 3.447ms
         - prepare-pipeline-driver-factory: 8.697ms
         - prepare-query-ctx: 3.826us
         - prepare-runtime-state: 4.247ms
       - InitialProcessDriverCount: 0
       - InitialProcessMem: 15.307 GB
       - InstanceAllocatedMemoryUsage: 1015.680 KB
       - InstanceDeallocatedMemoryUsage: 840.773 KB
       - InstanceNum: 1
       - InstancePeakMemoryUsage: 478.039 KB
       - JITCounter: 0
       - JITTotalCostTime: 0ns
       - QueryMemoryLimit: -1.000 B
      Pipeline (id=0):
         - isGroupExecution: false
         - ActiveTime: 11.183ms
         - BlockByInputEmpty: 2
         - BlockByOutputFull: 0
         - BlockByPrecondition: 0
         - DegreeOfParallelism: 1
         - DriverPrepareTime: 3.445ms
         - DriverTotalTime: 240.546ms
         - OverheadTime: 0ns
         - PeakDriverQueueSize: 0
         - PendingTime: 229.320ms
           - InputEmptyTime: 229.323ms
             - FirstInputEmptyTime: 229.245ms
             - FollowupInputEmptyTime: 78.368us
           - OutputFullTime: 0ns
           - PendingFinishTime: 0ns
           - PreconditionBlockTime: 0ns
         - ScheduleCount: 3
         - ScheduleTime: 42.480us
         - TotalDegreeOfParallelism: 1
         - YieldByLocalWait: 0
         - YieldByPreempt: 0
         - YieldByTimeLimit: 0
        RESULT_SINK (plan_node_id=-1):
          CommonMetrics:
             - IsFinalSink
             - CloseTime: 7.404us
             - OperatorAllocatedMemoryUsage: 19.320 KB
             - OperatorDeallocatedMemoryUsage: 20.281 KB
             - OperatorPeakMemoryUsage: 0.000 B
             - OperatorTotalTime: 5.905ms
             - PrepareTime: 3.384ms
             - PullChunkNum: 0
             - PullRowNum: 0
             - PullTotalTime: 0ns
             - PushChunkNum: 1
             - PushRowNum: 38
             - PushTotalTime: 5.897ms
             - SetFinishedTime: 30ns
             - SetFinishingTime: 60ns
          UniqueMetrics:
            result sink:
               - AppendChunkTime: 5.859ms
                 - ResultRendTime: 33.463us
                 - TupleConvertTime: 5.856ms
               - NumSentRows: 38
        CHUNK_ACCUMULATE (plan_node_id=-1):
          CommonMetrics:
             - IsSubordinate
             - CloseTime: 161ns
             - OperatorTotalTime: 1.133us
             - PrepareTime: 5.921us
             - PullChunkNum: 1
             - PullRowNum: 38
             - PullTotalTime: 280ns
             - PushChunkNum: 1
             - PushRowNum: 38
             - PushTotalTime: 613ns
             - SetFinishedTime: 50ns
             - SetFinishingTime: 29ns
          UniqueMetrics:
        PROJECT (plan_node_id=1):
          CommonMetrics:
             - CloseTime: 5.650us
             - OperatorAllocatedMemoryUsage: 1.016 KB
             - OperatorDeallocatedMemoryUsage: 416.000 B
             - OperatorPeakMemoryUsage: 640.000 B
             - OperatorTotalTime: 12.503us
             - PrepareTime: 7.204us
             - PullChunkNum: 1
             - PullRowNum: 38
             - PullTotalTime: 230ns
             - PushChunkNum: 1
             - PushRowNum: 38
             - PushTotalTime: 6.351us
             - RuntimeBloomFilterNum: 0
             - RuntimeInFilterNum: 0
             - SetFinishedTime: 141ns
             - SetFinishingTime: 131ns
          UniqueMetrics:
             - CommonSubExprComputeTime: 251ns
             - ExprComputeTime: 2.494us
        CHUNK_ACCUMULATE (plan_node_id=0):
          CommonMetrics:
             - IsSubordinate
             - CloseTime: 301ns
             - OperatorTotalTime: 2.636us
             - PrepareTime: 11.191us
             - PullChunkNum: 1
             - PullRowNum: 38
             - PullTotalTime: 191ns
             - PushChunkNum: 1
             - PushRowNum: 38
             - PushTotalTime: 1.823us
             - SetFinishedTime: 161ns
             - SetFinishingTime: 160ns
          UniqueMetrics:
        SCHEMA_SCAN (plan_node_id=0):
          CommonMetrics:
             - CloseTime: 64.822us
             - OperatorAllocatedMemoryUsage: 839.242 KB
             - OperatorDeallocatedMemoryUsage: 552.344 KB
             - OperatorPeakMemoryUsage: 307.672 KB
             - OperatorTotalTime: 5.292ms
             - PrepareTime: 16.070us
             - PullChunkNum: 1
             - PullRowNum: 38
             - PullTotalTime: 5.226ms
             - PushChunkNum: 0
             - PushRowNum: 0
             - PushTotalTime: 0ns
             - SetFinishedTime: 231ns
             - SetFinishingTime: 521ns
          UniqueMetrics:
             - MorselQueueType: fixed_morsel_queue
             - ChunkBufferCapacity: 64
             - DefaultChunkBufferCapacity: 64
             - FERPC: 211.509ms
             - FillChunk: 4.506ms
             - FilterTime: 12.890ms
             - IOTaskExecTime: 229.309ms
             - IOTaskWaitTime: 42.740us
             - MorselsCount: 1
             - PeakChunkBufferMemoryUsage: 250.513 KB
             - PeakChunkBufferSize: 1
             - PeakIOTasks: 1
             - PeakScanTaskQueueSize: 0
             - PrepareChunkSourceTime: 5.204ms
             - ScanTime: 229.352ms
             - SubmitTaskCount: 2
             - SubmitTaskTime: 8.015us
             - TabletCount: 1
 |
  1. EXPLAIN ANALYZE
+-------------------------------------------------------------------------------------------------------------------------------------+
| Explain String                                                                                                                      |
+-------------------------------------------------------------------------------------------------------------------------------------+
| Summary                                                                                                                     |
|     QueryId: 6b148971-71e6-11f0-8cea-00163e39052a                                                                           |
|     Version: 3.3.5-6d81f75                                                                                                  |
|     State: Finished                                                                                                         |
|     TotalTime: 2s51ms                                                                                                       |
|         ExecutionTime: 0ns [Scan: 0ns (NaN%), Network: 0ns (NaN%), ResultDeliverTime: 0ns (NaN%), ScheduleTime: 0ns (NaN%)] |
|         CollectProfileTime: 2s1ms                                                                                           |
|         FrontendProfileMergeTime: 361.325us                                                                                 |
|     QueryPeakMemoryUsage: ?, QueryAllocatedMemoryUsage: 0.000 B                                                             |
|     Top Most Time-consuming Nodes:                                                                                          |
|         1. RESULT_SINK: 0ns (NaN%)                                                                                          |
|         2. SCHEMA_SCAN (id=0) : 0ns (NaN%)                                                                                  |
|     Top Most Memory-consuming Nodes:                                                                                        |
|     NonDefaultVariables:                                                                                                    |
|         big_query_profile_threshold: 0s -> 30s                                                                              |
|         enable_adaptive_sink_dop: false -> true                                                                             |
|         enable_async_profile: true -> false                                                                                 |
|         enable_profile: false -> true                                                                                       |
|         parallel_fragment_exec_instance_num: 1 -> 8                                                                         |
| Fragment 0                                                                                                                  |
| │   BackendNum: 1                                                                                                           |
| │   InstancePeakMemoryUsage: ?, InstanceAllocatedMemoryUsage: ?                                                             |
| │   PrepareTime: ?                                                                                                          |
| │   MissingInstanceIds: 6b148971-71e6-11f0-8cea-00163e39052b                                                                |
| └──RESULT_SINK                                                                                                              |
|    │   SinkType: MYSQL_PROTOCAL                                                                                             |
|    └──SCHEMA_SCAN (id=0)                                                                                                    |
|           Estimates: [row: 1, cpu: ?, memory: ?, network: ?, cost: 0.0]                                                     |
|           TotalTime: 0ns (NaN%) [CPUTime: ?]                                                                                |
|           OutputRows: ?                                                                                                     |
|                                                                                                                                 |
+-------------------------------------------------------------------------------------------------------------------------------------+
  1. ANALYZE PROFILE 展示的和explain analyze一样,但是指标比 explain analyze 更加丰富
+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Explain String                                                                                                                                            |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Summary                                                                                                                                           |
|     QueryId: 135d8852-62fd-11f0-b356-00163e164034                                                                                                 |
|     Version: 3.3.5-6d81f75                                                                                                                        |
|     State: Finished                                                                                                                               |
|     TotalTime: 268ms                                                                                                                              |
|         ExecutionTime: 257.617ms [Scan: 229.352ms (89.03%), Network: 0ns (0.00%), ResultDeliverTime: 0ns (0.00%), ScheduleTime: 42.480us (0.02%)] |
|         CollectProfileTime: 2ms                                                                                                                   |
|         FrontendProfileMergeTime: 732.454us                                                                                                       |
|     QueryPeakMemoryUsage: ?, QueryAllocatedMemoryUsage: 1015.680 KB                                                                               |
|     Top Most Time-consuming Nodes:                                                                                                                |
|         1. SCHEMA_SCAN (id=0) : 234.646ms (97.54%)                                                                                           |
|         2. RESULT_SINK: 5.906ms (2.46%)                                                                                                           |
|         3. PROJECT (id=1) : 12.503us (0.01%)                                                                                                      |
|     Top Most Memory-consuming Nodes:                                                                                                              |
|     NonDefaultVariables:                                                                                                                          |
|         big_query_profile_threshold: 0s -> 30s                                                                                                    |
|         character_set_results: utf8 -> NULL                                                                                                       |
|         enable_adaptive_sink_dop: false -> true                                                                                                   |
|         enable_profile: false -> true                                                                                                             |
|         parallel_fragment_exec_instance_num: 1 -> 8                                                                                               |
|         sql_mode_v2: 32 -> 2097184                                                                                                                |
| Fragment 0                                                                                                                                        |
| │   BackendNum: 1                                                                                                                                 |
| │   InstancePeakMemoryUsage: 478.038 KB, InstanceAllocatedMemoryUsage: 1015.680 KB                                                                |
| │   PrepareTime: 16.399ms                                                                                                                         |
| └──RESULT_SINK                                                                                                                                    |
|    │   TotalTime: 5.906ms (2.46%) [CPUTime: 5.906ms]                                                                                              |
|    │   OutputRows: 38                                                                                                                             |
|    │   SinkType: MYSQL_PROTOCAL                                                                                                                   |
|    └──PROJECT (id=1)                                                                                                                              |
|       │   Estimates: [row: ?, cpu: ?, memory: ?, network: ?, cost: ?]                                                                             |
|       │   TotalTime: 12.503us (0.01%) [CPUTime: 12.503us]                                                                                         |
|       │   OutputRows: 38                                                                                                                          |
|       │   Expression: [4: COLUMN_NAME, 5: ORDINAL_POSITION, 7: IS_NULLABLE, 8: DATA_TYPE, ...]                                                    |
|       └──SCHEMA_SCAN (id=0)                                                                                                                  |
|              Estimates: [row: 1, cpu: ?, memory: ?, network: ?, cost: 0.0]                                                                   |
|              TotalTime: 234.646ms (97.54%) [CPUTime: 5.294ms, ScanTime: 229.352ms]                                                           |
|              OutputRows: 38                                                                                                                  |
|              SubordinateOperators:                                                                                                           |
|                  CHUNK_ACCUMULATE                                                                                                            |
|              Detail Timers: [ScanTime = IOTaskExecTime + IOTaskWaitTime]                                                                     |
|                  FERPC: 211.509ms                                                                                                            |
|                  IOTaskExecTime: 229.309ms                                                                                                   |
|                  IOTaskWaitTime: 42.740us                                                                                                    |
|                                                                                                                                                       |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
  1. trace 展示的是某个局部,比如说 某个规则的耗时
MySQL [(none)]> trace times SCHEDULE SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA` WHERE SCHEMA_NAME = 'fin_config';
+--------------------------------------------------+
| Explain String                                   |
+--------------------------------------------------+
| 0ms|-- Parser[1] 0                               |
| 0ms|-- Total[1] 0                                |
| 0ms|    -- Analyzer[1] 0                         |
| 0ms|        -- Lock[1] 0                         |
| 0ms|        -- AnalyzeDatabase[1] 0              |
| 0ms|        -- AnalyzeTemporaryTable[1] 0        |
| 0ms|        -- AnalyzeTable[1] 0                 |
| 0ms|    -- Transformer[1] 0                      |
| 0ms|    -- Optimizer[1] 0                        |
| 0ms|        -- MVPreprocess[1] 0                 |
| 0ms|            -- MVChooseCandidates[1] 0       |
| 0ms|            -- MVGenerateMvPlan[1] 0         |
| 0ms|            -- MVValidateMv[1] 0             |
| 0ms|            -- MVProcessWithView[1] 0        |
| 0ms|        -- MVTextRewrite[1] 0                |
| 0ms|        -- RuleBaseOptimize[1] 0             |
| 0ms|        -- CostBaseOptimize[1] 0             |
| 1ms|        -- PhysicalRewrite[1] 0              |
| 1ms|        -- PlanValidate[1] 0                 |
| 1ms|            -- InputDependenciesChecker[1] 0 |
| 1ms|            -- TypeChecker[1] 0              |
| 1ms|            -- CTEUniqueChecker[1] 0         |
| 1ms|            -- ColumnReuseChecker[1] 0       |
| 1ms|    -- ExecPlanBuild[1] 0                    |
| Tracer Cost: 9us                                 |
+--------------------------------------------------+

MySQL [(none)]> trace times OPTIMIZER SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA` WHERE SCHEMA_NAME = 'fin_config';
+----------------------------------------------------------+
| Explain String                                           |
+----------------------------------------------------------+
| 0ms|-- Parser[1] 0                                       |
| 0ms|-- Total[1] 0                                        |
| 0ms|    -- Analyzer[1] 0                                 |
| 0ms|        -- Lock[1] 0                                 |
| 0ms|        -- AnalyzeDatabase[1] 0                      |
| 0ms|        -- AnalyzeTemporaryTable[1] 0                |
| 0ms|        -- AnalyzeTable[1] 0                         |
| 0ms|    -- Transformer[1] 0                              |
| 0ms|    -- Optimizer[1] 0                                |
| 0ms|        -- MVPreprocess[1] 0                         |
| 0ms|            -- MVChooseCandidates[1] 0               |
| 0ms|            -- MVGenerateMvPlan[1] 0                 |
| 0ms|            -- MVValidateMv[1] 0                     |
| 0ms|            -- MVProcessWithView[1] 0                |
| 0ms|        -- MVTextRewrite[1] 0                        |
| 0ms|        -- RuleBaseOptimize[1] 0                     |
| 0ms|            -- RewriteTreeTask[59] 0                 |
| 0ms|                -- PushDownPredicateProjectRule[1] 0 |
| 0ms|                -- PushDownPredicateScanRule[1] 0    |
| 0ms|                -- MergeTwoProjectRule[2] 0          |
| 0ms|                -- PruneProjectColumnsRule[2] 0      |
| 0ms|                -- PruneScanColumnRule[2] 0          |
| 0ms|                -- PruneSubfieldRule[1] 0            |
| 0ms|                -- PruneProjectRule[2] 0             |
| 0ms|                -- MergeProjectWithChildRule[1] 0    |
| 0ms|        -- CostBaseOptimize[1] 0                     |
| 0ms|            -- OptimizeGroupTask[1] 0                |
| 0ms|            -- OptimizeExpressionTask[1] 0           |
| 0ms|            -- DeriveStatsTask[1] 0                  |
| 0ms|            -- ApplyRuleTask[1] 0                    |
| 0ms|                -- SchemaScanImplementationRule[1] 0 |
| 0ms|            -- EnforceAndCostTask[1] 0               |
| 0ms|        -- PhysicalRewrite[1] 0                      |
| 1ms|        -- PlanValidate[1] 0                         |
| 1ms|            -- InputDependenciesChecker[1] 0         |
| 1ms|            -- TypeChecker[1] 0                      |
| 1ms|            -- CTEUniqueChecker[1] 0                 |
| 1ms|            -- ColumnReuseChecker[1] 0               |
| 1ms|    -- ExecPlanBuild[1] 0                            |
| Tracer Cost: 21us                                        |
+----------------------------------------------------------+

其中这里面的[1] 数字代码该规则被应用的次数,如 PhysicalRewrite[1]则表示 改规则被应用了1次。
<think>好的,用户问的是“explain”和“explain analyze”在数据库中的区别。我需要先回忆一下这两个命令的基本功能。 首先,记得在数据库里,EXPLAIN是用来显示查询的执行计划,也就是数据库会如何执行这个查询,比如是否使用索引,连接顺序等。而EXPLAIN ANALYZE不仅显示执行计划,还会实际执行查询并返回执行时的统计信息,比如实际时间、行数等。所以两者的主要区别在于是否真正执行查询。 接下来需要确认用户可能的背景。他们可能是开发人员或者数据分析师,需要优化SQL查询性能。他们可能在使用PostgreSQL、MySQL或其他支持这两个命令的数据库。了解不同数据库的具体实现是否有差异,比如在输出格式或统计信息上的不同,但通常核心区别是一致的。 用户可能没有提到,但潜在需求可能是如何有效使用这两个命令来优化查询。比如,EXPLAIN用于计划阶段的分析,而EXPLAIN ANALYZE用于实际执行后的性能分析。需要指出两者的使用场景,比如在生产环境中谨慎使用ANALYZE,因为它会实际执行查询,可能对性能有影响。 另外,要强调EXPLAIN ANALYZE的真实数据重要性,因为优化器估算可能不准确,实际执行后的统计能帮助发现潜在问题,比如错误的行数估计导致选择了低效的执行计划。 还要注意示例的清晰性,比如用简单的SQL语句展示两者的输出差异,帮助用户直观理解。同时,需要提醒用户EXPLAIN ANALYZE可能会带来额外开销,特别是在处理大数据时,避免在敏感环境直接使用。 总结回答结构:先定义两者,再对比区别,包括是否执行查询、输出信息、用途和开销,最后给出使用建议。确保语言简洁,结构清晰,帮助用户快速掌握要点。</think>在数据库查询优化中,`EXPLAIN` 和 `EXPLAIN ANALYZE` 是两个关键的命令,用于分析 SQL 查询的执行计划,但两者的作用和输出信息有显著区别。以下是详细对比: --- ### **1. `EXPLAIN`:仅生成查询计划** - **功能**: 显示数据库优化器**预估**的查询执行计划,但**不会实际执行查询**。 - **输出内容**: - 执行步骤的顺序(如扫描表、使用索引、连接顺序)。 - 预估的成本(`cost`)、返回行数(`rows`)和每步操作的耗时。 - 使用的索引类型(如 B+树、哈希索引)。 - 示例输出: ```sql -- PostgreSQL 示例 EXPLAIN SELECT * FROM users WHERE age > 30; ``` ``` Seq Scan on users (cost=0.00..15.00 rows=500 width=36) Filter: (age > 30) ``` - **用途**: 快速检查优化器的逻辑是否合理(例如是否选择了低效的全表扫描)。 --- ### **2. `EXPLAIN ANALYZE`:执行并分析查询** - **功能**: 生成查询计划后**实际执行查询**,并返回**真实执行数据**。 - **输出内容**: - 所有 `EXPLAIN` 的信息。 - 实际耗时(如 `actual time=10.01..100.05 ms`)。 - 实际返回行数(`rows=480`)。 - 资源消耗(如内存、临时文件)。 - 示例输出: ```sql EXPLAIN ANALYZE SELECT * FROM users WHERE age > 30; ``` ``` Seq Scan on users (cost=0.00..15.00 rows=500 width=36) (actual time=0.012..5.234 rows=480 loops=1) Filter: (age > 30) Rows Removed by Filter: 20 Planning Time: 0.045 ms Execution Time: 5.260 ms ``` - **用途**: 验证优化器的预估是否准确(例如 `rows=500` vs `rows=480`),发现性能瓶颈。 --- ### **3. 核心区别对比** | **维度** | **`EXPLAIN`** | **`EXPLAIN ANALYZE`** | |--------------------|----------------------------------------|----------------------------------------| | **是否执行查询** | 否 | 是 | | **输出信息** | 预估成本、行数 | 实际耗时、行数、资源消耗 | | **用途** | 初步检查执行计划 | 验证真实性能,优化查询 | | **性能影响** | 无 | 可能因执行查询产生额外开销 | --- ### **4. 使用场景建议** - **`EXPLAIN`**: - 初步分析复杂查询的执行逻辑。 - 检查索引是否被正确使用(如避免全表扫描)。 - **`EXPLAIN ANALYZE`**: - 验证查询的真实性能(如耗时是否符合预期)。 - 发现优化器估算错误(例如统计信息过时导致行数估计偏差)。 --- ### **5. 注意事项** - **生产环境慎用 `EXPLAIN ANALYZE`**: 若查询涉及大量数据更新(如 `INSERT`/`DELETE`),`EXPLAIN ANALYZE` 会实际修改数据。 - **统计信息的影响**: 数据库的统计信息(如 `ANALYZE` 命令)会直接影响 `EXPLAIN` 的预估准确性。 --- 通过结合 `EXPLAIN` 和 `EXPLAIN ANALYZE`,可以全面诊断查询性能问题,例如: - 若 `EXPLAIN` 显示使用索引,但 `EXPLAIN ANALYZE` 实际耗时高,可能是索引碎片化或数据分布不均导致。 - 若预估行数与实际行数差异大,需更新统计信息或调整查询逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值