Erstellen eines physischen Datenbankmodells: Leistungsdesign. Erstellen Sie ein physisches Datenbankmodell: Performance Design Partitionierungstabellen in SQL Server in

Guten Abend / Tag / Morgen lieber Habralyudi! Wir entwickeln und ergänzen den Blog über mein bevorzugtes Open Source rdbms Postgresql weiter. Wie durch ein Wunder ist es so gekommen, dass das Thema des heutigen Themas hier nie angesprochen wurde. Ich muss sagen, dass die Partitionierung in Postgresql sehr gut dokumentiert ist, aber wird mich das aufhalten?).

Einführung

Im Allgemeinen bedeutet Partitionierung im Allgemeinen keine Art von Technologie, sondern eher einen Ansatz für das Datenbankdesign, der lange vor der Unterstützung des sogenannten DBMS auftauchte. partitionierte Tabellen. Die Idee ist ganz einfach - die Tabelle in mehrere Teile zu unterteilen. kleiner... Es gibt zwei Unterarten - horizontale und vertikale Aufteilung.
Horizontale Unterteilung
Teile der Tabelle enthalten verschiedene Zeilen davon. Nehmen wir an, wir haben eine Protokolltabelle einer abstrakten Anwendung - LOGS. Wir können es in Teile aufteilen - einen für Januar 2009 Logs, einen anderen für Februar 2009 usw.
Vertikales Schneiden
Teile einer Tabelle enthalten verschiedene Spalten davon. Eine Anwendung für die vertikale Partitionierung zu finden (wenn es wirklich gerechtfertigt ist) ist etwas schwieriger als für die horizontale Partitionierung. Als kugelförmiges Pferd schlage ich vor, diese Option in Betracht zu ziehen: Die Tabelle NEWS hat die Spalten ID, SHORTTEXT, LONGTEXT, und das Feld LONGTEXT wird viel seltener verwendet als die ersten beiden. In diesem Fall ist es sinnvoll, die NEWS-Tabelle in Spalten aufzuteilen (zwei Tabellen für SHORTTEXT bzw. LONGTEXT erstellen, die über Primärschlüssel verknüpft sind + eine NEWS-View erstellen, die beide Spalten enthält). Wenn wir also nur eine Beschreibung der Nachrichten benötigen, muss das DBMS nicht den gesamten Nachrichtentext von der Festplatte lesen.
Partitionierungsunterstützung in modernen DBMS
Die meisten modernen DBMS unterstützen die Tabellenpartitionierung in der einen oder anderen Form.
  • Orakel- unterstützt Partitionierung seit Version 8. Einerseits ist das Arbeiten mit Abschnitten sehr einfach (man muss sich gar keine Gedanken machen, man arbeitet wie mit einer normalen Tabelle *), andererseits ist alles sehr flexibel. Abschnitte können in "Unterpartitionen" unterteilt, gelöscht, geteilt, verschoben werden. Es werden verschiedene Optionen zur Indizierung einer partitionierten Tabelle (globaler Index, partitionierter Index) unterstützt. Link zu einer umfangreichen Beschreibung.
  • Microsoft SQL Server - Unterstützung für die Partitionierung ist vor kurzem erschienen (im Jahr 2005). Der erste Gebrauchseindruck ist „Na endlich!! :)“, der zweite ist „Es funktioniert, alles scheint in Ordnung zu sein“. MSDN-Dokumentation
  • MySQL- unterstützt seit Version 5.1.
  • Usw…
* -Es ist natürlich eine Lüge, es gibt eine Reihe von Standardschwierigkeiten - rechtzeitig einen neuen Abschnitt zu erstellen, den alten wegzuwerfen usw., aber trotzdem ist alles irgendwie einfach und klar.

Partitionierung in Postgresql

Die Tabellenpartitionierung in postgresql unterscheidet sich in der Implementierung geringfügig von anderen Datenbanken. Die Grundlage für die Partitionierung ist die Tabellenvererbung (eine Besonderheit von postgresql). Das heißt, wir müssen eine Haupttabelle haben, und ihre Untertabellen werden ihre Abschnitte sein. Wir betrachten die Partitionierung am Beispiel eines realitätsnahen Problems.
Formulierung des Problems
Die Datenbank wird verwendet, um Daten über Besucher der Site / Sites zu sammeln und zu analysieren. Die Datenmengen sind groß genug, um eine Partitionierung in Betracht zu ziehen. In den meisten Fällen verwendet die Analyse Daten vom letzten Tag.
1. Erstellen Sie die Haupttabelle:
CREATE TABLE analytics.events

user_id UUID NICHT NULL,
event_type_id SMALLINT NICHT NULL,
event_time TIMESTAMP DEFAULT jetzt () NOT NULL,
URL VARCHAR (1024) NICHT NULL,
Referrer VARCHAR (1024),
ip INET NICHT NULL
);

