Gemäß der MySQL-Dokumentation zu Ansichten
Ansichten (einschließlich aktualisierbarer Ansichten) sind in MySQL Server 5.6 verfügbar. Ansichten sind gespeicherte Abfragen, die beim Aufrufen eine Ergebnismenge erzeugen. Eine Ansicht fungiert als virtuelle Tabelle.
Das erste, was an einer Ansicht erkannt werden muss, ist, dass sie eine Ergebnismenge erzeugt. Die Ergebnismenge, die aus der in der Ansicht aufgerufenen Abfrage hervorgeht, ist eine virtuelle Tabelle, da sie bei Bedarf erstellt wird. Es gibt keine DDL, die Sie anschließend aufrufen können, um die Ergebnismenge sofort zu indizieren. Die Ergebnismenge ist in jeder Hinsicht eine Tabelle ohne Indizes. Tatsächlich handelt es sich bei dem von Ihnen ausgeführten LEFT JOIN im Grunde genommen um ein kartesisches Produkt mit einigen Filtern.
Um Ihnen einen genaueren Überblick über die Verbindung zweier Ansichten zu geben, verweise ich auf einen Beitrag, den ich im letzten Jahr verfasst habe, in dem die internen Mechanismen erläutert werden, mit denen MySQL JOINs und WHEREs bewertet ( Gibt es einen Ausführungsunterschied zwischen einer JOIN-Bedingung und einer WHERE-Bedingung? ). Ich werde Ihnen den Mechanismus zeigen, wie er in Understanding MySQL Internals (Seite 172) veröffentlicht wurde:
- Bestimmen Sie, mit welchen Schlüsseln die Datensätze aus Tabellen abgerufen werden können, und wählen Sie für jede Tabelle den besten aus.
- Entscheiden Sie für jede Tabelle, ob ein Tabellenscan besser ist als das Lesen eines Schlüssels. Wenn viele Datensätze mit dem Schlüsselwert übereinstimmen, werden die Vorteile des Schlüssels verringert und der Tabellenscan wird schneller.
- Bestimmen Sie die Reihenfolge, in der Tabellen verknüpft werden sollen, wenn mehr als eine Tabelle in der Abfrage vorhanden ist.
- Schreiben Sie die WHERE-Klauseln neu, um toten Code zu eliminieren, unnötige Berechnungen zu reduzieren und die Einschränkungen nach Möglichkeit zu ändern, um den Weg für die Verwendung von Schlüsseln freizumachen.
- Entfernen Sie nicht verwendete Tabellen aus dem Join.
- Bestimmen Sie, ob Schlüssel für
ORDER BY
und verwendet werden können GROUP BY
.
- Versuchen Sie, Unterabfragen zu vereinfachen und festzustellen, inwieweit ihre Ergebnisse zwischengespeichert werden können.
- Ansichten zusammenführen (Ansichtsreferenz als Makro erweitern)
OK, es scheint, als sollten Indizes verwendet werden. Schauen Sie jedoch genauer hin. Wenn Sie das Wort View
durch ersetzen Table
, schauen Sie, was mit der Ausführung des Mechanismus passiert:
MECHANISMUS GEÄNDERT
- Bestimmen Sie, von welchen Schlüsseln die Datensätze abgerufen werden können
views
, und wählen Sie jeweils den besten aus view
.
view
Entscheiden Sie für jeden , ob ein view
Scan besser ist als das Lesen auf einem Schlüssel. Wenn viele Datensätze mit dem Schlüsselwert übereinstimmen, werden die Vorteile des Schlüssels verringert und der view
Scanvorgang wird schneller.
- Bestimmen Sie die Reihenfolge, in der verbunden werden
views
soll, wenn mehr als eine views
in der Abfrage vorhanden ist.
- Schreiben Sie die WHERE-Klauseln neu, um toten Code zu eliminieren, unnötige Berechnungen zu reduzieren und die Einschränkungen nach Möglichkeit zu ändern, um den Weg für die Verwendung von Schlüsseln freizumachen.
- Beseitigen Sie nicht verwendete Elemente
views
aus dem Join.
- Bestimmen Sie, ob Schlüssel für
ORDER BY
und verwendet werden können GROUP BY
.
- Versuchen Sie, Unterabfragen zu vereinfachen und festzustellen, inwieweit ihre Ergebnisse zwischengespeichert werden können.
- Ansichten zusammenführen (Ansichtsreferenz als Makro erweitern)
Jede Tabelle (Ansicht) hat keinen Index. Daher wird die Arbeit mit virtuellen Tabellen, temporären Tabellen oder Tabellen ohne Indizes beim Ausführen eines JOIN wirklich undeutlich. Die verwendeten Schlüssel sind nur für JOIN-Operationen gedacht, nicht so sehr für das schnellere Nachschlagen.
Stellen Sie sich Ihre Anfrage so vor, als würden Sie zwei Telefonbücher abholen, die Gelben Seiten 2014 und die Gelben Seiten 2013. Jedes Buch mit den Gelben Seiten enthält die Weißen Seiten für Telefonnummern für Privathaushalte.
- Ende 2012 wurde eine Datenbanktabelle verwendet, um die Gelben Seiten 2013 zu generieren.
- Im Jahr 2013
- Die Leute haben die Telefonnummern geändert
- Die Leute erhielten neue Telefonnummern
- Die Leute ließen Telefonnummern fallen und wechselten zum Handy
- Ende 2013 wurde eine Datenbanktabelle verwendet, um die Gelben Seiten 2014 zu generieren.
Offensichtlich gibt es Unterschiede zwischen den beiden Telefonbüchern. Das Zusammenführen von Datenbanktabellen, um die Unterschiede zwischen 2013 und 2014 herauszufinden, sollte kein Problem darstellen.
Stellen Sie sich vor, Sie führen die beiden Telefonbücher von Hand zusammen, um Unterschiede zu lokalisieren. Klingt verrückt, nicht wahr? Ungeachtet dessen ist es genau das, was Sie von mysqld verlangen, wenn Sie zwei Ansichten verbinden. Denken Sie daran, dass Sie keine echten Tabellen verbinden und es keine Indizes gibt, aus denen Sie Huckepack nehmen können.
Lassen Sie uns nun auf die eigentliche Abfrage zurückblicken.
SELECT DISTINCT
viewA.TRID,
viewA.hits,
viewA.department,
viewA.admin,
viewA.publisher,
viewA.employee,
viewA.logincount,
viewA.registrationdate,
viewA.firstlogin,
viewA.lastlogin,
viewA.`month`,
viewA.`year`,
viewA.businesscategory,
viewA.mail,
viewA.givenname,
viewA.sn,
viewA.departmentnumber,
viewA.sa_title,
viewA.title,
viewA.supemail,
viewA.regionname
FROM
viewA
LEFT JOIN viewB ON viewA.TRID = viewB.TRID
WHERE viewB.TRID IS NULL
Sie verwenden eine virtuelle Tabelle (Tabelle ohne Indizes), viewA, und verbinden sie mit einer anderen virtuellen Tabelle, viewB. Die temporäre Tabelle, die intermittierend generiert wird, ist so groß wie viewA. Anschließend führen Sie eine interne Sortierung für die große temporäre Tabelle aus, um sie zu unterscheiden.
EPILOG
Angesichts der internen Mechanismen zur Auswertung von JOINs sollte Ihre ursprüngliche Abfrage (LEFT JOIN aus zwei Ansichten) Laufzeiten in Größenordnungen erhalten, da die Ergebnismenge einer Ansicht vorübergehend und indexlos ist. Gleichzeitig sollte die Antwort , die Sie von StackOverflow erhalten haben , angesichts des gleichen JOIN-Algorithmus, den ich gerade beschrieben habe, gut funktionieren.
Ich hoffe, die blutigen Details, die ich gerade gepostet habe, beantworten Ihre Frage, warum.