背景:服务器应用程序(C#)使用下面的查询(简化)从数据库中提取订单数据。我记录了这需要的平均时间,现在执行时间突然增加(平均从5ms到50ms)。所以我开始检查这个查询。使用变量时不使用索引
String ordernr = "123456789";
String sql = "SELECT * FROM MYDB.`MYTABLE` WHERE id = @id";
using (MySqlCommand cmd = new MySqlCommand(sql, conn))
{
cmd.Parameters.Add("@id", MySqlDbType.VarChar, 16).Value = ordernr;
using (MySqlDataReader reader = cmd.ExecuteReader())
{
//reading data
}
}
当我检查在MySQL查询时,我得到如下结果:
MariaDB [MYDB]> SET @id = '123456789';
Query OK, 0 rows affected (0.00 sec)
MariaDB [MYDB]> explain SELECT SQL_NO_CACHE * FROM MYDB.`MYTABLE` WHERE id = @id ;
+------+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | MYTABLE | ALL | NULL | NULL | NULL | NULL | 1448219 | Using where |
+------+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)
MariaDB [MYDB]> explain SELECT SQL_NO_CACHE * FROM MYDB.`MYTABLE` WHERE id = '123456789';
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | MYTABLE | const | PRIMARY | PRIMARY | 18 | const | 1 | |
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
MariaDB [MYDB]>
现在我的问题是,为什么
查询从服务器应用程序如下执行当我使用变量时,PRIMARY索引被忽略了吗?
我不知道这是性能下降的原因(因为在这个例子中,两个查询都返回0.00秒),但这让我皱眉为什么会有差异。我也在服务器应用程序中使用了一个准备好的查询和一个变量。所以我想检查一下这是否相关。
任何人都可以解释这一点吗?
这是一个MySQL的问题。无论客户端工具如何,您都会得到相同的行为。 “ID”列的类型和索引定义是什么?你是否传递一个整数ID的文本参数值? MySQL可能会将* table *数据转换为参数类型而不是相反,从而强制进行全表扫描 –
这确实是一个varchar字段(varchar(16)。在数据库中,以及在C#代码中设置的时候添加参数)。我可以补充说。 – Johan
为什么使用'varchar(6)'字段来存储数字键?除了转换和空间问题,排序规则是不同的,'2'在'123456'后出现。 –