Das Folgende ist ein Auszug aus einem Buch über Datenbankdesign (Beginning Database Design ISBN: 0-7645-7490-6):
Die Gefahr bei der Verwendung von Ansichten besteht darin, dass eine Abfrage nach einer Ansicht gefiltert wird und erwartet wird, dass ein sehr kleiner Teil einer sehr großen Tabelle gelesen wird. Jede Filterung sollte in der Ansicht durchgeführt werden, da jede Filterung für die Ansicht selbst angewendet wird, nachdem die Abfrage in der Ansicht die Ausführung abgeschlossen hat. Ansichten sind in der Regel nützlich, um den Entwicklungsprozess zu beschleunigen, können jedoch auf lange Sicht die Datenbankleistung vollständig beeinträchtigen.
Das Folgende ist ein Auszug aus der PostgreSQL 9.5-Dokumentation:
Die freie Verwendung von Ansichten ist ein Schlüsselaspekt für ein gutes SQL-Datenbankdesign. Mithilfe von Ansichten können Sie die Details der Struktur Ihrer Tabellen, die sich bei der Entwicklung Ihrer Anwendung ändern können, hinter konsistenten Schnittstellen zusammenfassen.
Die beiden Quellen scheinen sich zu widersprechen ("Nicht mit Ansichten gestalten" vs. "Mit Ansichten gestalten").
In PG werden Views jedoch über das Regelsystem implementiert. Daher wird möglicherweise (und das ist meine Frage) jede Filterung für die Ansicht als Filter in der Ansicht umgeschrieben, was zu einer einzelnen Abfrageausführung für die zugrunde liegenden Tabellen führt.
Ist meine Interpretation korrekt und kombiniert PG WHERE-Klauseln in und aus der Ansicht? Oder werden sie einzeln nacheinander ausgeführt? Irgendwelche kurzen, eigenständigen, korrekten (kompilierbaren) Beispiele?
SELECT * FROM my_view WHERE my_column = 'blablabla';
danach auf das Anwenden eines Filters: In der zweiten werden Ansichten verwendet, um das Datenmodell für die Anwendung, die es verwendet, transparent zu machen. Die erste Quelle weist Sie darauf hin, den FilterWHERE my_column = 'blablabla'
in die Ansichtsdefinition aufzunehmen, da dies zu einem besseren Ausführungsplan führt.Antworten:
Das Buch ist falsch.
Das Auswählen aus einer Ansicht ist genauso schnell oder langsam wie das Ausführen der zugrunde liegenden SQL-Anweisung - Sie können dies ganz einfach mit überprüfen
explain analyze
.Der Postgres-Optimierer (und der Optimierer für viele andere moderne DBMS) kann Prädikate für die Ansicht in die tatsächliche Ansichtsanweisung verschieben - vorausgesetzt, es handelt sich um eine einfache Anweisung (dies kann wiederum mit überprüft werden
explain analyze
).Der "schlechte Ruf" in Bezug auf die Leistung entsteht - glaube ich -, wenn Sie Ansichten überbeanspruchen und damit beginnen, Ansichten zu erstellen, die Ansichten verwenden, die Ansichten verwenden. Sehr oft führt dies zu Anweisungen, die im Vergleich zu einer Anweisung, die ohne die Ansichten von Hand erstellt wurde, zu viel bewirken, z. B. weil einige Zwischentabellen nicht benötigt würden. In fast allen Fällen ist der Optimierer nicht intelligent genug, um diese nicht benötigten Tabellen / Joins zu entfernen oder Prädikate über mehrere Ansichtsebenen hinweg nach unten zu verschieben (dies gilt auch für andere DBMS).
quelle
explain analyze
Anweisung verwendet wird?Um Ihnen ein Beispiel zu geben, was @a_horse erklärt hat :
Postgres implementiert das Informationsschema, das aus (manchmal komplexen) Ansichten besteht, die Informationen zu DB-Objekten in standardisierter Form bereitstellen. Dies ist bequem und zuverlässig - und kann erheblich teurer sein als der direkte Zugriff auf die Postgres-Katalogtabellen.
Sehr einfaches Beispiel, um alle sichtbaren Spalten einer Tabelle
... aus dem Informationsschema zu erhalten:
... aus dem Systemkatalog:
Vergleichen Sie die Abfragepläne und die Ausführungszeit für beide mit
EXPLAIN ANALYZE
.Die erste Abfrage basiert auf der Ansicht
information_schema.columns
, die sich zu mehreren Tabellen zusammenfügt, die wir hierfür überhaupt nicht benötigen.Die zweite Abfrage durchsucht nur die eine Tabelle
pg_catalog.pg_attribute
, daher viel schneller. (Die erste Abfrage benötigt jedoch nur wenige ms in gemeinsamen DBs.)Einzelheiten:
quelle
BEARBEITEN:
Mit Entschuldigung muss ich meine Behauptung zurückziehen, dass die akzeptierte Antwort nicht immer korrekt ist - es heißt, dass die Ansicht immer mit der gleichen Sache identisch ist, die als Unterabfrage geschrieben wurde. Ich denke, das ist unbestreitbar, und ich glaube jetzt zu wissen, was in meinem Fall vor sich geht.
Ich denke jetzt auch, dass es eine bessere Antwort auf die ursprüngliche Frage gibt.
Die ursprüngliche Frage ist, ob die Verwendung von Ansichten als Richtschnur dienen sollte (im Gegensatz zum Beispiel zum Wiederholen von SQL in Routinen, die möglicherweise zweimal oder öfter verwaltet werden müssen).
Meine Antwort wäre "nicht, wenn Ihre Abfrage Fensterfunktionen oder andere Funktionen verwendet, die das Optimierungsprogramm veranlassen, die Abfrage anders zu behandeln, wenn sie zu einer Unterabfrage wird, da das Erstellen der Unterabfrage (unabhängig davon, ob sie als Ansicht dargestellt wird oder nicht) die Leistung beeinträchtigen kann Wenn Sie zur Laufzeit mit Parametern filtern.
Die Komplexität meiner Fensterfunktion ist unnötig. Der Erklärungsplan dazu:
ist viel günstiger als hierfür:
Hoffe, das ist ein bisschen genauer und hilfreich.
Nach meinen jüngsten Erfahrungen (die mich veranlassen, diese Frage zu finden) ist die oben akzeptierte Antwort nicht unter allen Umständen korrekt. Ich habe eine relativ einfache Abfrage, die eine Fensterfunktion enthält:
Wenn ich diesen Filter hinzufüge:
Der Erklärungsplan, den ich erhalte, lautet wie folgt:
Hierbei wird der Primärschlüsselindex für die Train Service-Tabelle und ein nicht eindeutiger Index für die portion_consist-Tabelle verwendet. Es wird in 90 ms ausgeführt.
Ich habe eine Ansicht erstellt (hier einfügen, um die Übersichtlichkeit zu verdeutlichen, aber es ist buchstäblich die Abfrage in einer Ansicht):
Wenn ich diese Ansicht mit dem identischen Filter abfrage:
Dies ist der EXPLAIN-Plan:
Dies führt vollständige Scans an beiden Tischen durch und dauert 17 Sekunden.
Bis ich darauf stieß, habe ich Ansichten mit PostgreSQL großzügig genutzt (nachdem ich die weit verbreiteten Ansichten verstanden hatte, die in der akzeptierten Antwort zum Ausdruck kamen). Ich würde speziell die Verwendung von Ansichten vermeiden, wenn ich eine Vor-Aggregat-Filterung benötige, für die ich Set-Return-Funktionen verwenden würde.
Mir ist auch bewusst, dass CTEs in PostgreSQL strikt getrennt ausgewertet werden, sodass ich sie nicht so verwende, wie ich es zum Beispiel mit SQL Server tun würde, wo sie als Unterabfragen optimiert zu sein scheinen.
Meine Antwort lautet daher, dass es Fälle gibt, in denen Ansichten nicht genau so ausgeführt werden, wie die Abfrage, auf der sie basieren. Daher ist Vorsicht geboten. Ich benutze Amazon Aurora basierend auf PostgreSQL 9.6.6.
quelle
CASE WHEN (NOT ts.primary_direction) THEN '-1' :: INTEGER ELSE 1 END
Nebenbei bemerkt, wird die Abfrage unnötigerweise langsamer als nötig, und Sie sollten besser zwei weitere Bedingungen in der Reihenfolge schreiben.CASE WHEN (NOT ts.primary_direction) THEN dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq DESC) ELSE dense_rank() OVER (PARTITION BY ts.train_service_key ORDER BY pc.through_idx DESC, pc.first_portion ASC, pc.first_seq ASC) END AS coach_block_idx
dense_rank()
Problem ist, dass Ihre Sichtweise keinen Sinn ergibt und aufgrund Ihrer Verwendung andere Dinge bewirkt, sodass es sich nicht wirklich um ein Leistungsproblem handelt.(Ich bin ein großer Fan von Views, aber hier muss man sehr vorsichtig mit PG sein und ich möchte jeden ermutigen, Views generell auch in PG zu verwenden, um die Verständlichkeit und Wartbarkeit von Abfragen / Code zu verbessern.)
Tatsächlich und traurigerweise (WARNUNG :) verursachte die Verwendung von Ansichten in Postgres echte Probleme und verringerte unsere Leistung erheblich, abhängig von den Funktionen, die wir darin verwendeten :-( (zumindest mit v10.1). (Dies wäre bei anderen nicht der Fall.) moderne DB-Systeme wie Oracle.)
(Abhängig davon, was Sie genau meinen - no - intermediäre temporäre Tabellen können materialisiert werden, die Sie vielleicht nicht wollen oder auf die Prädikate nicht gedrückt werden ...)
Ich kenne mindestens zwei wichtige "Features", die uns mitten in der Migration von Oracle nach Postgres im Stich ließen, sodass wir PG in einem Projekt aufgeben mussten:
CTEs (
with
-Klausel-Unterabfragen / allgemeine Tabellenausdrücke ) sind (normalerweise) nützlich für die Strukturierung komplexerer Abfragen (auch in kleineren Anwendungen), werden jedoch in PG standardmäßig als "versteckte" Optimierungshinweise implementiert (z. B. Generieren von nicht indizierten temporären Tabellen) und Verstoßen Sie damit gegen das (für mich und viele andere wichtige) Konzept des deklarativen SQL ( Oracle-Doku ): zeinfache Abfrage:
umgeschrieben mit etwas CTE:
Weitere Quellen mit Diskussionen etc .: https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/
Fensterfunktionen mit
over
-Anweisungen sind möglicherweise unbrauchbar (werden normalerweise in Ansichten verwendet, z. B. als Quelle für Berichte, die auf komplexeren Abfragen basieren).unser Workaround für die
with
-KlauselnWir werden alle "Inline-Ansichten" in reale Ansichten mit einem speziellen Präfix umwandeln, damit sie die Liste / den Namespace der Ansichten nicht durcheinander bringen und leicht mit der ursprünglichen "Außenansicht" in Beziehung gesetzt werden können: - /
unsere lösung für die fensterfunktionen
Wir haben es erfolgreich mit der Oracle-Datenbank implementiert.
quelle