5

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

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

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

表格布局以显示示例:

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;

这里它使用字符串作为索引:

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 |
+----+-------------+---------+------+---------------+-----------+---------+-------+------+--------------------------+

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

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 |
+----+-------------+---------+-------+---------------+-----------+---------+------+------+--------------------------+
4

2 回答 2

12

手册所述:

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

SELECT * FROM tbl_name WHERE str_col =1;

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

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

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);
于 2012-05-08T00:15:51.900 回答
6

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

SELECT * FROM example WHERE stuff = CAST(200 AS CHAR);

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

SELECT * FROM example WHERE stuff = CONVERT(200 USING latin1);
于 2015-11-23T22:33:34.443 回答