説明分析
EXPLAIN ANALYZEステートメントはEXPLAINと同様に機能しますが、主な違いは、実際にステートメントを実行することです。これにより、クエリプランニングの一部として使用される見積もりを、実行中に検出された実際の値と比較できます。見積もりが実際の値と大幅に異なる場合は、影響を受けるテーブルでANALYZE TABLEを実行することを検討する必要があります。
ノート:
EXPLAIN ANALYZEを使用してDMLステートメントを実行すると、通常、データへの変更が実行されます。現在、DMLステートメントの実行プランはまだ表示できません。
あらすじ
- ExplainSym
- ExplainStmt
- ExplainableStmt
ExplainSym ::=
'EXPLAIN'
| 'DESCRIBE'
| 'DESC'
ExplainStmt ::=
ExplainSym ( TableName ColumnName? | 'ANALYZE'? ExplainableStmt | 'FOR' 'CONNECTION' NUM | 'FORMAT' '=' ( stringLit | ExplainFormatType ) ( 'FOR' 'CONNECTION' NUM | ExplainableStmt ) )
ExplainableStmt ::=
SelectStmt
| DeleteFromStmt
| UpdateStmt
| InsertIntoStmt
| ReplaceIntoStmt
| UnionStmt
EXPLAINANALYZE出力フォーマット
EXPLAINとは異なり、 EXPLAIN ANALYZEは対応するSQLステートメントを実行し、その実行時情報を記録して、実行プランと一緒に情報を返します。したがって、 EXPLAIN ANALYZEはEXPLAINステートメントの拡張と見なすことができます。 EXPLAIN (クエリ実行のmemory用)と比較すると、 EXPLAIN ANALYZEのexecution info結果には、 actRowsなどの情報の列も含まれdisk 。これらの列の詳細は次のとおりです。
| 属性名 | 説明 |
|---|---|
| actRows | オペレーターによって出力された行数。 |
| 実行情報 | オペレーターの実行情報。 timeは、すべてのサブオペレーターの合計実行時間を含めて、オペレーターに入るからオペレーターを離れるまでの合計wall timeを表します。演算子が親演算子によって(ループで)何度も呼び出される場合、時間は累積時間を参照します。 loopsは、現在のオペレーターが親オペレーターによって呼び出された回数です。 |
| メモリー | オペレーターが占有するメモリー・スペース。 |
| ディスク | オペレーターが占有するディスク容量。 |
例
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 INT NOT NULL);
Query OK, 0 rows affected (0.12 sec)
INSERT INTO t1 (c1) VALUES (1), (2), (3);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
EXPLAIN ANALYZE SELECT * FROM t1 WHERE id = 1;
+-------------+---------+---------+------+---------------+----------------------------------------------------------------+---------------+--------+------+
| id | estRows | actRows | task | access object | execution info | operator info | memory | disk |
+-------------+---------+---------+------+---------------+----------------------------------------------------------------+---------------+--------+------+
| Point_Get_1 | 1.00 | 1 | root | table:t1 | time:757.205µs, loops:2, Get:{num_rpc:1, total_time:697.051µs} | handle:1 | N/A | N/A |
+-------------+---------+---------+------+---------------+----------------------------------------------------------------+---------------+--------+------+
1 row in set (0.01 sec)
EXPLAIN ANALYZE SELECT * FROM t1;
+-------------------+---------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+-----------+------+
| id | estRows | actRows | task | access object | execution info | operator info | memory | disk |
+-------------------+---------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+-----------+------+
| TableReader_5 | 13.00 | 13 | root | | time:923.459µs, loops:2, cop_task: {num: 4, max: 839.788µs, min: 779.374µs, avg: 810.926µs, p95: 839.788µs, max_proc_keys: 12, p95_proc_keys: 12, rpc_num: 4, rpc_time: 3.116964ms, copr_cache_hit_ratio: 0.00} | data:TableFullScan_4 | 632 Bytes | N/A |
| └─TableFullScan_4 | 13.00 | 13 | cop[tikv] | table:t1 | proc max:0s, min:0s, p80:0s, p95:0s, iters:4, tasks:4 | keep order:false, stats:pseudo | N/A | N/A |
+-------------------+---------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------+-----------+------+
2 rows in set (0.00 sec)
オペレーターの実行情報
基本的なtimeおよびloopの実行情報に加えて、 execution infoにはオペレーター固有の実行情報も含まれます。これには、主にオペレーターがRPC要求を送信するために費やした時間と他のステップの期間が含まれます。
Point_Get
Point_Getオペレーターからの実行情報には、通常、次の情報が含まれます。
Get:{num_rpc:1, total_time:697.051µs}:TiKVに送信されたGetのRPC要求の数(num_rpc)とすべてのRPC要求の合計期間(total_time)。ResolveLock:{num_rpc:1, total_time:12.117495ms}:TiDBがデータの読み取り中にロックに遭遇した場合、最初にロックを解決する必要があります。これは通常、読み取りと書き込みの競合のシナリオで発生します。この情報は、ロックを解決する期間を示します。regionMiss_backoff:{num:11, total_time:2010 ms},tikvRPC_backoff:{num:11, total_time:10691 ms}:RPC要求が失敗すると、TiDBは要求を再試行する前にバックオフ時間を待機します。バックオフ統計には、バックオフのタイプ(regionMissやtikvRPCなど)、合計待機時間(total_time)、およびバックオフの合計数(num)が含まれます。
Batch_Point_Get
Batch_Point_Getオペレーターの実行情報はPoint_Getオペレーターの実行情報と似ていますが、 Batch_Point_Getは通常BatchGetのRPC要求をTiKVに送信してデータを読み取ります。
BatchGet:{num_rpc:2, total_time:83.13µs} :TiKVに送信されたBatchGet種類のRPC要求の数( num_rpc )とすべてのRPC要求に費やされた合計時間( total_time )。
TableReader
TableReader演算子の実行情報は、通常、次のとおりです。
cop_task: {num: 6, max: 1.07587ms, min: 844.312µs, avg: 919.601µs, p95: 1.07587ms, max_proc_keys: 16, p95_proc_keys: 16, tot_proc: 1ms, tot_wait: 1ms, rpc_num: 6, rpc_time: 5.313996 ms, copr_cache_hit_ratio: 0.00}
cop_task:copのタスクの実行情報が含まれます。例えば:num:警官タスクの数。max:minp95の実行に消費された実行時間の最大値、最小値、平均値、およびavg値。max_proc_keysおよびp95_proc_keys:すべての警官タスクでTiKVによってスキャンされた最大およびP95キー値。最大値とP95値の差が大きい場合、データ分布が不均衡になる可能性があります。rpc_num:TiKVに送信されたrpc_timeCopのRPC要求に費やされた合計数と合計時間。copr_cache_hit_ratio:copのタスク要求に対するコプロセッサーキャッシュのヒット率。
backoff:さまざまなタイプのバックオフとバックオフの合計待機時間が含まれます。
入れる
Insert演算子の実行情報は、通常、次のとおりです。
prepare:109.616µs, check_insert:{total_time:1.431678ms, mem_insert_time:667.878µs, prefetch:763.8µs, rpc:{BatchGet:{num_rpc:1, total_time:699.166µs},Get:{num_rpc:1, total_time:378.276µs }}}
prepare:式、デフォルト値、自動インクリメント値の計算など、書き込みの準備にかかる時間。check_insert:この情報は通常、競合チェックやTiDBトランザクションキャッシュへのデータの書き込みにかかる時間を含め、insert ignoreおよびinsert on duplicateのステートメントに表示されます。この時間の消費には、トランザクションのコミットに費やされた時間は含まれないことに注意してください。次の情報が含まれています。total_time:check_insertステップに費やされた合計時間。mem_insert_time:TiDBトランザクションキャッシュへのデータの書き込みにかかった時間。prefetch:TiKVから競合をチェックする必要があるデータを取得する期間。このステップでは、Batch_Get要求をTiKVに送信してデータを取得します。rpc:RPC要求をTiKVに送信するために消費された合計時間。これには、通常、BatchGetとGetの2種類のRPC時間が含まれます。BatchGet要求はprefetchステップで送信されます。Getinsert on duplicateステートメントがduplicate updateを実行すると、RPC要求が送信されます。
backoff:さまざまなタイプのバックオフとバックオフの合計待機時間が含まれます。
IndexJoin
IndexJoin人のオペレーターには、同時実行のために1人の外部ワーカーとN人の内部ワーカーがいます。結合結果は、外部テーブルの順序を保持します。詳細な実行プロセスは次のとおりです。
- 外部ワーカーはN個の外部行を読み取り、それをタスクにラップして、結果チャネルと内部ワーカーチャネルに送信します。
- 内部ワーカーはタスクを受け取り、タスクからキー範囲を構築し、キー範囲に従って内部行をフェッチします。次に、内側の行のハッシュテーブルを作成します。
- メイン
IndexJoinスレッドは、結果チャネルからタスクを受け取り、内部ワーカーがタスクの処理を終了するのを待ちます。 - メインの
IndexJoinスレッドは、内側の行のハッシュテーブルを検索することにより、各外側の行を結合します。
IndexJoin演算子には、次の実行情報が含まれています。
inner:{total:4.297515932s, concurrency:5, task:17, construct:97.96291ms, fetch:4.164310088s, build:35.219574ms}, probe:53.574945ms
Inner:内部ワーカーの実行情報:total:内部ワーカーが消費した合計時間。concurrency:同時内部ワーカーの数。task:内部ワーカーによって処理されたタスクの総数。construct:内部ワーカーがタスクに対応する内部テーブル行を読み取る前の準備時間。fetch:内部ワーカーが内部テーブルの行を読み取るのにかかる合計時間。Build:内部ワーカーが対応する内部テーブル行のハッシュテーブルを構築するのにかかる合計時間。
probe:メインIndexJoinスレッドが外部テーブル行と内部テーブル行のハッシュテーブルとの結合操作を実行するために消費した合計時間。
IndexHashJoin
IndexHashJoin演算子の実行プロセスは、 IndexJoin演算子の実行プロセスと同様です。 IndexHashJoin演算子には、1つの外部ワーカーとNつの内部ワーカーが並行して実行されますが、出力順序が外部テーブルの順序と一致することは保証されません。詳細な実行プロセスは次のとおりです。
- 外部ワーカーはN個の外部行を読み取り、タスクを作成して、それを内部ワーカーチャネルに送信します。
- 内部ワーカーは内部ワーカーチャネルからタスクを受け取り、すべてのタスクに対して次の3つの操作を順番に実行します。外側の行からハッシュテーブルを作成しますb。ビルドキーの範囲は外側の行から取得し、内側の行をフェッチしますc。ハッシュテーブルをプローブし、結合結果を結果チャネルに送信します。注:ステップaとステップbは同時に実行されています。
IndexHashJoinのメインスレッドは、結果チャネルから結合結果を受け取ります。
IndexHashJoin演算子には、次の実行情報が含まれています。
inner:{total:4.429220003s, concurrency:5, task:17, construct:96.207725ms, fetch:4.239324006s, build:24.567801ms, join:93.607362ms}
Inner:内部ワーカーの実行情報:total:内部ワーカーが消費した合計時間。concurrency:内部ワーカーの数。task:内部ワーカーによって処理されたタスクの総数。construct:内部ワーカーが内部テーブルの行を読み取る前の準備時間。fetch:内部ワーカーが内部テーブルの行を読み取るのにかかった合計時間。Build:内部ワーカーが外部テーブル行のハッシュテーブルを構築するために費やした合計時間。join:内部ワーカーが内部テーブル行および外部テーブル行のハッシュテーブルと結合するために消費された合計時間。
HashJoin
HashJoin人のオペレーターには、内部ワーカー、外部ワーカー、およびN人の参加ワーカーがいます。詳細な実行プロセスは次のとおりです。
- 内部ワーカーは内部テーブルの行を読み取り、ハッシュテーブルを作成します。
- 外部ワーカーは外部テーブルの行を読み取り、それをタスクにラップして、結合ワーカーに送信します。
- 結合ワーカーは、ステップ1のハッシュテーブルの構築が完了するのを待ちます。
- 結合ワーカーは、タスク内の外部テーブル行とハッシュテーブルを使用して結合操作を実行し、結合結果を結果チャネルに送信します。
HashJoinのメインスレッドは、結果チャネルから結合結果を受け取ります。
HashJoin演算子には、次の実行情報が含まれています。
build_hash_table:{total:146.071334ms, fetch:110.338509ms, build:35.732825ms}, probe:{concurrency:5, total:857.162518ms, max:171.48271ms, probe:125.341665ms, fetch:731.820853ms}
build_hash_table:内部テーブルのデータを読み取り、ハッシュテーブルの実行情報を作成します。total:合計時間消費。fetch:内部テーブルデータの読み取りに費やされた合計時間。build:ハッシュテーブルの作成に費やされた合計時間。
probe:参加ワーカーの実行情報:concurrency:参加ワーカーの数。total:すべての参加ワーカーが消費した合計時間。max:単一の結合ワーカーが実行する最長時間。probe:外部テーブル行およびハッシュテーブルとの結合に費やされた合計時間。fetch:結合ワーカーが外部テーブルの行データの読み取りを待機する合計時間。
lock_keys実行情報
悲観的トランザクションでDMLステートメントが実行される場合、オペレーターの実行情報にはlock_keysの実行情報も含まれる場合があります。例えば:
lock_keys: {time:94.096168ms, region:6, keys:8, lock_rpc:274.503214ms, rpc_count:6}
time:lock_keysの操作を実行する合計時間。region:lock_keys操作の実行に関係するリージョンの数。keys:Lockを必要とするKeyの数。lock_rpc:LockタイプのRPC要求をTiKVに送信するために費やされた合計時間。複数のRPC要求を並行して送信できるため、RPCの合計時間消費量は、lock_keysの操作の合計時間消費量よりも大きくなる可能性があります。rpc_count:TiKVに送信されたLockのタイプのRPC要求の総数。
commit_txn実行情報
書き込みタイプのDMLステートメントがautocommit=1のトランザクションで実行される場合、書き込み演算子の実行情報には、トランザクションコミットの期間情報も含まれます。例えば:
commit_txn: {prewrite:48.564544ms, wait_prewrite_binlog:47.821579, get_commit_ts:4.277455ms, commit:50.431774ms, region_num:7, write_keys:16, write_byte:536}
prewrite:トランザクションの2PCコミットのprewriteフェーズに費やされた時間。wait_prewrite_binlog::プリライトBinlogの書き込み待機にかかる時間。get_commit_ts:トランザクションコミットタイムスタンプの取得にかかった時間。commit:トランザクションの2PCコミット中にcommitフェーズに費やされた時間。write_keys:トランザクションに書き込まれた合計keys。write_byte:トランザクションに書き込まれたkey-valueの合計バイト数で、単位はバイトです。
MySQLの互換性
EXPLAIN ANALYZEはMySQL8.0の機能ですが、TiDBの出力形式と潜在的な実行プランはどちらもMySQLとは大幅に異なります。