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)
这完全有道理。
既然你说 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 和一次比较。需要全表扫描。
您的第二个查询是纯字符串比较,索引具有基于字符串的值。