Perché ricevo "Impossibile DOVE notato dopo aver letto le tabelle const" nella spiegazione della query?


27

Ho una chiave composta unica come fr (fromid, toid) nella tabella, quando eseguo la query con spiegato ottengo il seguente risultato:

Impossible WHERE noticed after reading const tables`

La query che ho eseguito:

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

Qualsiasi aiuto?

EDIT1:
quando utilizzo la query seguente:

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

Vedo USING WHEREinvece del messaggio precedente, ma quando utilizzo la query seguente:

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

Ricevo di nuovo il primo impossible ...messaggio! Cosa fanno queste parentesi qui?

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:
Come dice il sito mysql:

Impossibile DOVE notato dopo aver letto le tabelle const

MySQL ha letto tutte le tabelle const (e di sistema) e nota che la clausola WHERE è sempre falsa.

Ma nella query ottengo il risultato desiderato, la WHEREparte no false. C'è qualcuno che potrebbe spiegarlo e fare luce sull'argomento?


Cosa SELECT COUNT(1) FROM relationship WHERE fromid=78 AND toid=60;restituisce ???
RolandoMySQLDBA,

@RolandoMySQLDBA, ci saranno using indexin più invece diimpossible...
ALH,

Risposte:


23

Stai ricevendo il messaggio

Impossibile DOVE notato dopo aver letto le tabelle const

Questo è documentato nella pagina che hai già collegato .

MySQL ha letto tutte const(e system) le tabelle e nota che la WHEREclausola è sempre falsa

const le tabelle sono definite come

La tabella ha al massimo una riga corrispondente, che viene letta all'inizio della query. ... constviene utilizzato quando si confrontano tutte le parti di un PRIMARY KEYo UNIQUE indice con valori costanti.

Hai un UNIQUE KEYon (fromid,toid). La query su WHERE fromid=78 AND toid=60può essere soddisfatta leggendo questo indice univoco. Dal messaggio che stai ricevendo, questo non deve restituire risultati.

Allo stesso modo la query WHERE fromid=60 and toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')può anche utilizzare questo indice per individuare la riga di interesse (anche se ha ancora un predicato residuo da valutare se qualsiasi riga corrisponda).

L'altra tua query è diversa

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

ANDha una precedenza più alta di Or, quindi è la stessa di

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

Questo non può più usare quell'indice e ha una semantica diversa in quanto restituirà tutte le righe dove is_approved IN ('f','t')indipendentemente da quali siano i valori nelle altre colonne.


Quindi, come dovrei dire per esempio: se è fromid=12 AND toid=78allora controlla se is_approved='f'o is_approved='t'ois_approved='s'
ALH,

1
@ john.locke: questa è la tua terza query: WHERE fromid=60 AND toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')che può anche essere scritta come:WHERE fromid=60 AND toid=78 AND ( is_approved IN ('s', 'f', 't') )
ypercubeᵀᴹ

1
Esattamente. Poiché nessuna riga corrisponde alla fromid=60 AND toid=78parte, non sono necessari ulteriori controlli (per la is_approvedparte).
ypercubeᵀᴹ

1
Non si può avere fila s che lo fanno. C'è un vincolo unico su (fromid,toid)quindi ci sarebbe sicuramente un massimo di uno? E dal messaggio che dici che stai ricevendo MySQL non pensa che ce ne sia nemmeno uno. Vuoi dire che hai alcune righe corrispondenti fromid=60e alcune righe corrispondenti toid=78ma non necessariamente le stesse righe?
Martin Smith,

1
Forse questa è la AND-ORconfusione . Forse vuoi tutte le righe che hanno fromid=60e tutte le righe che hanno toid=78e quindi da quelle, mantieni solo quelle che hanno 's'o 'f'o t'è_approvato? Se sì, prova questa condizione:WHERE (fromid=60 OR toid=78) AND (is_approved IN ('s', 'f', 't'))
ypercubeᵀᴹ

5

MySql Explain utilizza i valori forniti, letteralmente, per attraversare le righe delle tabelle associate. Se si fornisce un valore costante / chiave non presente nella tabella associata, MySql Explain si interromperà con questo errore. È sufficiente eseguire una query sulle tabelle associate per i valori esistenti e fornire quelli nella query Spiegazione e tutto funzionerà come previsto.


3
Impossible WHERE noticed ...non è un errore. Fa parte della spiegazione.
ypercubeᵀᴹ

3

Impossible WHERE noticed after reading const tables nel spiegare la query?

Questo errore si verifica a causa dell'inserimento di un valore non valido in una colonna che sono chiave primaria o chiave univoca.

Prova con un valore corretto nella whereclausola.


0

Ci sto tuffando così tardi. Ma ecco cosa ho notato per me.

Stavo facendo questa query e la colonna dell'articolo era UNICA.

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

che avrebbe notato l' impossibile DOVE dopo aver letto le tabelle const

Tutto quello che dovevo fare era cambiare "=" in "mi piace" e ora sta usando il mio indice.

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

Non stava usando l'indice con il =?
ypercubeᵀᴹ

Non abbastanza pazzo, non lo era ... Lo stava dicendo solo nella spiegazione Impossible DOVE notato dopo aver letto le tabelle const
RichardW11,

Sì, ma quell'impossibile DOVE è generalmente buono. significa che la query non deve più leggere dalle tabelle o dagli indici. È stato lento? In caso contrario, non dovresti preoccuparti affatto.
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.