2. Wir werden nach Tag gemäß dem Feld event_time partitionieren. Wir werden für jeden Tag einen neuen Abschnitt erstellen. Wir benennen die Abschnitte gemäß der Regel: analytics.events_DDMMJJJJ. Hier ist ein Beispielabschnitt für den 1. Januar 2010.
TABELLEN ERSTELLEN analytics.events_01012010
event_id BIGINT DEFAULT nextval ("analytics.seq_events") PRIMÄRSCHLÜSSEL,
PRÜFEN (event_time> = TIMESTAMP "2010-01-01 00:00:00" UND event_time< TIMESTAMP "2010-01-02 00:00:00" )
) INHERITS (analytics.events);

* Dieser Quellcode wurde mit Source Code Highlighter hervorgehoben.


Beim Erstellen eines Abschnitts setzen wir explizit das Feld event_id (PRIMARY KEY wird nicht vererbt) und erstellen eine CHECK CONSTRAINT für das Feld event_time, um nicht zu viel einzufügen.

3. Erstellen Sie einen Index für das Feld event_time. Bei der Aufteilung der Tabelle in Abschnitte gehen wir davon aus, dass die meisten Abfragen der Ereignistabelle die Bedingung für das Feld event_time verwenden, daher hilft uns ein Index für dieses Feld sehr.

CREATE INDEX events_01012010_event_time_idx ON analytics.events_01012010 USING btree (event_time);

* Dieser Quellcode wurde mit Source Code Highlighter hervorgehoben.


4. Wir möchten sicherstellen, dass die Daten beim Einfügen in die Haupttabelle in dem dafür vorgesehenen Abschnitt erscheinen. Dazu machen wir den folgenden Trick - wir erstellen einen Trigger, der den Datenfluss steuert.
FUNKTION ERSTELLEN ODER ERSETZEN analytics.events_insert_trigger ()
RÜCKGABETRIGGER ALS $$
START
WENN (NEUE .event_time> = TIMESTAMP "2010-01-01 00:00:00" UND
NEU .event_time< TIMESTAMP "2010-01-02 00:00:00" ) THEN
EINFÜGEN IN analytics.events_01012010 WERTE (NEU. *);
SONST
AUSNAHME ANHEBEN "Datum % liegt außerhalb des gültigen Bereichs. Analytics.events_insert_trigger reparieren", NEU .event_time;
ENDE WENN;
RÜCKGABE NULL;
ENDE;
$$
SPRACHE plpgsql;

* Dieser Quellcode wurde mit Source Code Highlighter hervorgehoben.


CREATE TRIGGER events_before_insert
VOR DEM EINFÜGEN AUF analytics.events
FÜR JEDE ZEILE AUSFÜHRUNGSVERFAHREN analytics.events_insert_trigger ();

* Dieser Quellcode wurde mit Source Code Highlighter hervorgehoben.

5. Alles ist fertig, wir haben jetzt eine partitionierte analytics.events-Tabelle. Wir können beginnen, ihre Daten wütend zu analysieren. Übrigens haben wir CHECK-Constraints nicht nur erstellt, um Abschnitte vor fehlerhaften Daten zu schützen. Postgresql kann sie beim Erstellen eines Abfrageplans verwenden (obwohl mit einem Live-Index auf event_time der Gewinn minimal ist), verwenden Sie einfach die Anweisung "constraint_exclusion":

SET Einschränkung_Ausschluss = on;
SELECT * FROM analytics.events WHERE event_time> CURRENT_DATE;

* Dieser Quellcode wurde mit Source Code Highlighter hervorgehoben.

Ende des ersten Teils
Was haben wir also? Kommen wir Punkt für Punkt:
1. Tabellenereignisse, unterteilt in Abschnitte, die Analyse der verfügbaren Daten für den letzten Tag wird einfacher und schneller.
2. Der Horror der Erkenntnis, dass all dies irgendwie unterstützt werden muss, um rechtzeitig Abschnitte zu erstellen und nicht zu vergessen, den Trigger entsprechend zu ändern.

Wie einfach und sorglos es ist, mit partitionierten Tabellen zu arbeiten, erzähle ich Ihnen im zweiten Teil.

UPD1: Partitionierung durch Partitionierung ersetzt
UPD2:
Gestützt auf die Bemerkung eines Lesers, der leider keinen Bericht über Habré hat:
Bei der Vererbung sind bei der Gestaltung mehrere Dinge zu beachten. Abschnitte erben nicht den Primärschlüssel und fremde Schlüssel auf ihren Spalten. Das heißt, wenn Sie einen Abschnitt erstellen, müssen Sie explizit PRIMARY KEY und FOREIGN KEYs für die Abschnittsspalten erstellen. Ich selbst stelle fest, dass das Erstellen eines FOREIGN KEY für die Spalten einer partitionierten Tabelle nicht der beste Weg ist. In den meisten Fällen ist eine partitionierte Tabelle eine "Faktentabelle" und bezieht sich selbst auf die "Dimension" der Tabelle.

Oracle DBMS kann Partitionsansichten... Die Grundidee ist einfach. Lassen Sie die physische Tabelle in mehrere Tabellen aufteilen (optional mit den Methoden Aufteilen Tabellen) nach dem Partitionierungskriterium, was die Abfrageverarbeitung effizienter macht. Das Teilungskriterium heißt Partitionierungsprädikat... Anschließend können Sie die Ansichten erstellen und anpassen, um dem Benutzer den Zugriff auf die Daten in diesen Tabellen zu erleichtern. Der Präsentationsbereich ist nach einem Wertebereich definiert Partitionierungsschlüssel... Abfragen, die einen Wertebereich verwenden, um Daten aus Abschnitten einer Ansicht abzurufen, greifen nur auf die Abschnitte zu, die den Wertebereichen entsprechen Partitionierungsschlüssel.

