View mit abhängigen Views bearbeiten

Code:
SELECT
s.sid,
s.bezeichnung,
sum(p.a * p.b) AS flaeche
FROM s,p
WHERE s.sid = p.sid
AND p.jahr1 <= 2004 AND ((p.jahr2) >= 2004 OR p.jahr2 IS NULL)
GROUP BY s.sid,s.bezeichnung;
Ich würde sonst halt einfach eine Funktion schreiben, und dann eine View mit dem aktuellen Jahr (diese Abfrage wird am häufigsten gebraucht) erstellen, aber bin auf deinen Vorschlag gespannt.

Was spricht dagegen, das Jahr in die Viewausgabe aufzunehmen? (und dann natürlich von außen zu parametrieren wie es grad gebraucht wird?)
(Klammer2: ich finde bei Datenbankabfragen ja auch immer toll, wenn man den Daten ansieht, wo sie herkommen. Also den Kontext mitliefern, nicht nur ein "Ergebnis". Hier konkret bei Ausgabe des Selects Jahr1 und Jahr2: "pass auf alter, das sind Daten für das Jahr 2004! - und nicht nicht was Du gerade meinst, weil Du beim Klick auf den Reportbutton kurz gepennt hast")
Oder: Wenn es ums Verrecken darum geht, so oft das aktuelle Jahr abzufragen, dem View die Bestimmung des aktuellen Jahrs zu überlassen?

Ja und wenn das alles nicht nach Deinem Geschmack ist, dann wäre es jenachdem ein schöner Anwendungsfall für Sessionvariables innerhalb eines Views.
+ Man hat einen schlanken View (statt einer Function),
+ man hat eine innere Einschränkung (ob jetzt mit offengelegten Parameterwerten oder nicht), die eine sofortig(st)e Mengeneinschränkung erlaubt
+ man hat eine übersichtlichere DB /Datenmodell (ohne Function)
- man ist nicht mehr ohne weiteres Stateless

Und nebenbei wegen Null oder nicht usw.:
Ich würde niemals auf Integerbasis mit Datumswerten arbeiten sondern immer mit Date, Datetime, Timestamp..
Ich würde außerdem auch aufwändige is (not) Null Abfragen vermeiden (entsprechend modellieren) (bei dates ist das ein ähnliches Problem wie bei Boolean Werte verglichen mit tri-state "bools")
 
Werbung:
+ Man hat einen schlanken View (statt einer Function),
Auch wenn ich Dir grundsätzlich zustimme: eine Abfrage in einer Funktion zu kapseln ist auch nicht "dicker" als eine View. Eine SQL Funktion hat praktisch keinen Laufzeit-Overhead im Vergleich zu der darin enthaltenen Abfrage.

Da empfinde ich "Sessionvariablen" (die es eigentlich ja gar nicht gibt) als echten "Hack" (im negativen Sinn): da sind auf einmal zwei völlig unabhängige Stellen daran beteiligt das richtige Ergebnis zu liefern.

In diesem Fall, geht das mit der View aber wirklich nicht so einfach, bzw. es wäre nicht hilfreich.

Die Bedingung geht über zwei Spalten. Will man diese Spalten in der View haben um das Ergebnis später einschränken zu können, dann muss man auch über die beiden Spalten gruppieren.

Das führt aber dazu, dass man beim Selektieren von der View nochmal aggregieren muss um das gewünschte Ergebnis zu erhalten. Damit ist dann auf jeden Fall schon mal der Vorteil des "einfachen" Statements weg.

Was aber viel wichtiger ist: das ganz wird (deutlich) langsamer. Postgres kann in dem Fall die WHERE Bedingung nicht "in die View" integrieren. Es wird zuerst die Gruppierung der View über alle Daten ermittelt, dann wird das Resultat basierend auf der WHERE Bedingung gefiltert und das wird dann nochmal aggregiert.
 
Schlank, das war vielleicht das falsche Wort. Ein View ist für mich transparenter als eine Funktion, weniger mögliche Seiteneffekte, weniger Komplexität. Das würde ich immer bevorzugen. Ist vielleicht Geschmackssache, hat aber vielleicht auch was mit dem Thema Optimizer zu tun. Ganz generell gehe ich davon aus, dass ein View wahrscheinlich besser durch den Optimizer behandelt werden kann, als eine Funktion oder ein Selectstatement/ View mit enthaltener Funktion.

Das Prinzip von Sessionvariablen sehe ich da noch als deutlich kleineres Übel, weil sie keine strukturelle Komplexität in ein Statement bringen, sondern fast eher das Gegenteil. Funktional „reihen“ sie sich ein in herkömmlich verwendete Parameter, lediglich die Applizierung unterscheidet sich. Diese „völlige Unabhängigkeit“ kann ich zwar verstehen, betrachte es aber als total harmlos.

