1
CREATE TABLE `TEST` (
`ID1` mediumint(8) NOT NULL default '0',
`ID2` mediumint(8) NOT NULL default '0',
`DATE` datetime NOT NULL default '0000-00-00 00:00:00',
 UNIQUE KEY `COMBO_INDEX` (`ID1`,`ID2`),
 KEY `ID2` (`ID2`)
) ENGINE=InnoDB`

该表大约有 16196496 条记录

EXPLAIN SELECT * FROM TEST WHERE ID1 IN ('8518582',  '5398912',  '6120243',  '6841316',  '7580078',  '7671953',  '7775737',  '7792470',  '7887985',  '7888375',  '7946516',  '8008760',  '8111722',  '8211235',  '8262746',  '8365675',  '8396853', '8399818',  '8410062',  '8459079',  '8490683')

我得到的输出为

+----+-------------+------------------------+------+---------------+------+---------+------+----------+-------------+
| id | select_type | table                  | type | possible_keys | key  | key_len | ref  | rows     | Extra       |
+----+-------------+------------------------+------+---------------+------+---------+------+----------+-------------+
|  1 | SIMPLE      | TEST                   | ALL  | ID1           | NULL | NULL    | NULL | 16196496 | Using where |
+----+-------------+------------------------+------+---------------+------+---------+------+----------+-------------+

我不明白为什么查询不使用任何键。

此外,当我在这个 innodb 表中运行这个查询时,它花费了大量的时间 329 秒(MySQL 版本 5.0.45-log)。

而如果我在 myisam 表上运行相同的查询,它只需要 2 秒(尽管解释它显示相同的结果)。我正在使用 MySQL 5.5 版。

为什么查询不带任何键?

4

2 回答 2

1

innodb需要一个主键来快速查找索引中找到的行。只要你没有 - mysql 就不能这样做,所以它更喜欢全扫描。

http://dev.mysql.com/doc/refman/5.6/en/innodb-table-and-index.html

通过聚集索引访问一行速度很快,因为索引搜索直接指向包含所有行数据的页面。如果表很大,与使用与索引记录不同的页面存储行数据的存储组织相比,聚集索引架构通常会节省磁盘 I/O 操作。(例如,MyISAM 将一个文件用于数据行,将另一个文件用于索引记录。)

所以显而易见的解决方案 - 用主键替换唯一键(虽然我个人不喜欢自然主键,尤其是复合自然主键)。

PS:似乎我在评论中关于使用数字而不是字符串的猜测有所帮助。尽管有关添加主键的建议仍在起作用 - 这样做可以获得更好的性能。

于 2013-01-14T11:21:35.123 回答
0

我不确定,但我认为的另一个原因是“可能是没有足够的内存可用于加载索引并因此进行全面扫描”

于 2013-01-15T07:36:42.430 回答