All Products
Search
Document Center

Lindorm:Overview of query plans

Last Updated:Mar 28, 2026

Use the EXPLAIN syntax to inspect how Lindorm SQL executes a query. Query plans reveal the data scanning method, index selection, relational operations, and push-down behavior — giving you a clear view into what the query engine is doing so you can diagnose issues and tune performance.

Query plans are supported for LindormTable and LindormTSDB.

How it works

When Lindorm SQL receives a query, it parses the SQL into an abstract syntax tree, rewrites it into a logical plan, then applies rule-based or cost-based optimization to produce a physical plan. The physical plan is what actually runs — it specifies which operators execute in Lindorm SQL and which operations are pushed down to the storage engine.

EXPLAIN lets you inspect the plan at three depths:

DepthWhen to use
Physical plan (default)Diagnose performance issues: check which index is selected, the scan range, and how operations are ordered
Logical planDebug semantic issues: inspect how Lindorm SQL rewrites your query before optimization
Type planVerify column types: confirm the output schema without running a full plan

Query plan depths

Logical plan

The logical plan shows the query structure after rewriting, before optimization. Lindorm SQL generates it from the abstract syntax tree and may apply rewrites such as:

  • Replacing a constant expression with its computed value

  • Replacing AVG with equivalent SUM and COUNT expressions

Use EXPLAIN WITHOUT IMPLEMENTATION FOR to view the logical plan:

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;

Output:

********************* 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]])

For the full EXPLAIN syntax, see EXPLAIN.

Physical plan

The physical plan is the optimized, executable version of the query. The optimizer selects the best execution mode based on rule-based or cost-based policies. This is the default output of EXPLAIN and shows the complete execution path: which operators run in Lindorm SQL, which operations are pushed down to LindormTable or LindormTSDB, the index chosen, the scan range, and the filter conditions.

Use EXPLAIN FOR (or just EXPLAIN) to view the physical plan:

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

Output:

********************* 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_%))
])

Type plan

The type plan contains only the output column types for each column in the result set. It is generated based on query types and is applicable in specific scenarios. It is the most lightweight of the three depths and is useful for quickly verifying the output schema without inspecting the full execution tree.

Use EXPLAIN WITH TYPE FOR to view the type plan:

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;

Output:

********************* 1. row *********************
PLAN: lp INTEGER NOT NULL,
EXPR$1 BIGINT NOT NULL

For the full EXPLAIN syntax, see EXPLAIN.

Operators in query plans

Operators are the building blocks of a physical plan. Each operator represents a discrete step in query execution. Lindorm SQL includes general-purpose operators for computing and a set of extended operators for push-down and engine-specific operations.

General-purpose operators

These operators handle computing operations that run in Lindorm SQL — sorting, aggregation, projection, and calculation.

EnumerableLimit

Skips and truncates the result set based on OFFSET and LIMIT values. The plan output shows the source of the offset and fetch values.

When it appears: Any query with a LIMIT or OFFSET clause.

EnumerableSort

Sorts the result set based on the ORDER BY clause using a treemap-based sorting algorithm. The plan output shows the sorting key and direction.

When it appears: Queries with ORDER BY where sorting cannot be satisfied by the storage-layer scan order. If EnumerableSort appears in your plan, adding an index that matches the sort column may eliminate this operator.

EnumerableAggregate

Aggregates rows returned by lower-level operators using aggregate functions and optional grouping columns. Also handles the DISTINCT syntax. The plan output shows the grouping key and aggregate expressions.

When it appears: Queries with GROUP BY, aggregate functions (COUNT, SUM, AVG, etc.), or DISTINCT.

EnumerableCalc

Evaluates expressions — arithmetic operations, scalar functions (excluding aggregate and window functions) — and performs projection and filtering on rows. This is a general-purpose computation operator.

When it appears: Queries that apply expressions or filters that are not pushed down to the storage engine.

Extended operators

EnumerableLindormDirectQuery

Marks the portion of the query pushed down to the storage engine for execution. The explanation field describes what was pushed down and how the storage engine handled it. The content of explanation differs by engine:

LindormTable

FieldDescription
Candidate tablesThe candidate indexes evaluated, with scores
Chose data tableThe index selected for the query
Scan typeThe scan method (e.g., SingleScan, RangeScan)
rangesThe key range scanned
filterFilter conditions applied during the scan

LindormTSDB

The explanation field contains the parameters of the LindormTSDB API call invoked for the query.

Extended operators for LindormTSDB

These operators are specific to LindormTSDB queries.

TSDBDataScanRel

A variant of LogicalTableScan that performs metric scanning operations. The plan output includes:

  • filter — filter conditions applied to the scan

  • project — column mapping between the operator and the time series table

  • hint — hints passed down with the scan, such as _l_series_only

When it appears: Any query that reads from a LindormTSDB metric table.

TSDBShowTagRel

Optimizes queries that retrieve all values for a specific tag column — equivalent to the SHOW TAG VALUES syntax in InfluxDB. This operator appears at the lowest level of the plan tree and indicates that the tag enumeration is handled directly by the storage engine.

When it appears: Only for queries in the form SELECT DISTINCT <tagkey column> FROM <table>.

TSDBAggScanRel

A combined operator that merges EnumerableAggregation and TSDBDataScanRel into a single push-down step for aggregating time series data.

When it appears: Queries that aggregate time series data where both the scan and aggregation can be pushed down to LindormTSDB.

EnumerableDownsampleQuery

Handles queries that use the SAMPLE BY syntax — a Lindorm SQL extension for downsampling time series data in LindormTSDB. Because SAMPLE BY is a non-standard SQL dialect, it has its own logical operator (LogicalDownsampleQuery) and physical operator (EnumerableDownsampleQuery). The plan output includes:

  • project — column mapping between the operator and the higher-level plan

  • filter — filter conditions pushed down with the downsampling operation

  • ds_agg — the downsampling function and its parameters

  • aggregator — aggregate operators pushed down for cross-time-series aggregation

  • hint — hints pushed down to LindormTSDB

When it appears: Only in queries that use the SAMPLE BY syntax.

What's next

  • EXPLAIN — full syntax reference for all EXPLAIN variants