> ## 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.

> EXPLAIN に関するドキュメント

# EXPLAIN ステートメント

ステートメントの実行計画を表示します。

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

構文:

```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 ...]
```

例:

```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">
  ## EXPLAIN の種類
</div>

* `AST` — 抽象構文木。
* `SYNTAX` — AST レベルでの最適化後のクエリテキスト。
* `QUERY TREE` — クエリツリー レベルでの最適化後のクエリツリー。
* `PLAN` — クエリ実行プラン。
* `PIPELINE` — クエリ実行パイプライン。
* `ANALYZE` — クエリを実行し、計測されたランタイムメトリクスを実行計画に注釈として付加します。
* `ESTIMATE` — クエリの処理中にテーブルから読み取ると見積もられる行数、マーク数、パーツ数。
* `TABLE OVERRIDE` — テーブル関数のスキーマに対するテーブルオーバーライドの検証済み結果。

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

クエリASTをダンプします。`SELECT` だけでなく、あらゆる種類のクエリをサポートします。

設定:

* `graph` – [DOT](https://en.wikipedia.org/wiki/DOT_\(graph_description_language\)) グラフ記述言語で記述されたグラフとして AST を出力します。デフォルト: 0。

例:

```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>

構文解析後のクエリの抽象構文木 (AST) を表示します。

これは、クエリをパースしてクエリASTとクエリツリーを構築し、必要に応じてクエリアナライザと最適化パスを実行したうえで、クエリツリーをクエリASTに再変換することで行われます。

設定:

* `oneline` – クエリを1行で表示します。デフォルト: `0`。
* `run_query_tree_passes` – クエリツリーをダンプする前にクエリツリーパスを実行します。デフォルト: `0`。
* `query_tree_passes` – `run_query_tree_passes` が設定されている場合、実行するパス数を指定します。`query_tree_passes` を指定しない場合は、すべてのパスが実行されます。

例:

```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)
```

`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>

設定:

* `run_passes` — クエリツリーをダンプする前に、すべてのクエリツリーパスを実行します。デフォルト: `1`。
* `dump_passes` — クエリツリーをダンプする前に、使用されるパスの情報をダンプします。デフォルト: `0`。
* `passes` — 実行するパスの数を指定します。`-1` に設定すると、すべてのパスを実行します。デフォルト: `-1`。
* `dump_tree` — クエリツリーを表示します。デフォルト: `1`。
* `dump_ast` — クエリツリーから生成されたクエリ AST を表示します。デフォルト: `0`。

例:

```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>

クエリプランのステップを出力します。

設定:

* `optimize` — プランを表示する前に、クエリプランの最適化を適用するかどうかを制御します。デフォルト: 1。
* `header` — ステップの出力ヘッダーを表示します。デフォルト: 0。
* `description` — ステップの説明を表示します。デフォルト: 1。
* `indexes` — 使用された索引、フィルタリングされたパーツ数、および適用された各索引についてフィルタリングされたグラニュール数を表示します。デフォルト: 0。[MergeTree](/docs/ja/reference/engines/table-engines/mergetree-family/mergetree) テーブルでサポートされています。ClickHouse >= v25.9 以降、このステートメントが適切な出力を示すのは、`SETTINGS use_query_condition_cache = 0, use_skip_indexes_on_data_read = 0` とともに使用した場合のみです。
* `projections` — 解析されたすべてのプロジェクションと、プロジェクションの主キー条件に基づくパーツレベルのフィルタリングへの影響を表示します。各プロジェクションについて、このセクションには、プロジェクションの主キーを使って評価されたパーツ数、行数、マーク数、範囲数などの統計が含まれます。また、このフィルタリングにより、プロジェクション自体を読み取ることなくスキップされた data parts の数も表示します。プロジェクションが実際に読み取りに使用されたのか、それともフィルタリングのために解析されただけなのかは、`description` フィールドで判別できます。デフォルト: 0。[MergeTree](/docs/ja/reference/engines/table-engines/mergetree-family/mergetree) テーブルでサポートされています。
* `actions` — ステップの actions に関する詳細情報を表示します。デフォルト: 1。
* `sorting` — ソート済みの出力を生成する各プランステップについて、ソートの説明を表示します。デフォルト: 0。
* `keep_logical_steps` — joins について、物理的な join 実装に変換せずに、論理プランステップを保持します。デフォルト: 0。
* `json` — クエリプランのステップを [JSON](/docs/ja/reference/formats/JSON/JSON) フォーマットの 1 行として出力します。デフォルト: 0。不要なエスケープを避けるため、[TabSeparatedRaw (TSVRaw)](/docs/ja/reference/formats/TabSeparated/TabSeparatedRaw) フォーマットの使用を推奨します。
* `input_headers` — ステップの入力ヘッダーを表示します。デフォルト: 0。主に、入力ヘッダーと出力ヘッダーの不一致に関する問題をデバッグする開発者にのみ有用です。
* `column_structure` — ヘッダー内のカラム構造を、名前と型に加えて表示します。デフォルト: 0。主に、入力ヘッダーと出力ヘッダーの不一致に関する問題をデバッグする開発者にのみ有用です。
* `distributed` — 分散テーブルまたは並列レプリカについて、リモートノードで実行されるクエリプランを表示します。`json` と同時にはサポートされません。デフォルト: 0。
* `compact` — 有効にすると、プランから expression ステップと詳細な action 情報 (入力、関数、別名、出力位置) を非表示にします。`actions = 1` の場合にのみ効果があります。デフォルト: 1。
* `pretty` — インデントの代わりに罫線文字 (├──、└──、│) を使ってプランツリーを表示し、階層構造を視覚化します。さらに、join ステップのプロパティもインラインで整形して表示します。デフォルト: 1。

<Note>
  デフォルトでは、`explain_query_plan_default = 'pretty'` であるため、`actions`、`compact`、`pretty` は `1` に初期化され、プランはコンパクトで見やすく、action 注釈付きの形式で描画されます。`EXPLAIN` ステートメントでこれらのオプションのいずれかを明示的に指定した場合 (たとえば、`EXPLAIN actions = 0, compact = 0, pretty = 0 SELECT ...`) は、常にその指定がデフォルトを上書きします。

  ClickHouse 26.7 より前では、`actions`、`compact`、`pretty` のデフォルトは `0` でした。その出力は、`explain_query_plan_default = 'legacy'` を設定する (グローバル、またはクエリごとの `SETTINGS` で設定する) か、`compatibility` を `26.7` より古い任意のバージョンに設定することで、引き続き取得できます。

  `json` と `distributed` オプションでは、`explain_query_plan_default = 'pretty'` の場合でも、`pretty` のデフォルト (`actions`、`compact`、`pretty`) は有効になりません。出力に action の詳細を含めるには、`actions = 1` を手動で設定してください。
</Note>

例:

```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>
  Step およびクエリのコスト見積もりはサポートされていません。
</Note>

`json = 1` の場合、クエリプランは JSON フォーマットで表されます。各ノードは辞書で、常に `Node Type`、`Node Id`、`Plans` のキーを持ちます。`Node Type` はステップ名を表す文字列で、`Node Id` は一意のステップ識別子です (数値の接尾辞が付いたステップ名。例: `Union_10`) 。`Plans` は子ステップの説明を含む配列です。その他の任意のキーは、ノードの種類や設定に応じて追加されることがあります。

例:

```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"
            }
          ]
        }
      ]
    }
  }
]
```

`description` = 1 の場合、`Description` キーがステップに追加されます。

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

`header` = 1 の場合、`Header` キーがカラムの配列としてステップに追加されます。

例:

```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"
            }
          ]
        }
      ]
    }
  }
]
```

`indexes` = 1 の場合、`Indexes` キーが追加されます。これには、使用された索引の配列が含まれます。各索引は JSON で記述され、`Type` キー (文字列 `Partition Min-Max`、`Partition`、`Statistics`、`PrimaryKey` または `Skip`) と、必要に応じて以下のキーを持ちます。

* `Name` — 索引名 (現在は `Skip` 索引でのみ使用) 。
* `Keys` — 索引で使用されるカラムの配列。
* `Condition` — 使用された条件。
* `Description` — 索引の説明 (現在は `Skip` 索引でのみ使用) 。
* `Parts` — 索引の適用後/適用前のパーツ数。
* `Granules` — 索引の適用後/適用前のグラニュール数。
* `Ranges` — 索引の適用後のグラニュール範囲数。

例:

```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
  }
]
```

`projections` = 1 を指定すると、`Projections` キーが追加されます。これには、分析されたプロジェクションの配列が含まれます。各プロジェクションは、以下のキーを持つ JSON として記述されます：

* `Name` — プロジェクション名。
* `Condition` — プロジェクションで使用された主キー条件。
* `Description` — プロジェクションの使用方法の説明 (例: パーツレベルのフィルタリング) 。
* `Selected Parts` — プロジェクションによって選択されたパーツ数。
* `Selected Marks` — 選択されたマーク数。
* `Selected Ranges` — 選択された範囲数。
* `Selected Rows` — 選択された行数。
* `Filtered Parts` — パーツレベルのフィルタリングによってスキップされたパーツ数。

例：

```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
  }
]
```

`actions` = 1 の場合、追加されるキーはステップの種類によって異なります。

例：

```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"
        }
      ]
    }
  }
]
```

`compact = 0` かつ `actions = 1` を指定すると、`Expression` ステップとともに式に関する詳細情報を確認できます：

```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
```

`distributed` = 1 を指定すると、出力にはローカルのクエリプランだけでなく、リモートノードで実行されるクエリプランも含まれます。これは、分散クエリの分析やデバッグに役立ちます。

<Note>
  `distributed` は、`pretty` 出力ではリモート分片のプランがプランツリーに統合されないため、`legacy` (非`pretty`) 形式でのみ表示されます。このため、`distributed` を有効にすると、`explain_query_plan_default` の値に関係なく、`pretty` のデフォルト設定 (`actions`、`compact`、`pretty`) は自動的に無効になります。なお、`actions=1` は手動で設定できます。また、`distributed` オプションは `json` と併用できません。
</Note>

分散テーブルを使用した例:

```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
```

並列レプリカを使用した例：

```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)
```

どちらの例でも、クエリプランにはローカルおよびリモートのステップを含む完全な実行フローが示されています。

`pretty` = 1 を指定すると、プランツリーはインデントの代わりに罫線文字で表示され、主要なステップの追加情報も表示されます：

* **クエリ出力カラム** はプランの先頭に表示されます。
* フィルタ、集約キー、ソートの説明、ウィンドウ関数内の **式** は、人が読める SQL 風の表記で表示されます (例: `greater(plus(a, 1), 5)` ではなく `a + 1 > 5`) 。わかりやすさのため、内部カラム識別子のプレフィックス (`__table1.` など) は削除されます。
* **ソースステップ** (`ReadFromMergeTree` など) には、その出力カラムが表示されます。
* **フィルタステップ** には、SQL 表記のフィルタ条件が表示されます。ランタイム join フィルタが存在する場合は、それらは別個に表示されます。
* **集約ステップ** には、キーと、引数付きの集約関数 (例: `sum(c)`、`count()`) が表示されます。
* タプルリテラルの **IN set** にはその値が表示され (大きな set の場合は切り詰められます) 、サブクエリベースの set には `subquery1`、`subquery2` などのラベルが付き、`Set` engine tables 由来の set にはテーブル名が表示されます。
* **join ステップ** には、数学的記法を用いた join 関係、推定結果行数、
  およびどの出力カラムが左側と右側のどちらに由来するかが表示されます。異なる join タイプを
  表すために、次の記号が使用されます：

| Symbol                 | Join Type       |
| ---------------------- | --------------- |
| `⋈`                    | Inner Join      |
| `⟕`                    | Left Join       |
| `⟖`                    | Right Join      |
| `⟗`                    | Full Join       |
| `⋉`                    | Left Semi Join  |
| `⋊`                    | Right Semi Join |
| `⋉` with strikethrough | Left Anti Join  |
| `⋊` with strikethrough | Right Anti Join |
| `×`                    | Cross Join      |

たとえば、`t1 ⟕ t2` はテーブル `t1` と `t2` の left join を意味します。
テーブル名の後の角括弧内の数値 (例: `t1[100]`) は、テーブル統計が利用可能な場合の
推定行数を示します。

`pretty` オプションは `compact = 1` と組み合わせると効果的で、`Expression` ステップと詳細な action 情報が非表示になるため、プランが読みやすくなります。

JOINを使った詳しい例:

```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>

設定:

* `header` — 各出力ポートのヘッダーを表示します。デフォルト: 0。
* `graph` — [DOT](https://en.wikipedia.org/wiki/DOT_\(graph_description_language\)) グラフ記述言語で記述されたグラフを表示します。デフォルト: 0。
* `compact` — `graph` 設定が有効な場合、compact モードでグラフを表示します。デフォルト: 1。
* `compact_repeated_processor_chains` — テキスト出力で、隣接して繰り返されるプロセッサチェーンを、チェーンを 1 つだけ表示して繰り返し回数を付けることでコンパクトにします。これにより、たとえば JOIN で同じチェーンが何度も現れる場合に、並列パイプラインが読みやすくなります。グラフ出力には影響しません。デフォルト: 0。

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

`compact=0` かつ `graph=1` の場合、プロセッサ名には一意のプロセッサ識別子を示す追加の接尾辞が含まれます。

例:

```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` は実際にクエリを実行し、結果の行を破棄したうえで、各ステップに実行時に実際に何が起きたかを注記として付けた、`EXPLAIN PLAN` と同じプランツリーを出力します。

設定:

`EXPLAIN ANALYZE` では、`EXPLAIN PLAN` と同じ表示オプションを使用できます ([EXPLAIN PLAN](#explain-plan) セクションを参照) 。

* `header` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `description` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `projections` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `sorting` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `input_headers` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `column_structure` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。
* `actions` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。デフォルト: 1。
* `indexes` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。デフォルト: 1。
* `compact` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。デフォルト: 1。
* `pretty` — [EXPLAIN PLAN](#explain-plan) セクションを参照してください。デフォルト: 1。
* `processors` — `EXPLAIN ANALYZE` では、各ステージについて、プロセッサごとの経過時間分布 (`min`、`median`、`max`、`sum`) を示す追加の行を出力します。並列プロセッサ間の負荷の偏りを見つけるのに役立ちます。デフォルト: 0。

<Note>
  `EXPLAIN ANALYZE` はラップされたクエリを実際に実行するため、いくつかの点で、そのクエリと同じように動作し、実行しない `EXPLAIN` 形式とは異なります。

  * **クォータと制限。** クエリを直接実行した場合と同じ [quotas](/docs/ja/concepts/features/configuration/server-config/quotas)
    に対してカウントされ、同じ [limits](/docs/ja/concepts/features/configuration/settings/query-complexity)
    (たとえば `query_selects`、`read_rows`) の対象にもなります。プランニング中はクォータの対象外となるテーブル
    (`system.one` など) についてはカウントされません。
  * **失敗したトランザクション。** すでに失敗している [transaction](/docs/ja/concepts/features/operations/insert/transactions)
    (`ROLLED_BACK`) 内では、通常の `SELECT` と同様に `INVALID_TRANSACTION` で拒否されます。
    先に `ROLLBACK` を実行してください。
  * **ストリーミング読み取り。** ストリーミング (`FROM ... STREAM`) 読み取りに対しては、
    そのような読み取りは完了しないため、`NOT_IMPLEMENTED` で拒否されます。
  * **分散クエリ。** [distributed](/docs/ja/reference/engines/table-engines/special/distributed) モードで実行される
    クエリではサポートされていません。
</Note>

例:

```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
```

出力を見てみましょう。まずはヘッダーを見てみましょう。

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

* `Time` — 合計時間です。planning (つまり、plan の作成 + plan の最適化 + パイプラインの構築) フェーズと execution (パイプラインの実行) フェーズに分けて表示されます。
* `Read` — テーブルから読み取られた行数と非圧縮バイト数、および throughput です。これは通常のクエリのフッターで "Processed" として報告される数値と同じです。
* `Peak memory` — クエリが使用したピークメモリです。

次に、クエリプランに表示される新しい行を見ていきましょう。

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

行数とバイト数は、ステップ全体について一度だけ報告されます (`I/O` 行) 。時間と並列度は、ステップ内の各ステージごとに、その下のインデントされた行に報告されます。

* `rows <in> → <out>` — ステップに入力された行数と、ステップから出力された行数です。`(<selectivity>`%) は、そのステップがデータをどの程度絞り込んだか (`out/in`) 、または増やしたかを示します。入力行数と出力行数が同じ場合、および入力行数が `0` の場合は表示されません。
* `<bytes_in> → <bytes_out>` — ステップ内を流れる非圧縮のインメモリバイト数です (両方ともゼロの場合は省略されます) 。
* `time <t> (<share>%)` — そのステージがアクティブだった実時間と、クエリ実行時間に占める割合です (つまり、build time は含みません) 。ステージやステップは同時実行されるため、この割合の合計が 100% を超えることがあります。
* `parallelism <avg>/<max>` — このステージ内で同時に動作していた CPU スレッド数の平均値と、そのステージで使用可能な最大値です。値が最大値に近いほど、そのステージは十分に並列化されていたことを示します。1 に近い場合は、ほぼ直列に実行されていたことを示します。
* `Stage (<stage>)` — ステージ名です。ステージが 1 つだけのステップでは、`Stage (...)` ラベルは付かず、時間の行が直接出力されます。複数のステージを持つステップでは、各ステージごとにラベル付きの行が 1 行ずつ出力されます。たとえば `Aggregating` では `Stage (partial aggregation)` と `Stage (final aggregation)` が表示され、ハッシュ結合では `Stage (build)` と `Stage (probe)` が表示されます。

<Note>
  ClickHouse は、プランステップ内のタスク実行だけでなく、プランステップ自体の実行も並列化します。`parallelism` メトリクスが反映するのは、このステップの処理だけです。他のステップも同時に実行されることがあるため、この数値から、このステップの並列度をクエリ全体と比較することはできません。
</Note>

<Note>
  `parallelism` の最大値は、次の 2 つのうち小さい方として計算されます。

  1. プランステップ内のタスク総数
  2. `max_threads` で設定されたクエリ処理スレッドの最大数
</Note>

`processors = 1` の場合、各ステージの下に追加の行が出力され、そのステージのプロセッサごとの経過時間の分布が表示されます。

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

`<n>` はそのステージのプロセッサ数です。`median` と `max` の間に大きなギャップがある場合は、並列プロセッサ間で負荷に偏りがあることを示します。

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

クエリの実行時に、テーブルから読み取られると推定される行数、マーク数、パーツ数を表示します。[MergeTree](/docs/ja/reference/engines/table-engines/mergetree-family/mergetree) ファミリーのテーブルで使用できます。

**例**

テーブルを作成します。

```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>

仮想的なスキップ索引をディスク上に*マテリアライズ*することなく、それが `SELECT` クエリにもたらす効果を見積もります。[`CREATE HYPOTHETICAL INDEX`](/docs/ja/reference/statements/hypothetical-index#create-hypothetical-index) で 1 つ以上の候補を定義し、`EXPLAIN WHATIF SELECT ...` を実行すると、各候補について、適用可否、推定読み取りマーク数、推定バイト数、スキップ率を確認できます。

**構文**

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

**設定**

* `empirical` — `1` (デフォルト) では、スキップ率 (上限値) を測定するため、ベースラインで絞り込まれたグラニュールに対してメモリ内で索引を適用します。`0` ではその処理をスキップします。いずれの場合も、`empirical` で結果が得られない場合 (無効になっている、または索引をメモリ内で評価できない場合) 、推定器はカラム [STATISTICS](/docs/ja/reference/engines/table-engines/mergetree-family/mergetree#column-statistics) にフォールバックし、それも利用できなければ、最終的に適用可否のみのサマリーにフォールバックします。

**出力**

```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` — 推定値の算出方法を示します。
  * `empirical`: ベースラインで pruned されたグラニュールを対象に、メモリ内で索引を構築し、その索引によってスキップされるグラニュール数を数えます。これは上限値です。制限事項については [`CREATE HYPOTHETICAL INDEX`](/docs/ja/reference/statements/hypothetical-index#limitations) を参照してください。
  * `statistical`: カラム STATISTICS から導出されます。empirical が無効化されている場合 (`empirical = 0`) 、または empirical で結果を生成できず、かつ関連するカラムにカラム STATISTICS が定義されている場合に使用されます。
  * `applicability_only`: 索引は predicate に適用可能ですが、empirical と statistical のいずれでも結果を生成できなかったことを示します (たとえば `empirical = 0` でカラム STATISTICS が定義されていない場合) 。保守的な上限として `skip_ratio: 0.0%` を返します。
* `sampled_parts` / `sampled_marks` — `<baseline-pruned> / <total in the table>`。テーブル全体のうち、PK、partition、既存の索引による pruning を通過した割合、つまり仮想索引への入力となる部分を示します。
* `est_bytes` — 読み取られるバイト数の推定値です。テーブルの平均行サイズから導出されるため概算であり、ストレージや圧縮によって変動します。ベースラインの行はクエリが行を読み取る場合にのみ表示され、候補ごとの行はベースラインのバイト推定値がわかっている場合にのみ表示されます。

この設定は `WHATIF` と `SELECT` の間にインラインで記述します。`SETTINGS` キーワードはありません (これは、他の `EXPLAIN` バリアントでオプションを受け付ける方法と一致しています) 。

テーブルに仮想索引が定義されていない場合、`EXPLAIN WHATIF` は `status: not_applicable` を返し、作成を促すヒントを表示します。

**結合行 (複数候補)**

2 つ以上の候補が empirical で評価されると、`EXPLAIN WHATIF` は候補ごとの行の後に `(combined: idx_a, idx_b, ...)` という名前の追加ブロックを 1 つ付加します。これは、それらすべての索引を同時に持つ場合の総合的な効果を示します。実際の読み取りでは、あるグラニュールが保持されるのは、それが *すべて* のスキップ索引を通過した場合だけなので、結合推定値は各候補で生き残るグラニュールの積集合になります。したがって、この `skip_ratio` は少なくとも最良の単一候補と同等以上になります。相補的な索引は組み合わせることでより多くを prune し、冗長な索引では変化しません。

寄与するのは `source: empirical` の候補だけです。これは、結合された行が各 グラニュール ごとの生存集合の積集合を取って構築されるためです。`statistical` または `applicability_only` と推定された候補には グラニュール ごとのデータがないため除外されます。その結果、結合ブロックが表示されるのは少なくとも 2 つの候補が経験則ベースの推定を生成した場合だけで、それ以外の場合 (たとえば `empirical = 0` の場合) には省略されます。その推定フィールドは、`elapsed_us` が `0` である点を除き、候補ごとの経験則ベースのブロックと同じです — 結合推定は候補ごとのスキャンから導出されるものであり、新たなスキャンではありません。合成された `(combined: ...)` という名前はレポート用ラベルにすぎず、`force_data_skipping_indices` では使用できません。

**経験則ベースの例**

```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
```

仮に `minmax` を使うと、100 個のマークを 1 個まで絞り込めます — `skip_ratio: 99.0%`。(`est_bytes` は平均行サイズに基づく推定値のため、正確な値は変動します。)

**統計の例**

[カラム STATISTICS](/docs/ja/reference/engines/table-engines/mergetree-family/mergetree#column-statistics)はデフォルトで無効になっています。`statistical` パスを試すには、まず対象のカラムでこれらを定義し、materialize mutation が完了するまで待ちます:

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

次に、推定器がカラム STATISTICS を使用するよう、経験則ベースのパスを無効にします：

```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
```

この数値は、`b < 10` のカラム STATISTICS における選択性 (10000 行中およそ 10 行) に基づくもので、`skip_ratio` の上限として報告されます。`sampled_parts` / `sampled_marks` はなく、データは読み取られていません。

どちらの方法も利用できない場合 (たとえば `empirical = 0` で、かつカラム STATISTICS が定義されていない場合) 、推定器は `source: applicability_only` と保守的な `skip_ratio: 0.0%` を報告します。

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

テーブル関数を介してアクセスするテーブルのスキーマに対して、テーブルオーバーライドを適用した結果を表示します。
また、いくつかの検証も行い、オーバーライドによって何らかの問題が発生する場合は例外をスローします。

**例**

次のようなリモート MySQL テーブルがあるとします。

```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>
  検証は完全ではないため、クエリが成功しても、そのオーバーライドが問題を引き起こさないことは保証されません。
</Note>