Ansichtsabschnitte können durch Prädikate definiert werden Aufteilen entweder durch eine CHECK-Einschränkung oder eine WHERE-Klausel angegeben. Wie sich beide Techniken anwenden lassen, zeigen wir am Beispiel der leicht modifizierten Sales-Tabelle, die wir im vorherigen Abschnitt betrachtet haben. Angenommen, die Verkaufsdaten für ein Kalenderjahr werden in vier separaten Tabellen gespeichert, die jeweils einem Quartal des Jahres entsprechen – Q1_Sales, Q2_Sales, Q3_Sales und Q4_Sales.

Beispiel 20.14.

Verwenden der CHECK-Einschränkung. Mit der Hilfe ALTER-Befehle TABLE können Sie der Spalte "Sale Date" (s_date) jeder Tabelle Einschränkungen hinzufügen, sodass ihre Zeilen einem der Quartale des Jahres entsprechen. Die erstellte Verkaufssicht ermöglicht es dann, auf diese Tabellen einzeln oder alle zusammen zu verweisen.

ALTER TABLE Q1_Sales ADD CONSTRAINT C0 CHECK (s_date BETWEEN "jan-1-2002" UND "mar-31-2002"); ALTER TABLE Q2_Sales ADD CONSTRAINT C1 CHECK (s_date ZWISCHEN "apr 1-2002" UND "jun-30-2002"); ALTER TABLE Q3_Sales ADD CONSTRAINT C2 check (s_date ZWISCHEN "Jul-1-2002" UND "Sep-30-2002"); ALTER TABLE Q4_Sales ADD CONSTRAINT C3 check (s_date BETWEEN "oct-1-2002" UND "dec-31-2002"); CREATE VIEW sales_v AS SELECT * FROM Q1_Sales UNION ALL SELECT * FROM Q2_Sales UNION ALL SELECT * FROM Q3_Sales UNION ALL SELECT * FROM Q4_Sales;

Der Vorteil davon Partitionieren von Ansichten ist, dass das CHECK-Einschränkungsprädikat nicht für jede Zeile der Abfrage ausgewertet wird. Solche Vergleichselemente schließen das Einfügen von Zeilen in Tabellen aus, die die Vergleichskriterien nicht erfüllen. Strings, die dem Prädikat entsprechen Aufteilen werden schneller aus der Datenbank abgerufen.

Beispiel 20.15.

Partitionieren von Ansichten mit der WHERE-Klausel. Erstellen wir eine Ansicht für dieselben Tabellen wie im obigen Beispiel.

CREATE VIEW sales_v AS SELECT * FROM Q1_Sales WHERE s_date ZWISCHEN "jan-1-2002" UND "mar-31-2002" UNION ALL SELECT * FROM Q2_Sales WHERE s_date ZWISCHEN "apr-1-2002" UND "jun-30-2002" UNION ALL SELECT * FROM Q3_Sales WHERE s_date ZWISCHEN "Jul-1-2002" UND "Sep-30-2002" UNION ALL SELECT * FROM Q4_Sales WHERE s_date ZWISCHEN "oct-1-2002" UND "dec-31-2002";

Methode Partitionieren von Ansichten Die Verwendung einer WHERE-Klausel hat einige Nachteile. Zuerst das Kriterium Aufteilen wird zur Laufzeit für alle Zeilen in allen Abschnitten überprüft, die von der Abfrage abgedeckt werden. Zweitens können Benutzer versehentlich eine Zeile in den falschen Abschnitt einfügen, d.h. Fügen Sie im dritten Quartal eine Zeile für das erste Quartal ein, was zu einer falschen Stichprobenziehung der Daten für diese Quartale führt.

Diese Technik hat einen Vorteil gegenüber der Verwendung der CHECK-Einschränkung. Sie können eine Klausel, die dem WHERE-Prädikat entspricht, in einer entfernten Datenbank platzieren. Ein Ausschnitt der Definition der Repräsentation ist unten angegeben.

Bei der Entscheidung zum Erstellen müssen Sie die folgenden Faktoren berücksichtigen.

  • und das Löschen von Daten, arbeiten auf Partitionsebene und nicht auf der gesamten Basistabelle.
  • Der Zugriff auf einen der Abschnitte hat keine Auswirkungen auf die Daten in anderen Abschnitten.
  • Oracle DBMS verfügt über die notwendigen integrierten Funktionen zur Erkennung von geteilte Ansichten.
  • Partitionieren von Ansichten sehr nützlich, wenn Sie mit Tabellen arbeiten, die große Menge historische Daten.

Partitionieren von Tabellen in MS SQL Server DBMS

Erstellen von partitionierten Tabellen

MS SQL Server DBMS unterstützt auch Partitionierung Tabellen, Indizes und Ansichten. Im Gegensatz zur Oracle-Familie von DBMS, Partitionierung in einem DBMS der MS SQL Server Familie erfolgt sie nach einem einheitlichen Schema.

