为什么在解释查询中读取const表后会收到“不可能在哪里注意到”的信息?


27

当我运行带有解释的查询时,表中有一个独特的复合键,如fr(fromid,toid),得到以下结果:

Impossible WHERE noticed after reading const tables`

我运行的查询:

explain SELECT rid FROM relationship WHERE fromid=78 AND toid=60   

有什么帮助吗?

EDIT1:
当我使用以下查询时:

explain SELECT rid FROM relationship WHERE fromid=60 and toid=78 AND is_approved='s'  OR is_approved='f' OR is_approved='t'

我看到的USING WHERE不是上一条消息,而是当我使用以下查询时:

explain SELECT rid FROM relationship WHERE fromid=60 and toid=78 AND (is_approved='s'  OR is_approved='f' OR is_approved='t')  

我再次收到第一条impossible ...消息!这些括号在这里做什么?

编辑2:

CREATE TABLE `relationship` (
 `rid` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `fromid` mediumint(8) unsigned NOT NULL,
 `toid` mediumint(8) unsigned NOT NULL,
 `type` tinyint(3) unsigned NOT NULL,
 `is_approved` char(1) NOT NULL,
 PRIMARY KEY (`rid`),
 UNIQUE KEY `fromid` (`fromid`,`toid`),
 KEY `toid` (`toid`),
 CONSTRAINT `relationship_ibfk_1` FOREIGN KEY (`fromid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `relationship_ibfk_2` FOREIGN KEY (`toid`) REFERENCES `user` (`uid`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB

EDIT3:
作为mysql网站说:

读取const表后,不可能在哪里注意到

MySQL已读取所有const(和系统)表,并注意到WHERE子句始终为false。

但是在查询中我得到了想要的结果,但WHERE部分却没有false。有没有人可以解释这一点并阐明这个问题?


SELECT COUNT(1) FROM relationship WHERE fromid=78 AND toid=60;返回什么?
RolandoMySQLDBA 2012年

@RolandoMySQLDBA,将会有using index更多内容代替impossible...
ALH

Answers:


23

您正在收到消息

读取const表后,不可能在哪里注意到

这已记录在您已链接的页面中

MySQL已读取所有const(和system)表,并注意到该WHERE子句始终为false

const 表被定义为

该表最多具有一个匹配行,该行在查询开始时读取。const当将a PRIMARY KEYUNIQUE 索引的所有部分与常量值进行比较时,使用...。

你有一个UNIQUE KEY(fromid,toid)WHERE fromid=78 AND toid=60可以通过读取此唯一索引来满足查询。从收到的消息中,此操作必须不返回任何结果。

类似地,查询WHERE fromid=60 and toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')也可以使用该索引来定位感兴趣的行(尽管它仍然具有剩余谓词以评估是否匹配任何行)。

您的其他查询不一样

SELECT rid
FROM   relationship
WHERE  fromid = 60
       AND toid = 78
       AND is_approved = 's'
        OR is_approved = 'f'
        OR is_approved = 't' 

AND具有比更高的优先级Or,因此与

SELECT rid
FROM   relationship
WHERE  ( ( fromid = 60 ) AND ( toid = 78 ) AND ( is_approved = 's' ) )
        OR ( is_approved = 'f' )
        OR ( is_approved = 't' ) 

它不能再使用该索引,并且具有不同的语义,因为它将返回任何行,is_approved IN ('f','t')而与其他列中的值无关。


所以怎么说呢例如:如果fromid=12 AND toid=78然后检查is_approved='f'is_approved='t'is_approved='s'
ALH

1
@ john.locke:这是你的第三个查询:WHERE fromid=60 AND toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')这也可以写成:WHERE fromid=60 AND toid=78 AND ( is_approved IN ('s', 'f', 't') )
ypercubeᵀᴹ

1
究竟。由于没有行与fromid=60 AND toid=78零件匹配,因此不需要进一步检查(对于is_approved零件)。
–ypercubeᵀᴹ2012年

1
你不能有一排小号做到这一点。有一个唯一的约束,(fromid,toid)因此肯定会有一个最大值吗?从您说的消息中得知,MySQL甚至都没有。您的意思是您有一些匹配的行fromid=60和一些匹配toid=78但不一定相同的行吗?
马丁·史密斯

1
也许这就是AND-OR混乱。也许您希望所有具有的行fromid=60和所有具有的行,toid=78然后从中删除,仅保留具有's'or 'f't'is_approved的那些行?如果是的话,试试这个条件:WHERE (fromid=60 OR toid=78) AND (is_approved IN ('s', 'f', 't'))
ypercubeᵀᴹ

5

MySql Explain实际上使用您提供的值来遍历关联表的行。如果提供的常数/键值不在关联表中,则MySql Explain将因该错误而停止。只需在关联的表中查询确实存在的值并在Explain查询中提供这些值,一切将按预期工作。


3
Impossible WHERE noticed ...不是错误。这是解释的一部分。
ypercubeᵀᴹ

3

Impossible WHERE noticed after reading const tables 在解释查询?

发生此错误是由于将无效值放在主键或唯一键的列上。

尝试在where子句中使用正确的值。


0

我跳得太晚了。但是,这就是我为我注意到的。

我正在执行此查询,并且项目列为UNIQUE。

SELECT `vari-groupid` FROM shop_item_variations_group where `item` = 'itemnu1' limit 1

在读取const表后,这将引起“ 不可能的地方”的注意

我所要做的就是将“ =”更改为“ like”,现在它正在使用我的索引。

SELECT `vari-groupid` FROM shop_item_variations_group where `item` like 'itemnu1' limit 1

它不是在索引上使用索引=吗?
ypercubeᵀᴹ

还不够疯狂,不是……。这只是在解释const表后在“不可能的地方”中注意到这一点
RichardW11,

是的,但是“不可能的位置”通常很好。意味着查询不再需要从表或索引中读取任何内容。慢吗?如果没有,您根本不必担心。
ypercubeᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.