pingcap / pingcap/tidb

tidb can't use range scan when using `BETWEEN '1' AND '2'` filter on single column int primary key

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

Description

## Enhancement

```sql
use test
create table t1(a int primary key, b int, c int);
create table t2(a int, b int, c int);
explain select * from t1 where a between '1' and '2';
explain select * from t1 where a between 1 and 2;
explain select * from t1 where a >= '1' and a <= '2';
explain select * from t2 where _tidb_rowid between '1' and '2';
explain select * from t2 where _tidb_rowid between 1 and 2;
explain select * from t2 where _tidb_rowid >= '1' and _tidb_rowid <= '2';
```

Expect: all the execution plans can use table range scan.

In tidb v7.2.0:
```
> explain select * from t1 where a between '1' and '2';
+-------------------------+----------+-----------+---------------+------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------+----------+-----------+---------------+------------------------------------------------------------------------------+
| TableReader_7 | 8000.00 | root | | data:Selection_6 |
| └─Selection_6 | 8000.00 | cop[tikv] | | ge(cast(test.t1.a, double BINARY), 1), le(cast(test.t1.a, double BINARY), 2) |
| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t1 | keep order:false, stats:pseudo |
+-------------------------+----------+-----------+---------------+------------------------------------------------------------------------------+

> explain select * from t1 where a between 1 and 2;
+------------------------+---------+-----------+---------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+---------------+---------------------------------------------+
| TableReader_6 | 1.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 1.00 | cop[tikv] | table:t1 | range:[1,2], keep order:false, stats:pseudo |
+------------------------+---------+-----------+---------------+---------------------------------------------+

> explain select * from t1 where a >= '1' and a <= '2';
+------------------------+---------+-----------+---------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+---------------+---------------------------------------------+
| TableReader_6 | 1.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 1.00 | cop[tikv] | table:t1 | range:[1,2], keep order:false, stats:pseudo |
+------------------------+---------+-----------+---------------+---------------------------------------------+

> explain select * from t2 where _tidb_rowid between '1' and '2';
+---------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------+
| id | estRows | task | access object | operator info |
+---------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------+
| Projection_4 | 8000.00 | root | | test.t2.a, test.t2.b, test.t2.c |
| └─TableReader_7 | 8000.00 | root | | data:Selection_6 |
| └─Selection_6 | 8000.00 | cop[tikv] | | ge(cast(test.t2._tidb_rowid, double BINARY), 1), le(cast(test.t2._tidb_rowid, double BINARY), 2) |
| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:t2 | keep order:false, stats:pseudo |
+---------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------+

> explain select * from t2 where _tidb_rowid between 1 and 2;
+--------------------------+----------+-----------+---------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------+----------+-----------+---------------+---------------------------------------------+
| Projection_4 | 8000.00 | root | | test.t2.a, test.t2.b, test.t2.c |
| └─TableReader_6 | 10000.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 10000.00 | cop[tikv] | table:t2 | range:[1,2], keep order:false, stats:pseudo |
+--------------------------+----------+-----------+---------------+---------------------------------------------+

> explain select * from t2 where _tidb_rowid >= '1' and _tidb_rowid <= '2';
+--------------------------+----------+-----------+---------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+--------------------------+----------+-----------+---------------+---------------------------------------------+
| Projection_4 | 8000.00 | root | | test.t2.a, test.t2.b, test.t2.c |
| └─TableReader_6 | 10000.00 | root | | data:TableRangeScan_5 |
| └─TableRangeScan_5 | 10000.00 | cop[tikv] | table:t2 | range:[1,2], keep order:false, stats:pseudo |
+--------------------------+----------+-----------+---------------+---------------------------------------------+
```

In MySQL 8.0.33:
```
> create table t1(a int primary key, b int, c int);

> explain format = 'tree' select * from t1 where a between '1' and '2';
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+-----------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: (t1.a between '1' and '2') (cost=0.46 rows=1)
-> Index range scan on t1 using PRIMARY over (1 <= a <= 2) (cost=0.46 rows=1)
|
+-----------------------------------------------------------------------------------------------------------------------------------------------+

> explain format = 'tree' select * from t1 where a between 1 and 2;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: (t1.a between 1 and 2) (cost=0.46 rows=1)
-> Index range scan on t1 using PRIMARY over (1 <= a <= 2) (cost=0.46 rows=1)
|
+-------------------------------------------------------------------------------------------------------------------------------------------+

> explain format = 'tree' select * from t1 where a >= '1' and a <= '2';
+--------------------------------------------------------------------------------------------------------------------------------------------------+
| EXPLAIN |
+--------------------------------------------------------------------------------------------------------------------------------------------------+
| -> Filter: ((t1.a >= 1) and (t1.a <= 2)) (cost=0.46 rows=1)
-> Index range scan on t1 using PRIMARY over (1 <= a <= 2) (cost=0.46 rows=1)
|
+--------------------------------------------------------------------------------------------------------------------------------------------------+
```

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.