我试图对MySQL5.7数据库执行一个非常简单的查询,但查询速度很慢,解释程序显示它没有使用索引,尽管它将其列为可能的键.下面是查询、解释输出和表模式.有什么主意吗?谢谢

查询:SELECT text FROM LogMessages where lotNumber = 5556677

解释输出:

mysql> explain SELECT text FROM LogMessages where lotNumber = 5556677;
+----+-------------+------------------------------+------------+------+------------------------------------------------------------------------------+------+---------+------+----------+----------+-------------+
| id | select_type | table                        | partitions | type | possible_keys                                                                | key  | key_len | ref  | rows     | filtered | Extra       |
+----+-------------+------------------------------+------------+------+------------------------------------------------------------------------------+------+---------+------+----------+----------+-------------+
|  1 | SIMPLE      | LogMessages                  | NULL       | ALL  | idx_LogMessages_lotNumber                                                    | NULL | NULL    | NULL | 35086603 |    10.00 | Using where |
+----+-------------+------------------------------+------------+------+------------------------------------------------------------------------------+------+---------+------+----------+----------+-------------+
1 row in set, 5 warnings (0.07 sec)

表架构:表架构:

CREATE TABLE `LogMessages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lotNumber` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `text` text COLLATE utf8mb4_unicode_ci,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idLogMessages_UNIQUE` (`id`),
  KEY `idx_LogMessages_lotNumber` (`lotNumber`)
) ENGINE=InnoDB AUTO_INCREMENT=37545325 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

推荐答案

你已经得到了答案,但我想我应该给出更多的背景信息.

https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html解释了为什么不使用该索引:

对于字符串列和数字的比较,MySQL不能使用列上的索引来快速查找值.如果str_ol是索引字符串列,则在以下语句中执行查找时不能使用该索引:

SELECT * FROM tbl_name WHERE str_col=1;

这是因为有许多不同的字符串可以转换为值1,如‘1’、‘1’或‘1a’.

您问题中的解释报告显示为type: ALL,这意味着这是一个表扫描.它没有使用索引.

如果我们使用字符串文字,这是一个字符串到字符串的比较,所以它使用索引.

mysql> explain SELECT text FROM LogMessages where lotNumber = '5556677';
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
| id | select_type | table       | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | LogMessages | NULL       | ref  | idx_LogMessages_lotNumber | idx_LogMessages_lotNumber | 183     | const |    1 |   100.00 | NULL  |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+

如果我们在计算结果为字符串值的表达式中使用数字文字,它也使用索引.有几种方法可以做到这一点:

mysql> explain SELECT text FROM LogMessages where lotNumber = 5556677 collate utf8mb4_unicode_ci;
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
| id | select_type | table       | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | LogMessages | NULL       | ref  | idx_LogMessages_lotNumber | idx_LogMessages_lotNumber | 183     | const |    1 |   100.00 | NULL  |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+

mysql> explain SELECT text FROM LogMessages where lotNumber = cast(5556677 as char);
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
| id | select_type | table       | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | LogMessages | NULL       | ref  | idx_LogMessages_lotNumber | idx_LogMessages_lotNumber | 183     | const |    1 |   100.00 | NULL  |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+

mysql> explain SELECT text FROM LogMessages where lotNumber = concat(5556677);
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
| id | select_type | table       | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | LogMessages | NULL       | ref  | idx_LogMessages_lotNumber | idx_LogMessages_lotNumber | 183     | const |    1 |   100.00 | NULL  |
+----+-------------+-------------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-------+

在这三个示例中,type: ref表示它正在使用索引,执行非唯一查找.

Mysql相关问答推荐

用于将重复行的唯一列值作为单独列获取的SQL查询

使用JSON_CONTAINS搜索多个值的原理

将 GORM 与自定义连接表和外键结合使用

SQL:如何 Select 每个客户最后购买的产品?

将时间戳四舍五入到最接近的半小时而不遗漏丢失的数据

如何使用 express.js 和 react.js 删除连接表中的元素和关联元素

如何知道 Select 查询花费了多少时间?

如何在 SQL 的计算列中显示小数点后两位?

MySQL 视图

MySQL 添加一个 NOT NULL 列

MySQL时区更改?

获取Count(*)占GROUP BY中所有项目数的百分比

如何在sequelize中定义多列的唯一索引

如何在特定数据库中创建表?

MySQL 删除多列

比较 MySQL 中的日期忽略 DateTime 字段的时间部分

带有 OuterRef 的简单子查询

MySQL:唯一字段需要是索引吗?

设计用户角色和权限系统的最佳实践?

AWS RDS 实例升级停机时间