Por que estou recebendo o `Impossible WHERE notado após a leitura de tabelas const` na consulta de explicação?

27

Eu tenho uma chave composta exclusiva como fr (fromid, toid) na tabela. Quando executo a consulta com o explicador, obtenho o seguinte resultado:

Impossible WHERE noticed after reading const tables`

A consulta que eu executei:

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

Qualquer ajuda?

EDIT1:
Quando eu uso a consulta abaixo:

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

Eu vejo em USING WHEREvez da mensagem anterior, mas quando uso a consulta abaixo:

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

Recebo novamente a primeira impossible ...mensagem! O que esses parênteses fazem aqui?

EDIT2:

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:
Como o site mysql diz:

Impossível ONDE notado após a leitura de tabelas const

O MySQL leu todas as tabelas const (e system) e percebe que a cláusula WHERE é sempre falsa.

Mas, na consulta, obtenho o resultado desejado, a WHEREparte não é false. Existe alguém que possa explicar isso e lançar alguma luz sobre o assunto?

ALH
fonte
O que SELECT COUNT(1) FROM relationship WHERE fromid=78 AND toid=60;retorna ???
RolandoMySQLDBA
@RolandoMySQLDBA, haverá using indexextra em vez deimpossible...
ALH

Respostas:

23

Você está recebendo a mensagem

Impossível ONDE notado após a leitura de tabelas const

Isso está documentado na página que você já vinculou .

O MySQL leu todas as tabelas const(e system) e percebe que a WHEREcláusula é sempre falsa

const tabelas são definidas como

A tabela possui no máximo uma linha correspondente, que é lida no início da consulta. ... consté usado quando você compara todas as partes de a PRIMARY KEYou UNIQUE index com valores constantes.

Você tem um UNIQUE KEYon (fromid,toid). A consulta em WHERE fromid=78 AND toid=60pode ser atendida lendo este índice exclusivo. Na mensagem que você está recebendo, isso não deve retornar resultados.

Da mesma forma, a consulta WHERE fromid=60 and toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')também pode usar esse índice para localizar a linha de interesse (embora ainda tenha um predicado residual para avaliar se alguma linha corresponder).

Sua outra consulta é diferente

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

ANDtem uma precedência mais alta que Or, portanto, é o mesmo que

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

Isso não pode mais usar esse índice e possui semântica diferente, pois retornará todas as linhas onde, is_approved IN ('f','t')independentemente de quais sejam os valores nas outras colunas.

Martin Smith
fonte
Então, como devo dizer, por exemplo: se for, fromid=12 AND toid=78então verifique se is_approved='f'ou is_approved='t'ouis_approved='s'
ALH 21/07
11
@ john.locke: Esta é a sua terceira consulta: WHERE fromid=60 AND toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')o que também pode ser escrita como:WHERE fromid=60 AND toid=78 AND ( is_approved IN ('s', 'f', 't') )
ypercubeᵀᴹ
11
Exatamente. Como nenhuma linha corresponde à fromid=60 AND toid=78peça, não é necessária nenhuma verificação adicional (para a is_approvedpeça).
precisa saber é o seguinte
11
Você não pode ter linha s que fazem. Existe uma restrição única (fromid,toid)para que haja um máximo de uma, com certeza? E a partir da mensagem que você diz que está obtendo o MySQL, não pensa que exista mesmo. Você quer dizer que você tem algumas linhas correspondentes fromid=60e algumas linhas correspondentes, toid=78mas não necessariamente as mesmas linhas?
Martin Smith
11
Talvez seja essa a AND-ORconfusão . Talvez você queira que todas as linhas que possuem fromid=60e todas as linhas que possuem toid=78e, a partir delas , mantenham apenas aquelas que possuem 's'ou são 'f'ou são t'aprovadas? Se sim, tente esta condição:WHERE (fromid=60 OR toid=78) AND (is_approved IN ('s', 'f', 't'))
ypercubeᵀᴹ
5

O MySql Explain usa os valores que você fornece, literalmente, para percorrer as linhas das tabelas associadas. Se você fornecer um valor constante / chave que não está na tabela associada, o MySql Explain irá parar com este erro. Simplesmente consulte as tabelas associadas quanto aos valores existentes e forneça-os na consulta Explain, e tudo funcionará conforme o esperado.

grwww
fonte
3
Impossible WHERE noticed ...não é um erro. Faz parte da explicação.
ypercubeᵀᴹ
3

Impossible WHERE noticed after reading const tables em explicar consulta?

Este erro ocorre devido ao valor inválido ser colocado em uma coluna que é chave primária ou chave exclusiva.

Tente com um valor correto na wherecláusula.

Rjnish Kumar
fonte
0

Estou pulando até tarde. Mas aqui está o que eu notei para mim.

Eu estava fazendo essa consulta e a coluna do item era ÚNICA.

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

que obteria o Impossível WHERE notado depois de ler as tabelas const

Tudo que eu precisava fazer era mudar "=" para "curtir" e agora está usando meu índice.

SELECT `vari-groupid` FROM shop_item_variations_group where `item` like 'itemnu1' limit 1
RichardW11
fonte
Não estava usando o índice com o =?
ypercubeᵀᴹ 28/03
Não era louco o suficiente, não era .... Estava dizendo isso na explicação Impossível ONDE foi notado depois de ler tabelas const
RichardW11
Sim, mas esse "ONDE impossível" geralmente é bom. significa que a consulta não precisa mais ler as tabelas ou índices. Foi lento? Caso contrário, você não deve se preocupar.
ypercubeᵀᴹ 28/03