Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL未对某些查询使用多列索引_Mysql_Sql_Indexing_Myisam - Fatal编程技术网

MySQL未对某些查询使用多列索引

MySQL未对某些查询使用多列索引,mysql,sql,indexing,myisam,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=l

我在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)
它返回“number”作为要使用的键。但以下问题:

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使用该索引的索引?我知道我可以使用索引,但我希望MySQL能够找到执行查询的最佳计划。这是在MySQL 5.1和5.5上实现的,结果相同。

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

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

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

有两件事可以提高性能:

  • 分析表
    以更新优化器的索引统计信息,从而了解当前的密钥分布。您可以通过多种方式进行选择
  • 创建第二个覆盖索引,并反转字段。在现实世界中,这涉及到为一组三列或四列计算出最佳的一个或两个覆盖索引,这是通过基准测试和
    解释
    分析得出的结果。请看一看,以获得一些关于这样做的建议

  • SQL Fiddle显示两个()都使用了相同的索引。我投票决定将其移动到dba.stackexchange,这很奇怪,我认为它需要一个对MyISAM索引选择有大量了解的人。在数据完全对称的情况下(即每个文本有相同的4个数字),当搜索6个组合时,它使用文本编号索引,当搜索
    2
    时,它使用
    number
    ,我不知道为什么。我认为这可能是由于统计数据更新的阈值造成的,但为了避免这种情况,我将索引的创建移动到了数据插入后。此外,插入顺序没有任何区别(),索引中的顺序没有任何区别(),而且似乎总是发生在第二个最低的数字上,而不是具体的数字2。但是,当索引被反转时,您可能希望它在第二高的数字上使用
    索引,但它不是,它仍然在第二低的数字上。这对我来说完全是个谜。我试着分析这张桌子,但没关系。可以尝试第二个选项!