pingcap / pingcap/tidb

planner: select the wrong JOIN for TPCDS-Q76 if `tidb_distsql_scan_concurrency=30;tidb_executor_concurrency=16`

Open
#39,707 0 comments 0 reactions 1 assignee Claimed by @qw4990 View on GitHub
epic/cost-model sig/planner type/enhancement
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Enhancement

[query_76.zip](https://github.com/pingcap/tidb/files/10173540/query_76.zip)

When using the default config that `tidb_distsql_scan_concurrency=15 and tidb_executor_concurrency=5`, the planner can select the optimal plan:
```
explain select channel, col_name, d_year, d_qoy, i_category, COUNT(*) sales_cnt, SUM(ext_sales_price) sales_amt FROM (
SELECT 'store' as channel, 'ss_addr_sk' col_name, d_year, d_qoy, i_category, ss_ext_sales_price ext_sales_price
FROM store_sales, item, date_dim
WHERE ss_addr_sk IS NULL
AND ss_sold_date_sk=d_date_sk
AND ss_item_sk=i_item_sk
UNION ALL
SELECT 'web' as channel, 'ws_web_page_sk' col_name, d_year, d_qoy, i_category, ws_ext_sales_price ext_sales_price
FROM web_sales, item, date_dim
WHERE ws_web_page_sk IS NULL
AND ws_sold_date_sk=d_date_sk
AND ws_item_sk=i_item_sk
UNION ALL
SELECT 'catalog' as channel, 'cs_warehouse_sk' col_name, d_year, d_qoy, i_category, cs_ext_sales_price ext_sales_price
FROM catalog_sales, item, date_dim
WHERE cs_warehouse_sk IS NULL
AND cs_sold_date_sk=d_date_sk
AND cs_item_sk=i_item_sk) foo
GROUP BY channel, col_name, d_year, d_qoy, i_category
ORDER BY channel, col_name, d_year, d_qoy, i_category
limit 100;

+-----------------------------------------------+--------------+-----------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-----------------------------------------------+--------------+-----------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection_40 | 100.00 | root | | Column#251, Column#252, Column#253, Column#254, Column#255, Column#257, Column#258 |
| └─TopN_43 | 100.00 | root | | Column#251, Column#252, Column#253, Column#254, Column#255, offset:0, count:100 |
| └─HashAgg_48 | 603.00 | root | | group by:Column#251, Column#252, Column#253, Column#254, Column#255, funcs:count(1)->Column#257, funcs:sum(Column#256)->Column#258, funcs:firstrow(Column#251)->Column#251, funcs:firstrow(Column#252)->Column#252, funcs:firstrow(Column#253)->Column#253, funcs:firstrow(Column#254)->Column#254, funcs:firstrow(Column#255)->Column#255 |
| └─Union_49 | 6553181.10 | root | | |
| ├─Projection_50 | 6186173.47 | root | | store->Column#251, ss_addr_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.store_sales.ss_ext_sales_price |
| │ └─Projection_51 | 6186173.47 | root | | tpcds50.store_sales.ss_ext_sales_price, tpcds50.item.i_category, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy |
| │ └─HashJoin_61 | 6186173.47 | root | | inner join, equal:[eq(tpcds50.store_sales.ss_sold_date_sk, tpcds50.date_dim.d_date_sk)] |
| │ ├─TableReader_102(Build) | 73049.00 | root | | data:TableFullScan_101 |
| │ │ └─TableFullScan_101 | 73049.00 | cop[tikv] | table:date_dim | keep order:false |
| │ └─HashJoin_88(Probe) | 6186173.47 | root | | inner join, equal:[eq(tpcds50.item.i_item_sk, tpcds50.store_sales.ss_item_sk)] |
| │ ├─TableReader_97(Build) | 62000.00 | root | | data:TableFullScan_96 |
| │ │ └─TableFullScan_96 | 62000.00 | cop[tikv] | table:item | keep order:false |
| │ └─TableReader_100(Probe) | 6186173.47 | root | | data:Selection_99 |
| │ └─Selection_99 | 6186173.47 | cop[tikv] | | isnull(tpcds50.store_sales.ss_addr_sk), not(isnull(tpcds50.store_sales.ss_sold_date_sk)) |
| │ └─TableFullScan_98 | 144004764.00 | cop[tikv] | table:store_sales | keep order:false |
| ├─Projection_103 | 8889.81 | root | | web->Column#251, ws_web_page_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.web_sales.ws_ext_sales_price |
| │ └─IndexJoin_108 | 8889.81 | root | | inner join, inner:TableReader_105, outer key:tpcds50.web_sales.ws_sold_date_sk, inner key:tpcds50.date_dim.d_date_sk, equal cond:eq(tpcds50.web_sales.ws_sold_date_sk, tpcds50.date_dim.d_date_sk) |
| │ ├─HashJoin_140(Build) | 8889.81 | root | | inner join, equal:[eq(tpcds50.web_sales.ws_item_sk, tpcds50.item.i_item_sk)] |
| │ │ ├─TableReader_150(Build) | 8889.81 | root | | data:Selection_149 |
| │ │ │ └─Selection_149 | 8889.81 | cop[tikv] | | isnull(tpcds50.web_sales.ws_web_page_sk), not(isnull(tpcds50.web_sales.ws_sold_date_sk)) |
| │ │ │ └─TableFullScan_148 | 35996850.00 | cop[tikv] | table:web_sales | keep order:false |
| │ │ └─TableReader_152(Probe) | 62000.00 | root | | data:TableFullScan_151 |
| │ │ └─TableFullScan_151 | 62000.00 | cop[tikv] | table:item | keep order:false |
| │ └─TableReader_105(Probe) | 8889.81 | root | | data:TableRangeScan_104 |
| │ └─TableRangeScan_104 | 8889.81 | cop[tikv] | table:date_dim | range: decided by [tpcds50.web_sales.ws_sold_date_sk], keep order:false |
| └─Projection_155 | 358117.82 | root | | catalog->Column#251, cs_warehouse_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.catalog_sales.cs_ext_sales_price |
| └─Projection_156 | 358117.82 | root | | tpcds50.catalog_sales.cs_ext_sales_price, tpcds50.item.i_category, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy |
| └─HashJoin_166 | 358117.82 | root | | inner join, equal:[eq(tpcds50.catalog_sales.cs_sold_date_sk, tpcds50.date_dim.d_date_sk)] |
| ├─TableReader_207(Build) | 73049.00 | root | | data:TableFullScan_206 |
| │ └─TableFullScan_206 | 73049.00 | cop[tikv] | table:date_dim | keep order:false |
| └─HashJoin_193(Probe) | 358117.82 | root | | inner join, equal:[eq(tpcds50.item.i_item_sk, tpcds50.catalog_sales.cs_item_sk)] |
| ├─TableReader_202(Build) | 62000.00 | root | | data:TableFullScan_201 |
| │ └─TableFullScan_201 | 62000.00 | cop[tikv] | table:item | keep order:false |
| └─TableReader_205(Probe) | 358117.82 | root | | data:Selection_204 |
| └─Selection_204 | 358117.82 | cop[tikv] | | isnull(tpcds50.catalog_sales.cs_warehouse_sk), not(isnull(tpcds50.catalog_sales.cs_sold_date_sk)) |
| └─TableFullScan_203 | 71997669.00 | cop[tikv] | table:catalog_sales | keep order:false |
+-----------------------------------------------+--------------+-----------+---------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
36 rows in set (0.00 sec)
```

If use `tidb_distsql_scan_concurrency=30;tidb_executor_concurrency=16`:
```
+---------------------------------------------------+--------------+-----------+-----------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+---------------------------------------------------+--------------+-----------+-----------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection_40 | 100.00 | root | | Column#251, Column#252, Column#253, Column#254, Column#255, Column#257, Column#258 |
| └─TopN_43 | 100.00 | root | | Column#251, Column#252, Column#253, Column#254, Column#255, offset:0, count:100 |
| └─HashAgg_48 | 603.00 | root | | group by:Column#251, Column#252, Column#253, Column#254, Column#255, funcs:count(1)->Column#257, funcs:sum(Column#256)->Column#258, funcs:firstrow(Column#251)->Column#251, funcs:firstrow(Column#252)->Column#252, funcs:firstrow(Column#253)->Column#253, funcs:firstrow(Column#254)->Column#254, funcs:firstrow(Column#255)->Column#255 |
| └─Union_49 | 6553181.10 | root | | |
| ├─Projection_50 | 6186173.47 | root | | store->Column#251, ss_addr_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.store_sales.ss_ext_sales_price |
| │ └─Projection_51 | 6186173.47 | root | | tpcds50.store_sales.ss_ext_sales_price, tpcds50.item.i_category, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy |
| │ └─HashJoin_61 | 6186173.47 | root | | inner join, equal:[eq(tpcds50.store_sales.ss_sold_date_sk, tpcds50.date_dim.d_date_sk)] |
| │ ├─TableReader_102(Build) | 73049.00 | root | | data:TableFullScan_101 |
| │ │ └─TableFullScan_101 | 73049.00 | cop[tikv] | table:date_dim | keep order:false |
| │ └─IndexHashJoin_70(Probe) | 6186173.47 | root | | inner join, inner:IndexLookUp_67, outer key:tpcds50.item.i_item_sk, inner key:tpcds50.store_sales.ss_item_sk, equal cond:eq(tpcds50.item.i_item_sk, tpcds50.store_sales.ss_item_sk) |
| │ ├─TableReader_97(Build) | 62000.00 | root | | data:TableFullScan_96 |
| │ │ └─TableFullScan_96 | 62000.00 | cop[tikv] | table:item | keep order:false |
| │ └─IndexLookUp_67(Probe) | 6186173.47 | root | | |
| │ ├─IndexRangeScan_64(Build) | 144004764.00 | cop[tikv] | table:store_sales, index:PRIMARY(ss_item_sk, ss_ticket_number) | range: decided by [eq(tpcds50.store_sales.ss_item_sk, tpcds50.item.i_item_sk)], keep order:false |
| │ └─Selection_66(Probe) | 6186173.47 | cop[tikv] | | isnull(tpcds50.store_sales.ss_addr_sk), not(isnull(tpcds50.store_sales.ss_sold_date_sk)) |
| │ └─TableRowIDScan_65 | 144004764.00 | cop[tikv] | table:store_sales | keep order:false |
| ├─Projection_103 | 8889.81 | root | | web->Column#251, ws_web_page_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.web_sales.ws_ext_sales_price |
| │ └─HashJoin_114 | 8889.81 | root | | inner join, equal:[eq(tpcds50.web_sales.ws_sold_date_sk, tpcds50.date_dim.d_date_sk)] |
| │ ├─IndexJoin_129(Build) | 8889.81 | root | | inner join, inner:IndexLookUp_128, outer key:tpcds50.item.i_item_sk, inner key:tpcds50.web_sales.ws_item_sk, equal cond:eq(tpcds50.item.i_item_sk, tpcds50.web_sales.ws_item_sk) |
| │ │ ├─TableReader_152(Build) | 62000.00 | root | | data:TableFullScan_151 |
| │ │ │ └─TableFullScan_151 | 62000.00 | cop[tikv] | table:item | keep order:false |
| │ │ └─IndexLookUp_128(Probe) | 8889.81 | root | | |
| │ │ ├─IndexRangeScan_125(Build) | 35996850.00 | cop[tikv] | table:web_sales, index:PRIMARY(ws_item_sk, ws_order_number) | range: decided by [eq(tpcds50.web_sales.ws_item_sk, tpcds50.item.i_item_sk)], keep order:false |
| │ │ └─Selection_127(Probe) | 8889.81 | cop[tikv] | | isnull(tpcds50.web_sales.ws_web_page_sk), not(isnull(tpcds50.web_sales.ws_sold_date_sk)) |
| │ │ └─TableRowIDScan_126 | 35996850.00 | cop[tikv] | table:web_sales | keep order:false |
| │ └─TableReader_154(Probe) | 73049.00 | root | | data:TableFullScan_153 |
| │ └─TableFullScan_153 | 73049.00 | cop[tikv] | table:date_dim | keep order:false |
| └─Projection_155 | 358117.82 | root | | catalog->Column#251, cs_warehouse_sk->Column#252, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy, tpcds50.item.i_category, tpcds50.catalog_sales.cs_ext_sales_price |
| └─Projection_156 | 358117.82 | root | | tpcds50.catalog_sales.cs_ext_sales_price, tpcds50.item.i_category, tpcds50.date_dim.d_year, tpcds50.date_dim.d_qoy |
| └─HashJoin_166 | 358117.82 | root | | inner join, equal:[eq(tpcds50.catalog_sales.cs_sold_date_sk, tpcds50.date_dim.d_date_sk)] |
| ├─TableReader_207(Build) | 73049.00 | root | | data:TableFullScan_206 |
| │ └─TableFullScan_206 | 73049.00 | cop[tikv] | table:date_dim | keep order:false |
| └─IndexHashJoin_175(Probe) | 358117.82 | root | | inner join, inner:IndexLookUp_172, outer key:tpcds50.item.i_item_sk, inner key:tpcds50.catalog_sales.cs_item_sk, equal cond:eq(tpcds50.item.i_item_sk, tpcds50.catalog_sales.cs_item_sk) |
| ├─TableReader_202(Build) | 62000.00 | root | | data:TableFullScan_201 |
| │ └─TableFullScan_201 | 62000.00 | cop[tikv] | table:item | keep order:false |
| └─IndexLookUp_172(Probe) | 358117.82 | root | | |
| ├─IndexRangeScan_169(Build) | 71997669.00 | cop[tikv] | table:catalog_sales, index:PRIMARY(cs_item_sk, cs_order_number) | range: decided by [eq(tpcds50.catalog_sales.cs_item_sk, tpcds50.item.i_item_sk)], keep order:false |
| └─Selection_171(Probe) | 358117.82 | cop[tikv] | | isnull(tpcds50.catalog_sales.cs_warehouse_sk), not(isnull(tpcds50.catalog_sales.cs_sold_date_sk)) |
| └─TableRowIDScan_170 | 71997669.00 | cop[tikv] | table:catalog_sales | keep order:false |
+---------------------------------------------------+--------------+-----------+-----------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

`IndexJoin(catalog_sales, item)` and `IndexJoin(store_sales, item)` are much slower than `HashJoin(catalog_sales, item)` and `HashJoin(store_sales, item)`.

Here is another smaller case:
```
-- with the default config
explain SELECT 1
FROM store_sales, item
WHERE ss_addr_sk IS NULL and ss_item_sk=i_item_sk;
+-------------------------------+--------------+-----------+-------------------+--------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------------+--------------+-----------+-------------------+--------------------------------------------------------------------------------+
| Projection_8 | 6477501.00 | root | | 1->Column#47 |
| └─HashJoin_35 | 6477501.00 | root | | inner join, equal:[eq(tpcds50.item.i_item_sk, tpcds50.store_sales.ss_item_sk)] |
| ├─TableReader_44(Build) | 62000.00 | root | | data:TableFullScan_43 |
| │ └─TableFullScan_43 | 62000.00 | cop[tikv] | table:item | keep order:false |
| └─TableReader_47(Probe) | 6477501.00 | root | | data:Selection_46 |
| └─Selection_46 | 6477501.00 | cop[tikv] | | isnull(tpcds50.store_sales.ss_addr_sk) |
| └─TableFullScan_45 | 144004764.00 | cop[tikv] | table:store_sales | keep order:false |
+-------------------------------+--------------+-----------+-------------------+--------------------------------------------------------------------------------+

-- with the higher concurrency
mysql> set tidb_distsql_scan_concurrency = 30, tidb_executor_concurrency = 16;
Query OK, 0 rows affected (0.00 sec)

+------------------------------------+--------------+-----------+----------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------------------+--------------+-----------+----------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Projection_8 | 6477501.00 | root | | 1->Column#47 |
| └─IndexHashJoin_17 | 6477501.00 | root | | inner join, inner:IndexLookUp_14, outer key:tpcds50.item.i_item_sk, inner key:tpcds50.store_sales.ss_item_sk, equal cond:eq(tpcds50.item.i_item_sk, tpcds50.store_sales.ss_item_sk) |
| ├─TableReader_44(Build) | 62000.00 | root | | data:TableFullScan_43 |
| │ └─TableFullScan_43 | 62000.00 | cop[tikv] | table:item | keep order:false |
| └─IndexLookUp_14(Probe) | 6477501.00 | root | | |
| ├─IndexRangeScan_11(Build) | 144004764.00 | cop[tikv] | table:store_sales, index:PRIMARY(ss_item_sk, ss_ticket_number) | range: decided by [eq(tpcds50.store_sales.ss_item_sk, tpcds50.item.i_item_sk)], keep order:false |
| └─Selection_13(Probe) | 6477501.00 | cop[tikv] | | isnull(tpcds50.store_sales.ss_addr_sk) |
| └─TableRowIDScan_12 | 144004764.00 | cop[tikv] | table:store_sales | keep order:false |
+------------------------------------+--------------+-----------+----------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
8 rows in set (0.01 sec)

```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.