pingcap / pingcap/tidb

DELETE with implicit type conversion cannot use IndexRangeScan while SELECT can

Open
#68,055 2 comments 0 reactions 0 assignees View on GitHub
contribution severity/moderate sig/planner type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!
We found this anomaly during a MySQL-to-TiDB migration project, which caused the migration change to be rolled back.

### 1. Minimal reproduce step (Required)

``` sql
create table test(
order_id bigint,
key idx_order_id(order_id)
);
```
``` sql
tidb8.5.5 > explain delete from test where order_id='';
+---------------------------+----------+-----------+------------------------------------------+--------------------------------------------------------+
| id | estRows | task | access object | operator info |
+---------------------------+----------+-----------+------------------------------------------+--------------------------------------------------------+
| Delete_3 | N/A | root | | N/A |
| └─IndexReader_11 | 8000.00 | root | | index:Selection_10 |
| └─Selection_10 | 8000.00 | cop[tikv] | | eq(cast(fjm_worktime.test.order_id, double BINARY), 0) |
| └─IndexFullScan_9 | 10000.00 | cop[tikv] | table:test, index:idx_order_id(order_id) | keep order:false, stats:pseudo |
+---------------------------+----------+-----------+------------------------------------------+--------------------------------------------------------+
```

``` sql
tidb8.5.5 > explain select * from test where order_id='';
+------------------------+---------+-----------+------------------------------------------+---------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+------------------------------------------+---------------------------------------------+
| IndexReader_6 | 10.00 | root | | index:IndexRangeScan_5 |
| └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:test, index:idx_order_id(order_id) | range:[0,0], keep order:false, stats:pseudo |
+------------------------+---------+-----------+------------------------------------------+---------------------------------------------+
2 rows in set, 4 warnings (0.01 sec)

tidb8.5.5 > show warnings;
+---------+------+--------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '' |
| Warning | 1292 | Truncated incorrect DOUBLE value: '' |
+---------+------+--------------------------------------+
```

``` sql
mysql8.0.46 > explain delete from test where order_id='';
+----+-------------+-------+------------+-------+---------------+--------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------------+---------+-------+------+----------+-------------+
| 1 | DELETE | test | NULL | range | idx_order_id | idx_order_id | 9 | const | 1 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+--------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

mysql8.0.46 > show warnings;
+-------+------+----------------------------------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------------------------------+
| Note | 1003 | delete from `test`.`test` where (`test`.`test`.`order_id` = 0) |
+-------+------+----------------------------------------------------------------+
1 row in set (0.00 sec)

```

### 2. What did you expect to see? (Required)
DELETE should build range [0,0] on idx_order_id, same as SELECT and MySQL.

### 3. What did you see instead (Required)
DELETE keeps predicate as cast(order_id as double) = 0,
so it uses FullScan + Selection.

### 4. What is your TiDB version? (Required)
8.5.5

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.