4

我在 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”索引的查询需要 4 秒,而使用“text_number”索引的查询在几毫秒内完成。

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

4

2 回答 2

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);

通常,您可以针对大多数查询使用内置查询优化器,但对于关键或有问题的查询,最好仔细查看。

于 2013-09-12T15:07:36.447 回答
1

有两件事可以提高你的表现:

  1. ANALYZE TABLE更新优化器的索引统计信息,使其知道当前的键分布。您可以通过多种方式控制优化器的统计信息生成
  2. 使用反转的字段创建第二个覆盖索引。在现实世界中,这涉及为一组三或四列找出最佳的一或两个覆盖索引,这是您通过基准测试和EXPLAIN分析得出的结果。看看这个答案以获得一些关于这样做的建议。
于 2013-09-12T15:09:13.127 回答