Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Leistung von VIEW für Tabellen kombiniert mit UNION ALL

Ich stimme mit allen Punkten in Bill Karwins ausgezeichneter Antwort überein.

F: Ist es üblich, eine Ansicht für die diskutierte Union-Abfrage zu erstellen und sie in meinen Joins, Unterauswahlen usw. zu verwenden?

A: Bei MySQL ist es normaler, die Verwendung der "CREATE VIEW"-Anweisung zu vermeiden.

F: In Bezug auf die Leistung - wird es im Vergleich zum einfachen Einfügen in Joins, Unterauswahlen usw. schlechter, gleich oder besser sein?

A: Das Verweisen auf ein Ansichtsobjekt hat die gleiche Leistung wie eine entsprechende Inline-Ansicht.

(Es könnte ein winzig kleines bisschen mehr Arbeit bedeuten, das Ansichtsobjekt zu suchen, Berechtigungen zu überprüfen und dann die Ansichtsreferenz durch das gespeicherte SQL zu ersetzen, anstatt eine Anweisung zu senden, die nur ein winziges bisschen länger ist. Aber irgendetwas davon Unterschiede sind unbedeutend.)

F: Gibt es in diesem Fall irgendwelche Nachteile, wenn man eine Ansicht hat?

A: Der größte Nachteil besteht darin, wie MySQL eine Ansicht verarbeitet, unabhängig davon, ob sie gespeichert oder inline ist. MySQL führt immer die Ansichtsabfrage aus und materialisiert die Ergebnisse dieser Abfrage als temporäre MyISAM-Tabelle. Aber es gibt keinen Unterschied, ob die Ansichtsdefinition gespeichert oder inline eingebunden wird. (Andere RDBMS verarbeiten Ansichten ganz anders als MySQL).

Ein großer Nachteil einer Ansicht ist, dass Prädikate aus der äußeren Abfrage NIE in die Ansichtsabfrage gedrückt werden. Jedes Mal, wenn Sie auf diese Ansicht verweisen, selbst bei einer Abfrage nach einem einzelnen ID-Wert, führt MySQL die Ansichtsabfrage aus und erstellt eine temporäre MyISAM-Tabelle (ohne Indizes darauf), und DANN führt MySQL die äußere Abfrage gegen diese temporäre aus MyISAM-Tabelle.

Stellen Sie sich also in Bezug auf die Leistung einen Verweis auf eine Ansicht vor, die mit "CREATE TEMPORARY TABLE t (cols) ENGINE=MyISAM vergleichbar ist " und "INSERT INTO t (cols) SELECT ... ".

MySQL bezeichnet eine Inline-Ansicht tatsächlich als "abgeleitete Tabelle", und dieser Name macht sehr viel Sinn, wenn wir verstehen, was MySQL damit macht.

Meine persönliche Präferenz ist es, die Anweisung "CREATE VIEW" nicht zu verwenden. Der größte Nachteil (wie ich es sehe) ist, dass es SQL "versteckt", das ausgeführt wird. Für den zukünftigen Leser sieht der Verweis auf die Ansicht wie eine Tabelle aus. Und wenn er dann eine SQL-Anweisung schreibt, wird er auf die Ansicht verweisen, als wäre es eine Tabelle, also sehr praktisch. Dann beschließt er, diesen Tisch mit sich selbst zu verbinden, mit einem weiteren Verweis darauf. (Für die zweite Referenz führt MySQL diese Abfrage auch erneut aus und erstellt eine weitere temporäre (und nicht indizierte) MyISAM-Tabelle. Und jetzt gibt es eine JOIN-Operation dafür. Und dann wird ein Prädikat "WHERE view.column ='foo'" hinzugefügt auf der äußeren Abfrage.

Am Ende "verbirgt" es die offensichtlichste Leistungsverbesserung und verschiebt dieses Prädikat in die Ansichtsabfrage.

Und dann kommt jemand und beschließt, eine neue Ansicht zu erstellen, die auf die alte Ansicht verweist. Er benötigt nur eine Teilmenge von Zeilen und kann die vorhandene Ansicht nicht ändern, da dies etwas beschädigen könnte, also erstellt er eine neue Ansicht ... CREATE VIEW myview FROM publicview p WHERE p.col ='foo'.

Und jetzt führt ein Verweis auf myview zuerst die publicview-Abfrage aus, erstellt eine temporäre MyISAM-Tabelle, dann wird die myview-Abfrage darauf ausgeführt, wodurch eine weitere temporäre MyISAM-Tabelle erstellt wird, gegen die die äußere Abfrage ausgeführt wird.

Grundsätzlich birgt die Bequemlichkeit der Ansicht das Potenzial für unbeabsichtigte Performance-Probleme. Da die Ansichtsdefinition in der Datenbank für jedermann verfügbar ist, wird sie jemand verwenden, auch wenn es nicht die am besten geeignete Lösung ist.

Zumindest bei einer Inline-Ansicht ist sich die Person, die die SQL-Anweisung schreibt, besser bewusst, welche SQL tatsächlich ausgeführt wird, und wenn Sie all diese SQL-Anweisungen angelegt haben, haben Sie die Möglichkeit, sie für die Leistung zu optimieren.

Meine zwei Cent.

BEASTLY SQL ZÄHMEN

Ich finde, dass die Anwendung regulärer Formatierungsregeln (die meine Tools automatisch ausführen) monströses SQL in etwas verwandeln kann, das ich lesen und mit dem ich arbeiten kann.

SELECT row.col1
     , row.col2
     , person.*
  FROM some_table row
  LEFT
  JOIN ( SELECT 'person'  AS `person_type`
              , p.id      AS `id`
              , CONCAT(p.first_name,' ',p.surname) AS `name`
           FROM person p
          UNION ALL
         SELECT 'company' AS `person_type`
              , c.id      AS `id`
              , c.name    AS `name`
           FROM company c
       ) person
    ON person.id = row.person_id
   AND person.person_type = row.person_type

Ich würde die Inline-Ansicht genauso wahrscheinlich überhaupt vermeiden und bedingte Ausdrücke in der SELECT-Liste verwenden, obwohl dies für viele Spalten unhandlicher wird.

SELECT row.col1
     , row.col2
     , row.person_type AS ref_person_type
     , row.person_id   AS ref_person_id
     , CASE
       WHEN row.person_type = 'person'  THEN p.id 
       WHEN row.person_type = 'company' THEN c.id
       END AS `person_id`
     , CASE
       WHEN row.person_type = 'person'  THEN CONCAT(p.first_name,' ',p.surname)
       WHEN row.person_type = 'company' THEN c.name
       END AS `name`
  FROM some_table row
  LEFT
  JOIN person p
    ON row.person_type = 'person'
   AND p.id = row.person_id
  LEFT
  JOIN company c
    ON row.person_type = 'company'
   AND c.id = row.person_id