【问题标题】:TiDB indexes are not getting used for queriesTiDB 索引没有被用于查询
【发布时间】:2021-07-09 08:27:52
【问题描述】:

我正在使用 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.通过使用添加功能为字段提供数据类型来更新逻辑

                MySqlCommand cmd1 = new MySqlCommand
                {
                    CommandText = "Select * from Employee where EmpID = @EmpID"
                };

                cmd1.Parameters.Add($"@EmpID", MySqlDbType.VarChar).Value = 1234;

我想在处理请求时知道服务器端的查询表示。 更新后的逻辑(即第 2 点)是否会通过为 varchar 数据类型提供引号来形成查询?

【问题讨论】:

    标签: c# mysql asp.net-core tidb


    【解决方案1】:

    我认为 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,
        -> EmpID VARCHAR(200) NOT NULL
        -> );
    Query OK, 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'),('10');
    Query OK, 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)
    

    【讨论】:

    • 您能告诉我更新后的 c# 逻辑是否正确,是否可以用于索引?
    • C# 逻辑在我看来是正确的。但是我不是 C# 专家,所以也许其他人可以对此做出更好的判断。
    猜你喜欢
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-26
    • 2018-02-07
    • 2013-12-02
    • 1970-01-01
    相关资源
    最近更新 更多