Problem
In diesem Artikel konzentrieren wir uns auf die Demonstration der Tabellenpartitionierung. Die einfachste Erklärung für die Tabellenpartitionierung ist die Aufteilung großer Tabellen in kleine. Dieses Thema bietet Skalierbarkeit und Verwaltbarkeit.
Was ist Tabellenpartitionierung in SQL Server?
Angenommen, wir haben einen Tisch und er wächst von Tag zu Tag. In diesem Fall kann die Tabelle einige Probleme verursachen, die durch die unten definierten Schritte gelöst werden müssen:
- Pflege diese Tabelle. Es wird lange dauern und mehr Ressourcen (CPU, IO usw.) verbrauchen.
- Sichern.
- Sperrprobleme.
Aus oben genannten Gründen benötigen wir eine Tabellenpartitionierung. Dieser Ansatz hat die folgenden Vorteile:
- Verwaltungsfunktion:Wenn wir die Tabelle aufteilen, können wir jede Partition der Tabelle verwalten. Beispielsweise können wir nur eine Partition der Tabelle erstellen.
- Archivierungsfähigkeit:Einige Partitionen der Tabelle werden nur aus diesem Grund verwendet. Wir müssen diese Partition der Tabelle nicht sichern. Wir können eine Dateigruppensicherung verwenden und sie nur sichern, indem wir eine Partition der Tabelle ändern.
- Abfrageleistung:Der SQL Server-Abfrageoptimierer entscheidet sich für die Partitionsbeseitigung. Das bedeutet, dass SQL Server keine Suche nach der nicht verwandten Partition der Tabelle durchführt.
Vertikale und horizontale Tabellenpartitionierung in SQL Server
Tabellenpartitionierung ist ein allgemeines Konzept. Es gibt mehrere Partitionierungstypen, die für bestimmte Fälle funktionieren. Die wichtigsten und am weitesten verbreiteten sind die beiden Ansätze:vertikale Partitionierung und horizontale Partitionierung.
Die Besonderheiten jedes Typs spiegeln das Wesen einer Tabelle als Struktur wider, die aus Spalten und Zeilen besteht:
• Vertikale Partitionierung teilt die Tabelle in Spalten auf.
• Horizontale Partitionierung teilt die Tabelle in Zeilen auf.
Das typischste Beispiel für eine vertikale Tabellenpartitionierung ist eine Tabelle mit Mitarbeitern mit ihren Details – Namen, E-Mail-Adressen, Telefonnummern, Adressen, Geburtstage, Berufe, Gehälter und alle anderen Informationen, die möglicherweise benötigt werden. Ein Teil dieser Daten ist vertraulich. Außerdem benötigen die Betreiber in den meisten Fällen nur einige grundlegende Daten wie Namen und E-Mail-Adressen.
Durch die vertikale Partitionierung entstehen mehrere „engere“ Tabellen mit den notwendigen Daten zur Hand. Abfragen zielen nur auf einen bestimmten Teil ab. Auf diese Weise reduzieren Unternehmen die Belastung, beschleunigen die Aufgaben und stellen sicher, dass vertrauliche Daten nicht preisgegeben werden.
Die horizontale Tabellenpartitionierung führt dazu, dass eine allgemeine Tabelle in mehrere kleinere aufgeteilt wird, wobei jede Partikeltabelle die gleiche Anzahl von Spalten hat, aber die Anzahl von Zeilen geringer ist. Dies ist ein Standardansatz für übermäßig viele Tabellen mit chronologischen Daten.
Beispielsweise kann eine Tabelle mit den Daten für das ganze Jahr in kleinere Abschnitte für jeden Monat oder jede Woche unterteilt werden. Dann betrifft die Abfrage nur eine bestimmte kleinere Tabelle. Die horizontale Partitionierung verbessert die Skalierbarkeit für die Datenmengen mit ihrem Wachstum. Die partitionierten Tabellen bleiben kleiner und einfacher zu verarbeiten.
Jede Tabellenpartitionierung in SQL Server sollte mit Vorsicht betrachtet werden. Manchmal müssen Sie die Daten von mehreren partitionierten Tabellen gleichzeitig anfordern, und dann benötigen Sie JOINs in Abfragen. Außerdem kann die vertikale Partitionierung immer noch zu großen Tabellen führen, und Sie müssen sie weiter aufteilen. Bei Ihrer Arbeit sollten Sie sich auf die Entscheidungen für Ihre spezifischen Geschäftszwecke verlassen.
Nachdem wir nun das Konzept der Tabellenpartitionierung in SQL Server geklärt haben, ist es an der Zeit, mit der Demonstration fortzufahren.
Wir werden T-SQL-Skripte vermeiden und alle Schritte der Tabellenpartitionierung mit dem SQL Server-Partitionierungsassistenten handhaben.
Was benötigen Sie, um SQL-Datenbankpartitionen zu erstellen?
- WideWorldImporters-Beispieldatenbank
- SQL Server 2017 Developer Edition
Das folgende Bild zeigt uns, wie man eine Tabellenpartition entwirft. Wir werden eine Tabellenpartition nach Jahren erstellen und verschiedene Dateigruppen lokalisieren.
In diesem Schritt erstellen wir zwei Dateigruppen (FG_2013, FG_2014). Klicken Sie mit der rechten Maustaste auf eine Datenbank und klicken Sie dann auf die Registerkarte Dateigruppen.
Jetzt verbinden wir die Dateigruppen mit neuen PDF-Dateien.
Unsere Datenbankspeicherstruktur ist bereit für die Tabellenpartitionierung. Wir suchen die Tabelle, die partitioniert werden soll, und starten den Assistenten zum Erstellen von Partitionen.
Auf dem Screenshot unten wählen wir eine Spalte aus, auf die wir die Partitionsfunktion anwenden möchten. Die ausgewählte Spalte ist „Rechnungsdatum“.
Auf den nächsten beiden Bildschirmen werden wir eine Partitionsfunktion und ein Partitionsschema benennen.
Eine Partitionsfunktion definiert, wie die Partitionierung für die Zeilen [Sales].[Invoices] basierend auf der Spalte InvoiceDate durchgeführt wird.
Ein Partitionsschema definiert Zuordnungen für die Sales.Invoices-Zeilen zu Dateigruppen.
Weisen Sie die Partitionen Dateigruppen zu und legen Sie die Grenzen fest.
Left/Right Boundary definiert die Seite jedes Grenzwertintervalls, die links oder rechts sein kann. Wir werden solche Grenzen festlegen und auf Speicherplatz schätzen klicken. Diese Option liefert uns die Information über die Anzahl der Zeilen, die sich in den Grenzen befinden sollen.
Und schließlich wählen wir Sofort ausführen und klicken dann auf Weiter.
Sobald der Vorgang erfolgreich ist, klicken Sie auf Schließen.
Wie Sie sehen können, wurde unsere Sales.Invoices-Tabelle partitioniert. Diese Abfrage zeigt die Details der partitionierten Tabelle.
SELECT
OBJECT_SCHEMA_NAME(pstats.object_id) AS SchemaName
,OBJECT_NAME(pstats.object_id) AS TableName
,ps.name AS PartitionSchemeName
,ds.name AS PartitionFilegroupName
,pf.name AS PartitionFunctionName
,CASE pf.boundary_value_on_right WHEN 0 THEN 'Range Left' ELSE 'Range Right' END AS PartitionFunctionRange
,CASE pf.boundary_value_on_right WHEN 0 THEN 'Upper Boundary' ELSE 'Lower Boundary' END AS PartitionBoundary
,prv.value AS PartitionBoundaryValue
,c.name AS PartitionKey
,CASE
WHEN pf.boundary_value_on_right = 0
THEN c.name + ' > ' + CAST(ISNULL(LAG(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100)) + ' and ' + c.name + ' <= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100))
ELSE c.name + ' >= ' + CAST(ISNULL(prv.value, 'Infinity') AS VARCHAR(100)) + ' and ' + c.name + ' < ' + CAST(ISNULL(LEAD(prv.value) OVER(PARTITION BY pstats.object_id ORDER BY pstats.object_id, pstats.partition_number), 'Infinity') AS VARCHAR(100))
END AS PartitionRange
,pstats.partition_number AS PartitionNumber
,pstats.row_count AS PartitionRowCount
,p.data_compression_desc AS DataCompression
FROM sys.dm_db_partition_stats AS pstats
INNER JOIN sys.partitions AS p ON pstats.partition_id = p.partition_id
INNER JOIN sys.destination_data_spaces AS dds ON pstats.partition_number = dds.destination_id
INNER JOIN sys.data_spaces AS ds ON dds.data_space_id = ds.data_space_id
INNER JOIN sys.partition_schemes AS ps ON dds.partition_scheme_id = ps.data_space_id
INNER JOIN sys.partition_functions AS pf ON ps.function_id = pf.function_id
INNER JOIN sys.indexes AS i ON pstats.object_id = i.object_id AND pstats.index_id = i.index_id AND dds.partition_scheme_id = i.data_space_id AND i.type <= 1 /* Heap or Clustered Index */
INNER JOIN sys.index_columns AS ic ON i.index_id = ic.index_id AND i.object_id = ic.object_id AND ic.partition_ordinal > 0
INNER JOIN sys.columns AS c ON pstats.object_id = c.object_id AND ic.column_id = c.column_id
LEFT JOIN sys.partition_range_values AS prv ON pf.function_id = prv.function_id AND pstats.partition_number = (CASE pf.boundary_value_on_right WHEN 0 THEN prv.boundary_id ELSE (prv.boundary_id+1) END)
WHERE pstats.object_id = OBJECT_ID('Sales.Invoices')
ORDER BY TableName, PartitionNumber;
MS SQL Server-Partitionierungsleistung
Wir werden die Leistung von partitionierten und nicht partitionierten Tabellen für dieselbe Tabelle vergleichen. Verwenden Sie dazu die folgende Abfrage und aktivieren Sie Tatsächlichen Ausführungsplan einschließen.
DECLARE @Dt as date = '20131231'
SELECT COUNT(InvoiceDate)
FROM [Sales].[Invoices]
where InvoiceDate < @Dt
Wenn wir den Ausführungsplan untersuchen, stellen wir fest, dass er die Eigenschaften „Partitioniert“, „Tatsächliche Partitionsanzahl“ und „Tatsächlicher partitionierter Zugriff“ enthält.
Die Partitionierte Eigenschaft zeigt an, dass diese Tabelle für die Partition aktiviert ist.
Die Tatsächliche Partitionsanzahl Eigenschaft ist die Gesamtzahl der Partitionen, die von der SQL Server-Engine gelesen werden.
Der tatsächliche partitionierte Zugriff -Eigenschaft sind Partitionsnummern, die von der SQL Server-Engine bewertet werden. SQL Server eliminiert den Zugriff für andere Partitionen, was als Partitionsbeseitigung bezeichnet wird, und erzielt einen Vorteil bei der Abfrageleistung.
Sehen Sie sich nun den Ausführungsplan für nicht partitionierte Tabellen an.
Der Hauptunterschied zwischen diesen beiden Ausführungsplänen ist Anzahl gelesener Zeilen da diese Eigenschaft angibt, wie viele Zeilen für diese Abfrage gelesen werden. Wie Sie dem Komprimierungsdiagramm unten entnehmen können, sind die Werte der partitionierten Tabelle zu niedrig. Aus diesem Grund verbraucht es wenig IO.
Führen Sie als Nächstes die Abfrage aus und untersuchen Sie den Ausführungsplan.
DECLARE @DtBeg as date = '20140502'
DECLARE @DtEnd as date = '20140701'
SELECT COUNT(InvoiceDate)
FROM [Sales].[Invoices]
where InvoiceDate between @DtBeg and @DtEnd
Sperreneskalation auf Partitionsebene
Die Sperrenausweitung ist ein Mechanismus, der von SQL Server Lock Manager verwendet wird. Es sorgt dafür, dass eine Ebene von Objekten gesperrt wird. Wenn die Anzahl der zu sperrenden Zeilen zunimmt, ändert der Sperrmanager ein Sperrobjekt. Dies ist die Hierarchieebene der Sperrenausweitung „Zeile -> Seite -> Tabelle -> Datenbank“. In der partitionierten Tabelle können wir jedoch eine Partition sperren, da dies die Parallelität und Leistung erhöht. Die Standardstufe der Sperrenausweitung ist „TABLE“ in SQL Server.
Führen Sie die Abfrage mit der folgenden UPDATE-Anweisung aus.
BEGIN TRAN
DECLARE @Dt as date = '20131221'
UPDATE [Sales].[Invoices] SET CreditNoteReason = 'xxx' where InvoiceDate < @Dt
SP_LOCK
Das rote Kästchen definiert eine exklusive Sperre, die sicherstellt, dass nicht mehrere Aktualisierungen gleichzeitig an derselben Ressource vorgenommen werden können. Es kommt in der Rechnungen-Tabelle vor.
Jetzt werden wir den Eskalationsmodus für die Tabelle „Sales.Invoices“ festlegen, um sie zu automatisieren, und die Abfrage erneut ausführen.
ALTER TABLE Sales.Invoices SET (LOCK_ESCALATION = AUTO)
Nun definiert das rote Kästchen die exklusive Einrückungssperre, die angeforderte oder erworbene exklusive Sperren für einige Ressourcen in der Hierarchie unten schützt. In Kürze erlaubt uns diese Sperrebene, andere Partitionen von Tabellen zu aktualisieren oder zu löschen. Das bedeutet, dass wir ein weiteres Update starten oder eine andere Partition der Tabelle einfügen können.
In früheren Beiträgen haben wir auch das Problem des Wechselns zwischen Tabellenpartitionierung untersucht und eine exemplarische Vorgehensweise bereitgestellt. Diese Informationen können für Sie hilfreich sein, wenn Sie sich mit diesen Fällen befassen. Weitere Informationen finden Sie im Artikel.
Referenzen
- Sperrmodi
- Partitionierte Tabellen und Indizes