Im MS SQL Server gelten alle Tabellen und Indizes in der Datenbank als partitioniert, auch wenn sie nur aus einer Partition bestehen. Tatsächlich sind Partitionen die grundlegende Organisationseinheit in der physischen Architektur von Tabellen und Indizes. Dies bedeutet, dass die logische und physische Architektur von Tabellen und Indizes mit mehreren Partitionen die Architektur von Tabellen und Indizes mit einer einzelnen Partition vollständig widerspiegelt.

Partitionierung Tabellen und Indizes sind auf Zeilenebene hartcodiert ( Partitionierung nach Spalten ist nicht zulässig) und ermöglicht den Zugriff über einen einzigen Einstiegspunkt (Tabellenname oder Indexname), sodass der Anwendungscode die Anzahl der Partitionen nicht kennen muss. Partitionierung kann sowohl für die Basistabelle als auch für die zugehörigen Indizes ausgeführt werden.

Jeder Wertebereich in einem Abschnitt hat Grenzen, die in der FOR VALUES-Anweisung definiert sind. Wenn das Verkaufsdatum der 23. Juni 2006 war, wird die Zeile in Abschnitt 2 (P2) gespeichert.

Jetzt erstellen wir Partitionierungsschema. Partitionierungsschema ordnet Abschnitte verschiedenen Dateigruppen zu (genannt MyFilegroup1, MyFilegroup2, MyFilegroup3, MyFilegroup4) wie im folgenden Befehl gezeigt:

PARTITION SCHEME ERSTELLEN MyPartitionScheme AS MyPartitionFunction TO (MyFilegroup1, MyFilegroup2, MyFilegroup3, MyFilegroup4)

MyPartitionScheme ist der Name Partitionierungsschemata und der Name MyPartitionFunction definiert Partitionierungsfunktion... Dieser Befehl zeigt Daten in Abschnitten an, die einer oder mehreren Dateigruppen zugeordnet sind. Zeilen mit Daten mit den Werten der Spalte "Verkaufsdatum" (Date_of_Event date) bis zum 01.01.05 sind MyFilegroup1 zugeordnet. Zeilen in dieser Spalte mit Werten größer oder gleich 01.01.05 und bis 01.01.07 werden MyFilegroup2 zugewiesen. Zeilen mit Werten größer oder gleich 01.01.07 und bis 01.01.09 sind MyFilegroup3 zugeordnet. Alle anderen Zeilen mit Werten größer oder gleich 01.01.09 sind mit MyFilegroup4 verknüpft.

Für jeden Satz von Grenzwerten (die durch die FOR VALUES . angegeben werden) Partitionierungsfunktionen) ist die Anzahl der Abschnitte gleich "Anzahl der Grenzwerte" + 1 Abschnitt. Die vorherige CREATE PARTITION SCHEME-Klausel enthält drei Einschränkungen und vier Abschnitte. Unabhängig davon, ob Partitionen mit RANGE RIGHT oder RANGE LEFT erstellt werden, beträgt die Anzahl der Partitionen immer "Number of Boundary Values" + 1, bis zu 1000 Partitionen pro Tabelle.

Wir können jetzt erstellen partitionierte Tabelle Verkaufsfakten (SALES). Kreatur partitionierte Tabelle unterscheidet sich nicht wesentlich vom Erstellen einer regulären Tabelle, Sie müssen sich nur auf den Namen beziehen Partitionierungsschemata im EIN-Zustand, wie im Befehl unten gezeigt.

CREATE TABLE SALES (Sales_WB Bigint-Identität (1, 1) primär nicht geclustert NOT NULL, Cust_ID bigint null, Prod_ID bigint null, Store_ID bigint null, REG_ID char (10) null, Time_of_Event time null, Menge integer nicht null, Amount dez (8 , 2) not null, Date_of_Event date NOT NULL) ON MyPartitionScheme (Date_of_Event)

Einen Namen angeben Partitionierungsschemata, gibt der Designer an, dass es sich bei dieser Tabelle um Indizes handelt. Dadurch kann der Designer die Indexstruktur basierend auf den partitionierten Daten und nicht auf allen Daten in der Tabelle entwerfen. Die Erstellung von partitionierten Indizes beinhaltet die Erstellung separater B-Trees auf den partitionierten Indizes. Durch das Aufteilen der Indizes werden kleinere Indizes erstellt, und Datenbankadministrator oder CD wird einfacher, sie beim Ändern, Hinzufügen und Löschen von Daten zu pflegen.

Beim Erstellen von partitionierten Indizes können Sie ausgerichtet oder nicht ausgerichtete Indizes... Ausgerichtete Indizes implizieren einen direkten Link zu den partitionierten Tabellendaten. Bei nicht ausgerichteten Indizes wird ein anderer ausgewählt. Partitionierungsschema.

