tidb can't use range scan when using `BETWEEN '1' AND '2'` filter on single column int primary key
- 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
Assessment
This issue has not been assessed yet.