我在查询时有一张表,
EXPLAIN SELECT `id`
FROM `tblsender`
WHERE `userid` = '6'
AND `astatus` = '1'
AND `sender` = 'ABCDEF'
即使在以所有可能的方式编制索引之后,我仍然获得USING WHERE
。这是我的最终表结构代码。
CREATE TABLE IF NOT EXISTS `tblsender` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`sender` varchar(6) NOT NULL,
`astatus` tinyint(1) NOT NULL DEFAULT '0',
`userid` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `astatus` (`astatus`),
KEY `userid` (`userid`),
KEY `sender` (`sender`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=22975 ;
我甚至尝试了sender
列的全文,但仍然没有运气,我也尝试对所有where clause
列进行索引。
ALTER TABLE `tblsender` ADD INDEX ( `sender` , `astatus` , `userid` ) ;
仍然获得using where
,我该如何正确索引此表。
编辑:解释上述结构的输出。
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tblsender ref astatus,userid,sender astatus 1 const 1 Using where
并解释所有3列的输出
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tblsender ref astatus,userid,sender,sender_2 astatus 1 const 1 Using where
答案 0 :(得分:4)
使用小型数据集进行测试时,无法有效预测大型数据集上的优化器行为。
如查询计划所示,多列索引被视为候选者,但优化器选择不使用(在本例中为)。这并不意味着当它被认为更有益时它不会使用它。
我只能在没有看到您的实际数据集并且可能使用optimizer tracing的情况下进行推测,但我会提供合理的推测。
MySQL中的优化器是基于成本的。它尝试以最便宜的方式解决您的查询。请注意rows
= 1.这意味着优化器已经得出结论 - 从统计上来说,至少 - 它期望在astatus
的索引中只有1行匹配。 key_len
= 1,意味着astatus
只有1个字节宽 - 与多列索引相反,即11个字节宽(1 + 6 + 4) - astatus
index看起来是一个非常便宜的解决方案,所以它决定使用该索引。理论上使用较长的索引意味着更多的I / O,因此成本更高,尽管在这种情况下(由于数据集很小),我们人类认识到成本差异并不是特别有意义。
Using where
表示对于使用该索引实际返回的每一行,服务器需要验证行是否与WHERE
子句的其余部分匹配,但是如果我们只期望大约1要匹配,这没什么大不了的。
我建议您没有理由担心,因为当前数据集的小尺寸无法为您提供预测未来行为的有用信息。在这种特定情况下,Using where
是表中少量行的工件。
您需要更多数据。但是,是的,你确实需要一个多列索引。