Von diesen beiden Methoden wird ein ausgerichteter Index bevorzugt, der standardmäßig ausgewählt ist, wenn nach der Erstellung partitionierte Tabelle Indizes werden erstellt, ohne einen anderen anzugeben Partitionierungsschemata... Die Verwendung ausgerichteter Indizes bietet die Flexibilität, die Sie zum Erstellen benötigen zusätzliche Abschnitte in der Tabelle und ermöglicht es Ihnen auch, die Zugehörigkeit eines bestimmten Abschnitts in eine andere Tabelle zu übertragen. Um die meisten der damit verbundenen Aufgaben zu lösen Aufteilen, es reicht, Indizes zu beantragen Partitionierungsschema Tabellen.

Beispiel. 20.19.

Erstellen wir ein partitioniertes nicht gruppierter Index auf der aufgeteilt die Tabelle "Sales" (SALES) aus dem vorherigen Beispiel 20.18.

PARTITION SCHEME ERSTELLEN Index_primary_Left_Scheme ALS PARTITION Index_Left_Partition ALL TO ()

Führen wir nun den Befehl aus, um den Index wie unten gezeigt zu erstellen.

CREATE NONCLUSTERED INDEX cl_multiple_partition ON multiple_partition (Custom_ID) ON Index_primary_Left_Scheme (Custom_ID)

Darin nicht gruppierter Index als Indexschlüssel wird die Spalte „Kunden-ID“ (Cust_ID) verwendet, die nicht Partitionierungsschlüssel Verkaufstabellen (SALES).

Entscheidungen über Partitionierung von Indizes vom CD-Designer in der Designphase oder vom CD-Administrator in der CD-Betriebsphase akzeptiert. Der Zweck Partitionierung von Indizes besteht darin, entweder die Abfrageleistung sicherzustellen oder die Indexverwaltungsverfahren zu vereinfachen.

In diesem Artikel werde ich die Besonderheiten von Abfrageausführungsplänen beim Zugriff auf partitionierte Tabellen demonstrieren. Beachten Sie, dass es einen großen Unterschied zwischen partitionierten Tabellen (die nur in SQL Server 2005 verfügbar waren) und partitionierten Ansichten (die seit SQL Server 2000 verfügbar waren und immer noch in SQL Server 2005 und höher verfügbar sind) gibt. Ich werde die Besonderheiten von Abfrageplänen für partitionierte Ansichten in einem anderen Artikel demonstrieren.

Tabelle ansehen

Erstellen wir eine einfache partitionierte Tabelle:

Partitionsfunktion pf (int) als Bereich für Werte (0, 10, 100) erstellen

erstelle Partitionsschema ps als Partition pf all to ()

Tabelle erstellen t (a int, b int) auf ps (a)

Dieses Skript erstellt eine Tabelle mit vier Partitionen. SQL Server hat den IDs jeder der vier Partitionen Werte zugewiesen, wie in der Tabelle gezeigt:

PtnId Werte
1 t.a<= 0
2 0 < t.a <= 10
3 10 < t.a <= 100
4 100 < t.a

Sehen wir uns nun einen Plan für eine solche Abfrage an, die den Optimierer zwingen würde, einen Tabellenscan zu verwenden:


…… | –Konstanter Scan (WERTE: (((1)), ((2)), ((3)), ((4))))
…….| –Tabellenscan (OBJEKT: ([t]))

Im obigen Plan listet SQL Server explizit alle Abschnittsbezeichner in der Anweisung "Constant Scan" auf, die einen Tabellenscan implementiert und Daten an die Join-Anweisung für verschachtelte Schleifen liefert. Dabei ist zu beachten, dass der Nested-Loop-Join-Operator die innere Tabelle (in diesem Fall einen vollständigen Tabellenscan) einmal für jeden Wert aus der äußeren Tabelle (in unserem Fall "Konstanter Scan") durchläuft. Daher scannen wir die Tabelle viermal; einmal für jede Abschnittskennung.

Es sollte auch beachtet werden, dass das Verbinden von verschachtelten Schleifen deutlich zeigt, dass die äußere Tabelle die Werte der Spalte ist, in der die Abschnitts-IDs gespeichert sind. Während dies in der textuellen Darstellung des Ausführungsplans nicht sofort sichtbar ist (leider bemerken wir diese Informationen manchmal nicht), verwendet der Tabellenscan eine Spalte mit Abschnitts-IDs, die ausgewählt werden, um den Scan durchzuführen und zu bestimmen, welcher Abschnitt gescannt werden soll. Diese Informationen sind immer im grafischen Ausführungsplan (Sie müssen sich die Eigenschaften des Tabellenansichtsoperators ansehen) sowie in der XML-Darstellung des Abfrageausführungsplans verfügbar:

Statische Abschnittsfilterung

Betrachten Sie die folgende Abfrage:

wähle * von t wobei a< 100

| –Verschachtelte Schleifen (Inner Join, OUTER REFERENCES :() PARTITION ID :())
……. | –Konstanter Scan (WERTE: (((1)), ((2)), ((3))))
<(100)) PARTITION ID:())

Das Prädikat "a<100» явно исключает все строки для секции со значением идентификатора равным 4. В данном случае, нет смысла в просмотре соответствующей секции, поскольку ни одна из строк этой секции не удовлетворяет условию предиката. Оптимизатор учитывает этот факт и исключает эту секцию из плана исполнения запроса. В операторе «Constant Scan» указаны только три секции. У нас принято называть это статической фильтрацией секций (static partition elimination), поскольку мы знаем, что во время компиляции список просматриваемых секций остаётся статичным.

