“使用索引”,其复合索引为:A =,B =,C <=

问题描述 投票:0回答:1

尽管查询很简单,但下面的执行计划似乎令人失望且次优。

我正在使用MySQL 5.7。这是fiddle(尽管它仅提供5.6)。

CREATE TABLE `event` (
  `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(63) CHARSET ASCII COLLATE ASCII_BIN NOT NULL,
  `is_sequenced` TINYINT(3) UNSIGNED NOT NULL,
  `sequence_number` BIGINT(20) UNSIGNED DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `Name-SequenceNumber` (`name`,`sequence_number`),
  KEY `Name-IsSequenced` (`name`,`is_sequenced`,`id`)
) ENGINE=INNODB
;

INSERT INTO `event`
(id, `name`, is_sequenced, sequence_number)
VALUES
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL),
(NULL, 'OrderCreated', 0, NULL)
;

我们将使用Name-IsSequenced二级索引。让我们尝试以下EXPLAIN。 (查询位于Fiddle中。打开“查看执行计划”以查看其EXPLAIN结果。)

EXPLAIN
SELECT * -- This part needs the PK
FROM `event` e
WHERE e.name = 'OrderCreated'
AND e.is_sequenced = 0
AND e.id <= 3
;

到目前为止,很好。 Using index condition很有意义:整个条件都可以在期望的索引Name-IsSequenced上解决,然后需要PK才能获得SELECT *的剩余数据。

如果我们仅选择属于二级索引的内容,我们应该能够将其提高到Using index,对吗? (请注意,PK始终是任何二级索引的一部分,但我们甚至可以通过在二级索引的末尾包含id来确保这一点。结果应该是相同的。)]

EXPLAIN
SELECT id
FROM `event` e
WHERE e.name = 'OrderCreated'
AND e.is_sequenced = 0
AND e.id <= 3
;

现在,结果为Using where; Using index。等等,那是……更糟?!我们减少了工作量,该计划表明它正在努力工作。

Using index应该是可以实现的。找到name=OrderCreated的范围,然后在其中找到is_sequenced=0的子范围,然后在里面找到id<=3的子范围。

[奇怪的是,我还有其他实验(有更多数据),在这些实验中,我可以通过将Using index更改为id<=3(与id=3结合使用以防止它偏爱PK)来获得FORCE INDEX。我看不出有什么区别。 (如果我们使用Fiddle尝试此操作,则它保持不变-可能是因为数据集很小。)

谁能解释为什么执行计划未表明预期有效使用二级索引?有没有一种方法可以理顺它?

尽管查询很简单,但下面的执行计划似乎令人失望且次优。我正在使用MySQL 5.7。这是小提琴(尽管它仅提供5.6)。创建表`event`(...

mysql mysql-5.7 secondary-indexes composite-index
1个回答
0
投票
WHERE e.name = 'OrderCreated'
  AND e.is_sequenced = 0
  AND e.id <= 3
© www.soinside.com 2019 - 2024. All rights reserved.