【问题标题】:Using Where during Explain for MySQL Query在解释 MySQL 查询期间使用 Where
【发布时间】:2017-06-30 09:35:54
【问题描述】:

查询时我有一张表,

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

【问题讨论】:

  • 当所有三列都包含在单个索引中时,请显示来自EXPLAIN 的输出。
  • @Michael-sqlbot,很抱歉回复晚了,因为我遇到了一些互联网连接问题。我已经更新了我的问题。
  • 您将 userid 和 astatus 作为字符串传递;省略撇号。
  • @BernhardDöbler 有帮助吗?

标签: mysql


【解决方案1】:

在使用小型数据集进行测试时,您无法有效地预测优化器在大型数据集上的行为。

如查询计划所示,多列索引被视为候选,但优化器选择不使用它在这种情况下。这并不意味着当它被认为更有益时它不会使用它。

我只能在没有看到你的实际数据集的情况下进行推测,也许使用optimizer tracing,但我会提供一个合理的推测。

MySQL 中的优化器是基于成本的。它试图以尽可能最低成本的方式解决您的查询。请注意rows = 1。这意味着优化器已经得出结论——至少从统计上看——它预计在astatus 的索引中只有1 行将匹配。 key_len = 1,这意味着 astatus 只有 1 个字节宽——与多列索引相反,它是 11 个字节宽 (1 + 6 + 4)——astatus 索引看起来非常便宜解决方案,因此它决定使用该索引。理论上,使用更长的索引意味着更多的 I/O,因此成本更高,尽管在这种情况下(因为数据集较小)我们人类认识到成本差异并不是特别有意义。

Using where 意味着对于使用该索引实际返回的每一行,服务器将需要验证这些行是否与 WHERE 子句的其余部分匹配,但如果我们只期望大约 1 行匹配,没什么大不了的。

那么,我建议您不必担心,因为当前数据集的小规模无法为您提供预测未来行为的有用信息。在这种特定情况下,Using where 是表中少量行的产物。

您需要更多数据。但是,是的,您确实需要一个多列索引。

【讨论】:

  • 我在那个表中有 22k 行。正如您所解释的,可能 where 子句只需要返回一行,然后它不使用索引列。表有 192kb 的数据,可能你是对的,它只是没有使用索引。感谢您花时间解释。
  • @yuri1000 如果您第一次在桌子上运行ANALYZE TABLE,您也可能会得到不同的结果。索引统计信息可能向优化器提供的提示不太理想。
猜你喜欢
  • 2012-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2013-10-11
相关资源
最近更新 更多