pingcap / pingcap/tidb

some special case when can be simplied as one path rather then keeping the both

Open
#58,742 0 comments 0 reactions 0 assignees View on GitHub
planner/cascades sig/planner type/enhancement
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Enhancement
```
drop table if exists t;
create table t(a int primary key, b int);
insert into t values (1, 11), (4, 44), (2, 22), (3, 33);
set session tidb_executor_concurrency = 4;
set @@session.tidb_hash_join_concurrency = 5;
set @@session.tidb_distsql_scan_concurrency = 15;

mysql> explain select count(distinct case when a > 0 and a <= 1000 then b end) from t;
+---------------------------+-------------+-----------+---------------+--------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+---------------------------+-------------+-----------+---------------+--------------------------------------------------------------------+
| StreamAgg_6 | 1.00 | root | | funcs:count(distinct Column#4)->Column#3 |
| └─Projection_11 | 10000.00 | root | | case(and(gt(test.t.a, 0), le(test.t.a, 1000)), test.t.b)->Column#4 |
| └─TableReader_10 | 10000.00 | root | | data:TableFullScan_9 |
| └─TableFullScan_9 | 10000.00 | cop[tikv] | table:t | keep order:false, stats:pseudo |
+---------------------------+-------------+-----------+---------------+--------------------------------------------------------------------+
4 rows in set (0.00 sec)
```

let's break this down as:
* a>0 and a<=1000, then count(distinct b)
* a<=0 or a>1000, then count(distinct NULL * N) if any, if will be equivalent to count(distinct NULL * 1), equal to 0 at last. since we only care about the count result, so it can be simplified.

so what we should care about is the condition 1, the second is meaningless, so the plan can be xformed as below:
```
HashAgg_10 1.00 root funcs:count(distinct planner__cascades__integration.t.b)->Column#3
└─TableReader_11 250.00 root data:TableRangeScan_12
└─TableRangeScan_12 250.00 cop[tikv] table:t range:(0,1000], keep order:false, stats:pseudo
```
just push the condition on `a` down to the source, make it as the access range. the access count can be dramatically reduced.

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.