文档

查询计划概述

更新时间:

Lindorm支持查看SQL语句在数据库中的执行过程,帮助您定位和排查SQL执行问题。您可以通过EXPLAIN语句查看不同深度的执行计划,进一步分析优化查询逻辑,以提升查询性能。

适用引擎

适用于宽表引擎和时序引擎。

背景信息

查询计划(Query Plan)是对一条SQL查询语句在数据库中执行过程的描述,也称为执行计划(Execution Plan)。在诊断查询性能时,通常需要先查看目标查询语句的执行计划,排查SQL语句的每一步执行是否存在问题。因此,理解查询计划是进行SQL语句优化的前提条件,同时了解查询计划中的算子是理解EXPLAIN命令的关键。

查询计划深度

Lindorm SQL提供了EXPLAIN语句,方便查看一条查询语句在SQL引擎中生成的查询计划。

共包含三种计划深度:逻辑计划、物理计划和类型计划。

逻辑计划

Lindorm SQL仅生成查询语句未经优化器优化的、原始的逻辑计划。

逻辑计划是SQL引擎根据抽象语法树进行查询改写后生成的查询计划。生成逻辑计划的过程中,数据引擎会改写部分逻辑操作,使逻辑计划对SQL引擎后续的优化和执行更加友好。例如,将常量表达式直接改写为一个计算后的常量、将AVG聚合改写为SUM聚合或COUNT聚合等等。您可以通过在EXPLAIN语句中添加深度表达式来生成逻辑计划。EXPLAIN的语法介绍,请参见EXPLAIN

假设查询语句如下:

SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;

生成逻辑计划:​

EXPLAIN WITHOUT IMPLEMENTATION FOR SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;
********************* 1. row *********************
PLAN: LogicalSort(sort0=[$0], dir0=[ASC])
  LogicalAggregate(group=[{0}], EXPR$1=[COUNT($1)])
    LogicalProject(lp=[LOCATE('9378', $0)], c1=[$1])
      LogicalFilter(condition=[LIKE($0, '3_%')])
        LindormTableScan(table=[[db, test]])

物理计划

物理计划是查询经过优化器计算后的执行计算结果。数据库系统中的优化器会基于一定的规则策略或代价策略,为生成的逻辑计划选择最适合的执行方式。这样的执行方式(包括最后被选定的结果,以及候选项)被称为物理计划。

执行EXPLAIN语句时,默认返回物理计划,它包含了SQL引擎的执行算子以及下推到宽表引擎上的执行算子。

物理计划可以很明确地展示SQL查询语句的执行过程,包括数据的扫描方式、关系运算的执行顺序等。

假设查询语句如下:

SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;

生成物理计划:

