Warum erhalte ich in EXPLAIN-Abfragen die Meldung "Unmöglich, WO nach dem Lesen von const-Tabellen bemerkt"?

27

Ich habe einen eindeutigen zusammengesetzten Schlüssel wie fr (fromid, toid) in der Tabelle, wenn ich die Abfrage mit EXPLAIN ausführe, erhalte ich das folgende Ergebnis:

Impossible WHERE noticed after reading const tables`

Die Abfrage, die ich ausgeführt habe:

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

Irgendeine Hilfe?

EDIT1:
Wenn ich die folgende Abfrage verwende:

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

Ich sehe USING WHEREanstelle der vorherigen Nachricht, aber wenn ich die folgende Abfrage verwende:

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

Ich bekomme wieder das erste impossible ... Nachricht! Was machen diese Klammern hier?

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:
Wie MySQL-Site sagt:

Unmöglich, wo nach dem Lesen von const-Tabellen bemerkt

MySQL hat alle const-Tabellen (und Systemtabellen) gelesen und festgestellt, dass die WHERE-Klausel immer falsch ist.

Aber bei der Abfrage bekomme ich das gewünschte Ergebnis, das WHERETeil geht nicht false. Gibt es jemanden, der dies erklären und Licht ins Dunkel bringen könnte?

ALH
quelle
Was kommt SELECT COUNT(1) FROM relationship WHERE fromid=78 AND toid=60;zurück ???
RolandoMySQLDBA
@RolandoMySQLDBA, es wird using indexin extra stattimpossible...
ALH

Antworten:

23

Sie erhalten die Nachricht

Unmöglich, wo nach dem Lesen von const-Tabellen bemerkt

Dies ist auf der Seite dokumentiert, die Sie bereits verlinkt haben .

MySQL hat alle const(und system) Tabellen gelesen und festgestellt, dass die WHEREKlausel immer falsch ist

const Tabellen sind definiert als

Die Tabelle enthält höchstens eine übereinstimmende Zeile, die zu Beginn der Abfrage gelesen wird. ... constwird verwendet, wenn Sie alle Teile eines PRIMARY KEYoder eines UNIQUE Index mit konstanten Werten vergleichen.

Du hast einen UNIQUE KEYan (fromid,toid). Die Abfrage für WHERE fromid=78 AND toid=60kann durch Lesen dieses eindeutigen Indexes erfüllt werden. Von der Nachricht, die Sie erhalten, dürfen keine Ergebnisse zurückgegeben werden.

In ähnlicher Weise kann die Abfrage WHERE fromid=60 and toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')diesen Index auch verwenden, um die interessierende Zeile zu lokalisieren (obwohl sie immer noch ein verbleibendes Prädikat hat, das ausgewertet werden muss, wenn eine Zeile übereinstimmt).

Ihre andere Frage ist anders

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

ANDhat eine höhere Priorität als Or, dies ist also dasselbe wie

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

Dieser Index kann nicht mehr verwendet werden und hat eine andere Semantik, da er alle Zeilen zurückgibt, is_approved IN ('f','t')unabhängig von den Werten in den anderen Spalten.

Martin Smith
quelle
Also, wie soll ich zum Beispiel sagen: Wenn es fromid=12 AND toid=78dann überprüfen, ob is_approved='f'oder is_approved='t'oderis_approved='s'
ALH
1
@ john.locke: Das ist deine dritte Frage, WHERE fromid=60 AND toid=78 AND (is_approved='s' OR is_approved='f' OR is_approved='t')die auch geschrieben werden kann als:WHERE fromid=60 AND toid=78 AND ( is_approved IN ('s', 'f', 't') )
ypercubeᵀᴹ
1
Genau. Da keine Zeile mit dem fromid=60 AND toid=78Teil übereinstimmt , ist keine weitere Prüfung (für das is_approvedTeil) erforderlich .
Ypercubeᵀᴹ
1
Sie können keine Zeile haben s , die tun. Es gibt eine eindeutige Einschränkung, (fromid,toid)sodass es mit Sicherheit maximal eine geben würde. Und aus der Nachricht, die Sie sagen, dass Sie MySQL erhalten, geht nicht hervor, dass es überhaupt eine gibt, die dies tut. Meinen Sie damit, dass Sie einige übereinstimmende Zeilen fromid=60und einige übereinstimmende Zeilen haben, toid=78aber nicht unbedingt dieselben Zeilen?
Martin Smith
1
Vielleicht ist das die AND-ORVerwirrung . Vielleicht möchten Sie alle Zeilen, die haben fromid=60und alle Zeilen, die haben toid=78und von denen dann nur diejenigen behalten, die entweder 's'oder 'f'oder t'is_approved haben? Wenn ja, probieren Sie diese Bedingung aus:WHERE (fromid=60 OR toid=78) AND (is_approved IN ('s', 'f', 't'))
ypercubeᵀᴹ
5

MySql Explain verwendet die von Ihnen angegebenen Werte, um Zeilen der zugeordneten Tabellen zu durchlaufen. Wenn Sie eine Konstante / einen Schlüsselwert angeben, der nicht in der zugehörigen Tabelle enthalten ist, wird MySql Explain mit diesem Fehler beendet. Fragen Sie einfach die zugeordneten Tabellen nach vorhandenen Werten ab und geben Sie diese in Ihrer Erklärungsabfrage an, und alles funktioniert wie erwartet.

grwww
quelle
3
Impossible WHERE noticed ...ist kein Fehler. Es ist Teil der Erklärung.
ypercubeᵀᴹ
3

Impossible WHERE noticed after reading const tables in EXPLAIN-Abfrage?

Dieser Fehler tritt auf, weil in eine Spalte ein ungültiger Wert eingegeben wurde, der entweder ein Primärschlüssel oder ein eindeutiger Schlüssel ist.

Versuchen Sie es mit einem korrekten Wert in der whereKlausel.

Rjnish Kumar
quelle
0

Ich bin so spät dran. Aber hier ist, was mir aufgefallen ist.

Ich habe diese Abfrage durchgeführt und die Elementspalte war EINZIGARTIG.

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

Das würde das Unmögliche bewirken, wo es nach dem Lesen von const-Tabellen auffällt

Ich musste nur "=" in "like" ändern und jetzt wird mein Index verwendet.

SELECT `vari-groupid` FROM shop_item_variations_group where `item` like 'itemnu1' limit 1
RichardW11
quelle
War es nicht mit dem Index =?
ypercubeᵀᴹ
Nein, verrückt genug, war es nicht .... Es war nur das, was in der Erklärung Unmöglich, wo nach dem Lesen von const-Tabellen bemerkt
RichardW11
Ja, aber das "unmögliche WO" ist normalerweise gut. bedeutet, dass die Abfrage nicht mehr aus den Tabellen oder Indizes lesen muss. War es langsam? Wenn nicht, sollten Sie sich überhaupt keine Sorgen machen.
Ypercubeᵀᴹ