如何解决TiDB 索引没有被用于查询
我使用 MysqL 连接器连接 TiDB。 我发现我的查询中没有使用索引。 经过我的分析,我发现由于铸造索引没有使用。 例如
CREATE TABLE Employee (
ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,EmpID VARCHAR(200) NOT NULL
);
CREATE INDEX idx_EmpID ON Employee(EmpID);
1.Explain SELECT * FROM Employee WHERE EmpID= 123;
2.Explain SELECT * FROM Employee WHERE EmpID= '123';
在上面的示例中,如果我运行第一个查询并使用解释检查执行计划,那么在第二个查询中没有使用索引,因为我正在为正在使用的 varchar 数据类型索引提供引号。
但是这个解决方案需要通过 .net MysqLconnector 库进行测试。 目前我正在使用 MysqL 命令参数来执行查询。
1.AddWithValue 函数的当前逻辑
MysqLCommand cmd1 = new MysqLCommand
{
CommandText = "Select * from Employee where EmpID = @EmpID"
};
cmd1.Parameters.AddWithValue($"@EmpID",1234);
2.通过使用Add函数为字段提供数据类型来更新逻辑
MysqLCommand cmd1 = new MysqLCommand
{
CommandText = "Select * from Employee where EmpID = @EmpID"
};
cmd1.Parameters.Add($"@EmpID",MysqLDbType.VarChar).Value = 1234;
我想在处理请求时知道服务器端的查询表示。 更新后的逻辑,即第 2 点是否会通过为 varchar 数据类型提供引号来形成查询?
解决方法
我认为 TiDB 和 MySQL 在这里有相同的行为。如果您正在比较 VARCHAR 列 与一个字符串,它将它作为一个字符串进行比较,它将使用索引。当它与一个 整数然后它将尝试将每一行的值转换为整数,然后进行比较。然后 它不能使用索引。请注意,您需要向表中添加几行以获得更真实的 解释计划。另请注意,根据类型,结果可能会有所不同。
mysql 8.0.22 > CREATE TABLE Employee (
-> ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,-> EmpID VARCHAR(200) NOT NULL
-> );
Query OK,0 rows affected (0.14 sec)
mysql 8.0.22 > CREATE INDEX idx_EmpID ON Employee(EmpID);
Query OK,0 rows affected (0.11 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql 8.0.22 > EXPLAIN SELECT * FROM Employee WHERE EmpID= 123;
+----+-------------+----------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | Employee | NULL | index | idx_EmpID | idx_EmpID | 802 | NULL | 1 | 100.00 | Using where; Using index |
+----+-------------+----------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
1 row in set,3 warnings (0.00 sec)
mysql 8.0.22 > EXPLAIN SELECT * FROM Employee WHERE EmpID= '123';
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | Employee | NULL | ref | idx_EmpID | idx_EmpID | 802 | const | 1 | 100.00 | Using index |
+----+-------------+----------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
1 row in set,1 warning (0.00 sec)
mysql 8.0.22 > INSERT INTO Employee(EmpID) VALUES ('010'),('10');
Query OK,2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql 8.0.22 > SELECT * FROM Employee;
+----+-------+
| ID | EmpID |
+----+-------+
| 1 | 010 |
| 2 | 10 |
+----+-------+
2 rows in set (0.00 sec)
mysql 8.0.22 > SELECT * FROM Employee WHERE EmpID='10';
+----+-------+
| ID | EmpID |
+----+-------+
| 2 | 10 |
+----+-------+
1 row in set (0.00 sec)
mysql 8.0.22 > SELECT * FROM Employee WHERE EmpID=10;
+----+-------+
| ID | EmpID |
+----+-------+
| 1 | 010 |
| 2 | 10 |
+----+-------+
2 rows in set (0.00 sec)
tidb 5.7.25-TiDB-v5.0.0 > CREATE TABLE Employee (
-> ID BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,0 rows affected (0.15 sec)
tidb 5.7.25-TiDB-v5.0.0 > CREATE INDEX idx_EmpID ON Employee(EmpID);
Query OK,0 rows affected (2.87 sec)
tidb 5.7.25-TiDB-v5.0.0 > EXPLAIN SELECT * FROM Employee WHERE EmpID= 123;
+-------------------------+----------+-----------+----------------+------------------------------------+
| id | estRows | task | access object | operator info |
+-------------------------+----------+-----------+----------------+------------------------------------+
| TableReader_7 | 8000.00 | root | | data:Selection_6 |
| └─Selection_6 | 8000.00 | cop[tikv] | | eq(cast(test.employee.empid),123) |
| └─TableFullScan_5 | 10000.00 | cop[tikv] | table:Employee | keep order:false,stats:pseudo |
+-------------------------+----------+-----------+----------------+------------------------------------+
3 rows in set (0.01 sec)
tidb 5.7.25-TiDB-v5.0.0 > EXPLAIN SELECT * FROM Employee WHERE EmpID= '123';
+------------------------+---------+-----------+----------------------------------------+-----------------------------------------------------+
| id | estRows | task | access object | operator info |
+------------------------+---------+-----------+----------------------------------------+-----------------------------------------------------+
| IndexReader_6 | 10.00 | root | | index:IndexRangeScan_5 |
| └─IndexRangeScan_5 | 10.00 | cop[tikv] | table:Employee,index:idx_EmpID(EmpID) | range:["123","123"],keep order:false,stats:pseudo |
+------------------------+---------+-----------+----------------------------------------+-----------------------------------------------------+
2 rows in set (0.00 sec)
tidb 5.7.25-TiDB-v5.0.0 > INSERT INTO Employee(EmpID) VALUES ('010'),2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0
tidb 5.7.25-TiDB-v5.0.0 > SELECT * FROM Employee;
+----+-------+
| ID | EmpID |
+----+-------+
| 1 | 010 |
| 2 | 10 |
+----+-------+
2 rows in set (0.00 sec)
tidb 5.7.25-TiDB-v5.0.0 > SELECT * FROM Employee WHERE EmpID='10';
+----+-------+
| ID | EmpID |
+----+-------+
| 2 | 10 |
+----+-------+
1 row in set (0.00 sec)
tidb 5.7.25-TiDB-v5.0.0 > SELECT * FROM Employee WHERE EmpID=10;
+----+-------+
| ID | EmpID |
+----+-------+
| 1 | 010 |
| 2 | 10 |
+----+-------+
2 rows in set (0.00 sec)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。