我在查询时有一张表,
EXPLAIN SELECT `id`
FROM `tblsender`
WHERE `userid` = '6'
AND `astatus` = '1'
AND `sender` = 'ABCDEF'
Run Code Online (Sandbox Code Playgroud)
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 ;
Run Code Online (Sandbox Code Playgroud)
我什至尝试了列的全文sender,但仍然没有运气,我还尝试对所有where clause列建立索引。
ALTER TABLE `tblsender` ADD INDEX ( `sender` , `astatus` , `userid` ) ;
Run Code Online (Sandbox Code Playgroud)
仍然得到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
Run Code Online (Sandbox Code Playgroud)
并一起解释所有 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
Run Code Online (Sandbox Code Playgroud)
在使用小数据集进行测试时,您无法有效预测优化器在大数据集上的行为。
如查询计划所示,多列索引被视为候选索引,但优化器选择在这种情况下不使用它。这并不意味着当它被认为更有益时它不会使用它。
我只能在没有看到您的实际数据集并且可能使用优化器跟踪的情况下进行推测,但我会提供合理的推测。
MySQL 中的优化器是基于成本的。它尝试以尽可能成本最低的方式解决您的查询。请注意rows= 1。这意味着优化器已得出结论(至少在统计上),它预计只有 1 行将在 的索引中匹配astatus。当key_len= 1 时,意味着astatus只有 1 个字节宽——与多列索引相反,多列索引的宽度为 11 个字节 (1 + 6 + 4)——该astatus索引看起来是一个非常便宜的解决方案,因此它决定采用该解决方案指数。使用较长的索引理论上意味着更多的 I/O,因此成本更高,尽管在这种情况下(由于数据集较小)我们人类认识到成本差异并不是特别有意义。
Using where意味着对于使用该索引实际返回的每一行,服务器将需要验证这些行是否与子句的其余部分匹配WHERE,但如果我们只期望大约 1 行匹配,那就没什么大不了的。
那么,我建议您不必担心,因为当前数据集的规模较小,无法为您提供预测未来行为的有用信息。在这种特定情况下,Using where是表中行数较少的产物。
您需要更多数据。但是,是的,您确实需要一个多列索引。