Lastenausgleich von Lese- und Schreibvorgängen in der Datenbank

Lastenausgleich von Lese- und Schreibvorgängen in der Datenbank
In meinem vorherigen Artikel Artikel habe ich das Konzept und die Implementierung einer Datenbank beschrieben, die auf Funktionen basiert, anstatt auf Tabellen und Feldern, wie es in relationalen Datenbanken der Fall ist. Viele Beispiele wurden präsentiert, die die Vorteile dieses Ansatzes im Vergleich zu klassischen Methoden verdeutlichen. Einige hielten diese Beispiele für nicht überzeugend genug.

In diesem Artikel werde ich zeigen, wie ein solches Konzept es ermöglicht, das Schreiben und Lesen in der Datenbank schnell und einfach zu balancieren, ohne die Logik der Funktionsweise zu ändern. Ähnliche Funktionen wurden in modernen kommerziellen Datenbanksystemen (insbesondere Oracle und Microsoft SQL Server) versucht umzusetzen. Am Ende des Artikels werde ich aufzeigen, dass ihre Ergebnisse, milde ausgedrückt, nicht besonders überzeugend waren.

Beschreibung

Wie bereits zuvor werde ich die Beschreibung zur besseren Verständlichkeit an Beispielen beginnen. Stellen wir uns vor, wir müssen eine Logik implementieren, die eine Liste von Abteilungen mit der Anzahl der Mitarbeiter und deren Gesamteinkommen zurückgibt.

In einer funktionalen Datenbank würde dies folgendermaßen aussehen:

CLASS Abteilung ‘Abteilung’;
name ‘Bezeichnung’ = DATENSTRING[100] (Abteilung);

CLASS Employee 'Mitarbeiter';
department 'Abteilung' = DATA Department (Employee);
salary 'Gehalt' = DATA NUMERIC[10,2] (Employee);

countEmployees 'Anzahl der Mitarbeiter' (Department d) = 
    GRUPPE SUMME 1 WENN Abteilung(Mitarbeiter e) = d;
GehaltSumme 'Gesamtgehalt' (Abteilung d) = 
    GRUPPE SUMME gehalt(Mitarbeiter e) WENN abteilung(e) = d;

WÄHLE name(Abteilung d), countMitarbeiter(d), GehaltSumme(d);

Die Komplexität der Ausführung dieser Abfrage in einem beliebigen DBMS wird gleich sein O(Anzahl der Mitarbeiter), da für diese Berechnung die gesamte Mitarbeiter-Tabelle gescannt und dann nach Abteilung gruppiert werden muss. Zudem wird es einen geringen (wir gehen davon aus, dass es deutlich mehr Mitarbeiter als Abteilungen gibt) Aufschlag in Abhängigkeit vom gewählten Plan geben. O(log Anzahl der Mitarbeiter) oder O(Anzahl der Abteilungen) für die Gruppierung und andere.

Es ist klar, dass die Kosten für die Ausführung in verschiedenen DBMS unterschiedlich sein können, aber die Komplexität bleibt unverändert.

In der vorgeschlagenen Implementierung wird das funktionale DBMS eine Unterabfrage generieren, die die erforderlichen Werte pro Abteilung berechnet, und anschließend einen JOIN mit der Abteilungstabelle durchführen, um den Namen zu erhalten. Für jede Funktion kann bei der Deklaration jedoch ein spezieller MARKER MATERIALIZED festgelegt werden. Das System erstellt automatisch das entsprechende Feld für jede solche Funktion. Bei Änderung des Funktionswerts wird auch der Feldwert innerhalb derselben Transaktion geändert. Bei Zugriff auf diese Funktion wird auf das bereits berechnete Feld zugegriffen.

Insbesondere wenn MATERIALIZED für Funktionen gesetzt wird countEmployees und salarySum, werden zwei Felder in der Abteilungstabelle hinzugefügt, die die Anzahl der Mitarbeiter und deren Gesamtgehalt speichern. Bei jeglicher Änderung der Mitarbeiter, deren Gehälter oder Zugehörigkeiten zu Abteilungen wird das System die Werte dieser Felder automatisch anpassen. Der oben genannte Befehl wird dann direkt auf diese Felder zugreifen und wird in O(Anzahl der Abteilungen).