Ich habe unter Oracle sowas viel benutzt, wo es allerdings auch eleganter umsetzbar ist. Eleganterer Einsatz ändert aber nichts an der Wirkmacht (möglicher Performance Gewinn) einer Session Variable (bzw. Package Variable bei Oracle). Viel bedeutet dabei allerdings ein sehr bewusster Umgang (by Design), Session Variables werden über die ganze „Anwendung“ hinweg als Dimensionsobjekte benutzt, vielleicht eine Handvoll, z.B. eine Art Mandanten Paramter, ein Geschäftsjahr (siehe Thema des Threads und sowas). Das gilt dann systemweit und wird von Views, Prozeduren und Funktionen verwendet. Man kann so eine ganze, konsistente Datenschicht anlegen, ohne das ein Entwickler jemals aktiv diese Variable gesetzt hat (oder es vergessen kann). Aber es ist zu einem guten Teil sowieso hier Theorie, weil Sessionvariablen unter PG (noch- meinst Du das?) nicht soweit sind und weil ihr Einsatz systematisch eher für Client/Server Systeme als für Multi Tier in Frage kommt oder besser, für statefull Verbindungen.

Was die Grenzen des PG Optimizers angeht, bin ich nicht so gut im Bilde, weil ich dort noch keinen Bedarf hatte. Wenn Du sagst, dass da an der Stelle Schluss ist, meinetwegen. Aber diese Grenzen gibt es immer wieder und immer wieder woanders (in den verschiedenen RDBMS). Da würde ich 2 Bereiche unterscheiden. Kleine WaldUndWiesenAnwendung mit ein paar hundert T Datensätzen oder auch Millionen, jedenfalls unproblematisch und immer geeignet, straigt forward zu entwickeln. Da interessiert mich dann eben nicht, ob da grad mal doppelt oder alles aggregiert wird. (Ja, perspektivisch sollte es skalieren.) Da muss und sollte aber niemand primär an performance bedingte Strukturänderungen und denken (Stichwort premature Optimization). Und dann gibt es Großsysteme, wo Performance mitgedacht werden muss im Modell oder mindestens aber an vielen Stellen in Selectstatements.

Einen Tod muss man dann meist sterben, pragmatische, schnelle 0815 Entwicklung mit Performanceschwächen oder beste Performance mit ausgefeilter Modell- und Statement Optimierung und natürlich der sehr gezielten Nutzung spezifischer DB Fähigkeiten wie Partitionierung usw..

Die „is Null“ Sache sehe ich da eigentlich ähnlich wie Du. Mit NULL Werten wird man nie glücklich und man sollte sie nur einsetzen, wenn nicht anders möglich. Es ist sicher nicht die reine Lehre, dort dann magic numbers einzusetzen, vielleicht unkonventionell (wie Sessionvariables), aber in einem durchdesignten, geschlossenen System finde ich es okay.

Und wenn ich weder Sessionvariables noch doppelte Gruppierung, noch magic numbers haben möchte, kann man das Statement oben wahrscheinlich in einigen unterschiedlichen Varianten formulieren. Das machte aber für mich nur Sinn, wenn man Modell, Mengengerüste, Indizierung, Nutzungsfrequenz usw. wirklich kennt.
 
Ganz generell gehe ich davon aus, dass ein View wahrscheinlich besser durch den Optimizer behandelt werden kann, als eine Funktion oder ein Selectstatement/ View mit enthaltener Funktion.

Bei einer SQL Funktion ("language sql") die als "stable" definiert ist, wird zur Laufzeit der Funktionsaufruf komplett entfernt und durch die, in der Funktion enthaltenen Abfrage ersetzt. Somit ist so eine Funktion genauso schnell wie eine View. Im execution plan sieht man gar keinen Funktionsaufruf mehr. Das ist ein bisschen vergleichbar mit den in Oracle 21 eingeführten "SQL Macros" um den Overhead eines PL/SQL Aufrufs zu vermeiden (die aber die Einschränkung haben, dass sie nur skalare Werte zurückliefern können, keine Resultate)
 
Okay, aber da wäre nur ein kleiner Teil des Problems oder? Hier ging es ja um Functions, die Select Statements abbilden / ersetzen sollen (weil kaum/kein overhead) und die dann eher nicht "stable" wären.
 
Doch die sind stable (aber nicht immutable)

Schau Dir mal dieses Beispiel an.

Der Funktionsaufruf ist im 2. execution plan gar nicht mehr zu sehen und sieht identisch zu der Variante aus, die ohne Funktion arbeitet.
 
Werbung:
Zurück
Oben