EXPLAIN SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;
********************* 1. row *********************
PLAN: EnumerableSort(sort0=[$0], dir0=[ASC])
  EnumerableAggregate(group=[{0}], EXPR$1=[COUNT($1)])
    EnumerableCalc(expr#0..3=[{inputs}], expr#4=['9378'], expr#5=[LOCATE($t4, $t0)], lp=[$t5], c1=[$t1])
      EnumerableLindormDirectQuery(
explanation=[SELECT p1,c1,c2,c3 from test where ((p1 < 4) AND (p1 >= 3) AND (p1 LIKE 3_%)) supportEmptyResult true
Candidate tables: 
    Data table: test, scores=1..0..1, need query back=false, sort type=FORWARD
Chose data table [test].
---
SELECT p1,c1,c2,c3 from test supportEmptyResult true
SingleScan on test
    ranges: [3\x00, 4\x00]
    filter: ((p1 < 4) AND (p1 >= 3) AND (p1 LIKE 3_%))
])

类型计划

Lindorm SQL仅生成返回结果集中数据行的列类型。

类型计划是基于查询类型的特定查询计划。相较于逻辑计划和物理计划,类型计划是最粗糙的一种查询计划。您可以通过在EXPLAIN语句中添加深度表达式来生成类型计划。EXPLAIN的语法介绍,请参见EXPLAIN

假设查询语句如下:

SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;

生成类型计划:​

EXPLAIN WITH TYPE FOR SELECT LOCATE('9378', p1) AS lp, COUNT(c1) FROM (SELECT * FROM test WHERE p1 like '3_%') GROUP BY lp ORDER BY lp;
********************* 1. row *********************
PLAN: lp INTEGER NOT NULL,
EXPR$1 BIGINT NOT NULL

解读执行计划

以下是Lindorm SQL中组成物理计划的常用物理算子。

通用物理算子

Lindorm SQL实现了一套通用物理算子供优化器生成物理计划,包括查询中诸如排序、聚合、投影、运算等通用计算行为。以下是查询中常见的物理算子:

  • EnumerableLimit算子

    通用LIMIT算子,基于用户指定的OFFSET和LIMIT对结果集数据进行跳过截取。显示执行计划时,会显示该算子所需的offsetfetch来源。

  • EnumerableSort算子

    通用排序算子,基于用户指定的ORDER BY表达式对数据进行排序。该默认排序算法基于TreeMap实现。显示执行计划时,会显示该算子排序键的来源。

  • EnumerableAggregate算子

    通用聚合算子,基于用户指定的聚合函数以及可能存在的分组列对下层算子迭代返回的数据进行聚合,同时也可用于DISTINCT的实现。显示执行计划时,会显示该算子的分组键、聚合函数相关的表达式。

  • EnumerableCalc算子

    表达式计算算子。可以实现常见表达式的执行,如运算表达式、函数(非聚合函数或窗口函数)表达式。此外,对于类似投影、过滤等计算,大多数情况下也是通过EnumerableCalc算子来实现。

扩展物理算子

下推算子EnumerableLindormDirectQuery

EnumerableLindormDirectQuery算子是Lindorm SQL中通用的扩展算子,表示查询中下推到存储引擎进行计算的部分。该算子的返回结果包含在explanation字段中。不同数据引擎中,explanation字段的信息可能包含不同的信息,具体如下:

数据引擎

explanation包含信息

宽表引擎

返回在宽表引擎上执行的运算内容。包含以下信息:

  • 索引的选择。

  • 数据扫描的方式。

  • 数据扫描的范围。

  • 数据过滤条件。

时序引擎

返回对时序引擎调用的API参数。

时序引擎特有扩展算子

  • TSDBDataScanRel算子

    面向Lindorm时序引擎实现最基础的数据扫描算子,由逻辑算子LogicalTableScan转换而来,表示在某个具体的指标(metric)上执行的Scan操作。该算子在展示时会包含以下内容:

    • filter:扫描时同时自带的过滤条件。

    • project:上层计划算子表达式与时序表之间的列映射关系。

    • hint:扫描时同时下推的Scan HINT(例如 _l_series_only)。

  • TSDBShowTagRel算子

    ​面向查询某个标签列下所有标签值的优化实现,对标influxDB的SHOW TAG VALUES能力。其在查询计划树(Plan Tree)中的位置与TSDBDataScanRel算子相似,往往位于计划树最下层节点,主要用于标识在数据引擎上扫描数据的方法。只有一种查询会被优化到使用该算子,即SELECT DISTINCT ${tagkey column} FROM ${table}

  • TSDBAggScanRel算子

    ​面向Lindorm时序引擎实现的时间线聚合算子,由EnumerableAggregation算子和TSDBDataScanRel算子合并优化而来。

  • EnumerableDownsampleQuery算子

    EnumerableDownsampleQuery算子是Lindorm SQL面向SAMPLE BY语句实现的一个算子。SAMPLE BY语句是面向时序降采样场景拓展的SQL方言,该语句所有上下文都是拓展出来的,包括其逻辑算子(LogicalDownsampleQuery)和物理算子(EnumerableDownsampleQuery)。因此,只有使用SAMPLE BY语句才会生成EnumerableDownsampleQuery算子。

    ​该算子在显示查询计划时包含以下字段:

    • project: 上层计划算子表达式与EnumerableDownsampleQuery算子之间的列映射关系。

    • filter:随着降采样计算一并下推到时序引擎的过滤条件。

    • ds_agg:降采样函数及其参数。

    • aggregator:当存在可下推到时序引擎执行的跨时间线聚合时,一并下推的聚合算子。

    • hint:下推到时序引擎的HINT。

  • 本页导读 (1)
文档反馈