Welche Einschränkungen gibt es? Nur eine: Diese Funktion muss eine endliche Anzahl von Eingabewerten haben, für die ihr Wert definiert ist. Ansonsten lässt sich eine Tabelle nicht erstellen, die all ihre Werte speichert, da es keine Tabelle mit einer unendlichen Anzahl von Zeilen geben kann.

Beispiel:

Mitarbeiteranzahl ‘Anzahl der Mitarbeiter mit einem Gehalt > N’ (Abteilung d, NUMERIC[10,2] N) = 
    GRUPPENSUMME Gehalt(Mitarbeiter e) WENN abteilung(e) = d UND gehalt(e) > N;

Diese Funktion ist für eine unendliche Anzahl von Werten der Zahl N definiert (zum Beispiel sind negative Werte geeignet). Daher kann sie nicht als MATERIALIZED gesetzt werden. Das ist also eine logische, keine technische Einschränkung (nicht, weil wir es nicht umsetzen konnten). Ansonsten gibt es keine Einschränkungen. Gruppierungen, Sortierungen, AND und OR, PARTITION, Rekursionen usw. können verwendet werden.

Beispielsweise kann in der Aufgabe 2.2 des vorherigen Artikels MATERIALIZED auf beide Funktionen gesetzt werden:

gekauft 'Kauft' (Kunde c, Produkt p, GANZZAHL y) = 
    GRUPPENSUMME sum(Detail d) WENN 
        kunde(bestellung(d)) = c UND 
        produkt(d) = p UND 
        extrahiereJahr(datum(bestellung(d))) = y MATERIALISIERT;
bewertung 'Bewertung' (Kunde c, Produkt p, GANZZAHL y) = 
    PARTITIONSSUMME 1 BESTELLEN DESC gekauft(c, p, y), p VON c, y MATERIALISIERT;
WÄHLEN contactName(Kunde c), name(Produkt p) WO bewertung(c, p, 1997) < 3;

Das System erstellt selbstständig eine Tabelle mit den Schlüsseltypen Kunde, Produkt und INTEGER, fügt zwei Felder hinzu und aktualisiert deren Werte bei Änderungen. Bei weiteren Zugriffen auf diese Funktionen erfolgt keine Berechnung, sondern es werden die Werte aus den entsprechenden Feldern gelesen.

Mit diesem Mechanismus können Sie beispielsweise rekursive Abfragen (CTE) vermeiden. Insbesondere betrachten wir Gruppen, die durch eine Eltern-Kind-Beziehung eine Baumstruktur bilden (jede Gruppe hat einen Bezug zu ihrem Elternteil):

Eltern = DATEN Gruppe (Gruppe);

In einer funktionalen Datenbank kann die Logik der Rekursion wie folgt definiert werden:

level (Group child, Group parent) = REKURSION 1l WENN child IST Gruppe UND parent == child
                                                             SCHRITT 2l WENN parent == parent($parent);
isParent (Group child, Group parent) = WAHR WENN level(child, parent) MATERIALISIERT;

Da für die Funktion isParent MATERIALIZED gesetzt ist, wird eine Tabelle mit zwei Schlüsseln (Gruppen) erstellt, in der das Feld isParent nur dann wahr ist, wenn der erste Schlüssel ein Nachkomme des zweiten ist. Die Anzahl der Datensätze in dieser Tabelle entspricht der Anzahl der Gruppen multipliziert mit der durchschnittlichen Baumtiefe. Wenn es beispielsweise erforderlich ist, die Anzahl der Nachkommen einer bestimmten Gruppe zu zählen, können Sie diese Funktion wie folgt ansprechen:

childrenCount (Gruppe g) = GRUPPENSUM 1 WENN isParent(Gruppe Kind, g);

Im SQL-Abfrage wird dabei kein CTE verwendet. Stattdessen erfolgt eine einfache GROUP BY-Anweisung.

Mit diesem Mechanismus können Sie auch bei Bedarf die Denormalisierung der Datenbank leicht durchführen:

CLASS Order 'Bestellung';
date 'Datum' = DATUM DATUM (Bestellung);

CLASS OrderDetail 'Bestellzeile';
order 'Bestellung' = DATA Order (OrderDetail);
date 'Datum' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;

Bei der Verwendung der Funktion date Die Bestellzeile wird aus einer Tabelle mit Bestellzeilen basierend auf dem Feld gelesen, für das ein Index besteht. Bei Änderungen des Bestelldatums wird das System automatisch das denormalisierte Datum in der Zeile neu berechnen.