Wenn aufgrund der statischen Filterung alle Partitionen bis auf eine ausgeschlossen werden, benötigen wir die Operatoren "Konstanter Scan" und "Nested Loops Join" überhaupt nicht:

wähle * von t wobei a< 0

| –Tabellenscan (OBJEKT: ([t]), WO: ([t]. [A]<(0)) PARTITION ID:((1)))

Beachten Sie, dass der Hinweis "PARTITION ID: ((1))", der die ID des zu scannenden Abschnitts angibt, jetzt Teil der Table Scan-Anweisung ist.

Dynamische Abschnittsfilterung

In einigen Fällen kann SQL Server nicht feststellen, dass sich die Zusammensetzung der angezeigten Abschnitte zum Zeitpunkt der Kompilierung nicht ändert, aber es kann erkennen, dass einige Abschnitte ausgeschlossen werden können.

wähle * von t wobei a< @i

| –Verschachtelte Schleifen (Inner Join, OUTER REFERENCES :() PARTITION ID :())
……. | –Filter (WO :(<=RangePartitionNew([@i],(0),(0),(10),(100))))
……. | | –Konstanter Scan (WERTE: (((1)), ((2)), ((3)), ((4))))
……. | –Tabellenscan (OBJEKT: ([t]), WO: ([t]. [A]<[@i]) PARTITION ID:())

Dies ist eine parametrisierte Abfrage. Da wir den Wert des Parameters vor der Ausführung nicht kennen (die Tatsache, dass ich eine Konstante als Parameter im selben Batch verwende, ändert nichts am Sachverhalt), ist es in der Kompilierungsphase unmöglich, den Wert des Abschnitts zu bestimmen Kennung für den Operator "Konstanter Scan". Möglicherweise müssen Sie sich nur Abschnitt 1 ansehen, oder es werden die Abschnitte 1 und 2 usw. Daher gibt diese Anweisung alle vier Abschnitts-IDs an, und wir verwenden die Filterung von Abschnitts-IDs zur Laufzeit. Wir nennen dies dynamische Partitionsbeseitigung.

Der Filter vergleicht jede Abschnittskennung mit dem Ergebnis der Sonderfunktion "RangePartitionNew". Diese Funktion berechnet die Ergebnisse der Anwendung der Partitionierungsfunktion auf den Parameterwert. Die Argumente für diese Funktion (von links nach rechts) sind:

  • der Wert (in diesem Fall der @i-Parameter), den wir in der Abschnitts-ID anzeigen möchten;
  • ein boolesches Flag, das angibt, ob die Partitionierungsfunktion Grenzwerte links (0) oder rechts (1) anzeigt;
  • Grenzwerte von Abschnitten (in diesem Fall sind es 0, 10 und 100).

Da @i in diesem Beispiel 0 ist, ist das Ergebnis von "RangePartitionNew" 1. Somit sehen wir nur den Abschnitt mit der ID 1. Beachten Sie, dass wir im Gegensatz zum statischen Abschnittsfilterungsbeispiel nur einen Abschnitt scannen, aber - wir haben noch "Constant Scan" und "Nested Loops Join". Wir brauchen diese Operatoren, weil wir die Abschnitte nicht kennen, die vor der Ausführungsphase gescannt werden.

In einigen Fällen kann der Optimierer bereits zur Kompilierzeit feststellen, dass wir nur einen Abschnitt scannen, auch wenn er nicht feststellen kann, welchen. Wenn eine Abfrage beispielsweise ein Partitionierungsschlüssel-Äquivalenzprädikat verwendet, wissen wir, dass nur eine Partition diese Bedingung erfüllen kann. Daher benötigen wir trotz der Tatsache, dass wir eine dynamische Filterung von Abschnitten haben mussten, die Operatoren "Constant Scan" und "Nested Loops Join" nicht. Beispiel:

wähle * aus t wobei a = @i

| –Table Scan (OBJEKT: ([t]), WO: ([t]. [A] = [@ i]) PARTITION ID: (RangePartitionNew ([@ i], (0), (0), (10 ),(100))))

Kombination aus statischer und dynamischer Abschnittsfilterung

SQL Server kann statische und dynamische Partitionsfilterung in einem einzigen Abfrageplan kombinieren:

wähle * aus t wobei a> 0 und a< @i

| –Verschachtelte Schleifen (Inner Join, OUTER REFERENCES :() PARTITION ID :())
…… | –Filter (WO :(<=RangePartitionNew([@i],(0),(0),(10),(100))))
…… | | –Konstanter Scan (WERTE: (((2)), ((3)), ((4))))
…… | –Tabellenscan (OBJEKT: ([t]), WO: ([t]. [A]<[@i] AND [t].[a]>(0)) PARTITIONS-ID :())

Beachten Sie, dass im letzteren Plan eine statische Filterung des Abschnitts ID = 1 mit "Konstanter Scan" und eine dynamische Filterung für andere durch die Prädikate definierte Abschnitte vorhanden ist.

$-Partition

Sie können die RangePartitionNew-Funktion explizit mit $ partition aufrufen:

wähle *, $ partition.pf (a) von t

| –Skalar berechnen (DEFINE: (= RangePartitionNew ([t]. [A], (0), (0), (10), (100))))
…… | –Nested Loops (Inner Join, OUTER REFERENCES :() PARTITION ID :())
……… .. | –Konstanter Scan (WERTE: (((1)), ((2)), ((3)), ((4))))
……… .. | –Tabellenscan (OBJEKT: ([t]))

Ein charakteristisches Merkmal eines solchen Abfrageausführungsplans ist das Erscheinungsbild des Compute Scalar-Operators.

Weitere Informationen

Unter modernen Bedingungen ist es manchmal sehr seltsam zu hören "Wir müssen die 1C-Datenbank minimieren - ihr Volumen überschreitet 50 GB". Würden die Administratoren von SAP R3 oder Oracle e Business Suite oder sogar MS Dynamics Ax dies tun, würden sie wahrscheinlich gefeuert. Trotzdem ist es für 1C "Standard-Praxis".

Bei Dateiversionen geht die Geschichte zurück auf Version 1C 7.7 mit einer Begrenzung von 2 GB für die Größe der Datenbank. Jetzt gilt die 2GB-Grenze nur noch für die Größe der Tabelle, die Dateigröße kann schon sehr, sehr klein ausfallen. Stimmt, wenn Ihre Datenbank auf diese Größe angewachsen ist, wurden dort wahrscheinlich Daten aktiv eingegeben - vielleicht müssen Sie über einen Client-Server nachdenken?

Tatsächlich besteht der Zweck dieses Artikels darin, Benutzer der Client-Server-Version von 1C davon abzuhalten, Datenbankfaltungen durchzuführen, indem etwas "fortgeschrittenere" Technologien verwendet werden.

Die endgültige Zahl beträgt 30-40 Tonnen, mindestens 20-25, wenn Sie eine Festplatte kaufen und 500 GB zusätzlichen Speicherplatz erhalten

Daher sind Produkte wie
Wahrscheinlich gute Produkte, und erfüllen ihre Ziele. Die Struktur der Tabellen ändert sich jedoch von Version zu Version der Plattform. 1C wurde uns mehr als einmal davon erzählt. Das Datentrennzeichen erschien in der 14. Version und das war's ... höchstwahrscheinlich wird diese Verarbeitung für die 14. Version nicht mehr funktionieren. Ja, und irgendwie beängstigend, ganz zu schweigen von der Verletzung der Lizenzvereinbarung.

Und selbst danach wird es Benutzer geben, die gelöschte Daten "plötzlich plötzlich brauchten", die "nur" eine Nummer korrigieren wollten, die "die Reihenfolge nicht beeinflusst" im Dokument des geschlossenen Zeitraums. Und es ist noch schlimmer, wenn sich herausstellt, dass jemand diese Dokumente ständig zu einem nur ihm bekannten Zweck ansieht. Natürlich sind dies alles nur Fehler in der Arbeitsweise, aber dennoch wird es zu Unzufriedenheit der Benutzer kommen.


-
Öffnen Sie Management Studio in der Liste der Datenbanken, wählen Sie die gewünschte aus, öffnen Sie ihre Eigenschaften.
- Gehen Sie wie in der Abbildung gezeigt zur Registerkarte "Dateigruppen" und fügen Sie eine weitere Dateigruppe hinzu (z. B. heißt sie SECONDARY).

- Gehen Sie auf die Registerkarte "Dateien" und fügen Sie eine neue Datei hinzu, für die wir die erstellte Dateigruppe auswählen. Diese Datei KANN AUF EINER ANDEREN DISK POSITIONIERT WERDEN


-
Nun zum Beispiel mit der Verarbeitung: Wir bestimmen, welche Tabellen wir sicher an ein langsameres (naja, oder umgekehrt, alles an ein langsameres, den Rest - an ein schnelleres) Medium "spenden" können. Hier gilt die 80/20-Regel. 80 % der Operationen werden mit 20 % der Daten durchgeführt, also überlegen Sie, welche Platten Sie schnell brauchen und welche nicht sehr gut sind. "Speicherung von Zusatzinformationen", Belege zur Erfassung von Anfangssalden, Belege, die Sie nicht mehr sofort verwenden, definieren als solche, die in die Dateigruppe "langsam" übernommen werden können.

Wählen Sie die Tabelle aus, die Sie in eine andere Dateigruppe übertragen möchten - wählen Sie das Menü zum Ändern der Tabelle (Projekt) und ändern Sie die Dateigruppe in den Eigenschaften:

auch die Indizes der Tabelle werden in diese Dateigruppe übertragen.
Ein ziemlich praktischer Mechanismus zum Verteilen von Tabellen über ein Disk-Array mit unterschiedlichen Geschwindigkeiten. Dies widerspricht nicht der Lizenzvereinbarung, da in der Lösung verwenden wir keinen anderen Zugang zu Daten und zur Informationsbasis als die 1C-Plattform. Wir werden die Speicherung dieser Daten nur in bequemer Weise organisieren.


