EXPLAIN Statement

Shows the execution plan of a statement.

Syntax:

  1. EXPLAIN [AST | SYNTAX | PLAN | PIPELINE] [setting = value, ...] SELECT ... [FORMAT ...]

Example:

  1. EXPLAIN SELECT sum(number) FROM numbers(10) UNION ALL SELECT sum(number) FROM numbers(10) ORDER BY sum(number) ASC FORMAT TSV;
  1. Union
  2. Expression (Projection)
  3. Expression (Before ORDER BY and SELECT)
  4. Aggregating
  5. Expression (Before GROUP BY)
  6. SettingQuotaAndLimits (Set limits and quota after reading from storage)
  7. ReadFromStorage (SystemNumbers)
  8. Expression (Projection)
  9. MergingSorted (Merge sorted streams for ORDER BY)
  10. MergeSorting (Merge sorted blocks for ORDER BY)
  11. PartialSorting (Sort each block for ORDER BY)
  12. Expression (Before ORDER BY and SELECT)
  13. Aggregating
  14. Expression (Before GROUP BY)
  15. SettingQuotaAndLimits (Set limits and quota after reading from storage)
  16. ReadFromStorage (SystemNumbers)

EXPLAIN Types

  • AST — Abstract syntax tree.
  • SYNTAX — Query text after AST-level optimizations.
  • PLAN — Query execution plan.
  • PIPELINE — Query execution pipeline.

EXPLAIN AST

Dump query AST. Supports all types of queries, not only SELECT.

Examples:

  1. EXPLAIN AST SELECT 1;
  1. SelectWithUnionQuery (children 1)
  2. ExpressionList (children 1)
  3. SelectQuery (children 1)
  4. ExpressionList (children 1)
  5. Literal UInt64_1
  1. EXPLAIN AST ALTER TABLE t1 DELETE WHERE date = today();
  1. explain
  2. AlterQuery t1 (children 1)
  3. ExpressionList (children 1)
  4. AlterCommand 27 (children 1)
  5. Function equals (children 1)
  6. ExpressionList (children 2)
  7. Identifier date
  8. Function today (children 1)
  9. ExpressionList

EXPLAIN SYNTAX

Returns query after syntax optimizations.

Example:

  1. EXPLAIN SYNTAX SELECT * FROM system.numbers AS a, system.numbers AS b, system.numbers AS c;
  1. SELECT
  2. `--a.number` AS `a.number`,
  3. `--b.number` AS `b.number`,
  4. number AS `c.number`
  5. FROM
  6. (
  7. SELECT
  8. number AS `--a.number`,
  9. b.number AS `--b.number`
  10. FROM system.numbers AS a
  11. CROSS JOIN system.numbers AS b
  12. ) AS `--.s`
  13. CROSS JOIN system.numbers AS c

EXPLAIN PLAN

Dump query plan steps.

Settings:

  • header — Prints output header for step. Default: 0.
  • description — Prints step description. Default: 1.
  • indexes — Shows used indexes, the number of filtered parts and the number of filtered granules for every index applied. Default: 0. Supported for MergeTree tables.
  • actions — Prints detailed information about step actions. Default: 0.
  • json — Prints query plan steps as a row in JSON format. Default: 0. It is recommended to use TSVRaw format to avoid unnecessary escaping.

Example:

  1. EXPLAIN SELECT sum(number) FROM numbers(10) GROUP BY number % 4;
  1. Union
  2. Expression (Projection)
  3. Expression (Before ORDER BY and SELECT)
  4. Aggregating
  5. Expression (Before GROUP BY)
  6. SettingQuotaAndLimits (Set limits and quota after reading from storage)
  7. ReadFromStorage (SystemNumbers)

Note

Step and query cost estimation is not supported.

When json = 1, the query plan is represented in JSON format. Every node is a dictionary that always has the keys Node Type and Plans. Node Type is a string with a step name. Plans is an array with child step descriptions. Other optional keys may be added depending on node type and settings.

Example:

  1. EXPLAIN json = 1, description = 0 SELECT 1 UNION ALL SELECT 2 FORMAT TSVRaw;
  1. [
  2. {
  3. "Plan": {
  4. "Node Type": "Union",
  5. "Plans": [
  6. {
  7. "Node Type": "Expression",
  8. "Plans": [
  9. {
  10. "Node Type": "SettingQuotaAndLimits",
  11. "Plans": [
  12. {
  13. "Node Type": "ReadFromStorage"
  14. }
  15. ]
  16. }
  17. ]
  18. },
  19. {
  20. "Node Type": "Expression",
  21. "Plans": [
  22. {
  23. "Node Type": "SettingQuotaAndLimits",
  24. "Plans": [
  25. {
  26. "Node Type": "ReadFromStorage"
  27. }
  28. ]
  29. }
  30. ]
  31. }
  32. ]
  33. }
  34. }
  35. ]

With description = 1, the Description key is added to the step:

  1. {
  2. "Node Type": "ReadFromStorage",
  3. "Description": "SystemOne"
  4. }

With header = 1, the Header key is added to the step as an array of columns.

Example:

  1. EXPLAIN json = 1, description = 0, header = 1 SELECT 1, 2 + dummy;
  1. [
  2. {
  3. "Plan": {
  4. "Node Type": "Expression",
  5. "Header": [
  6. {
  7. "Name": "1",
  8. "Type": "UInt8"
  9. },
  10. {
  11. "Name": "plus(2, dummy)",
  12. "Type": "UInt16"
  13. }
  14. ],
  15. "Plans": [
  16. {
  17. "Node Type": "SettingQuotaAndLimits",
  18. "Header": [
  19. {
  20. "Name": "dummy",
  21. "Type": "UInt8"
  22. }
  23. ],
  24. "Plans": [
  25. {
  26. "Node Type": "ReadFromStorage",
  27. "Header": [
  28. {
  29. "Name": "dummy",
  30. "Type": "UInt8"
  31. }
  32. ]
  33. }
  34. ]
  35. }
  36. ]
  37. }
  38. }
  39. ]

With indexes = 1, the Indexes key is added. It contains an array of used indexes. Each index is described as JSON with Type key (a string MinMax, Partition, PrimaryKey or Skip) and optional keys:

  • Name — An index name (for now, is used only for Skip index).
  • Keys — An array of columns used by the index.
  • Condition — A string with condition used.
  • Description — An index (for now, is used only for Skip index).
  • Initial Parts — A number of parts before the index is applied.
  • Selected Parts — A number of parts after the index is applied.
  • Initial Granules — A number of granules before the index is applied.
  • Selected Granulesis — A number of granules after the index is applied.

Example:

  1. "Node Type": "ReadFromMergeTree",
  2. "Indexes": [
  3. {
  4. "Type": "MinMax",
  5. "Keys": ["y"],
  6. "Condition": "(y in [1, +inf))",
  7. "Initial Parts": 5,
  8. "Selected Parts": 4,
  9. "Initial Granules": 12,
  10. "Selected Granules": 11
  11. },
  12. {
  13. "Type": "Partition",
  14. "Keys": ["y", "bitAnd(z, 3)"],
  15. "Condition": "and((bitAnd(z, 3) not in [1, 1]), and((y in [1, +inf)), (bitAnd(z, 3) not in [1, 1])))",
  16. "Initial Parts": 4,
  17. "Selected Parts": 3,
  18. "Initial Granules": 11,
  19. "Selected Granules": 10
  20. },
  21. {
  22. "Type": "PrimaryKey",
  23. "Keys": ["x", "y"],
  24. "Condition": "and((x in [11, +inf)), (y in [1, +inf)))",
  25. "Initial Parts": 3,
  26. "Selected Parts": 2,
  27. "Initial Granules": 10,
  28. "Selected Granules": 6
  29. },
  30. {
  31. "Type": "Skip",
  32. "Name": "t_minmax",
  33. "Description": "minmax GRANULARITY 2",
  34. "Initial Parts": 2,
  35. "Selected Parts": 1,
  36. "Initial Granules": 6,
  37. "Selected Granules": 2
  38. },
  39. {
  40. "Type": "Skip",
  41. "Name": "t_set",
  42. "Description": "set GRANULARITY 2",
  43. "Initial Parts": 1,
  44. "Selected Parts": 1,
  45. "Initial Granules": 2,
  46. "Selected Granules": 1
  47. }
  48. ]

With actions = 1, added keys depend on step type.

Example:

  1. EXPLAIN json = 1, actions = 1, description = 0 SELECT 1 FORMAT TSVRaw;
  1. [
  2. {
  3. "Plan": {
  4. "Node Type": "Expression",
  5. "Expression": {
  6. "Inputs": [],
  7. "Actions": [
  8. {
  9. "Node Type": "Column",
  10. "Result Type": "UInt8",
  11. "Result Type": "Column",
  12. "Column": "Const(UInt8)",
  13. "Arguments": [],
  14. "Removed Arguments": [],
  15. "Result": 0
  16. }
  17. ],
  18. "Outputs": [
  19. {
  20. "Name": "1",
  21. "Type": "UInt8"
  22. }
  23. ],
  24. "Positions": [0],
  25. "Project Input": true
  26. },
  27. "Plans": [
  28. {
  29. "Node Type": "SettingQuotaAndLimits",
  30. "Plans": [
  31. {
  32. "Node Type": "ReadFromStorage"
  33. }
  34. ]
  35. }
  36. ]
  37. }
  38. }
  39. ]

EXPLAIN PIPELINE

Settings:

  • header — Prints header for each output port. Default: 0.
  • graph — Prints a graph described in the DOT) graph description language. Default: 0.
  • compact — Prints graph in compact mode if graph setting is enabled. Default: 1.

Example:

  1. EXPLAIN PIPELINE SELECT sum(number) FROM numbers_mt(100000) GROUP BY number % 4;
  1. (Union)
  2. (Expression)
  3. ExpressionTransform
  4. (Expression)
  5. ExpressionTransform
  6. (Aggregating)
  7. Resize 2 1
  8. AggregatingTransform × 2
  9. (Expression)
  10. ExpressionTransform × 2
  11. (SettingQuotaAndLimits)
  12. (ReadFromStorage)
  13. NumbersMt × 2 0 1

EXPLAIN ESTIMATE

Shows the estimated number of rows, marks and parts to be read from the tables while processing the query. Works with tables in the MergeTree family.

Example

Creating a table:

  1. CREATE TABLE ttt (i Int64) ENGINE = MergeTree() ORDER BY i SETTINGS index_granularity = 16, write_final_mark = 0;
  2. INSERT INTO ttt SELECT number FROM numbers(128);
  3. OPTIMIZE TABLE ttt;

Query:

  1. EXPLAIN ESTIMATE SELECT * FROM ttt;

Result:

  1. ┌─database─┬─table─┬─parts─┬─rows─┬─marks─┐
  2. default ttt 1 128 8
  3. └──────────┴───────┴───────┴──────┴───────┘