Vorteile

Wozu dient dieser gesamte Mechanismus? In klassischen Datenbanksystemen können Entwickler oder DBAs ohne Neuschreiben der Abfragen nur die Indizes ändern, Statistiken definieren und dem Abfrageplaner Hinweise geben, wie sie ausgeführt werden sollen (Hinweise sind jedoch nur in kommerziellen Datenbanksystemen verfügbar). Egal wie sehr sie sich bemühen, sie können die erste Abfrage im Artikel nicht ausführen, ohne die Abfragen zu ändern und Trigger zu schreiben. Über (Anzahl der Abteilungen) ohne Änderungen an den Abfragen und ohne das Hinzufügen von Triggern. In dem vorgeschlagenen Schema kann man sich in der Entwicklungsphase keine Gedanken über die Datenstruktur und über die zu verwendenden Aggregationen machen. Das kann alles während des Betriebs ganz entspannt geändert werden.

In der Praxis sieht das folgendermaßen aus. Einige Personen entwickeln direkt die Logik basierend auf der gestellten Aufgabe. Sie haben keine Ahnung von Algorithmen und deren Komplexität, von Ausführungsplänen, von Join-Typen oder von anderen technischen Aspekten. Diese Personen sind eher Geschäftsanalytiker als Entwickler. Dann geht alles in die Test- oder Produktionsphase. Das Logging von langen Abfragen wird aktiviert. Wenn eine lange Abfrage entdeckt wird, entscheiden dann andere Personen (mehr technische, also im Prinzip DBAs) über die Aktivierung einer MATERIALIZED-Ansicht für eine bestimmte Zwischenfunktion. Dadurch wird die Schreibgeschwindigkeit etwas verlangsamt (da ein zusätzliches Feld in der Transaktion aktualisiert werden muss). Allerdings wird nicht nur diese Abfrage deutlich beschleunigt, sondern auch alle anderen, die diese Funktion nutzen. Die Entscheidung, welche Funktion materialisiert werden soll, ist dabei relativ einfach. Zwei Hauptparameter: Anzahl möglicher Eingabewerte (genau so viele Datensätze werden in der entsprechenden Tabelle vorhanden sein) und wie häufig sie in anderen Funktionen verwendet wird.

Analoga

Moderne kommerzielle DBMS verfügen über ähnliche Mechanismen: MATERIALIZED VIEW mit FAST REFRESH (Oracle) und INDEXED VIEW (Microsoft SQL Server). In PostgreSQL kann ein MATERIALIZED VIEW nicht innerhalb einer Transaktion aktualisiert werden, sondern nur auf Anfrage (und das unter sehr strengen Einschränkungen), weshalb wir diesen nicht berücksichtigen. Es gibt jedoch einige Probleme, die seine Verwendung erheblich einschränken.

Zunächst kann die Materialisierung nur aktiviert werden, wenn bereits eine normale VIEW erstellt wurde. Andernfalls müssten alle anderen Abfragen, die das neu erstellte View ansprechen, umgeschrieben werden, um diese Materialisierung zu nutzen. Alternativ könnte man alles beim Alten lassen, was jedoch mindestens ineffizient wäre, falls bereits bestimmte vorab berechnete Daten vorhanden sind, die durch viele Abfragen nicht immer genutzt, sondern neu berechnet werden.

Zweitens gibt es eine Vielzahl an Einschränkungen:

Oracle

5.3.8.4 Allgemeine Einschränkungen für Fast Refresh

Die definierende Abfrage der materialisierten Ansicht unterliegt den folgenden Einschränkungen:

  • Die materialisierte Ansicht darf keine Referenzen auf sich wiederholende Ausdrücke wie enthalten: SYSDATE und ROWNUM.
  • Die materialisierte Ansicht darf keine Referenzen auf RAW oder LONG RAW Datentypen enthalten.
  • Sie darf keine SELECT Listenunterabfragen enthalten.
  • Sie darf keine analytischen Funktionen (zum Beispiel, RANK) in der SELECT Klausel enthalten.
  • Sie darf keine Referenzen auf eine Tabelle enthalten, für die ein XMLIndex Index definiert ist.
  • Sie darf keine MODEL Klausel enthalten.
  • Sie darf keine HAVING Klausel mit einer Unterabfrage enthalten.
  • Sie darf keine geschachtelten Abfragen enthalten, die ANY, ALL, oder NOT EXISTS.
  • Sie darf keine [START WITH …] VERBINDUNG HERSTELLEN Klausel enthalten.
  • Es können keine mehreren Detail-Tabellen an unterschiedlichen Standorten enthalten sein.
  • EIN BESTÄTIGEN Materialisierte Ansichten dürfen keine Remote-Detail-Tabellen haben.
  • Verschachtelte materialisierte Ansichten müssen eine Verknüpfung oder Aggregation haben.
  • Materialisierte Verknüpfungsansichten und materialisierte Aggregatansichten mit einer GRUPPE NACH Klausel dürfen nicht aus einer indexorganisierten Tabelle auswählen.