DBCC-TRACEON (1807)

Wir schreiben diesen Befehl in Management Studio, führen ihn aus und können erfolgreich Datenbanken über das Netzwerk erstellen. Natürlich muss in diesem Fall die Instanz von SQL Server unter einem Domänenkonto ausgeführt werden und dieses Konto muss über Rechte auf den erforderlichen Netzwerkordner verfügen.
Seien Sie jedoch bei der Verwendung dieses Befehls sehr vorsichtig, falls Ihr Netzwerk während der Arbeit mit einer Datenbank verloren geht, die gesamte Datenbank während ihrer Abwesenheit nicht verfügbar ist. Microsoft hat diese Möglichkeit aus einem bestimmten Grund für die Massennutzung geschlossen. Im Allgemeinen soll diese Funktion Datenbanken auf NAS-Speichern erstellen, was ich sehr empfehle. Auch ein stabiler und zuverlässiger Dateiserver mit direkter Verbindung zum Server mit MS SQL DBMS ist geeignet.
Weitere Details zu anderen Ablaufverfolgungsflags finden Sie im Artikel http://msdn.microsoft.com/ru-ru/library/ms188396.aspx
Jene. ein Teil der Dateigruppe kann im Allgemeinen im Netzwerk gespeichert werden, und selbst dort erweitert sich der Speicherplatz problemlos.

Tabellen in verschiedene Dateigruppen zu unterteilen ist sicherlich gut ... aber Sie werden sagen, dass es hier ein paar Tabellen gibt ... die seit 2005 bestehen ... und bereits ein Dutzend Gigabyte belegen ... wenn wir nur könnten legen Sie alle Daten in sie und legen Sie eine separate Festplatte und aktuellen Urlaub.
Ob Sie es glauben oder nicht, auch dies ist möglich, wenn auch nicht ganz einfach:

Erstellen Sie eine Datumspartitionierungsfunktion:

Partitionsfunktion YearSection erstellen (datetime)
als Bereichsrecht für Werte ("20110101");

Alles vor 2011 wird in einen Abschnitt fallen, alles nach dem - in einen anderen.

Erstellen Sie ein Partitionierungsschema

Partitionsschema erstellen YearScheme
als Partition YearSection to (SECONDARY, PRIMARY);

Damit sagen wir, dass alle Daten bis zu einem Alter von 11 Jahren in die Dateigruppe "Sekundär" fallen und danach - in die Dateigruppe "Primär".

Jetzt bleibt die Tabelle mit der Unterteilung in Abschnitte neu aufzubauen. Am einfachsten geht das über das Management Studio, denn der Prozess ist nicht einfach. Sie müssen den Clustered-Index für die Tabelle (der eigentlich die Tabelle selbst ist) neu erstellen, indem Sie das Partitionierungsschema auswählen, das Sie für den Index erstellt haben:

In der Abbildung sehen Sie, dass die Auswahl nicht verfügbar ist - alles ist korrekt, Die Partitionierung von Tabellen ist nur in der Enterprise MS SQL Server-Version möglich... Der Clusterindex ist leicht zu unterscheiden - ein Bild mit Klammern. Es wird für den PH und alle 1C-Objekte erstellt. Für PH gibt es immer einen gruppierten Index nach Zeitraum. Für Dokumente und Verzeichnisse wäre es natürlich schön, ein weiteres zu erstellen, das die Voraussetzung enthält, für die die Partitionierung erfolgen soll ... aber dies ist bereits ein Verstoß gegen die Lizenzvereinbarung.

Dafür müssen Sie die Basis jedoch nicht einklappen, sondern gehen Sie wie folgt vor:
a) Erklären Sie allen, wie Auswahlen verwendet werden, wie sie gespeichert werden, wie Protokollintervalle verwendet werden, wie sie gespeichert werden
b) Markieren Sie unnötige Daten zum Löschen, wenn sie keine semantische Last tragen (Gegenparteien und Nomenklaturen, mit denen Sie nicht viel arbeiten) - dies bringt den Benutzern mehr Nutzen als das Falten. Wenn Ressourcen verfügbar sind, automatische Markierung zum Löschen nicht verwendeter Objekte einrichten und im Programmcode eine Standardauswahl treffen, damit Objekte, die von Benutzern nicht benötigt werden, nicht standardmäßig angezeigt werden - zum Löschen markiert
c) Konfigurieren Sie weitere nützliche "Standardfilter" - zum Beispiel damit jeder Manager standardmäßig nur seine eigenen Dokumente sieht. Und wenn er die Dokumente des "Kameraden" sehen möchte, müssen Sie die Auswahl deaktivieren.

Vergessen Sie bei allen Anforderungen, die an der Auswahl beteiligt sind, nicht, das Flag "Index mit zusätzlicher Bestellung" zu setzen - dann wird dieser "Komfort" die Systemleistung nicht beeinträchtigen.

Fortsetzung des Themas:
Router

Standard-Gadgets sind bedingungslos aus modernen Versionen von Windows OC verschwunden. Aber die Benutzer sind es nicht gewohnt, etwas Gutes zu verlieren und verwenden daher aktiv Analoga. Lange bevor ...