> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentação do EXPLAIN

# Instrução EXPLAIN

Mostra o plano de execução de uma instrução.

<div class="vimeo-container">
  <Frame>
    <iframe
      src="//www.youtube.com/embed/hP6G2Nlz_cA"
      frameborder="0"
      allow="autoplay;
fullscreen;
picture-in-picture"
      allowfullscreen
    />
  </Frame>
</div>

Sintaxe:

```sql theme={null}
EXPLAIN [AST | SYNTAX | QUERY TREE | PLAN | PIPELINE | ANALYZE | ESTIMATE | TABLE OVERRIDE | WHATIF] [setting = value, ...]
    [
      SELECT ... |
      tableFunction(...) [COLUMNS (...)] [ORDER BY ...] [PARTITION BY ...] [PRIMARY KEY] [SAMPLE BY ...] [TTL ...]
    ]
    [FORMAT ...]
```

Exemplo:

```sql theme={null}
EXPLAIN SELECT sum(number) FROM numbers(10) UNION ALL SELECT sum(number) FROM numbers(10) ORDER BY sum(number) ASC FORMAT TSV;
```

```sql theme={null}
Output: sum(number)

Union
├──Aggregating
│  │  Keys:
│  │  Aggregates: sum(number)
│  │  Skip merging: 0
│  └──ReadFromSystemNumbers
│        Output: number
└──Sorting (Sorting for ORDER BY)
   │  Sort description: sum(number) ASC
   └──Aggregating
      │  Keys:
      │  Aggregates: sum(number)
      │  Skip merging: 0
      └──ReadFromSystemNumbers
            Output: number
```

<div id="explain-types">
  ## Tipos de EXPLAIN
</div>

* `AST` — Árvore de sintaxe abstrata.
* `SYNTAX` — Texto da consulta após otimizações no nível da AST.
* `QUERY TREE` — Árvore de consulta após otimizações no nível da árvore de consulta.
* `PLAN` — Plano de execução da consulta.
* `PIPELINE` — Pipeline de execução da consulta.
* `ANALYZE` — Executa a consulta e anota o plano de execução com métricas de runtime medidas.
* `ESTIMATE` — Número estimado de linhas, marcas e partes a serem lidas das tabelas durante o processamento da consulta.
* `TABLE OVERRIDE` — Resultado validado de um override de tabela em um esquema de função de tabela.

<div id="explain-ast">
  ### EXPLAIN AST
</div>

Exibe a AST da consulta. Compatível com todos os tipos de consulta, não apenas `SELECT`.

Configurações:

* `graph` – Exibe a AST como um grafo descrito na linguagem de descrição de grafos [DOT](https://en.wikipedia.org/wiki/DOT_\(graph_description_language\)). Padrão: 0.

Exemplos:

```sql theme={null}
EXPLAIN AST SELECT 1;
```

```sql theme={null}
SelectWithUnionQuery (children 1)
 ExpressionList (children 1)
  SelectQuery (children 1)
   ExpressionList (children 1)
    Literal UInt64_1
```

```sql theme={null}
EXPLAIN AST ALTER TABLE t1 DELETE WHERE date = today();
```

```sql theme={null}
  explain
  AlterQuery  t1 (children 1)
   ExpressionList (children 1)
    AlterCommand 27 (children 1)
     Function equals (children 1)
      ExpressionList (children 2)
       Identifier date
       Function today (children 1)
        ExpressionList
```

<div id="explain-syntax">
  ### EXPLAIN SYNTAX
</div>

Mostra a Árvore de Sintaxe Abstrata (AST) de uma consulta após a análise de sintaxe.

Isso é feito fazendo o parsing da consulta, construindo a AST e a árvore de consulta da consulta, opcionalmente executando o analisador de consultas e os passes de otimização, e então convertendo a árvore de consulta de volta para a AST da consulta.

Configurações:

* `oneline` – Imprime a consulta em uma única linha. Padrão: `0`.
* `run_query_tree_passes` – Executa os passes da árvore de consulta antes de exibi-la. Padrão: `0`.
* `query_tree_passes` – Se `run_query_tree_passes` estiver definido, especifica quantos passes executar. Sem especificar `query_tree_passes`, ele executa todos os passes.

Exemplos:

```sql title="Query" theme={null}
EXPLAIN SYNTAX SELECT * FROM system.numbers AS a, system.numbers AS b, system.numbers AS c WHERE a.number = b.number AND b.number = c.number;
```

```sql title="Response" theme={null}
SELECT *
FROM system.numbers AS a, system.numbers AS b, system.numbers AS c
WHERE (a.number = b.number) AND (b.number = c.number)
```

Usando `run_query_tree_passes`:

```sql title="Query" theme={null}
EXPLAIN SYNTAX run_query_tree_passes = 1 SELECT * FROM system.numbers AS a, system.numbers AS b, system.numbers AS c WHERE a.number = b.number AND b.number = c.number;
```

```sql title="Response" theme={null}
SELECT
    __table1.number AS `a.number`,
    __table2.number AS `b.number`,
    __table3.number AS `c.number`
FROM system.numbers AS __table1
ALL INNER JOIN system.numbers AS __table2 ON __table1.number = __table2.number
ALL INNER JOIN system.numbers AS __table3 ON __table2.number = __table3.number
```

<div id="explain-query-tree">
  ### EXPLAIN QUERY TREE
</div>

Configurações:

* `run_passes` — Executa todos os passes da árvore de consulta antes de exibir a árvore de consulta. Padrão: `1`.
* `dump_passes` — Exibe informações sobre os passes usados antes de exibir a árvore de consulta. Padrão: `0`.
* `passes` — Especifica quantos passes devem ser executados. Se definido como `-1`, executa todos os passes. Padrão: `-1`.
* `dump_tree` — Exibe a árvore de consulta. Padrão: `1`.
* `dump_ast` — Exibe a AST da consulta gerada a partir da árvore de consulta. Padrão: `0`.

Exemplo:

```sql theme={null}
EXPLAIN QUERY TREE SELECT id, value FROM test_table;
```

```sql theme={null}
QUERY id: 0
  PROJECTION COLUMNS
    id UInt64
    value String
  PROJECTION
    LIST id: 1, nodes: 2
      COLUMN id: 2, column_name: id, result_type: UInt64, source_id: 3
      COLUMN id: 4, column_name: value, result_type: String, source_id: 3
  JOIN TREE
    TABLE id: 3, table_name: default.test_table
```

<div id="explain-plan">
  ### EXPLAIN PLAN
</div>

Exibe os passos do plano de consulta.

Configurações:

* `optimize` — Controla se as otimizações do plano de consulta são aplicadas antes da exibição do plano. Padrão: 1.
* `header` — Exibe o cabeçalho de saída do passo. Padrão: 0.
* `description` — Exibe a descrição do passo. Padrão: 1.
* `indexes` — Mostra os índices usados, o número de partes filtradas e o número de grânulos filtrados para cada índice aplicado. Padrão: 0. Compatível com tabelas [MergeTree](/docs/pt-BR/reference/engines/table-engines/mergetree-family/mergetree). A partir do ClickHouse >= v25.9, esta instrução só exibe uma saída adequada quando usada com `SETTINGS use_query_condition_cache = 0, use_skip_indexes_on_data_read = 0`.
* `projections` — Mostra todas as projeções analisadas e seu efeito na filtragem no nível de partes com base nas condições da chave primária da projeção. Para cada projeção, esta seção inclui estatísticas como o número de partes, linhas, marcas e intervalos avaliados usando a chave primária da projeção. Também mostra quantas partes de dados foram ignoradas devido a essa filtragem, sem ler a própria projeção. Se uma projeção foi realmente usada para leitura ou apenas analisada para filtragem pode ser determinado pelo campo `description`. Padrão: 0. Compatível com tabelas [MergeTree](/docs/pt-BR/reference/engines/table-engines/mergetree-family/mergetree).
* `actions` — Exibe informações detalhadas sobre as ações do passo. Padrão: 1.
* `sorting` — Exibe a descrição da ordenação para cada passo do plano que produz saída ordenada. Padrão: 0.
* `keep_logical_steps` — Mantém os passos lógicos do plano para junções em vez de convertê-los em implementações físicas de junção. Padrão: 0.
* `json` — Exibe os passos do plano de consulta como uma linha no formato [JSON](/docs/pt-BR/reference/formats/JSON/JSON). Padrão: 0. Recomenda-se usar o formato [TabSeparatedRaw (TSVRaw)](/docs/pt-BR/reference/formats/TabSeparated/TabSeparatedRaw) para evitar escapes desnecessários.
* `input_headers` — Exibe os cabeçalhos de entrada do passo. Padrão: 0. Em geral, isso só é útil para desenvolvedores depurarem problemas relacionados à incompatibilidade entre cabeçalhos de entrada e saída.
* `column_structure` — Exibe também a estrutura das colunas nos cabeçalhos, além do nome e do tipo. Padrão: 0. Em geral, isso só é útil para desenvolvedores depurarem problemas relacionados à incompatibilidade entre cabeçalhos de entrada e saída.
* `distributed` — Mostra os planos de consulta executados em nós remotos para tabelas distribuídas ou réplicas paralelas. Não é compatível com `json`. Padrão: 0.
* `compact` — Quando ativado, oculta do plano os passos de expressão e as informações detalhadas das ações (entradas, funções, aliases e posições de saída). Só tem efeito quando `actions = 1`. Padrão: 1.
* `pretty` — Exibe a árvore do plano usando caracteres de desenho de linha (├──, └──, │) em vez de indentação para visualizar a hierarquia. Também formata as propriedades do passo de junção em linha. Padrão: 1.

<Note>
  Por padrão, `explain_query_plan_default = 'pretty'`, portanto `actions`, `compact` e `pretty` são inicializados com `1`, e o plano é renderizado na forma compacta, com formatação pretty e com anotações de ações. Especificar explicitamente qualquer uma dessas opções na instrução `EXPLAIN` (por exemplo, `EXPLAIN actions = 0, compact = 0, pretty = 0 SELECT ...`) sempre substitui o padrão.

  Antes do ClickHouse 26.7, os valores padrão de `actions`, `compact` e `pretty` eram `0`. Você ainda pode obter essa saída definindo `explain_query_plan_default = 'legacy'` (globalmente ou em `SETTINGS` por consulta) ou definindo `compatibility` para qualquer versão anterior à `26.7`.

  As opções `json` e `distributed` não habilitam os padrões de `pretty` (`actions`, `compact` e `pretty`), mesmo quando `explain_query_plan_default = 'pretty'`. Para incluir detalhes das ações na saída delas, defina `actions = 1` manualmente.
</Note>

Exemplo:

```sql theme={null}
EXPLAIN SELECT sum(number) FROM numbers(10) GROUP BY number % 4  LIMIT 1;
```

```sql theme={null}
Output: sum(number)

Limit (preliminary LIMIT)
│  Limit 1
│  Offset 0
└──Aggregating
   │  Keys: number MOD 4
   │  Aggregates: sum(number)
   │  Skip merging: 0
   └──ReadFromSystemNumbers
         Output: number
```

<Note>
  Não há suporte à estimativa de custo do passo e da consulta.
</Note>

Quando `json = 1`, o plano da consulta é representado em formato JSON. Cada nó é um dicionário que sempre tem as chaves `Node Type`, `Node Id` e `Plans`. `Node Type` é uma string com o nome do passo, e `Node Id` é um identificador exclusivo do passo (o nome do passo com um sufixo numérico, por exemplo, `Union_10`). `Plans` é um array com descrições dos passos filhos. Outras chaves opcionais podem ser adicionadas dependendo do tipo de nó e das configurações.

Exemplo:

```sql theme={null}
EXPLAIN json = 1, description = 0 SELECT 1 UNION ALL SELECT 2 FORMAT TSVRaw;
```

```json theme={null}
[
  {
    "Plan": {
      "Node Type": "Union",
      "Node Id": "Union_10",
      "Plans": [
        {
          "Node Type": "Expression",
          "Node Id": "Expression_13",
          "Plans": [
            {
              "Node Type": "ReadFromStorage",
              "Node Id": "ReadFromStorage_0"
            }
          ]
        },
        {
          "Node Type": "Expression",
          "Node Id": "Expression_16",
          "Plans": [
            {
              "Node Type": "ReadFromStorage",
              "Node Id": "ReadFromStorage_4"
            }
          ]
        }
      ]
    }
  }
]
```

Com `description` = 1, a chave `Description` é adicionada ao passo:

```json theme={null}
{
  "Node Type": "ReadFromStorage",
  "Description": "SystemOne"
}
```

Com `header` = 1, a chave `Header` é adicionada ao passo na forma de um array de colunas.

Exemplo:

```sql theme={null}
EXPLAIN json = 1, description = 0, header = 1 SELECT 1, 2 + dummy;
```

```json theme={null}
[
  {
    "Plan": {
      "Node Type": "Expression",
      "Node Id": "Expression_5",
      "Header": [
        {
          "Name": "1",
          "Type": "UInt8"
        },
        {
          "Name": "plus(2, dummy)",
          "Type": "UInt16"
        }
      ],
      "Plans": [
        {
          "Node Type": "ReadFromStorage",
          "Node Id": "ReadFromStorage_0",
          "Header": [
            {
              "Name": "dummy",
              "Type": "UInt8"
            }
          ]
        }
      ]
    }
  }
]
```

Com `indexes` = 1, a chave `Indexes` é adicionada. Ela contém um array dos índices usados. Cada índice é descrito como JSON com a chave `Type` (uma string `Partition Min-Max`, `Partition`, `Statistics`, `PrimaryKey` ou `Skip`) e chaves opcionais:

* `Name` — O nome do índice (atualmente usado apenas para índices `Skip`).
* `Keys` — O array de colunas usado pelo índice.
* `Condition` — A condição usada.
* `Description` — A descrição do índice (atualmente usada apenas para índices `Skip`).
* `Parts` — O número de partes após/antes da aplicação do índice.
* `Granules` — O número de grânulos após/antes da aplicação do índice.
* `Ranges` — O número de intervalos de grânulos após a aplicação do índice.

Exemplo:

```json theme={null}
"Node Type": "ReadFromMergeTree",
"Indexes": [
  {
    "Type": "Partition Min-Max",
    "Keys": ["y"],
    "Condition": "(y in [1, +inf))",
    "Parts": 4/5,
    "Granules": 11/12
  },
  {
    "Type": "Partition",
    "Keys": ["y", "bitAnd(z, 3)"],
    "Condition": "and((bitAnd(z, 3) not in [1, 1]), and((y in [1, +inf)), (bitAnd(z, 3) not in [1, 1])))",
    "Parts": 3/4,
    "Granules": 10/11
  },
  {
    "Type": "PrimaryKey",
    "Keys": ["x", "y"],
    "Condition": "and((x in [11, +inf)), (y in [1, +inf)))",
    "Parts": 2/3,
    "Granules": 6/10,
    "Search Algorithm": "generic exclusion search"
  },
  {
    "Type": "Skip",
    "Name": "t_minmax",
    "Description": "minmax GRANULARITY 2",
    "Parts": 1/2,
    "Granules": 2/6
  },
  {
    "Type": "Skip",
    "Name": "t_set",
    "Description": "set GRANULARITY 2",
    "": 1/1,
    "Granules": 1/2
  }
]
```

Com `projections` = 1, a chave `Projections` é adicionada. Ela contém um array de projeções analisadas. Cada projeção é descrita como JSON com as seguintes chaves:

* `Name` — O nome da projeção.
* `Condition` — A condição da chave primária usada pela projeção.
* `Description` — A descrição de como a projeção é usada (por exemplo, filtragem em nível de partes).
* `Selected Parts` — Número de partes selecionadas pela projeção.
* `Selected Marks` — Número de marcas selecionadas.
* `Selected Ranges` — Número de intervalos selecionados.
* `Selected Rows` — Número de linhas selecionadas.
* `Filtered Parts` — Número de partes ignoradas devido à filtragem em nível de partes.

Exemplo:

```json theme={null}
"Node Type": "ReadFromMergeTree",
"Projections": [
  {
    "Name": "region_proj",
    "Description": "Projection has been analyzed and is used for part-level filtering",
    "Condition": "(region in ['us_west', 'us_west'])",
    "Search Algorithm": "binary search",
    "Selected Parts": 3,
    "Selected Marks": 3,
    "Selected Ranges": 3,
    "Selected Rows": 3,
    "Filtered Parts": 2
  },
  {
    "Name": "user_id_proj",
    "Description": "Projection has been analyzed and is used for part-level filtering",
    "Condition": "(user_id in [107, 107])",
    "Search Algorithm": "binary search",
    "Selected Parts": 1,
    "Selected Marks": 1,
    "Selected Ranges": 1,
    "Selected Rows": 1,
    "Filtered Parts": 2
  }
]
```

Com `actions` = 1, as chaves adicionadas dependem do tipo de passo.

Exemplo:

```sql theme={null}
EXPLAIN json = 1, actions = 1, description = 0 SELECT 1 FORMAT TSVRaw;
```

```json theme={null}
[
  {
    "Plan": {
      "Node Type": "Expression",
      "Node Id": "Expression_5",
      "Expression": {
        "Inputs": [
          {
            "Name": "dummy",
            "Type": "UInt8"
          }
        ],
        "Actions": [
          {
            "Node Type": "INPUT",
            "Result Type": "UInt8",
            "Result Name": "dummy",
            "Arguments": [0],
            "Removed Arguments": [0],
            "Result": 0
          },
          {
            "Node Type": "COLUMN",
            "Result Type": "UInt8",
            "Result Name": "1",
            "Column": "Const(UInt8)",
            "Arguments": [],
            "Removed Arguments": [],
            "Result": 1
          }
        ],
        "Outputs": [
          {
            "Name": "1",
            "Type": "UInt8"
          }
        ],
        "Positions": [1]
      },
      "Plans": [
        {
          "Node Type": "ReadFromStorage",
          "Node Id": "ReadFromStorage_0"
        }
      ]
    }
  }
]
```

Com `compact = 0` e `actions = 1`, os passos de `Expression` podem ser vistos juntamente com informações detalhadas sobre as expressões:

```sql theme={null}
EXPLAIN actions = 1, compact = 0 SELECT sum(number) FROM numbers(10) GROUP BY number % 4;
```

```text theme={null}
Output: sum(number)

Expression ((Project names + Projection))
│  Actions: INPUT : 0 -> sum(__table1.number) UInt64 : 0
│           INPUT :: 1 -> modulo(__table1.number, 4_UInt8) UInt8 : 1
│           ALIAS sum(__table1.number) :: 0 -> sum(number) UInt64 : 2
│  Positions: 2
└──Aggregating
   │  Keys: number MOD 4
   │  Aggregates: sum(number)
   │  Skip merging: 0
   └──Expression ((Before GROUP BY + Change column names to column identifiers))
      │  Actions: INPUT : 0 -> number UInt64 : 0
      │           COLUMN Const(UInt8) -> 4_UInt8 UInt8 : 1
      │           ALIAS number :: 0 -> __table1.number UInt64 : 2
      │           FUNCTION modulo(__table1.number : 2, 4_UInt8 :: 1) -> modulo(__table1.number, 4_UInt8) UInt8 : 0
      │  Positions: 0 2
      └──ReadFromSystemNumbers
            Output: number
```

Com `distributed` = 1, a saída inclui não apenas o plano de consulta local, mas também os planos de consulta que serão executados nos nós remotos. Isso é útil para analisar e depurar consultas distribuídas.

<Note>
  `distributed` é exibido apenas na forma `legacy` (sem `pretty`), porque a saída `pretty` não integra os planos de shard remotos à árvore do plano. Por esse motivo, habilitar `distributed` desabilita automaticamente os padrões de `pretty` (`actions`, `compact` e `pretty`), independentemente de `explain_query_plan_default`. Você ainda pode definir `actions=1` manualmente. A opção `distributed` também não é compatível com `json`.
</Note>

Exemplo com tabela distribuída:

```sql theme={null}
EXPLAIN distributed=1 SELECT * FROM remote('127.0.0.{1,2}', numbers(2)) WHERE number = 1;
```

```sql theme={null}
Union
  Expression ((Project names + (Projection + (Change column names to column identifiers + (Project names + Projection)))))
    Filter ((WHERE + Change column names to column identifiers))
      ReadFromSystemNumbers
  Expression ((Project names + (Projection + Change column names to column identifiers)))
    ReadFromRemote (Read from remote replica)
      Expression ((Project names + Projection))
        Filter ((WHERE + Change column names to column identifiers))
          ReadFromSystemNumbers
```

Exemplo com réplicas paralelas:

```sql theme={null}
SET enable_parallel_replicas = 2, max_parallel_replicas = 2, cluster_for_parallel_replicas = 'default';

EXPLAIN distributed=1 SELECT sum(number) FROM test_table GROUP BY number % 4;
```

```sql theme={null}
Expression ((Project names + Projection))
  MergingAggregated
    Union
      Aggregating
        Expression ((Before GROUP BY + Change column names to column identifiers))
          ReadFromMergeTree (default.test_table)
      ReadFromRemoteParallelReplicas
        BlocksMarshalling
          Aggregating
            Expression ((Before GROUP BY + Change column names to column identifiers))
              ReadFromMergeTree (default.test_table)
```

Em ambos os exemplos, o plano de consulta exibe o fluxo de execução completo, incluindo etapas locais e remotas.

Com `pretty` = 1, a árvore do plano é exibida usando caracteres de desenho de linhas em vez de recuo, e informações adicionais são mostradas para os passos principais:

* As **colunas de saída da consulta** são exibidas no topo do plano.
* **Expressões** em filtros, chaves de agregação, descrições de ordenação e funções de janela são exibidas em uma notação semelhante a SQL legível por humanos (por exemplo, `a + 1 > 5` em vez de `greater(plus(a, 1), 5)`). Os prefixos internos de identificadores de coluna (como `__table1.`) são removidos para maior clareza.
* **Passos de origem** (como `ReadFromMergeTree`) exibem suas colunas de saída.
* **Passos de filtro** exibem a condição de filtro em notação SQL. Quando há filtros de join em tempo de execução, eles são mostrados separadamente.
* **Passos de agregação** exibem chaves e funções de agregação com seus argumentos (por exemplo, `sum(c)`, `count()`).
* **Conjuntos de `IN`** de literais Tuple mostram seus valores (truncados para conjuntos grandes), conjuntos baseados em subconsulta são rotulados como `subquery1`, `subquery2` etc., e conjuntos de tabelas com o motor `Set` mostram o nome da tabela.
* **Passos de join** exibem a relação de join usando notação matemática, a contagem estimada de linhas do resultado,
  e quais colunas de saída vêm do lado esquerdo e do lado direito. Os símbolos a seguir são usados para
  representar diferentes tipos de join:

| Símbolo                | Tipo de junção         |
| ---------------------- | ---------------------- |
| `⋈`                    | Junção interna         |
| `⟕`                    | Junção à esquerda      |
| `⟖`                    | Junção à direita       |
| `⟗`                    | Junção completa        |
| `⋉`                    | Junção semi à esquerda |
| `⋊`                    | Junção semi à direita  |
| `⋉` with strikethrough | Junção anti à esquerda |
| `⋊` with strikethrough | Junção anti à direita  |
| `×`                    | Junção cruzada         |

Por exemplo, `t1 ⟕ t2` significa uma junção à esquerda entre as tabelas `t1` e `t2`.
O número entre colchetes após o nome da tabela (por exemplo, `t1[100]`) indica a contagem estimada de linhas
quando há estatísticas da tabela disponíveis.

A opção `pretty` funciona bem em conjunto com `compact = 1`, que oculta os passos `Expression` e as informações detalhadas de ações, tornando o plano mais fácil de ler.

Um exemplo detalhado com junções:

```sql theme={null}
CREATE TABLE t1 (id UInt64, value String) ENGINE = MergeTree ORDER BY id;
CREATE TABLE t2 (id UInt64, value String) ENGINE = MergeTree ORDER BY id;
INSERT INTO t1 SELECT number, toString(number) FROM numbers(100);
INSERT INTO t2 SELECT number, toString(number) FROM numbers(100);

EXPLAIN actions = 1, compact = 1, pretty = 1
SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.id FORMAT Raw;
```

```text theme={null}
Output: id, value, id, value

Join (JOIN FillRightFirst)
│  t1[100] ⋈ t2[100]
│  Type: inner | Strictness: all | Algorithm: SpillingHashJoin(HashJoin)
│  Result rows: 100
│  Join conditions: id = id
│  Output:
│    Left:  id, value
│    Right: id, value
├──ReadFromMergeTree (default.t1)
│     Read type: Default
│     Parts: 1 | Granules: 1
│     Output: id, value
│     Runtime filters: RF1(id, id from default.t2)
└──BuildRuntimeFilter (Build runtime join filter on id)
   │  Filter id: RF1
   │  Source table: default.t2
   └──ReadFromMergeTree (default.t2)
         Read type: Default
         Parts: 1 | Granules: 1
         Output: id, value
```

<div id="explain-pipeline">
  ### EXPLAIN PIPELINE
</div>

Configurações:

* `header` — Imprime o cabeçalho de cada porta de saída. Padrão: 0.
* `graph` — Imprime um grafo descrito na linguagem de descrição de grafos [DOT](https://en.wikipedia.org/wiki/DOT_\(graph_description_language\)). Padrão: 0.
* `compact` — Imprime o grafo no modo compacto se a configuração `graph` estiver habilitada. Padrão: 1.
* `compact_repeated_processor_chains` — Compacta cadeias repetidas adjacentes de processadores na saída de texto, mostrando uma cópia da cadeia com uma contagem de repetições. Isso pode facilitar a leitura de pipelines paralelos quando a mesma cadeia aparece muitas vezes, por exemplo, em junções. Isso não afeta a saída do grafo. Padrão: 0.

```text theme={null}
Resize 16 → 1
  FillingRightJoinSide          │
    SimpleSquashingTransform    │ × 16
      Resize 1 → 16
```

Quando `compact=0` e `graph=1`, os nomes dos processadores conterão um sufixo adicional com um identificador exclusivo do processador.

Exemplo:

```sql theme={null}
EXPLAIN PIPELINE SELECT sum(number) FROM numbers_mt(100000) GROUP BY number % 4;
```

```sql theme={null}
(Union)
(Expression)
ExpressionTransform
  (Expression)
  ExpressionTransform
    (Aggregating)
    Resize 2 → 1
      AggregatingTransform × 2
        (Expression)
        ExpressionTransform × 2
          (SettingQuotaAndLimits)
            (ReadFromStorage)
            NumbersRange × 2 0 → 1
```

<div id="explain-analyze">
  ### EXPLAIN ANALYZE
</div>

`EXPLAIN ANALYZE` de fato executa a consulta, descarta as linhas de resultado e imprime a mesma árvore de plano que `EXPLAIN PLAN`, com cada passo anotado com o que realmente aconteceu em tempo de execução.

Configurações:

`EXPLAIN ANALYZE` aceita as mesmas opções de exibição que `EXPLAIN PLAN` (documentadas na seção [EXPLAIN PLAN](#explain-plan)).

* `header` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `description` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `projections` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `sorting` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `input_headers` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `column_structure` — consulte a seção [EXPLAIN PLAN](#explain-plan).
* `actions` — consulte a seção [EXPLAIN PLAN](#explain-plan). Padrão: 1.
* `indexes` — consulte a seção [EXPLAIN PLAN](#explain-plan). Padrão: 1.
* `compact` — consulte a seção [EXPLAIN PLAN](#explain-plan). Padrão: 1.
* `pretty` — consulte a seção [EXPLAIN PLAN](#explain-plan). Padrão: 1.
* `processors` — Para `EXPLAIN ANALYZE`, imprime uma linha adicional por estágio com a distribuição do tempo decorrido por processador: `min`, `median`, `max` e `sum`. Útil para identificar desequilíbrio de carga entre processadores paralelos. Padrão: 0.

<Note>
  Como `EXPLAIN ANALYZE` realmente executa a consulta encapsulada, ele se comporta como essa
  consulta — e, diferentemente das formas `EXPLAIN` que não executam — de várias maneiras:

  * **Cotas e limites.** Ele é contabilizado nas mesmas [quotas](/docs/pt-BR/concepts/features/configuration/server-config/quotas)
    e está sujeito aos mesmos [limits](/docs/pt-BR/concepts/features/configuration/settings/query-complexity)
    (por exemplo, `query_selects`, `read_rows`) que a execução direta da consulta. Fontes isentas de cotas durante o planejamento
    (como `system.one`) não são contabilizadas.
  * **Transações com falha.** Dentro de uma [transação](/docs/pt-BR/concepts/features/operations/insert/transactions)
    que já falhou (`ROLLED_BACK`), ele é rejeitado com `INVALID_TRANSACTION`,
    assim como uma instrução `SELECT` simples — emita `ROLLBACK` primeiro.
  * **Leituras de streaming.** Em uma leitura de streaming (`FROM ... STREAM`), ele é rejeitado com
    `NOT_IMPLEMENTED`, porque esse tipo de leitura nunca termina.
  * **Consultas distribuídas.** Não há suporte para ele em consultas executadas em
    modo [Distributed](/docs/pt-BR/reference/engines/table-engines/special/distributed).
</Note>

Exemplo:

```sql theme={null}
EXPLAIN ANALYZE SELECT number % 10 AS k, count() FROM numbers_mt(1000000) GROUP BY k;
```

```text theme={null}
Query summary:
  Time:        10.72 ms (planning 6.45 ms · execution 4.26 ms)
  Read:        1.00 million rows, 8.00 MB (234.49 million rows/s., 1.88 GB/s.)
  Peak memory: 28.98 KiB

Output: number MOD 10, count()

Expression ((Project names + Projection))
│  I/O: rows 10 → 10 · 90 B → 90 B
│    time 21.82 us (0.5%) · parallelism 0.98/1
└──Aggregating
   │  Keys: number MOD 10
   │  Aggregates: count()
   │  Skip merging: 0
   │  I/O: rows 1.00 million → 10 (0.00%) · 1.00 MB → 90 B
   │    Stage (partial aggregation): time 868.45 us (20.4%) · parallelism 3.80/15
   │    Stage (final aggregation): time 445.27 us (10.4%) · parallelism 1.11/16
   └──Expression ((Before GROUP BY + Change column names to column identifiers))
      │  I/O: rows 1.00 million → 1.00 million · 8.00 MB → 1.00 MB
      │    time 677.07 us (15.9%) · parallelism 4.31/15
      └──ReadFromSystemNumbers
            Output: number
            I/O: rows 0 → 1.00 million · 0 B → 8.00 MB
              time 993.94 us (23.3%) · parallelism 7.52/15
```

Vamos examinar a saída. Primeiro, vamos ver o cabeçalho.

```txt theme={null}
   Query summary:
     Time:        <total> (planning <planning> · execution <execution>)
     Read:        <rows> rows, <bytes> (<rows/s>, <bytes/s>)
     Peak memory: <peak>
```

* `Time` — tempo total dividido entre as fases de planejamento (isto é, criação do plano + otimização do plano + construção do pipeline) e execução (execução do pipeline).
* `Read` — linhas e bytes não comprimidos lidos das tabelas, com a taxa de transferência — os mesmos números que o rodapé padrão da consulta informa como "Processed".
* `Peak memory` — pico de memória usado pela consulta.

Agora vamos examinar as novas linhas que aparecem no plano da consulta.

```txt theme={null}
I/O: rows <in> → <out> (<selectivity>%) · <bytes_in> → <bytes_out>
  [Stage (<stage>): ]time <t> (<share>%) · parallelism <avg>/<max>
```

Linhas e bytes são informados uma vez para todo o passo (a linha `I/O`). O tempo e o paralelismo são informados por estágio do passo nas linhas indentadas abaixo.

* `rows <in> → <out>` — linhas que entraram e saíram do passo; (`<selectivity>`%) mostra o quanto o passo filtrou (`out/in`) ou expandiu os dados; fica oculto quando as linhas de entrada são iguais às linhas de saída e quando as linhas de entrada são iguais a `0`.
* `<bytes_in> → <bytes_out>` — bytes não comprimidos em memória que passam pelo passo (omitido quando ambos são zero).
* `time <t> (<share>%)` — tempo de relógio em que o estágio esteve ativo e sua participação no tempo de execução da consulta (isto é, sem o tempo de compilação). Observe que as participações podem somar mais de 100%, porque estágios e passos são executados de forma concorrente.
* `parallelism <avg>/<max>` — número médio de threads de CPU trabalhando ao mesmo tempo neste estágio, do máximo que ele poderia usar. Um valor próximo do máximo significa que o estágio foi bem paralelizado; próximo de 1 significa que ele foi executado principalmente de forma serial.
* `Stage (<stage>)` — o nome do estágio. Um passo com um único estágio imprime a linha de tempo diretamente, sem um rótulo `Stage (...)`. Passos com vários estágios imprimem uma linha identificada para cada estágio; por exemplo, `Aggregating` mostra `Stage (partial aggregation)` e `Stage (final aggregation)`, e um hash join mostra `Stage (build)` e `Stage (probe)`.

<Note>
  O ClickHouse paraleliza não apenas a execução de tarefas dentro de um passo do plano, mas também a execução dos próprios passos do plano. A métrica `parallelism` reflete apenas o trabalho deste passo. Outros passos podem ser executados de forma concorrente, portanto esse número não mostra como o paralelismo do passo se compara ao da consulta como um todo.
</Note>

<Note>
  O número máximo em `parallelism` é calculado como o valor mínimo entre:

  1. o número total de tarefas dentro do passo do plano;
  2. o número máximo de threads de processamento de consultas definido em `max_threads`.
</Note>

Com `processors = 1`, uma linha extra é impressa abaixo de cada estágio, mostrando a distribuição do tempo decorrido entre os processadores do estágio:

```txt theme={null}
Time per processor (<n>): min <t> · median <t> · max <t> · sum <t>
```

`<n>` é o número de processadores no estágio. Uma grande diferença entre `median` e `max` indica um desequilíbrio de carga entre processadores paralelos.

<div id="explain-estimate">
  ### EXPLAIN ESTIMATE
</div>

Mostra o número estimado de linhas, marcas e partes que serão lidas das tabelas durante o processamento da consulta. Funciona com tabelas da família [MergeTree](/docs/pt-BR/reference/engines/table-engines/mergetree-family/mergetree).

**Exemplo**

Criando uma tabela:

```sql title="Query" theme={null}
CREATE TABLE ttt (i Int64) ENGINE = MergeTree() ORDER BY i SETTINGS index_granularity = 16, write_final_mark = 0;
INSERT INTO ttt SELECT number FROM numbers(128);
OPTIMIZE TABLE ttt;
```

```sql title="Query" theme={null}
EXPLAIN ESTIMATE SELECT * FROM ttt;
```

```text title="Response" theme={null}
┌─database─┬─table─┬─parts─┬─rows─┬─marks─┐
│ default  │ ttt   │     1 │  128 │     8 │
└──────────┴───────┴───────┴──────┴───────┘
```

<div id="explain-whatif">
  ### EXPLAIN WHATIF
</div>

Estima o benefício que um skip index hipotético teria em uma consulta `SELECT`, *sem* materializar o índice em disco. Defina um ou mais candidatos com [`CREATE HYPOTHETICAL INDEX`](/docs/pt-BR/reference/statements/hypothetical-index#create-hypothetical-index) e, em seguida, execute `EXPLAIN WHATIF SELECT ...` para ver, para cada candidato: aplicabilidade, marcas lidas estimadas, bytes estimados e taxa de descarte.

**Sintaxe**

```sql theme={null}
EXPLAIN WHATIF [empirical = 0] SELECT ...
```

**Configurações**

* `empirical` — `1` (padrão) executa o índice em memória sobre os grânulos filtrados pela referência para medir a taxa de descarte (um limite superior). `0` ignora esse caminho. De qualquer forma, se `empirical` não produzir um resultado (por estar desabilitado ou porque o índice não pode ser avaliado em memória), o estimador recorre às [estatísticas](/docs/pt-BR/reference/engines/table-engines/mergetree-family/mergetree#column-statistics) da coluna e, por fim, a um resumo apenas de aplicabilidade se nenhuma das duas opções estiver disponível.

**Saída**

```text theme={null}
Baseline (after PK + partition + existing indexes):
  table:       db.t
  parts:       1
  marks:       100
  est_bytes:   1.50 MiB             (only when the query reads rows)

With idx_b (minmax, hypothetical):
  status:       applicable
  marks:        1
  est_bytes:    15.00 KiB           (only when baseline bytes are known)
  skip_ratio:   99.0%

Estimation:
  source:           empirical | statistical | applicability_only
  empirical_status: ok | unsupported | disabled
  sampled_parts:    50 / 100        (only when source = empirical)
  sampled_marks:    50 / 100        (only when source = empirical)
  elapsed_us:       631             (only when source = empirical)
```

* `source` — como a estimativa foi gerada.
  * `empirical`: construiu o índice em memória sobre os grânulos remanescentes após o pruning de referência e contou os grânulos que o índice pularia. Este é um limite superior — veja as limitações em [`CREATE HYPOTHETICAL INDEX`](/docs/pt-BR/reference/statements/hypothetical-index#limitations).
  * `statistical`: derivado de estatísticas de coluna. Usado quando a estimativa empírica está desabilitada (`empirical = 0`) ou não conseguiu produzir um resultado, e há estatísticas de coluna definidas nas colunas relevantes.
  * `applicability_only`: o índice é aplicável ao predicado, mas nem a estimativa empírica nem a estatística produziram um resultado (por exemplo, `empirical = 0` e nenhuma estatística de coluna definida). Informa `skip_ratio: 0.0%` como um limite conservador.
* `sampled_parts` / `sampled_marks` — `<baseline-pruned> / <total in the table>`. Mostra que fração da tabela restou após o pruning por PK, partição e índices existentes, ou seja, a entrada para o índice hipotético.
* `est_bytes` — uma estimativa dos bytes lidos, derivada do tamanho médio de linha da tabela; por isso, é aproximada e varia conforme o armazenamento e a compressão. A linha de referência aparece apenas quando a consulta lê linhas; a linha de cada candidato, apenas quando a estimativa de bytes da linha de referência é conhecida.

A configuração é escrita inline entre `WHATIF` e `SELECT` — não há palavra-chave `SETTINGS` (isso corresponde à forma como outras variantes de `EXPLAIN` aceitam suas opções).

Se nenhum índice hipotético estiver definido para a tabela, `EXPLAIN WHATIF` informa `status: not_applicable` com uma dica para criar um.

**Linha combinada (múltiplos candidatos)**

Quando dois ou mais candidatos são avaliados empiricamente, `EXPLAIN WHATIF` acrescenta um bloco extra chamado `(combined: idx_a, idx_b, ...)` após as linhas de cada candidato. Ele informa o benefício conjunto de ter *todos* esses índices ao mesmo tempo: uma leitura real mantém um grânulo apenas se ele sobreviver a *todos* os skip indexes, portanto a estimativa combinada é a interseção dos grânulos sobreviventes dos candidatos. Seu `skip_ratio` é, portanto, pelo menos tão alto quanto o do melhor candidato individual — índices complementares fazem mais pruning em conjunto, enquanto índices redundantes o mantêm inalterado.

Só contribuem os candidatos com `source: empirical`, porque a linha combinada é formada pela interseção dos conjuntos de sobrevivência por grânulo de cada um. Os candidatos estimados como `statistical` ou `applicability_only` não têm dados por grânulo e são excluídos; consequentemente, o bloco combinado aparece somente quando pelo menos dois candidatos produziram uma estimativa empírica, e é omitido caso contrário (por exemplo, com `empirical = 0`). Seus campos de estimativa são os mesmos de um bloco empírico por candidato, exceto que `elapsed_us` é `0` — a estimativa combinada é derivada das varreduras por candidato, não de uma nova varredura. O nome sintético `(combined: ...)` é apenas um rótulo do relatório e não pode ser usado com `force_data_skipping_indices`.

**Exemplo empírico**

```sql theme={null}
CREATE TABLE t (a UInt64, b UInt64) ENGINE = MergeTree ORDER BY a
SETTINGS index_granularity = 100;

INSERT INTO t SELECT number, number FROM numbers(10000);

CREATE HYPOTHETICAL INDEX idx_b ON t (b) TYPE minmax GRANULARITY 1;

EXPLAIN WHATIF SELECT * FROM t WHERE b = 42;
```

```text theme={null}
Baseline (after PK + partition + existing indexes):
  table:       default.t
  parts:       1
  marks:       100
  est_bytes:   85.52 KiB

With idx_b (minmax, hypothetical):
  status:       applicable
  marks:        1
  est_bytes:    875.00 B
  skip_ratio:   99.0%

Estimation:
  source:           empirical
  empirical_status: ok
  sampled_parts:    1 / 1
  sampled_marks:    100 / 100
```

O `minmax` hipotético reduziria de 100 marcas para 1 — `skip_ratio: 99.0%`. (`est_bytes` é uma estimativa com base no tamanho médio da linha, portanto o valor exato varia.)

**Exemplo estatístico**

As [estatísticas](/docs/pt-BR/reference/engines/table-engines/mergetree-family/mergetree#column-statistics) de coluna vêm desativadas por padrão. Para usar o caminho `statistical`, primeiro defina-as nas colunas relevantes e aguarde a conclusão da mutação de materialização:

```sql theme={null}
ALTER TABLE t ADD STATISTICS b TYPE TDigest;
ALTER TABLE t MATERIALIZE STATISTICS b SETTINGS mutations_sync = 1;
```

Em seguida, desative o caminho empírico para que o estimador passe a usar as estatísticas de coluna:

```sql theme={null}
EXPLAIN WHATIF empirical = 0 SELECT * FROM t WHERE b < 10;
```

```text theme={null}
With idx_b (minmax, hypothetical):
  status:       applicable
  marks:        1
  est_bytes:    1.66 KiB
  skip_ratio:   99.9%

Estimation:
  source:           statistical
  empirical_status: disabled
```

O número vem da seletividade das estatísticas da coluna de `b < 10` (cerca de 10 linhas em 10000) e é informado como um limite superior de `skip_ratio`. Não há `sampled_parts` / `sampled_marks` — nenhum dado foi lido.

Se nenhum dos dois caminhos estiver disponível (por exemplo, `empirical = 0` e nenhuma estatística de coluna definida), o estimador informa `source: applicability_only` e um `skip_ratio: 0.0%` conservador.

<div id="explain-table-override">
  ### EXPLAIN TABLE OVERRIDE
</div>

Mostra o resultado de um override de tabela em um esquema acessado por meio de uma função de tabela.
Também faz algumas validações, gerando uma exceção se o override causar algum tipo de falha.

**Exemplo**

Suponha que você tenha uma tabela MySQL remota como esta:

```sql title="Query" theme={null}
CREATE TABLE db.tbl (
    id INT PRIMARY KEY,
    created DATETIME DEFAULT now()
)
```

```sql title="Query" theme={null}
EXPLAIN TABLE OVERRIDE mysql('127.0.0.1:3306', 'db', 'tbl', 'root', 'clickhouse')
PARTITION BY toYYYYMM(assumeNotNull(created))
```

```text title="Response" theme={null}
┌─explain─────────────────────────────────────────────────┐
│ PARTITION BY uses columns: `created` Nullable(DateTime) │
└─────────────────────────────────────────────────────────┘
```

<Note>
  A validação não está completa, portanto uma consulta bem-sucedida não garante que o override não cause problemas.
</Note>