5.3.8.5 Einschränkungen für schnelles Aktualisieren von materialisierten Ansichten mit nur Verknüpfungen

Für die Definition von Abfragen für materialisierte Ansichten mit nur Verknüpfungen und ohne Aggregationen gelten die folgenden Einschränkungen für schnelles Aktualisieren:

  • Alle Einschränkungen aus „Allgemeine Einschränkungen für schnelles Aktualisieren«.
  • Sie dürfen keine GRUPPE NACH Klauseln oder Aggregationen enthalten.
  • Die Rowids aller Tabellen in der FROM Liste müssen in der SELECT Abfrage erscheinen.
  • Materialisierte Ansicht-Protokolle müssen mit Rowids für alle Basis-Tabellen in der FROM Abfrage erscheinen.
  • Es kann keine schnell aktualisierbare materialisierte Ansicht aus mehreren Tabellen mit einfachen Verknüpfungen erstellt werden, die eine Objekttyp-Spalte in der SELECT Anweisung enthalten.

Außerdem wird die von Ihnen gewählte Aktualisierungsmethode nicht optimal effizient sein, wenn:

  • Die definierende Abfrage einen äußeren Join verwendet, der sich wie ein innerer Join verhält. Wenn die definierende Abfrage einen solchen Join enthält, ziehen Sie in Betracht, die definierende Abfrage so umzuschreiben, dass sie einen inneren Join enthält.
  • Die SELECT Liste der materialisierten Ansicht enthält Ausdrücke über Spalten aus mehreren Tabellen.

5.3.8.6 Einschränkungen für schnelles Aktualisieren von materialisierten Ansichten mit Aggregationen

Für die Definition von Abfragen für materialisierte Ansichten mit Aggregationen oder Verknüpfungen gelten die folgenden Einschränkungen für schnelles Aktualisieren:

Schnelles Aktualisieren wird für beide EIN BESTÄTIGEN und EIN FORDERUNG materialisierte Ansichten unterstützt, jedoch gelten die folgenden Einschränkungen:

  • Alle Tabellen in der materialisierten Ansicht müssen materialisierte Ansicht-Protokolle haben, und die materialisierten Ansicht-Protokolle müssen:
    • Alle Spalten der in der materialisierten Ansicht referenzierten Tabelle enthalten.
    • Mit ROWID und EINSCHLIESSEN NEU WERTE.
    • Die SEQUENZ Klausel angeben, wenn die Tabelle voraussichtlich eine Mischung aus Einfügungen/Direktladungen, Löschungen und Aktualisierungen haben wird.

  • Nur SUMME, ANZAHL, DURCHSCHNITT, STANDDEV, VARIANZ, MIN und MAX werden für schnelles Aktualisieren unterstützt.
  • ANZAHL(*) muss angegeben werden.
  • Aggregatfunktionen dürfen nur als äußerster Teil des Ausdrucks auftreten. Das heißt, Aggregationen wie AVG(AVG(x)) oder AVG(x)+ AVG(x) sind nicht erlaubt.
  • Für jedes Aggregat wie AVG(expr), muss das entsprechende COUNT(expr) vorhanden sein. Oracle empfiehlt, dass SUM(expr) angegeben wird.
  • Wenn VARIANCE(expr) oder STDDEV(expr) angegeben ist, COUNT(expr) und SUM(expr) muss angegeben werden. Oracle empfiehlt, dass SUM(expr * expr) angegeben wird.
  • Die SELECT Spalte in der definierenden Abfrage kann kein komplexer Ausdruck mit Spalten aus mehreren Basistabellen sein. Ein möglicher Workaround ist die Verwendung einer geschachtelten materialisierten Ansicht.
  • Die SELECT Die Liste muss alle GRUPPE NACH Spalten enthalten.
  • Die materialisierte Ansicht basiert nicht auf einer oder mehreren entfernten Tabellen.
  • Wenn Sie einen CHAR Datentyp in den Filterspalten eines materialisierten Sichtprotokolls verwenden, müssen die Zeichencodierungen der Master-Website und der materialisierten Ansicht übereinstimmen.
  • Wenn die materialisierte Ansicht eine der folgenden Eigenschaften hat, wird ein schneller Refresh nur bei konventionellen DML-Einfügungen und direkten Ladevorgängen unterstützt.
    • Materialisierte Ansichten mit MIN oder MAX Aggregaten
    • Materialisierte Ansichten, die SUM(expr) aber keine COUNT(expr)
    • Materialisierte Ansichten ohne ANZAHL(*)

    Eine solche materialisierte Ansicht wird als Insert-Only-Materialized View bezeichnet.

  • Eine materialisierte Ansicht mit MAX oder MIN ist nach Lösch- oder gemischten DML-Anweisungen schnell aktualisierbar, wenn sie kein WHERE Klausel enthalten.
    Der Max/Min-Schnell-Refresh nach Lösch- oder gemischten DML-Anweisungen verhält sich nicht wie im Insert-Only-Fall. Es werden die Max/Min-Werte für die betroffenen Gruppen gelöscht und neu berechnet. Sie müssen sich seiner Leistungsauswirkungen bewusst sein.
  • Materialisierte Ansichten mit benannten Ansichten oder Unterabfragen in der FROM Klausel können schnell aktualisiert werden, wenn die Ansichten vollständig zusammengeführt werden können. Informationen darüber, welche Ansichten zusammengeführt werden, finden Sie in Oracle Database SQL Language Reference.
  • Wenn keine äußeren Joins vorhanden sind, können Sie willkürliche Auswahlen und Joins in der WHERE Klausel enthalten.
  • Materialisierte Aggregatansichten mit äußeren Verknüpfungen sind schnell aktualisierbar nach konventionellen DML und direkten Ladeoperationen, vorausgesetzt, dass nur die äußere Tabelle verändert wurde. Außerdem müssen einzigartige Einschränkungen an den Verknüpfungsspalten der inneren Verknüpfungstabelle bestehen. Wenn äußere Verknüpfungen vorhanden sind, müssen alle Verknüpfungen durch ANDund müssen den Gleichheits-(=) Operator verwenden.
  • Für materialisierte Ansichten mit CUBE, ROLLUP, Gruppierungssets oder deren Kombinationen gelten die folgenden Einschränkungen:
    • Die SELECT Die Liste sollte ein Gruppierungsunterscheidung enthalten, die entweder eine GROUPING_ID -Funktion auf allen GRUPPE NACH Ausdrücken oder GROUPING -Funktionen für jeden GRUPPE NACH Ausdruck. Zum Beispiel, wenn die GRUPPE NACH Klausel der materialisierten Ansicht «GRUPPE NACH CUBE(a, b)« ist, dann sollte die Liste entweder « SELECT GROUPING_ID(a, b)» oder «GROUPING(a)GROUPING(b) AND » enthalten, damit die materialisierte Ansicht schnell aktualisierbar ist.sollte keine doppelten Gruppierungen ergeben. Zum Beispiel, «
    • GRUPPE NACH GROUP BY a, ROLLUP(a, b)» ist nicht schnell aktualisierbar, da es zu doppelten Gruppierungen «(a), (a, b), UND (a)führt.«.

5.3.8.7 Einschränkungen für schnelles Aktualisieren von materialisierten Ansichten mit UNION ALL

