MySQL没有为某些查询使用多列索引

时间:2013-09-12 14:19:29

标签: mysql sql indexing myisam

我在MyISAM表中有一个包含数百万条MySQL记录的表。很简单,就是这样:

CREATE TABLE `test` (
  `text` varchar(5) DEFAULT NULL,
  `number` int(5) DEFAULT NULL,
  KEY `number` (`number`) USING BTREE,
  KEY `text_number` (`text`,`number`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

它填充了这些数据:

INSERT INTO `test` VALUES ('abcd', '1');
INSERT INTO `test` VALUES ('abcd', '2');
INSERT INTO `test` VALUES ('abcd', '3');
INSERT INTO `test` VALUES ('abcd', '4');
INSERT INTO `test` VALUES ('bbbb', '1');
INSERT INTO `test` VALUES ('bbbb', '2');
INSERT INTO `test` VALUES ('bbbb', '3');

当我运行以下查询时:

EXPLAIN SELECT * FROM `test` WHERE (`text` = 'bbbb' AND `number` = 2)

返回'数字'作为使用的关键。但是以下查询:

EXPLAIN SELECT * FROM `test` WHERE (`text` = 'bbbb' AND `number` = 1)

返回' text_number'作为使用的关键,这对我来说更有意义,因为这个组合键与WHERE中的2列完全匹配。在这些记录数量上,性能不是问题,但是在几百万条记录中,使用“&text”' index需要4秒,而使用' text_number' index在几毫秒内完成。

对此有合理的解释吗?如何更改MySQL使用索引的索引?我知道我可以使用USE INDEX,但我希望MySQL能够找到执行查询的最佳计划。这是在MySQL 5.1和5.5上,结果相同。

2 个答案:

答案 0 :(得分:1)

如果您希望某些查询能够改变游戏性能,那么最好使用自己的索引,例如:

EXPLAIN SELECT * FROM `test` USE INDEX (number) WHERE (`text` = 'bbbb' AND `number` = 1);
or
EXPLAIN SELECT * FROM `test` USE INDEX (text_number) WHERE (`text` = 'bbbb' AND `number` = 1);

通常,您可以在大多数查询中继内置查询优化器,但对于关键或有问题的查询,最好仔细观察。

答案 1 :(得分:1)

可以提高绩效的两件事:

  1. ANALYZE TABLE更新优化程序的索引统计信息,以便它知道当前的密钥分发。您可以通过多种方式control the optimizer's statistics generation
  2. 创建第二个覆盖索引,并反转字段。在现实世界中,这涉及计算一组三列或四列的最佳一个或两个覆盖索引,这是通过基准测试和EXPLAIN分析得出的。关于这方面的一些建议,请查看this answer