From c31dbd2fe85f528b8b01c73fcbd1ecbcb240e9d6 Mon Sep 17 00:00:00 2001 From: time-and-fate <25057648+time-and-fate@users.noreply.github.com> Date: Mon, 17 Oct 2022 15:27:10 +0800 Subject: [PATCH 1/7] add --- explain-joins.md | 163 +++++++++++------------- explain-overview.md | 68 ++++++++++ explain-subqueries.md | 86 ++++++------- partitioned-table.md | 8 +- sql-statements/sql-statement-explain.md | 4 + subquery-optimization.md | 4 +- 6 files changed, 194 insertions(+), 139 deletions(-) diff --git a/explain-joins.md b/explain-joins.md index a50a7b01992dd..4d8a3df5aee64 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -41,6 +41,10 @@ ANALYZE TABLE t1, t2; If the number of estimated rows that need to be joined is small (typically less than 10000 rows), it is preferable to use the index join method. This method of join works similar to the primary method of join used in MySQL. In the following example, the operator `├─TableReader_28(Build)` first reads the table `t1`. For each row that matches, TiDB will probe the table `t2`: +> **Note:** +> +> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). + {{< copyable "sql" >}} ```sql @@ -48,17 +52,16 @@ EXPLAIN SELECT /*+ INL_JOIN(t1, t2) */ * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_ ``` ```sql -+---------------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+---------------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------+ -| IndexJoin_10 | 180000.00 | root | | inner join, inner:IndexLookUp_9, outer key:test.t1.id, inner key:test.t2.t1_id | -| ├─TableReader_28(Build) | 142020.00 | root | | data:TableFullScan_27 | -| │ └─TableFullScan_27 | 142020.00 | cop[tikv] | table:t1 | keep order:false | -| └─IndexLookUp_9(Probe) | 1.27 | root | | | -| ├─IndexRangeScan_7(Build) | 1.27 | cop[tikv] | table:t2, index:t1_id(t1_id) | range: decided by [eq(test.t2.t1_id, test.t1.id)], keep order:false | -| └─TableRowIDScan_8(Probe) | 1.27 | cop[tikv] | table:t2 | keep order:false | -+---------------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------+ -6 rows in set (0.00 sec) ++---------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++---------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| IndexJoin_11 | 90000.00 | root | | inner join, inner:IndexLookUp_10, outer key:test.t1.id, inner key:test.t2.t1_id, equal cond:eq(test.t1.id, test.t2.t1_id) | +| ├─TableReader_29(Build) | 71010.00 | root | | data:TableFullScan_28 | +| │ └─TableFullScan_28 | 71010.00 | cop[tikv] | table:t1 | keep order:false | +| └─IndexLookUp_10(Probe) | 90000.00 | root | | | +| ├─IndexRangeScan_8(Build) | 90000.00 | cop[tikv] | table:t2, index:t1_id(t1_id) | range: decided by [eq(test.t2.t1_id, test.t1.id)], keep order:false | +| └─TableRowIDScan_9(Probe) | 90000.00 | cop[tikv] | table:t2 | keep order:false | ++---------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ ``` Index join is efficient in memory usage, but might be slower to execute than other join methods when a large number of probe operations are required. Consider also the following query: @@ -83,46 +86,39 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ ``` ```sql -Query OK, 0 rows affected (0.29 sec) - -+-----------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------+-----------------------+------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+-----------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------+-----------------------+------+ -| IndexJoin_13 | 90000.00 | 20000 | root | | time:613.19955ms, loops:21, inner:{total:42.494047ms, concurrency:5, task:12, construct:33.149671ms, fetch:9.322956ms, build:8.66µs}, probe:32.435355ms | inner join, inner:TableReader_9, outer key:test.t2.t1_id, inner key:test.t1.id | 269.63341903686523 MB | N/A | -| ├─TableReader_19(Build) | 90000.00 | 90000 | root | | time:586.613252ms, loops:95, cop_task: {num: 3, max: 205.893949ms, min: 185.051354ms, avg: 194.878702ms, p95: 205.893949ms, max_proc_keys: 31715, p95_proc_keys: 31715, tot_proc: 332ms, tot_wait: 4ms, rpc_num: 4, rpc_time: 584.907774ms, copr_cache_hit_ratio: 0.00}, backoff{regionMiss: 2ms} | data:TableFullScan_18 | 182.624906539917 MB | N/A | -| │ └─TableFullScan_18 | 90000.00 | 90000 | cop[tikv] | table:t2 | time:0ns, loops:0, tikv_task:{proc max:72ms, min:64ms, p80:72ms, p95:72ms, iters:102, tasks:3} | keep order:false | N/A | N/A | -| └─TableReader_9(Probe) | 0.00 | 5 | root | | time:8.432051ms, loops:14, cop_task: {num: 14, max: 629.805µs, min: 226.129µs, avg: 420.979µs, p95: 629.805µs, max_proc_keys: 4, p95_proc_keys: 4, rpc_num: 15, rpc_time: 5.953229ms, copr_cache_hit_ratio: 0.00} | data:Selection_8 | N/A | N/A | -| └─Selection_8 | 0.00 | 5 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:0s, min:0s, p80:0s, p95:0s, iters:14, tasks:14} | eq(test.t1.int_col, 1) | N/A | N/A | -| └─TableRangeScan_7 | 1.00 | 25 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:0s, min:0s, p80:0s, p95:0s, iters:14, tasks:14} | range: decided by [test.t2.t1_id], keep order:false | N/A | N/A | -+-----------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------+-----------------------+------+ -6 rows in set (0.61 sec) - -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| HashJoin_19 | 90000.00 | 20000 | root | | time:406.098528ms, loops:22, build_hash_table:{total:148.574644ms, fetch:146.843636ms, build:1.731008ms}, probe:{concurrency:5, total:2.026547436s, max:406.039309ms, probe:205.337813ms, fetch:1.821209623s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 30.00731658935547 MB | 0 Bytes | -| ├─TableReader_22(Build) | 71.01 | 10000 | root | | time:147.072725ms, loops:12, cop_task: {num: 3, max: 145.847743ms, min: 50.932527ms, avg: 113.009029ms, p95: 145.847743ms, max_proc_keys: 31724, p95_proc_keys: 31724, tot_proc: 284ms, rpc_num: 3, rpc_time: 338.950488ms, copr_cache_hit_ratio: 0.00} | data:Selection_21 | 29.679713249206543 MB | N/A | -| │ └─Selection_21 | 71.01 | 10000 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:132ms, min:48ms, p80:132ms, p95:132ms, iters:83, tasks:3} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_20 | 71010.00 | 71010 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:128ms, min:48ms, p80:128ms, p95:128ms, iters:83, tasks:3} | keep order:false | N/A | N/A | -| └─TableReader_24(Probe) | 90000.00 | 90000 | root | | time:365.918504ms, loops:91, cop_task: {num: 3, max: 398.62145ms, min: 338.460345ms, avg: 358.732721ms, p95: 398.62145ms, max_proc_keys: 31715, p95_proc_keys: 31715, tot_proc: 536ms, rpc_num: 3, rpc_time: 1.076128895s, copr_cache_hit_ratio: 0.00} | data:TableFullScan_23 | 182.62489891052246 MB | N/A | -| └─TableFullScan_23 | 90000.00 | 90000 | cop[tikv] | table:t2 | time:0ns, loops:0, tikv_task:{proc max:100ms, min:40ms, p80:100ms, p95:100ms, iters:102, tasks:3} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -6 rows in set (0.41 sec) - -+------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| HashJoin_20 | 90000.00 | 20000 | root | | time:441.897092ms, loops:21, build_hash_table:{total:138.600864ms, fetch:136.353899ms, build:2.246965ms}, probe:{concurrency:5, total:2.207403854s, max:441.850032ms, probe:148.01937ms, fetch:2.059384484s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 30.00731658935547 MB | 0 Bytes | -| ├─TableReader_25(Build) | 71.01 | 10000 | root | | time:138.081807ms, loops:12, cop_task: {num: 3, max: 134.702901ms, min: 53.356202ms, avg: 93.372186ms, p95: 134.702901ms, max_proc_keys: 31724, p95_proc_keys: 31724, tot_proc: 236ms, rpc_num: 3, rpc_time: 280.017658ms, copr_cache_hit_ratio: 0.00} | data:Selection_24 | 29.680171966552734 MB | N/A | -| │ └─Selection_24 | 71.01 | 10000 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:80ms, min:52ms, p80:80ms, p95:80ms, iters:83, tasks:3} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_23 | 71010.00 | 71010 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:80ms, min:52ms, p80:80ms, p95:80ms, iters:83, tasks:3} | keep order:false | N/A | N/A | -| └─TableReader_22(Probe) | 90000.00 | 90000 | root | | time:413.560548ms, loops:91, cop_task: {num: 3, max: 432.938474ms, min: 231.263355ms, avg: 365.710741ms, p95: 432.938474ms, max_proc_keys: 31715, p95_proc_keys: 31715, tot_proc: 488ms, rpc_num: 3, rpc_time: 1.097021983s, copr_cache_hit_ratio: 0.00} | data:TableFullScan_21 | 182.62489891052246 MB | N/A | -| └─TableFullScan_21 | 90000.00 | 90000 | cop[tikv] | table:t2 | time:0ns, loops:0, tikv_task:{proc max:80ms, min:80ms, p80:80ms, p95:80ms, iters:102, tasks:3} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -6 rows in set (0.44 sec) ++-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ +| IndexJoin_14 | 90000.00 | 0 | root | | time:330.2ms, loops:1, inner:{total:72.2ms, concurrency:5, task:12, construct:58.6ms, fetch:13.5ms, build:2.12µs}, probe:26.1ms | inner join, inner:TableReader_10, outer key:test.t2.t1_id, inner key:test.t1.id, equal cond:eq(test.t2.t1_id, test.t1.id) | 88.5 MB | N/A | +| ├─TableReader_20(Build) | 90000.00 | 90000 | root | | time:307.2ms, loops:96, cop_task: {num: 24, max: 130.6ms, min: 170.9µs, avg: 33.5ms, p95: 105ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 472ms, rpc_num: 24, rpc_time: 802.4ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_19 | 58.6 MB | N/A | +| │ └─TableFullScan_19 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:34ms, min:0s, avg: 15.3ms, p80:24ms, p95:30ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 701.6µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | +| └─TableReader_10(Probe) | 12617.92 | 0 | root | | time:11.9ms, loops:12, cop_task: {num: 42, max: 848.8µs, min: 199µs, avg: 451.8µs, p95: 846.2µs, max_proc_keys: 7, p95_proc_keys: 5, rpc_num: 42, rpc_time: 18.3ms, copr_cache_hit_ratio: 0.00, distsql_concurrency: 15} | data:Selection_9 | N/A | N/A | +| └─Selection_9 | 12617.92 | 0 | cop[tikv] | | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42}, scan_detail: {total_process_keys: 56, total_process_keys_size: 174608, total_keys: 77, get_snapshot_time: 727.7µs, rocksdb: {block: {cache_hit_count: 154}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| └─TableRangeScan_8 | 90000.00 | 56 | cop[tikv] | table:t1 | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42} | range: decided by [test.t2.t1_id], keep order:false | N/A | N/A | ++-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ ++------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_20 | 90000.00 | 0 | root | | time:313.6ms, loops:1, build_hash_table:{total:24.6ms, fetch:21.2ms, build:3.32ms}, probe:{concurrency:5, total:1.57s, max:313.5ms, probe:18.9ms, fetch:1.55s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.0 MB | 0 Bytes | +| ├─TableReader_23(Build) | 9955.54 | 10000 | root | | time:23.6ms, loops:12, cop_task: {num: 11, max: 504.6µs, min: 203.7µs, avg: 377.4µs, p95: 504.6µs, rpc_num: 11, rpc_time: 3.92ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_22 | 14.9 MB | N/A | +| │ └─Selection_22 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 241.4µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_21 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_25(Probe) | 90000.00 | 90000 | root | | time:293.7ms, loops:91, cop_task: {num: 24, max: 105.7ms, min: 210.9µs, avg: 31.4ms, p95: 103.8ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 407ms, rpc_num: 24, rpc_time: 752.2ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_24 | 58.6 MB | N/A | +| └─TableFullScan_24 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:31ms, min:0s, avg: 13ms, p80:19ms, p95:26ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 637.2µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | ++------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_21 | 90000.00 | 0 | root | | time:331.7ms, loops:1, build_hash_table:{total:32.7ms, fetch:26ms, build:6.73ms}, probe:{concurrency:5, total:1.66s, max:331.3ms, probe:16ms, fetch:1.64s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.3 MB | 0 Bytes | +| ├─TableReader_26(Build) | 9955.54 | 10000 | root | | time:30.4ms, loops:13, cop_task: {num: 11, max: 1.87ms, min: 844.7µs, avg: 1.29ms, p95: 1.87ms, rpc_num: 11, rpc_time: 13.5ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_25 | 12.2 MB | N/A | +| │ └─Selection_25 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 521µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_24 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_23(Probe) | 90000.00 | 90000 | root | | time:308.6ms, loops:91, cop_task: {num: 24, max: 123.3ms, min: 518.9µs, avg: 32.4ms, p95: 113.4ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 499ms, rpc_num: 24, rpc_time: 776ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_22 | 58.6 MB | N/A | +| └─TableFullScan_22 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:44ms, min:0s, avg: 16.8ms, p80:27ms, p95:40ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 955.4µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | ++------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ``` -In the above example, the index join operation is missing an index on `t1.int_col`. Once this index is added, the performance of the operation improves from `0.61 sec` to `0.14 sec`, as the following result shows: +In the above example, the index join operation is missing an index on `t1.int_col`. Once this index is added, the performance of the operation improves from `0.3 sec` to `0.06 sec`, as the following result shows: ```sql -- Re-add index @@ -134,44 +130,37 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ ``` ```sql -Query OK, 0 rows affected (3.65 sec) - -+---------------------------------+----------+---------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------+-----------------------+------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+---------------------------------+----------+---------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------+-----------------------+------+ -| IndexJoin_11 | 90000.00 | 0 | root | | time:136.876686ms, loops:1, inner:{total:114.948158ms, concurrency:5, task:7, construct:5.329114ms, fetch:109.610054ms, build:2.38µs}, probe:1.699799ms | inner join, inner:IndexLookUp_10, outer key:test.t1.id, inner key:test.t2.t1_id | 29.864535331726074 MB | N/A | -| ├─TableReader_32(Build) | 10000.00 | 10000 | root | | time:95.755212ms, loops:12, cop_task: {num: 3, max: 95.652443ms, min: 30.758712ms, avg: 57.545129ms, p95: 95.652443ms, max_proc_keys: 31724, p95_proc_keys: 31724, tot_proc: 124ms, rpc_num: 3, rpc_time: 172.528417ms, copr_cache_hit_ratio: 0.00} | data:Selection_31 | 29.679298400878906 MB | N/A | -| │ └─Selection_31 | 10000.00 | 10000 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:44ms, min:28ms, p80:44ms, p95:44ms, iters:84, tasks:3} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_30 | 71010.00 | 71010 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:44ms, min:28ms, p80:44ms, p95:44ms, iters:84, tasks:3} | keep order:false | N/A | N/A | -| └─IndexLookUp_10(Probe) | 9.00 | 0 | root | | time:103.93801ms, loops:7 | | 2.1787109375 KB | N/A | -| ├─IndexRangeScan_8(Build) | 9.00 | 0 | cop[tikv] | table:t2, index:t1_id(t1_id) | time:0s, loops:0, cop_task: {num: 7, max: 23.969244ms, min: 12.003682ms, avg: 14.659066ms, p95: 23.969244ms, tot_proc: 100ms, rpc_num: 7, rpc_time: 102.435966ms, copr_cache_hit_ratio: 0.00}, tikv_task:{proc max:24ms, min:12ms, p80:16ms, p95:24ms, iters:7, tasks:7} | range: decided by [eq(test.t2.t1_id, test.t1.id)], keep order:false | N/A | N/A | -| └─TableRowIDScan_9(Probe) | 9.00 | 0 | cop[tikv] | table:t2 | time:0ns, loops:0 | keep order:false | N/A | N/A | -+---------------------------------+----------+---------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------+-----------------------+------+ -7 rows in set (0.14 sec) - -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| HashJoin_31 | 90000.00 | 0 | root | | time:402.263795ms, loops:1, build_hash_table:{total:128.467151ms, fetch:126.871282ms, build:1.595869ms}, probe:{concurrency:5, total:2.010969815s, max:402.212295ms, probe:8.924769ms, fetch:2.002045046s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 29.689788818359375 MB | 0 Bytes | -| ├─TableReader_34(Build) | 10000.00 | 10000 | root | | time:126.765972ms, loops:11, cop_task: {num: 3, max: 126.721293ms, min: 54.375481ms, avg: 84.518849ms, p95: 126.721293ms, max_proc_keys: 31724, p95_proc_keys: 31724, tot_proc: 208ms, rpc_num: 3, rpc_time: 253.478218ms, copr_cache_hit_ratio: 0.00} | data:Selection_33 | 29.679292678833008 MB | N/A | -| │ └─Selection_33 | 10000.00 | 10000 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:72ms, min:56ms, p80:72ms, p95:72ms, iters:84, tasks:3} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_32 | 71010.00 | 71010 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:72ms, min:56ms, p80:72ms, p95:72ms, iters:84, tasks:3} | keep order:false | N/A | N/A | -| └─TableReader_36(Probe) | 90000.00 | 90000 | root | | time:400.447175ms, loops:90, cop_task: {num: 3, max: 400.838264ms, min: 309.474053ms, avg: 341.01943ms, p95: 400.838264ms, max_proc_keys: 31719, p95_proc_keys: 31719, tot_proc: 528ms, rpc_num: 3, rpc_time: 1.02298055s, copr_cache_hit_ratio: 0.00} | data:TableFullScan_35 | 182.62786674499512 MB | N/A | -| └─TableFullScan_35 | 90000.00 | 90000 | cop[tikv] | table:t2 | time:0ns, loops:0, tikv_task:{proc max:108ms, min:72ms, p80:108ms, p95:108ms, iters:102, tasks:3} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -6 rows in set (0.40 sec) - -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -| HashJoin_32 | 90000.00 | 0 | root | | time:356.282882ms, loops:1, build_hash_table:{total:154.187155ms, fetch:151.259305ms, build:2.92785ms}, probe:{concurrency:5, total:1.781087041s, max:356.238312ms, probe:7.406146ms, fetch:1.773680895s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 29.689788818359375 MB | 0 Bytes | -| ├─TableReader_41(Build) | 10000.00 | 10000 | root | | time:151.190175ms, loops:11, cop_task: {num: 3, max: 151.055697ms, min: 56.214348ms, avg: 96.70463ms, p95: 151.055697ms, max_proc_keys: 31724, p95_proc_keys: 31724, tot_proc: 240ms, rpc_num: 3, rpc_time: 290.019942ms, copr_cache_hit_ratio: 0.00} | data:Selection_40 | 29.679292678833008 MB | N/A | -| │ └─Selection_40 | 10000.00 | 10000 | cop[tikv] | | time:0ns, loops:0, tikv_task:{proc max:80ms, min:56ms, p80:80ms, p95:80ms, iters:84, tasks:3} | eq(test.t1.int_col, 1) | N/A | N/A | -| │ └─TableFullScan_39 | 71010.00 | 71010 | cop[tikv] | table:t1 | time:0ns, loops:0, tikv_task:{proc max:80ms, min:56ms, p80:80ms, p95:80ms, iters:84, tasks:3} | keep order:false | N/A | N/A | -| └─TableReader_43(Probe) | 90000.00 | 90000 | root | | time:354.68523ms, loops:90, cop_task: {num: 3, max: 354.313475ms, min: 328.460762ms, avg: 345.530558ms, p95: 354.313475ms, max_proc_keys: 31719, p95_proc_keys: 31719, tot_proc: 508ms, rpc_num: 3, rpc_time: 1.036492374s, copr_cache_hit_ratio: 0.00} | data:TableFullScan_42 | 182.62786102294922 MB | N/A | -| └─TableFullScan_42 | 90000.00 | 90000 | cop[tikv] | table:t2 | time:0ns, loops:0, tikv_task:{proc max:84ms, min:64ms, p80:84ms, p95:84ms, iters:102, tasks:3} | keep order:false | N/A | N/A | -+------------------------------+----------+---------+-----------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+-----------------------+---------+ -6 rows in set (0.36 sec) ++----------------------------------+----------+---------+-----------+------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+-----------+------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++----------------------------------+----------+---------+-----------+------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+-----------+------+ +| IndexJoin_12 | 90000.00 | 0 | root | | time:65.6ms, loops:1, inner:{total:129.7ms, concurrency:5, task:7, construct:7.13ms, fetch:122.5ms, build:16.4µs}, probe:2.54ms | inner join, inner:IndexLookUp_11, outer key:test.t1.id, inner key:test.t2.t1_id, equal cond:eq(test.t1.id, test.t2.t1_id) | 28.7 MB | N/A | +| ├─TableReader_33(Build) | 9955.54 | 10000 | root | | time:15.4ms, loops:16, cop_task: {num: 11, max: 1.52ms, min: 211.5µs, avg: 416.8µs, p95: 1.52ms, rpc_num: 11, rpc_time: 4.36ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_32 | 13.9 MB | N/A | +| │ └─Selection_32 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 185µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_31 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─IndexLookUp_11(Probe) | 90000.00 | 0 | root | | time:115.6ms, loops:7 | | 555 Bytes | N/A | +| ├─IndexRangeScan_9(Build) | 90000.00 | 0 | cop[tikv] | table:t2, index:t1_id(t1_id) | time:114.3ms, loops:7, cop_task: {num: 7, max: 42ms, min: 1.3ms, avg: 16.2ms, p95: 42ms, tot_proc: 71ms, rpc_num: 7, rpc_time: 113.2ms, copr_cache_hit_ratio: 0.29, distsql_concurrency: 15}, tikv_task:{proc max:37ms, min:0s, avg: 11.3ms, p80:20ms, p95:37ms, iters:7, tasks:7}, scan_detail: {total_keys: 9296, get_snapshot_time: 141.9µs, rocksdb: {block: {cache_hit_count: 18592}}} | range: decided by [eq(test.t2.t1_id, test.t1.id)], keep order:false | N/A | N/A | +| └─TableRowIDScan_10(Probe) | 90000.00 | 0 | cop[tikv] | table:t2 | | keep order:false | N/A | N/A | ++----------------------------------+----------+---------+-----------+------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+-----------+------+ ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_32 | 90000.00 | 0 | root | | time:320.2ms, loops:1, build_hash_table:{total:19.3ms, fetch:16.8ms, build:2.52ms}, probe:{concurrency:5, total:1.6s, max:320.1ms, probe:16.1ms, fetch:1.58s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.0 MB | 0 Bytes | +| ├─TableReader_35(Build) | 9955.54 | 10000 | root | | time:18.6ms, loops:12, cop_task: {num: 11, max: 713.8µs, min: 197.3µs, avg: 368.5µs, p95: 713.8µs, rpc_num: 11, rpc_time: 3.83ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_34 | 14.9 MB | N/A | +| │ └─Selection_34 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 178.9µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_33 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_37(Probe) | 90000.00 | 90000 | root | | time:304.4ms, loops:91, cop_task: {num: 24, max: 114ms, min: 251.1µs, avg: 33.1ms, p95: 110.4ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 492ms, rpc_num: 24, rpc_time: 793ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_36 | 58.6 MB | N/A | +| └─TableFullScan_36 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:38ms, min:3ms, avg: 14.1ms, p80:23ms, p95:35ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 139497, get_snapshot_time: 577.2µs, rocksdb: {delete_skipped_count: 44208, key_skipped_count: 253431, block: {cache_hit_count: 3527}}} | keep order:false | N/A | N/A | ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| id | estRows | actRows | task | access object | execution info | operator info | memory | disk | ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ +| HashJoin_33 | 90000.00 | 0 | root | | time:306.3ms, loops:1, build_hash_table:{total:20.5ms, fetch:17.1ms, build:3.45ms}, probe:{concurrency:5, total:1.53s, max:305.9ms, probe:17.1ms, fetch:1.51s} | inner join, equal:[eq(test.t1.id, test.t2.t1_id)] | 32.0 MB | 0 Bytes | +| ├─TableReader_42(Build) | 9955.54 | 10000 | root | | time:19.6ms, loops:12, cop_task: {num: 11, max: 1.07ms, min: 246.1µs, avg: 600µs, p95: 1.07ms, rpc_num: 11, rpc_time: 6.17ms, copr_cache_hit_ratio: 1.00, distsql_concurrency: 15} | data:Selection_41 | 19.7 MB | N/A | +| │ └─Selection_41 | 9955.54 | 10000 | cop[tikv] | | tikv_task:{proc max:104ms, min:3ms, avg: 24.4ms, p80:33ms, p95:104ms, iters:113, tasks:11}, scan_detail: {get_snapshot_time: 282.9µs, rocksdb: {block: {}}} | eq(test.t1.int_col, 1) | N/A | N/A | +| │ └─TableFullScan_40 | 71010.00 | 71010 | cop[tikv] | table:t1 | tikv_task:{proc max:101ms, min:3ms, avg: 23.8ms, p80:33ms, p95:101ms, iters:113, tasks:11} | keep order:false | N/A | N/A | +| └─TableReader_44(Probe) | 90000.00 | 90000 | root | | time:289.2ms, loops:91, cop_task: {num: 24, max: 108.2ms, min: 252.8µs, avg: 31.3ms, p95: 106.1ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 445ms, rpc_num: 24, rpc_time: 750.4ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_43 | 58.6 MB | N/A | +| └─TableFullScan_43 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:31ms, min:3ms, avg: 13.3ms, p80:24ms, p95:30ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 139497, get_snapshot_time: 730.2µs, rocksdb: {delete_skipped_count: 44208, key_skipped_count: 253431, block: {cache_hit_count: 3527}}} | keep order:false | N/A | N/A | ++------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ ``` > **Note:** diff --git a/explain-overview.md b/explain-overview.md index 6b3e8cae09cd5..6f7b8507f58c3 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -57,6 +57,74 @@ The following describes the output of the `EXPLAIN` statement above: * `access object` shows the table, partition and index that is being accessed. The parts of the index are also shown, as in the case above that the column `a` from the index was used. This can be useful in cases where you have composite indexes. * `operator info` shows additional details about the access. See [Operator info overview](#operator-info-overview) for additional details. +> **Note:** +> +> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. +> Before v6.4.0, it means the estimated row count expected to be processed by the Probe side operators for every row from the Build side operator, not the estimated total row count expected to be processed by the Probe side operators. However, the actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so there is an inconsistency in their meanings. +> +> For example: +> +> ```sql +> CREATE TABLE t1(a INT, b INT); +> CREATE TABLE t2(a INT, b INT, INDEX ia(a)); +> EXPLAIN SELECT /*+ INL_JOIN(t2) */ * FROM t1 JOIN t2 ON t1.a = t2.a; +> EXPLAIN SELECT (SELECT a FROM t2 WHERE t2.a = t1.b LIMIT 1) FROM t1; +> ``` +> +> ```sql +> -- Before v6.4.0: +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> | id | estRows | task | access object | operator info | +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> | IndexJoin_12 | 12487.50 | root | | inner join, inner:IndexLookUp_11, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a) | +> | ├─TableReader_24(Build) | 9990.00 | root | | data:Selection_23 | +> | │ └─Selection_23 | 9990.00 | cop[tikv] | | not(isnull(test.t1.a)) | +> | │ └─TableFullScan_22 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +> | └─IndexLookUp_11(Probe) | 1.25 | root | | | +> | ├─Selection_10(Build) | 1.25 | cop[tikv] | | not(isnull(test.t2.a)) | +> | │ └─IndexRangeScan_8 | 1.25 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo | +> | └─TableRowIDScan_9(Probe) | 1.25 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> | id | estRows | task | access object | operator info | +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> | Projection_12 | 10000.00 | root | | test.t2.a | +> | └─Apply_14 | 10000.00 | root | | CARTESIAN left outer join | +> | ├─TableReader_16(Build) | 10000.00 | root | | data:TableFullScan_15 | +> | │ └─TableFullScan_15 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +> | └─Limit_17(Probe) | 1.00 | root | | offset:0, count:1 | +> | └─IndexReader_21 | 1.00 | root | | index:Limit_20 | +> | └─Limit_20 | 1.00 | cop[tikv] | | offset:0, count:1 | +> | └─IndexRangeScan_19 | 1.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo | +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> +> -- From v6.4.0: +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> | id | estRows | task | access object | operator info | +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> | IndexJoin_12 | 12487.50 | root | | inner join, inner:IndexLookUp_11, outer key:test.t1.a, inner key:test.t2.a, equal cond:eq(test.t1.a, test.t2.a) | +> | ├─TableReader_24(Build) | 9990.00 | root | | data:Selection_23 | +> | │ └─Selection_23 | 9990.00 | cop[tikv] | | not(isnull(test.t1.a)) | +> | │ └─TableFullScan_22 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +> | └─IndexLookUp_11(Probe) | 12487.50 | root | | | +> | ├─Selection_10(Build) | 12487.50 | cop[tikv] | | not(isnull(test.t2.a)) | +> | │ └─IndexRangeScan_8 | 12500.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo | +> | └─TableRowIDScan_9(Probe) | 12487.50 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | +> +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> | id | estRows | task | access object | operator info | +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> | Projection_12 | 10000.00 | root | | test.t2.a | +> | └─Apply_14 | 10000.00 | root | | CARTESIAN left outer join | +> | ├─TableReader_16(Build) | 10000.00 | root | | data:TableFullScan_15 | +> | │ └─TableFullScan_15 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +> | └─Limit_17(Probe) | 10000.00 | root | | offset:0, count:1 | +> | └─IndexReader_21 | 10000.00 | root | | index:Limit_20 | +> | └─Limit_20 | 10000.00 | cop[tikv] | | offset:0, count:1 | +> | └─IndexRangeScan_19 | 10000.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo | +> +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ +> ``` + ### Operator overview An operator is a particular step that is executed as part of returning query results. The operators that perform table scans (of the disk or the TiKV Block Cache) are listed as follows: diff --git a/explain-subqueries.md b/explain-subqueries.md index 5f67a8c5ac1ca..72180298c4aef 100644 --- a/explain-subqueries.md +++ b/explain-subqueries.md @@ -54,19 +54,17 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2); ``` ```sql -+----------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+----------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| IndexJoin_14 | 5.00 | root | | inner join, inner:IndexLookUp_13, outer key:test.t2.t1_id, inner key:test.t1.id, equal cond:eq(test.t2.t1_id, test.t1.id) | -| ├─StreamAgg_49(Build) | 5.00 | root | | group by:test.t2.t1_id, funcs:firstrow(test.t2.t1_id)->test.t2.t1_id | -| │ └─IndexReader_50 | 5.00 | root | | index:StreamAgg_39 | -| │ └─StreamAgg_39 | 5.00 | cop[tikv] | | group by:test.t2.t1_id, | -| │ └─IndexFullScan_31 | 50000.00 | cop[tikv] | table:t2, index:t1_id(t1_id) | keep order:true | -| └─IndexLookUp_13(Probe) | 1.00 | root | | | -| ├─IndexRangeScan_11(Build) | 1.00 | cop[tikv] | table:t1, index:PRIMARY(id) | range: decided by [eq(test.t1.id, test.t2.t1_id)], keep order:false | -| └─TableRowIDScan_12(Probe) | 1.00 | cop[tikv] | table:t1 | keep order:false | -+----------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ -8 rows in set (0.00 sec) ++--------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++--------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| IndexJoin_15 | 21.11 | root | | inner join, inner:TableReader_12, outer key:test.t2.t1_id, inner key:test.t1.id, equal cond:eq(test.t2.t1_id, test.t1.id) | +| ├─StreamAgg_44(Build) | 21.11 | root | | group by:test.t2.t1_id, funcs:firstrow(test.t2.t1_id)->test.t2.t1_id | +| │ └─IndexReader_45 | 21.11 | root | | index:StreamAgg_34 | +| │ └─StreamAgg_34 | 21.11 | cop[tikv] | | group by:test.t2.t1_id, | +| │ └─IndexFullScan_26 | 90000.00 | cop[tikv] | table:t2, index:t1_id(t1_id) | keep order:true | +| └─TableReader_12(Probe) | 21.11 | root | | data:TableRangeScan_11 | +| └─TableRangeScan_11 | 21.11 | cop[tikv] | table:t1 | range: decided by [test.t2.t1_id], keep order:false | ++--------------------------------+----------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ ``` From the query results above, you can see that TiDB uses the index join operation `| IndexJoin_14` to join and transform the subquery. In the execution plan, the execution process is as follows: @@ -85,17 +83,15 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t3); ``` ```sql -+----------------------------------+---------+-----------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+----------------------------------+---------+-----------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------+ -| IndexJoin_17 | 1978.13 | root | | inner join, inner:IndexLookUp_16, outer key:test.t3.t1_id, inner key:test.t1.id, equal cond:eq(test.t3.t1_id, test.t1.id) | -| ├─TableReader_44(Build) | 1978.00 | root | | data:TableFullScan_43 | -| │ └─TableFullScan_43 | 1978.00 | cop[tikv] | table:t3 | keep order:false | -| └─IndexLookUp_16(Probe) | 1.00 | root | | | -| ├─IndexRangeScan_14(Build) | 1.00 | cop[tikv] | table:t1, index:PRIMARY(id) | range: decided by [eq(test.t1.id, test.t3.t1_id)], keep order:false | -| └─TableRowIDScan_15(Probe) | 1.00 | cop[tikv] | table:t1 | keep order:false | -+----------------------------------+---------+-----------+-----------------------------+---------------------------------------------------------------------------------------------------------------------------+ -6 rows in set (0.01 sec) ++-----------------------------+---------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------+---------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ +| IndexJoin_18 | 999.00 | root | | inner join, inner:TableReader_15, outer key:test.t3.t1_id, inner key:test.t1.id, equal cond:eq(test.t3.t1_id, test.t1.id) | +| ├─IndexReader_41(Build) | 999.00 | root | | index:IndexFullScan_40 | +| │ └─IndexFullScan_40 | 999.00 | cop[tikv] | table:t3, index:t1_id(t1_id) | keep order:false | +| └─TableReader_15(Probe) | 999.00 | root | | data:TableRangeScan_14 | +| └─TableRangeScan_14 | 999.00 | cop[tikv] | table:t1 | range: decided by [test.t3.t1_id], keep order:false | ++-----------------------------+---------+-----------+------------------------------+---------------------------------------------------------------------------------------------------------------------------+ ``` Semantically because `t3.t1_id` is guaranteed unique, it can be executed directly as an `INNER JOIN`. @@ -111,17 +107,16 @@ EXPLAIN SELECT * FROM t1 WHERE id IN (SELECT t1_id FROM t2 WHERE t1_id != t1.int ``` ```sql -+-----------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+-----------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ -| MergeJoin_9 | 45446.40 | root | | semi join, left key:test.t1.id, right key:test.t2.t1_id, other cond:ne(test.t2.t1_id, test.t1.int_col) | -| ├─IndexReader_24(Build) | 180000.00 | root | | index:IndexFullScan_23 | -| │ └─IndexFullScan_23 | 180000.00 | cop[tikv] | table:t2, index:t1_id(t1_id) | keep order:true | -| └─TableReader_22(Probe) | 56808.00 | root | | data:Selection_21 | -| └─Selection_21 | 56808.00 | cop[tikv] | | ne(test.t1.id, test.t1.int_col) | -| └─TableFullScan_20 | 71010.00 | cop[tikv] | table:t1 | keep order:true | -+-----------------------------+-----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ -6 rows in set (0.00 sec) ++-----------------------------+----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------+----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ +| MergeJoin_9 | 45446.40 | root | | semi join, left key:test.t1.id, right key:test.t2.t1_id, other cond:ne(test.t2.t1_id, test.t1.int_col) | +| ├─IndexReader_24(Build) | 90000.00 | root | | index:IndexFullScan_23 | +| │ └─IndexFullScan_23 | 90000.00 | cop[tikv] | table:t2, index:t1_id(t1_id) | keep order:true | +| └─TableReader_22(Probe) | 56808.00 | root | | data:Selection_21 | +| └─Selection_21 | 56808.00 | cop[tikv] | | ne(test.t1.id, test.t1.int_col) | +| └─TableFullScan_20 | 71010.00 | cop[tikv] | table:t1 | keep order:true | ++-----------------------------+----------+-----------+------------------------------+--------------------------------------------------------------------------------------------------------+ ``` From the result above, you can see that TiDB uses a `Semi Join` algorithm. Semi-join differs from inner join: semi-join only permits the first value on the right key (`t2.t1_id`), which means that the duplicates are eliminated as a part of the join operator task. The join algorithm is also Merge Join, which is like an efficient zipper-merge as the operator reads data from both the left and the right side in sorted order. @@ -137,17 +132,16 @@ EXPLAIN SELECT * FROM t3 WHERE t1_id NOT IN (SELECT id FROM t1 WHERE int_col < 1 ``` ```sql -+-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ -| IndexMergeJoin_20 | 1598.40 | root | | anti semi join, inner:TableReader_15, outer key:test.t3.t1_id, inner key:test.t1.id | -| ├─TableReader_28(Build) | 1998.00 | root | | data:TableFullScan_27 | -| │ └─TableFullScan_27 | 1998.00 | cop[tikv] | table:t3 | keep order:false | -| └─TableReader_15(Probe) | 1.00 | root | | data:Selection_14 | -| └─Selection_14 | 1.00 | cop[tikv] | | lt(test.t1.int_col, 100) | -| └─TableRangeScan_13 | 1.00 | cop[tikv] | table:t1 | range: decided by [test.t3.t1_id], keep order:true | -+-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+ -6 rows in set (0.00 sec) ++-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------+ +| IndexJoin_16 | 799.20 | root | | anti semi join, inner:TableReader_12, outer key:test.t3.t1_id, inner key:test.t1.id, equal cond:eq(test.t3.t1_id, test.t1.id) | +| ├─TableReader_28(Build) | 999.00 | root | | data:TableFullScan_27 | +| │ └─TableFullScan_27 | 999.00 | cop[tikv] | table:t3 | keep order:false | +| └─TableReader_12(Probe) | 999.00 | root | | data:Selection_11 | +| └─Selection_11 | 999.00 | cop[tikv] | | lt(test.t1.int_col, 100) | +| └─TableRangeScan_10 | 999.00 | cop[tikv] | table:t1 | range: decided by [test.t3.t1_id], keep order:false | ++-----------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------+ ``` This query starts by reading the table `t3` and then probes the table `t1` based on the `PRIMARY KEY`. The join type is an _anti semi join_; anti because this example is for the non-existence of the value (`NOT IN`) and semi-join because only the first row needs to match before the join is rejected. diff --git a/partitioned-table.md b/partitioned-table.md index dbea56ad914c6..7d8ccdb53e4fe 100644 --- a/partitioned-table.md +++ b/partitioned-table.md @@ -1637,10 +1637,10 @@ mysql> explain select /*+ TIDB_INLJ(t1, t2) */ t1.* from t1, t2 where t2.code = | ├─TableReader_16(Build) | 9.99 | root | | data:Selection_15 | | │ └─Selection_15 | 9.99 | cop[tikv] | | eq(test.t2.code, 0), not(isnull(test.t2.id)) | | │ └─TableFullScan_14 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -| └─IndexLookUp_10(Probe) | 1.25 | root | partition:all | | -| ├─Selection_9(Build) | 1.25 | cop[tikv] | | not(isnull(test.t1.id)) | -| │ └─IndexRangeScan_7 | 1.25 | cop[tikv] | table:t1, index:id(id) | range: decided by [eq(test.t1.id, test.t2.id)], keep order:false, stats:pseudo | -| └─TableRowIDScan_8(Probe) | 1.25 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─IndexLookUp_10(Probe) | 12.49 | root | partition:all | | +| ├─Selection_9(Build) | 12.49 | cop[tikv] | | not(isnull(test.t1.id)) | +| │ └─IndexRangeScan_7 | 12.50 | cop[tikv] | table:t1, index:id(id) | range: decided by [eq(test.t1.id, test.t2.id)], keep order:false, stats:pseudo | +| └─TableRowIDScan_8(Probe) | 12.49 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +---------------------------------+----------+-----------+------------------------+---------------------------------------------------------------------------------------------------------------------+ 8 rows in set (0.00 sec) ``` diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index ec1b72d93d66d..b924cc20575a4 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -38,6 +38,10 @@ ExplainableStmt ::= > > When you use the MySQL client to connect to TiDB, to read the output result in a clearer way without line wrapping, you can use the `pager less -S` command. Then, after the `EXPLAIN` result is output, you can press the right arrow button on your keyboard to horizontally scroll through the output. +> **Note:** +> +> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). + Currently, `EXPLAIN` in TiDB outputs 5 columns: `id`, `estRows`, `task`, `access object`, `operator info`. Each operator in the execution plan is described by these attributes, with each row in the `EXPLAIN` output describing an operator. The description of each attribute is as follows: | Attribute name | Description | diff --git a/subquery-optimization.md b/subquery-optimization.md index 6391c832eeb80..bb7bb633f94cc 100644 --- a/subquery-optimization.md +++ b/subquery-optimization.md @@ -58,8 +58,8 @@ explain select * from t1 where t1.a in (select t2.a from t2); | ├─HashAgg_21(Build) | 7992.00 | root | | group by:test.t2.a, funcs:firstrow(test.t2.a)->test.t2.a | | │ └─IndexReader_28 | 9990.00 | root | | index:IndexFullScan_27 | | │ └─IndexFullScan_27 | 9990.00 | cop[tikv] | table:t2, index:idx(a) | keep order:false, stats:pseudo | -| └─TableReader_11(Probe) | 1.00 | root | | data:TableRangeScan_10 | -| └─TableRangeScan_10 | 1.00 | cop[tikv] | table:t1 | range: decided by [test.t2.a], keep order:false, stats:pseudo | +| └─TableReader_11(Probe) | 7992.00 | root | | data:TableRangeScan_10 | +| └─TableRangeScan_10 | 7992.00 | cop[tikv] | table:t1 | range: decided by [test.t2.a], keep order:false, stats:pseudo | +------------------------------+---------+-----------+------------------------+----------------------------------------------------------------------------+ ``` From 5f2cd1b9c97da1d1ef4fe778a056c5413b8f5dae Mon Sep 17 00:00:00 2001 From: time-and-fate <25057648+time-and-fate@users.noreply.github.com> Date: Mon, 17 Oct 2022 15:40:21 +0800 Subject: [PATCH 2/7] add empty line --- explain-joins.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/explain-joins.md b/explain-joins.md index 4d8a3df5aee64..67d59acf74efd 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -96,6 +96,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ | └─Selection_9 | 12617.92 | 0 | cop[tikv] | | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42}, scan_detail: {total_process_keys: 56, total_process_keys_size: 174608, total_keys: 77, get_snapshot_time: 727.7µs, rocksdb: {block: {cache_hit_count: 154}}} | eq(test.t1.int_col, 1) | N/A | N/A | | └─TableRangeScan_8 | 90000.00 | 56 | cop[tikv] | table:t1 | tikv_task:{proc max:0s, min:0s, avg: 0s, p80:0s, p95:0s, iters:42, tasks:42} | range: decided by [test.t2.t1_id], keep order:false | N/A | N/A | +-----------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+---------+------+ + +------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ @@ -106,6 +107,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ | └─TableReader_25(Probe) | 90000.00 | 90000 | root | | time:293.7ms, loops:91, cop_task: {num: 24, max: 105.7ms, min: 210.9µs, avg: 31.4ms, p95: 103.8ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 407ms, rpc_num: 24, rpc_time: 752.2ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_24 | 58.6 MB | N/A | | └─TableFullScan_24 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:31ms, min:0s, avg: 13ms, p80:19ms, p95:26ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 69753, get_snapshot_time: 637.2µs, rocksdb: {delete_skipped_count: 97368, key_skipped_count: 236847, block: {cache_hit_count: 3509}}} | keep order:false | N/A | N/A | +------------------------------+----------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ + +------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +------------------------------+----------+---------+-----------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ @@ -141,6 +143,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ | ├─IndexRangeScan_9(Build) | 90000.00 | 0 | cop[tikv] | table:t2, index:t1_id(t1_id) | time:114.3ms, loops:7, cop_task: {num: 7, max: 42ms, min: 1.3ms, avg: 16.2ms, p95: 42ms, tot_proc: 71ms, rpc_num: 7, rpc_time: 113.2ms, copr_cache_hit_ratio: 0.29, distsql_concurrency: 15}, tikv_task:{proc max:37ms, min:0s, avg: 11.3ms, p80:20ms, p95:37ms, iters:7, tasks:7}, scan_detail: {total_keys: 9296, get_snapshot_time: 141.9µs, rocksdb: {block: {cache_hit_count: 18592}}} | range: decided by [eq(test.t2.t1_id, test.t1.id)], keep order:false | N/A | N/A | | └─TableRowIDScan_10(Probe) | 90000.00 | 0 | cop[tikv] | table:t2 | | keep order:false | N/A | N/A | +----------------------------------+----------+---------+-----------+------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+-----------+------+ + +------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ @@ -151,6 +154,7 @@ EXPLAIN ANALYZE SELECT * FROM t1 INNER JOIN t2 ON t1.id = t2.t1_id WHERE t1.int_ | └─TableReader_37(Probe) | 90000.00 | 90000 | root | | time:304.4ms, loops:91, cop_task: {num: 24, max: 114ms, min: 251.1µs, avg: 33.1ms, p95: 110.4ms, max_proc_keys: 10687, p95_proc_keys: 9184, tot_proc: 492ms, rpc_num: 24, rpc_time: 793ms, copr_cache_hit_ratio: 0.62, distsql_concurrency: 15} | data:TableFullScan_36 | 58.6 MB | N/A | | └─TableFullScan_36 | 90000.00 | 90000 | cop[tikv] | table:t2 | tikv_task:{proc max:38ms, min:3ms, avg: 14.1ms, p80:23ms, p95:35ms, iters:181, tasks:24}, scan_detail: {total_process_keys: 69744, total_process_keys_size: 217533936, total_keys: 139497, get_snapshot_time: 577.2µs, rocksdb: {delete_skipped_count: 44208, key_skipped_count: 253431, block: {cache_hit_count: 3527}}} | keep order:false | N/A | N/A | +------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ + +------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ | id | estRows | actRows | task | access object | execution info | operator info | memory | disk | +------------------------------+----------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+---------+ From cbf94e40d05ea389492b86f0838a8e083c8ca45a Mon Sep 17 00:00:00 2001 From: time-and-fate <25057648+time-and-fate@users.noreply.github.com> Date: Mon, 17 Oct 2022 15:50:21 +0800 Subject: [PATCH 3/7] update --- explain-joins.md | 2 +- explain-overview.md | 2 +- sql-statements/sql-statement-explain.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/explain-joins.md b/explain-joins.md index 67d59acf74efd..962310d6c22f2 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -219,7 +219,7 @@ The `operator info` column in the `EXPLAIN` result table also records other info ### Runtime Statistics -If [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) (default value: 1GB) is exceeded, TiDB will attempt to use temporary storage on condition that the `oom-use-tmp-storage` value is `true` (default). This means that the `Build` operator used as part of the hash join might be created on disk. Runtime statistics such as memory usage are visible in the `execution info` of the `EXPLAIN ANALYZE` result table. The following example shows the output of `EXPLAIN ANALYZE` with a 1GB (default) `tidb_mem_quota_query` quota, and a 500MB quota. At 500MB, disk is used for temporary storage: +If [`tidb_mem_quota_query`](/system-variables.md#tidb_mem_quota_query) (default value: 1 GB) is exceeded, TiDB will attempt to use temporary storage on condition that the `oom-use-tmp-storage` value is `true` (default). This means that the `Build` operator used as part of the hash join might be created on disk. Runtime statistics such as memory usage are visible in the `execution info` of the `EXPLAIN ANALYZE` result table. The following example shows the output of `EXPLAIN ANALYZE` with a 1 GB (default) `tidb_mem_quota_query` quota, and a 500 MB quota. At 500 MB, disk is used for temporary storage: ```sql EXPLAIN ANALYZE SELECT /*+ HASH_JOIN(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; diff --git a/explain-overview.md b/explain-overview.md index 6f7b8507f58c3..cabba7b760f64 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -59,7 +59,7 @@ The following describes the output of the `EXPLAIN` statement above: > **Note:** > -> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. +> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meanings of the displayed row count are different before and after v6.4.0. > Before v6.4.0, it means the estimated row count expected to be processed by the Probe side operators for every row from the Build side operator, not the estimated total row count expected to be processed by the Probe side operators. However, the actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so there is an inconsistency in their meanings. > > For example: diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index b924cc20575a4..4b4dfbe25d031 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -40,7 +40,7 @@ ExplainableStmt ::= > **Note:** > -> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). +> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meanings of the displayed row count are different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). Currently, `EXPLAIN` in TiDB outputs 5 columns: `id`, `estRows`, `task`, `access object`, `operator info`. Each operator in the execution plan is described by these attributes, with each row in the `EXPLAIN` output describing an operator. The description of each attribute is as follows: From 0ec3bba0b24ba02a929082bdef221ffda1c31739 Mon Sep 17 00:00:00 2001 From: time-and-fate <25057648+time-and-fate@users.noreply.github.com> Date: Fri, 11 Nov 2022 18:42:19 +0800 Subject: [PATCH 4/7] sync changes from docs-cn --- correlated-subquery-optimization.md | 56 ++++++++++++------------- explain-joins.md | 2 +- explain-overview.md | 9 +++- optimizer-hints.md | 28 ++++++------- sql-statements/sql-statement-explain.md | 2 +- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/correlated-subquery-optimization.md b/correlated-subquery-optimization.md index 1021e24dce258..1477dfe06f48f 100644 --- a/correlated-subquery-optimization.md +++ b/correlated-subquery-optimization.md @@ -57,20 +57,20 @@ explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) ``` ```sql -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | -| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | -| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | -| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | -| └─MaxOneRow_15(Probe) | 1.00 | root | | | -| └─HashAgg_27 | 1.00 | root | | funcs:sum(Column#10)->Column#7 | -| └─IndexLookUp_28 | 1.00 | root | | | -| ├─IndexRangeScan_25(Build) | 10.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | -| └─HashAgg_17(Probe) | 1.00 | cop[tikv] | | funcs:sum(test.t2.a)->Column#10 | -| └─TableRowIDScan_26 | 10.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | +| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | +| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | +| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─MaxOneRow_15(Probe) | 10000.00 | root | | | +| └─StreamAgg_20 | 10000.00 | root | | funcs:sum(Column#14)->Column#7 | +| └─Projection_45 | 100000.00 | root | | cast(test.t2.a, decimal(10,0) BINARY)->Column#14 | +| └─IndexLookUp_44 | 100000.00 | root | | | +| ├─IndexRangeScan_42(Build) | 100000.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | +| └─TableRowIDScan_43(Probe) | 100000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` Disabling the decorrelation rule can also achieve the same effect: @@ -84,20 +84,20 @@ explain select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1. ``` ```sql -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | -| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | -| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | -| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | -| └─MaxOneRow_15(Probe) | 1.00 | root | | | -| └─HashAgg_27 | 1.00 | root | | funcs:sum(Column#10)->Column#7 | -| └─IndexLookUp_28 | 1.00 | root | | | -| ├─IndexRangeScan_25(Build) | 10.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | -| └─HashAgg_17(Probe) | 1.00 | cop[tikv] | | funcs:sum(test.t2.a)->Column#10 | -| └─TableRowIDScan_26 | 10.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | +| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | +| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | +| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─MaxOneRow_15(Probe) | 10000.00 | root | | | +| └─StreamAgg_20 | 10000.00 | root | | funcs:sum(Column#14)->Column#7 | +| └─Projection_45 | 100000.00 | root | | cast(test.t2.a, decimal(10,0) BINARY)->Column#14 | +| └─IndexLookUp_44 | 100000.00 | root | | | +| ├─IndexRangeScan_42(Build) | 100000.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | +| └─TableRowIDScan_43(Probe) | 100000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` After disabling the subquery decorrelation rule, you can see `range: decided by [eq(test.t2.b, test.t1.b)]` in `operator info` of `IndexRangeScan_25(Build)`. It means that the decorrelation of correlated subquery is not performed and TiDB uses the index range query. diff --git a/explain-joins.md b/explain-joins.md index fe5db806e73bf..b27818df9712d 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -43,7 +43,7 @@ If the number of estimated rows that need to be joined is small (typically less > **Note:** > -> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meaning of the displayed row count is different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). +> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). {{< copyable "sql" >}} diff --git a/explain-overview.md b/explain-overview.md index 523d8a74e154f..4cf23cd84ec42 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -59,8 +59,9 @@ The following describes the output of the `EXPLAIN` statement above: > **Note:** > -> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meanings of the displayed row count are different before and after v6.4.0. -> Before v6.4.0, it means the estimated row count expected to be processed by the Probe side operators for every row from the Build side operator, not the estimated total row count expected to be processed by the Probe side operators. However, the actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so there is an inconsistency in their meanings. +> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. +> Before v6.4.0, `estRows` means the estimated row count expected to be processed by the Probe side operators for each row from the Build side operator. From v6.4.0, `estRows` means the estimated **total row count** expected to be processed by the Probe side operators. The actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so the meanings of `estRows` and `actRows` for those operatos are consistent from v6.4.0. +> > > For example: > @@ -99,6 +100,8 @@ The following describes the output of the `EXPLAIN` statement above: > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > > -- From v6.4.0: +> +> -- You can find the difference between `estRows` of `IndexLookUp_11`、`Selection_10`、`IndexRangeScan_8` and `TableRowIDScan_9` and that before v6.4.0. > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ @@ -111,6 +114,8 @@ The following describes the output of the `EXPLAIN` statement above: > | │ └─IndexRangeScan_8 | 12500.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.a)], keep order:false, stats:pseudo | > | └─TableRowIDScan_9(Probe) | 12487.50 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ +> +> -- You can find the difference between `estRows` of `Limit_17`、`IndexReader_21`、`Limit_20` and `IndexRangeScan_19` and that before v6.4.0. > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ diff --git a/optimizer-hints.md b/optimizer-hints.md index 8cf19d06cfaea..483a01c7a269d 100644 --- a/optimizer-hints.md +++ b/optimizer-hints.md @@ -249,20 +249,20 @@ explain select * from t1 where t1.a < (select /*+ NO_DECORRELATE() */ sum(t2.a) ``` ```sql -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| id | estRows | task | access object | operator info | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ -| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | -| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | -| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | -| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | -| └─MaxOneRow_15(Probe) | 1.00 | root | | | -| └─HashAgg_27 | 1.00 | root | | funcs:sum(Column#10)->Column#7 | -| └─IndexLookUp_28 | 1.00 | root | | | -| ├─IndexRangeScan_25(Build) | 10.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | -| └─HashAgg_17(Probe) | 1.00 | cop[tikv] | | funcs:sum(test.t2.a)->Column#10 | -| └─TableRowIDScan_26 | 10.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | -+----------------------------------------+----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| id | estRows | task | access object | operator info | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ +| Projection_10 | 10000.00 | root | | test.t1.a, test.t1.b | +| └─Apply_12 | 10000.00 | root | | CARTESIAN inner join, other cond:lt(cast(test.t1.a, decimal(10,0) BINARY), Column#7) | +| ├─TableReader_14(Build) | 10000.00 | root | | data:TableFullScan_13 | +| │ └─TableFullScan_13 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo | +| └─MaxOneRow_15(Probe) | 10000.00 | root | | | +| └─StreamAgg_20 | 10000.00 | root | | funcs:sum(Column#14)->Column#7 | +| └─Projection_45 | 100000.00 | root | | cast(test.t2.a, decimal(10,0) BINARY)->Column#14 | +| └─IndexLookUp_44 | 100000.00 | root | | | +| ├─IndexRangeScan_42(Build) | 100000.00 | cop[tikv] | table:t2, index:idx(b) | range: decided by [eq(test.t2.b, test.t1.b)], keep order:false, stats:pseudo | +| └─TableRowIDScan_43(Probe) | 100000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | ++------------------------------------------+-----------+-----------+------------------------+--------------------------------------------------------------------------------------+ ``` From the preceding execution plan, you can see that the optimizer does not perform decorrelation. The execution plan still contains the Apply operator. The filter condition (`t2.b = t1.b`) with the correlated column is still the filter condition when accessing the `t2` table. diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index 5c316cc6a4427..c50d1428f9d12 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -40,7 +40,7 @@ ExplainableStmt ::= > **Note:** > -> For the `estRows` of all Probe side sub-operators of `IndexJoin` and `Apply`, the meanings of the displayed row count are different before and after v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). +> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). Currently, `EXPLAIN` in TiDB outputs 5 columns: `id`, `estRows`, `task`, `access object`, `operator info`. Each operator in the execution plan is described by these attributes, with each row in the `EXPLAIN` output describing an operator. The description of each attribute is as follows: From 2851e55fba5fcb9c7314f0f6f208ef9053bd1a11 Mon Sep 17 00:00:00 2001 From: Zhou Kunqin <25057648+time-and-fate@users.noreply.github.com> Date: Mon, 14 Nov 2022 19:31:48 +0800 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: TomShawn <41534398+TomShawn@users.noreply.github.com> --- explain-joins.md | 2 +- explain-overview.md | 8 ++++---- sql-statements/sql-statement-explain.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/explain-joins.md b/explain-joins.md index b27818df9712d..fa1ef33cae6aa 100644 --- a/explain-joins.md +++ b/explain-joins.md @@ -43,7 +43,7 @@ If the number of estimated rows that need to be joined is small (typically less > **Note:** > -> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). +> In the returned execution plan, for all probe-side child nodes of `IndexJoin` and `Apply` operators, the meaning of `estRows` since v6.4.0 is different from that before v6.4.0. For more details, see [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). {{< copyable "sql" >}} diff --git a/explain-overview.md b/explain-overview.md index 4cf23cd84ec42..975b904769990 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -59,7 +59,7 @@ The following describes the output of the `EXPLAIN` statement above: > **Note:** > -> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. +> In the returned execution plan, for all probe-side child nodes of `IndexJoin` and `Apply` operators, the meaning of `estRows` since v6.4.0 is different from that before v6.4.0. > Before v6.4.0, `estRows` means the estimated row count expected to be processed by the Probe side operators for each row from the Build side operator. From v6.4.0, `estRows` means the estimated **total row count** expected to be processed by the Probe side operators. The actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so the meanings of `estRows` and `actRows` for those operatos are consistent from v6.4.0. > > @@ -99,9 +99,9 @@ The following describes the output of the `EXPLAIN` statement above: > | └─IndexRangeScan_19 | 1.00 | cop[tikv] | table:t2, index:ia(a) | range: decided by [eq(test.t2.a, test.t1.b)], keep order:false, stats:pseudo | > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > -> -- From v6.4.0: +> -- Since v6.4.0: > -> -- You can find the difference between `estRows` of `IndexLookUp_11`、`Selection_10`、`IndexRangeScan_8` and `TableRowIDScan_9` and that before v6.4.0. +> -- You can find that the `estRows` column values for `IndexLookUp_11`, `Selection_10`, `IndexRangeScan_8`, and `TableRowIDScan_9` since v6.4.0 are different from that before v6.4.0. > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ @@ -115,7 +115,7 @@ The following describes the output of the `EXPLAIN` statement above: > | └─TableRowIDScan_9(Probe) | 12487.50 | cop[tikv] | table:t2 | keep order:false, stats:pseudo | > +---------------------------------+----------+-----------+-----------------------+-----------------------------------------------------------------------------------------------------------------+ > -> -- You can find the difference between `estRows` of `Limit_17`、`IndexReader_21`、`Limit_20` and `IndexRangeScan_19` and that before v6.4.0. +> -- You can find that the `estRows` column values for `Limit_17`, `IndexReader_21`, `Limit_20`, and `IndexRangeScan_19` since v6.4.0 are different from that before v6.4.0. > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ > | id | estRows | task | access object | operator info | > +---------------------------------+----------+-----------+-----------------------+------------------------------------------------------------------------------+ diff --git a/sql-statements/sql-statement-explain.md b/sql-statements/sql-statement-explain.md index c50d1428f9d12..ffa984683fce8 100644 --- a/sql-statements/sql-statement-explain.md +++ b/sql-statements/sql-statement-explain.md @@ -40,7 +40,7 @@ ExplainableStmt ::= > **Note:** > -> In the execution plan, for all Probe side operators of `IndexJoin` and `Apply`, the meaning of `estRows` from v6.4.0 is different that before v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). +> In the returned execution plan, for all probe-side child nodes of `IndexJoin` and `Apply` operators, the meaning of `estRows` since v6.4.0 is different from that before v6.4.0. You can find details in [TiDB Query Execution Plan Overview](/explain-overview.md#understand-explain-output). Currently, `EXPLAIN` in TiDB outputs 5 columns: `id`, `estRows`, `task`, `access object`, `operator info`. Each operator in the execution plan is described by these attributes, with each row in the `EXPLAIN` output describing an operator. The description of each attribute is as follows: From 1bcf6092bac2a4d3f380c1fd5073382e5fd05c51 Mon Sep 17 00:00:00 2001 From: Zhou Kunqin <25057648+time-and-fate@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:10:12 +0800 Subject: [PATCH 6/7] Update explain-overview.md Co-authored-by: TomShawn <41534398+TomShawn@users.noreply.github.com> --- explain-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/explain-overview.md b/explain-overview.md index 975b904769990..7cc229128bda0 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -60,7 +60,7 @@ The following describes the output of the `EXPLAIN` statement above: > **Note:** > > In the returned execution plan, for all probe-side child nodes of `IndexJoin` and `Apply` operators, the meaning of `estRows` since v6.4.0 is different from that before v6.4.0. -> Before v6.4.0, `estRows` means the estimated row count expected to be processed by the Probe side operators for each row from the Build side operator. From v6.4.0, `estRows` means the estimated **total row count** expected to be processed by the Probe side operators. The actual row count displayed (the `actRows` column) in the `EXPLAIN ANALYZE` statement means the total row count, so the meanings of `estRows` and `actRows` for those operatos are consistent from v6.4.0. +> Before v6.4.0, `estRows` means the number of estimated rows to be processed by the probe side operators for each row from the build side operators. Since v6.4.0, `estRows` means the **total number** of estimated rows to be processed by the probe side operators. The actual number of rows displayed (indicated by the `actRows` column) in the result of `EXPLAIN ANALYZE` means the total row count, so since v6.4.0 the meanings of `estRows` and `actRows` for the probe side child nodes of `IndexJoin` and `Apply` operators are consistent. > > > For example: From 919f09f2853d90c17d32ea790d83ffe9edf992cd Mon Sep 17 00:00:00 2001 From: TomShawn <41534398+TomShawn@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:27:11 +0800 Subject: [PATCH 7/7] Update explain-overview.md --- explain-overview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/explain-overview.md b/explain-overview.md index 7cc229128bda0..7a7bea72c0bda 100644 --- a/explain-overview.md +++ b/explain-overview.md @@ -60,6 +60,7 @@ The following describes the output of the `EXPLAIN` statement above: > **Note:** > > In the returned execution plan, for all probe-side child nodes of `IndexJoin` and `Apply` operators, the meaning of `estRows` since v6.4.0 is different from that before v6.4.0. +> > Before v6.4.0, `estRows` means the number of estimated rows to be processed by the probe side operators for each row from the build side operators. Since v6.4.0, `estRows` means the **total number** of estimated rows to be processed by the probe side operators. The actual number of rows displayed (indicated by the `actRows` column) in the result of `EXPLAIN ANALYZE` means the total row count, so since v6.4.0 the meanings of `estRows` and `actRows` for the probe side child nodes of `IndexJoin` and `Apply` operators are consistent. > >