Materialisierte Ansichten mit dem UNION ALL Mengenoperator unterstützen die Schnellaktualisierung OPTION, wenn die folgenden Bedingungen erfüllt sind: Die definierende Abfrage muss den

  • Operator an oberster Stelle haben. UNION ALL Der Operator darf nicht in einer Unterabfrage eingebettet sein, mit einer Ausnahme: Der

    Die UNION ALL kann in einer Unterabfrage in der UNION ALL Klausel sein, sofern die definierende Abfrage die Form hat FROM SELECT * FROM (Ansicht oder Unterabfrage mit ) wie im folgenden Beispiel: UNION ALLCREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM customers c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM customers c WHERE c.cust_last_name = 'Jones');CREATE MATERIALIZED VIEW unionall_inside_view_mv REFRESH FAST ON DEMAND AS SELECT * FROM view_with_unionall;

    Beachten Sie, dass die Ansicht
    

    view_with_unionall die Anforderungen für eine schnelle Aktualisierung erfüllt. Jeder Abfrageblock in der

  • Jeder Abfrageblock in der UNION ALL Die Abfrage muss die Anforderungen an eine schnell aktualisierbare materielles Sichtfeld mit Aggregaten oder an eine schnell aktualisierbare materielles Sichtfeld mit Joins erfüllen.

    Die entsprechenden Logs für materielle Sichten müssen entsprechend dem erforderlichen Typ der schnell aktualisierbaren materiellen Sichtungen auf den Tabellen erstellt werden.
    Beachten Sie, dass die Oracle-Datenbank auch den Sonderfall einer materiellen Sicht mit nur einem einzelnen Joins einer Tabelle erlaubt, vorausgesetzt, die ROWID Spalte ist in die SELECT Liste und ins Log der materiellen Sicht aufgenommen worden. Dies wird in der definierten Abfrage der Sicht dargestellt. die Anforderungen für eine schnelle Aktualisierung erfüllt..

  • Die SELECT Die Liste jeder Abfrage muss ein UNION ALL Marker enthalten, und die UNION ALL Spalte muss in jedem UNION ALL Zweig einen eindeutigen konstanten numerischen oder Zeichenwert haben. Darüber hinaus muss die Markerspalte in der gleichen ordinalen Position in der SELECT Liste jedes Abfrageblocks erscheinen. Siehe «UNION ALL Marker und Abfrageumformung» für weitere Informationen zu UNION ALL Markern.
  • Einige Funktionen wie äußere Joins, nur Einfüge-Aggregate aus der Sicht der materiellen Abfragen und entfernte Tabellen werden für materielle Sichten mit UNION ALLnicht unterstützt. Beachten Sie jedoch, dass materielle Sichten, die in der Replikation verwendet werden und die keine Joins oder Aggregationen enthalten, schnell aktualisiert werden können, wenn UNION ALL oder entfernte Tabellen verwendet werden.
  • Der Kompatibilitäts-Initialisierungsparameter muss auf 9.2.0 oder höher eingestellt sein, um eine schnell aktualisierbare materielle Sicht zu erstellen. UNION ALL.

Ich möchte die Oracle-Anhänger nicht beleidigen, aber angesichts ihrer Liste von Einschränkungen entsteht der Eindruck, dass dieser Mechanismus nicht für den allgemeinen Gebrauch geschrieben wurde. Es sieht aus, als hätte eine große Zahl indischer Entwickler an verschiedenen Versionen gearbeitet, wobei jeder das beigetragen hat, was er konnte. Die Nutzung dieses Mechanismus für echte Logik gleicht dem Gehen durch ein Minenfeld. Jederzeit kann man auf eine der nicht offensichtlichen Einschränkungen stoßen. Wie dies funktioniert, ist ebenfalls eine eigene Frage, die jedoch den Rahmen dieses Artikels sprengt.

Microsoft SQL Server

Zusätzliche Anforderungen

