不带引号的 MySQL 文本字段

jci*_*sio 3 mysql index varchar

我刚刚遇到了一些奇怪的事情。base_id 是一个 varchar(255)。当我执行不带引号的 SELECT 时,它会扫描整个表:

mysql> EXPLAIN SELECT sid FROM rf_fo.scald_atoms WHERE base_id = 493457;
+----+-------------+-------------+-------+---------------+---------+---------+------+-------+--------------------------+
| id | select_type | table       | type  | possible_keys | key     | key_len | ref  | rows  | Extra                    |
+----+-------------+-------------+-------+---------------+---------+---------+------+-------+--------------------------+
|  1 | SIMPLE      | scald_atoms | index | base_id       | base_id | 767     | NULL | 84404 | Using where; Using index |
+----+-------------+-------------+-------+---------------+---------+---------+------+-------+--------------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

有报价就可以了。

mysql> EXPLAIN SELECT sid FROM rf_fo.scald_atoms WHERE base_id = '493457';
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------------+
| id | select_type | table       | type  | possible_keys | key     | key_len | ref   | rows | Extra       |
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------------+
|  1 | SIMPLE      | scald_atoms | const | base_id       | base_id | 767     | const |    1 | Using index |
+----+-------------+-------------+-------+---------------+---------+---------+-------+------+-------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Rol*_*DBA 5

这完全有道理。

既然你说 base_id 是 VARCHAR(255),你的第一个查询

SELECT sid FROM rf_fo.scald_atoms WHERE base_id = 493457;
Run Code Online (Sandbox Code Playgroud)

真的像这样

SELECT sid FROM rf_fo.scald_atoms WHERE CAST(base_id as unsigned) = 493457;
Run Code Online (Sandbox Code Playgroud)

这会导致每个 base_id 经历一次 CAST 和一次比较。需要全表扫描。

您的第二个查询是纯字符串比较,索引具有基于字符串的值。