为什么使用INT来选择包含比使用字符串慢得多的数字的Varchar索引?

nic*_*nda 4 mysql indexing innodb database-performance

我有一个包含数千行的表,其中包含一个包含数字的Varchar列.尽管讨论了为什么这个列不是数字类型,但从该表中选择行显示出一种奇怪的行为.

虽然该列上有索引,但使用数字字符串查找行比使用Ints(0.54秒)快得多(0.01秒).这是什么原因?似乎无法转换和使用索引的值...

我忽略了什么吗?看起来它没有强制转换为将其用于索引?我是否必须提供有关索引使用的提示,或者是否有数据库切换来完成此操作?或者,如果我误解了Explain输出,为什么它会慢得多?

表布局显示示例:

CREATE TABLE `example` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `stuff` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_stuff` (`stuff`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Run Code Online (Sandbox Code Playgroud)

这里使用String作为索引:

explain select * from example where stuff='200';
----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+
| id | select_type | table   | type | possible_keys | key       | key_len | ref   | rows | Extra                    |
+----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | example | ref  | idx_stuff     | idx_stuff | 137     | const |    1 | Using where; Using index |
+----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+
Run Code Online (Sandbox Code Playgroud)

这里看起来它没有将Int转换为String来用于查找索引:

explain select * from example where stuff=200;
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table   | type  | possible_keys | key       | key_len | ref  | rows | Extra                    |
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
|  1 | SIMPLE      | example | index | idx_stuff     | idx_stuff | 137     | NULL |    2 | Using where; Using index |
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
Run Code Online (Sandbox Code Playgroud)

egg*_*yal 10

手册所述:

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

SELECT * FROM tbl_name WHERE str_col=1;

这样做的原因是,有许多不同的字符串可以转换为价值1,例如'1',' 1''1a'.

如有必要,您可以CAST将整数转换为字符串,以便利用索引:

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);
Run Code Online (Sandbox Code Playgroud)


Kev*_*ers 6

警告:如果索引的字符集不匹配,MySQL也可以跳过索引,即使两个值都匹配CHAR.如果以下查询不起作用:

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);
Run Code Online (Sandbox Code Playgroud)

然后,通过运行获取数据库字符集,show variables like 'character_set_database';并在CONVERT语句中使用它,如下所示(此示例假定您的数据库字符集是latin1- 用您的值替换它character_set_database):

SELECT * FROM example WHERE stuff = CONVERT(200 USING latin1);
Run Code Online (Sandbox Code Playgroud)

  • 转换为我工作,但CAST不会.谢谢! (2认同)