Neben den SET-Optionen und den Anforderungen an deterministische Funktionen müssen die folgenden Anforderungen erfüllt sein:

  • Der Benutzer, der ausführt CREATE INDEX muss der Eigentümer der Ansicht sein.
  • Beim Erstellen des Index muss die IGNORE_DUP_KEY Option auf AUS (Standard-Einstellung) gesetzt sein.
  • Tabellen müssen mit zweigeteilten Namen referenziert werden, Schema.Tabellenname in der Definitionsansicht.
  • Benutzerdefinierte Funktionen, die in der Ansicht referenziert werden, müssen mit der WITH SCHEMABINDING Option erstellt werden.
  • Alle in der Ansicht referenzierten benutzerdefinierten Funktionen müssen mit zweigeteilten Namen referenziert werden, <schema>.<function>.
  • Die Datenzugriffseigenschaft einer benutzerdefinierten Funktion muss NO SQL, und die externe Zugriffs-Eigenschaft muss NEIN.
  • Gemeinsame Sprachlaufzeit (CLR)-Funktionen können in der Auswahlliste der Ansicht erscheinen, dürfen jedoch nicht Teil der Definition des Schlüsselindex der Gruppierung sein. CLR-Funktionen dürfen nicht in der WHERE-Klausel der Ansicht oder der ON-Klausel einer JOIN-Operation in der Ansicht erscheinen.
  • Die CLR-Funktionen und Methoden von benutzerdefinierten CLR-Typen, die in der Sichtdefinition verwendet werden, müssen die Eigenschaften wie in der folgenden Tabelle angegeben festgelegt haben.

    Eigenschaft
    Hinweis

    DETERMINISTIC = TRUE
    Muss ausdrücklich als Attribut der Microsoft .NET Framework-Methode deklariert werden.

    PRECISE = TRUE
    Muss ausdrücklich als Attribut der .NET Framework-Methode deklariert werden.

    DATA ACCESS = NO SQL
    Bestimmt durch Festlegen des DataAccess-Attributs auf DataAccessKind.None und des SystemDataAccess-Attributs auf SystemDataAccessKind.None.

    EXTERNAL ACCESS = NO
    Diese Eigenschaft ist standardmäßig auf NEIN für CLR-Routinen eingestellt.

  • Die Sicht muss unter Verwendung der WITH SCHEMABINDING Option erstellt werden.
  • Die Sicht darf nur Basis-Tabellen referenzieren, die sich in derselben Datenbank wie die Sicht befinden. Die Sicht darf keine anderen Sichten referenzieren.
  • Die SELECT-Anweisung in der Sichtdefinition darf folgende Transact-SQL-Elemente nicht enthalten:

    ANZAHL
    ROWSET-Funktionen (OPENDATASOURCE, OPENQUERY, OPENROWSET, UND OPENXML)
    OUTER Verknüpfungen (LEFT, RIGHT, oder FULL)

    Abgeleitete Tabelle (definiert durch Angabe einer SELECT Anweisung im FROM Abschnitt)
    Selbstverknüpfungen
    Spalten mithilfe von SELECT * oder SELECT

    .*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, oder DURCHSCHNITT
    Gemeinsame Tabellenausdrücke (CTE)

    float1, text, ntext, image, XML, oder filestream Spalten
    Unterabfrage
    OVER Abschnitt, der Rang- oder Aggregatfensterfunktionen enthält

    Volltextprädikate (CONTAINS, FREETEXT)
    SUMME Funktion, die einen nullable Ausdruck referenziert
    ORDER BY

    CLR benutzerdefinierte Aggregatfunktion
    TOP
    CUBE, ROLLUP, oder GROUPING SETS Operatoren

    MIN, MAX
    UNION, EXCEPT, oder INTERSECT Operatoren
    TABLESAMPLE

    Tabellenvariablen
    OUTER APPLY oder CROSS APPLY
    PIVOT, UNPIVOT

    Sparse-Spaltenmengen
    Inline (TVF) oder mehrstückige tabellenwertige Funktionen (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Die indizierte Sicht kann enthalten float Spalten; solche Spalten dürfen jedoch nicht im Schlüssel des Cluster-Indexes enthalten sein.

  • Wenn GROUP BY ist vorhanden, muss die DEFINITION DER SICHT enthalten COUNT_BIG(*) und darf nicht enthalten HAVING. Diese GROUP BY Einschränkungen gelten nur für die Definition der indizierten Sicht. Eine Abfrage kann eine indizierte Sicht in ihrem Ausführungsplan verwenden, auch wenn sie diese GROUP BY Einschränkungen nicht erfüllt.
  • Wenn die Sichtdefinition eine enthält GROUP BY In der Klausel kann der Schlüssel des einzigartigen, gruppierten Index nur auf die angegebenen Spalten verweisen. GROUP BY Klausel enthalten.
  • Hier sieht man, dass die Inder nicht angezogen wurden, da sie sich entschieden haben, nach dem Motto 'Wenig, aber gut' zu arbeiten. Das heißt, sie haben zwar mehr Minen auf dem Feld, aber deren Anordnung ist transparenter. Am meisten ärgert jedoch diese Einschränkung:

    Die Sicht darf nur Basis-Tabellen referenzieren, die sich in derselben Datenbank wie die Sicht befinden. Die Sicht darf keine anderen Sichten referenzieren.

    In unserer Terminologie bedeutet das, dass die Funktion nicht auf eine andere materialisierte Funktion zugreifen kann. Das schneidet die gesamte Ideologie im Keim ab.
    Diese Einschränkung (und die folgenden Texte) reduziert die Einsatzmöglichkeiten erheblich:

    Die SELECT-Anweisung in der Sichtdefinition darf folgende Transact-SQL-Elemente nicht enthalten:

    ANZAHL
    ROWSET-Funktionen (OPENDATASOURCE, OPENQUERY, OPENROWSET, UND OPENXML)
    OUTER Verknüpfungen (LEFT, RIGHT, oder FULL)

    Abgeleitete Tabelle (definiert durch Angabe einer SELECT Anweisung im FROM Abschnitt)
    Selbstverknüpfungen
    Spalten mithilfe von SELECT * oder SELECT

    .*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, oder DURCHSCHNITT
    Gemeinsame Tabellenausdrücke (CTE)

    float1, text, ntext, image, XML, oder filestream Spalten
    Unterabfrage
    OVER Abschnitt, der Rang- oder Aggregatfensterfunktionen enthält

    Volltextprädikate (CONTAINS, FREETEXT)
    SUMME Funktion, die einen nullable Ausdruck referenziert
    ORDER BY

    CLR benutzerdefinierte Aggregatfunktion
    TOP
    CUBE, ROLLUP, oder GROUPING SETS Operatoren

    MIN, MAX
    UNION, EXCEPT, oder INTERSECT Operatoren
    TABLESAMPLE

    Tabellenvariablen
    OUTER APPLY oder CROSS APPLY
    PIVOT, UNPIVOT

    Sparse-Spaltenmengen
    Inline (TVF) oder mehrstückige tabellenwertige Funktionen (MSTVF)
    OFFSET

    CHECKSUM_AGG

    OUTER JOINS, UNION, ORDER BY und andere sind nicht erlaubt. Es wäre wahrscheinlich einfacher gewesen, zu sagen, was verwendet werden kann, als was nicht erlaubt ist. Die Liste wäre wahrscheinlich viel kürzer gewesen.

    Zusammenfassend lässt sich sagen: Ein riesiger Satz von Einschränkungen in jeder (ich bemerke kommerziellen) DBMS vs. keine (außer einer logischen, nicht technischen) in der LGPL-Technologie. Es sollte jedoch beachtet werden, dass die Implementierung dieses Mechanismus in relationaler Logik etwas komplizierter ist als in der beschriebenen funktionalen.

    Implementierung

    Wie funktioniert das? Als 'virtuelle Maschine' wird PostgreSQL verwendet. Innen gibt es einen komplexen Algorithmus, der sich mit dem Aufbau von Abfragen beschäftigt. Hier ist der Quellcode. Und es handelt sich nicht nur um eine große Sammlung von Heuristiken mit einer Menge von If-Bedingungen. Wenn Sie also ein paar Monate Zeit haben, können Sie versuchen, sich mit der Architektur vertraut zu machen.

    Funktioniert das effizient? Ziemlich effizient. Leider ist es schwer, das zu beweisen. Ich kann nur sagen, dass im Durchschnitt Tausende von Anfragen in großen Anwendungen effizienter sind als bei einem guten Entwickler. Ein ausgezeichneter SQL-Programmierer kann jede Anfrage effizienter schreiben, aber bei einer Flut von Anfragen hat er einfach nicht die Motivation oder die Zeit dafür. Das Einzige, was ich als Beweis für die Effizienz anführen kann, ist, dass auf der Basis dieser Datenbank einige Projekte basieren. ERP-Systeme, in denen es Tausende von verschiedenen MATERIALIZED Funktionen gibt, mit Tausenden von Nutzern und Terabyte großen Datenbanken mit Hunderten von Millionen von Einträgen, die auf einem ganz normalen Dual-Prozessor-Server betrieben werden. Jeder, der möchte, kann die Effizienz überprüfen oder in Frage stellen, indem er die Plattform und PostgreSQL herunterlädt, das SQL-Logging aktiviert und versucht, die Logik und Daten dort anzupassen.

    In den folgenden Artikeln werde ich außerdem erklären, wie man Einschränkungen für Funktionen festlegen kann, wie man mit Sitzungen arbeitet, Änderungen vornimmt und vieles mehr.

    Quelle: habr.com

    Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster