Planen der Übernahme von In-Memory-OLTP-Funktionen in SQL Server

Gilt für: SQL Server (alle unterstützten Versionen) Azure SQL Datenbank-Azure SQL Managed Instance

Dieser Artikel beschreibt, auf welche Weise sich die Übernahme von In-Memory-Funktionen auf andere Aspekte Ihres Geschäftssystems auswirkt.

A. Übernahme von In-Memory-OLTP-Funktionen

In den folgenden Unterabschnitten werden die Faktoren erläutert, die Sie berücksichtigen müssen, wenn Sie planen, In-Memory-Funktionen zu übernehmen und zu implementieren. Viele erläuternde Informationen finden Sie unter:

A.1 Erforderliche Komponenten

Eine erforderliche Komponente für die Verwendung der In-Memory-Funktionen kann die Edition oder Dienstebene des SQL-Produkts umfassen. Diese und andere erforderliche Komponenten finden Sie unter:

A.2 Prognose der Menge an aktivem Arbeitsspeicher

Verfügt Ihr System über genügend Arbeitsspeicher zur Unterstützung einer neuen speicheroptimierten Tabelle?

Microsoft SQL Server

Eine speicheroptimierte Tabelle mit 200 GB Daten erfordert mehr als 200 GB aktiven Arbeitsspeicher für deren Unterstützung. Vor der Implementierung einer speicheroptimierten Tabelle, die eine große Datenmenge enthält, müssen Sie die Menge an zusätzlichem aktiven Arbeitsspeicher prognostizieren, den Sie Ihrem Servercomputer möglicherweise hinzufügen müssen. Einen Leitfaden für die Schätzung finden Sie unter:

Azure SQL-Datenbank

Bei einer Datenbank, die im Clouddienst von Azure SQL-Datenbank gehostet wird, wirkt sich die ausgewählte Dienstebene auf die Menge an aktivem Arbeitsspeicher aus, die Ihre Datenbank verwenden darf. Sie sollten planen, die Speicherverwendung Ihrer Datenbank mithilfe einer Warnung zu überwachen. Einzelheiten dazu finden Sie unter:

Speicheroptimierte Tabellenvariablen

Eine Tabellenvariable, die als speicheroptimiert gilt, wird manchmal vor einer herkömmlichen #TempTable bevorzugt, die sich in der Datenbank tempdb befindet. Solche Tabellenvariablen können ohne das Verwenden signifikanter Mengen an aktivem Arbeitsspeicher erhebliche Leistungssteigerungen bieten.

A.3 Die Tabelle muss offline sein, um in „speicheroptimiert“ konvertiert zu werden

Einige Funktionen von ALTER TABLE sind für speicheroptimierte Tabellen verfügbar. Sie können jedoch keine ALTER TABLE-Anweisung ausgeben, um eine datenträgerbasierte Tabelle in eine speicheroptimierte Tabelle zu konvertieren. Stattdessen müssen Sie eine manuellere Vorgehensweise verwenden. Im Folgenden werden verschiedene Methoden zum Konvertieren Ihrer datenträgerbasierenden Tabelle in eine speicheroptimierte Tabelle beschrieben.

Manuelle Skripterstellung

Eine Möglichkeit, Ihre datenträgerbasierte Tabelle in eine speicheroptimierte Tabelle zu konvertieren, besteht darin, die erforderlichen Transact-SQL-Schritte selbst zu codieren.

  1. Halten Sie die Aktivität der Anwendung an.

  2. Führen Sie eine vollständige Sicherung durch.

  3. Benennen Sie Ihre datenträgerbasierte Tabelle um.

  4. Geben Sie eine CREATE TABLE-Anweisung aus, um Ihre neue speicheroptimierte Tabelle zu erstellen.

  5. Wählen Sie mithilfe einer untergeordneten SELECT-Anweisung Teilmengen aus Ihrer datenträgerbasierten Tabelle aus, um diese mithilfe von INSERT INTO in Ihre speicheroptimierte Tabelle einzufügen.

  6. Führen Sie die DROP-Anweisung für Ihre datenträgerbasierte Tabelle aus.

  7. Führen Sie eine weitere vollständige Sicherung durch.

  8. Setzen Sie die Aktivität der Anwendung fort.

Ratgeber für die Speicheroptimierung

Das Tool „Ratgeber für die Speicheroptimierung“ kann ein Skript generieren, um bei der Implementierung der Umkehrung einer datenträgerbasierten Tabelle in eine speicheroptimierte Tabelle zu helfen. Das Tool ist als Teil der SQL Server Data Tools (SSDT) installiert.

DACPAC-Datei

Sie können Ihre Datenbank direkt mithilfe einer von SSDT verwalteten DACPAC-Datei aktualisieren. In SSDT können Sie Änderungen an dem Schema angeben, das in der DACPAC-Datei codiert ist.

Sie arbeiten mit DACPAC-Dateien im Kontext eines Visual Studio-Projekts vom Typ Datenbank.

A.4 Leitfaden, um herauszufinden, ob In-Memory-OLTP-Funktionen für Ihre Anwendung geeignet sind

Einen Leitfaden, um herauszufinden, ob In-Memory-OLTP-Funktionen die Leistung Ihrer bestimmten Anwendung verbessern können, finden Sie unter:

B. Nicht unterstützte Funktionen

Funktionen, die in bestimmten In-Memory-OLTP-Szenarios nicht unterstützt werden, werden in folgendem Artikel beschrieben:

In den folgenden Unterabschnitten werden einige der wichtigeren, nicht unterstützten Funktionen hervorgehoben.

B.1 SNAPSHOT einer Datenbank

Nachdem eine speicheroptimierte Tabelle oder ein speicheroptimiertes Modul zum ersten Mal in einer gegebenen Datenbank erstellt wurde, kann niemals ein SNAPSHOT (Momentaufnahme) der Datenbank erstellt werden. Der spezifische Grund dafür ist der folgende:

  • Das erste speicheroptimierte Element macht es unmöglich, die letzte Datei der speicheroptimierten FILEGROUP je zu verwerfen, und
  • keine Datenbank, die eine Datei in der speicheroptimierten FILEGROUP hat, kann einen SNAPSHOT unterstützen.

Normalerweise kann ein SNAPSHOT für schnelle Testiterationen praktisch sein.

B.2 Datenbankübergreifende Abfragen

Speicheroptimierte Tabellen bieten keine Unterstützung für datenbankübergreifende Transaktionen. Innerhalb einer Transaktion oder Abfrage, die auf eine speicheroptimierte Tabelle zugreift, können Sie nicht gleichzeitig auf eine andere Datenbank zugreifen.

Tabellenvariablen sind nicht transaktional. Aus diesem Grund können speicheroptimierte Tabellenvariablen in datenbankübergreifenden Abfragen verwendet werden.

B.3 READPAST-Tabellenhinweis

Keine Abfrage kann den READPAST- Tabellenhinweis auf speicheroptimierte Tabellen anwenden.

Der READPAST-Hinweis ist hilfreich bei Szenarios, in denen mehrere Sitzungen jeweils auf den gleichen Satz von Zeilen zugreifen und diesen bearbeiten, sowie bei der Verarbeitung einer Warteschlange.

B.4 RowVersion, Sequence

  • In einer speicheroptimierten Tabelle kann keine Spalte für RowVersion markiert werden.

  • Ein SEQUENCE -Objekt kann nicht mit einer Einschränkung in speicheroptimierten Tabelle verwendet werden. Sie können keine z.B. keine DEFAULT-Einschränkung mit einer NEXT VALUE FOR-Klausel erstellen. SEQUENCE-Anweisungen können mit INSERT- und UPDATE-Anweisungen verwendet werden.

C. Administrative Wartung

Dieser Abschnitt beschreibt die Unterschiede in der Datenbankverwaltung bei der Verwendung von speicheroptimierten Tabellen.

C.1 Identity Seed Reset, Increment > 1

DBCC CHECKIDENT, um den Startwert einer IDENTITY-Spalte zu korrigieren, kann nicht für eine speicheroptimierte Tabelle verwendet werden.

Der Inkrementwert wird für eine IDENTITÄTSSPALTE in einer speicheroptimierten Tabelle auf genau 1 beschränkt.

C.2 DBCC CHECKDB kann keine speicheroptimierten Tabellen überprüfen

Der Befehl DBCC CHECKDB tut nichts, wenn sein Ziel eine speicheroptimierte Tabelle ist. Dies können Sie mithilfe der folgenden Schritte umgehen:

  1. Sichern Sie das Transaktionsprotokoll.

  2. Sichern Sie die Dateien in der speicheroptimierten FILEGROUP auf einem NULL-Gerät. Der Sicherungsvorgang ruft die Prüfsummenverifizierung auf.

    Wenn eine Beschädigung gefunden wird, fahren Sie mit den nächsten Schritten fort.

  3. Kopieren Sie Daten aus Ihren speicheroptimierten Tabellen in datenträgerbasierte Tabellen für die temporäre Speicherung.

  4. Stellen Sie die Dateien der speicheroptimierten FILEGROUP wieder her.

  5. Fügen Sie die Daten, die Sie in den datenträgerbasierten Tabellen temporär gespeichert haben, mithilfe der INSERT INTO-Anweisung in die speicheroptimierten Tabellen ein.

  6. Führen Sie eine DROP-Anweisung auf die datenträgerbasierten Tabellen aus, in denen die Daten temporär gespeichert waren.

D: Leistung

Dieser Abschnitt beschreibt Situationen, in denen die ausgezeichnete Leistung von speicheroptimierten Tabellen unterhalb des Gesamtpotenzials bleiben kann.

D.1 Index-Überlegungen

Alle Indizes für eine speicheroptimierte Tabelle werden von den tabellenbezogenen Anweisungen CREATE TABLE und ALTER TABLE erstellt und verwaltet. Sie können keine CREATE INDEX-Anweisung auf speicheroptimierte Tabellen anwenden.

Der herkömmliche B-Struktur-Nichtclusterindex ist häufig die sensible und einfache Wahl, wenn Sie zuerst eine speicheroptimierte Tabelle implementieren. Später, nachdem Sie gesehen haben, wie Ihre Anwendung ausgeführt wird, können Sie in Betracht ziehen, zu einem anderen Indextyp zu wechseln.

Hinweis

In der SQL Server-Dokumentation wird der Begriff „B-Struktur“ im Allgemeinen in Bezug auf Indizes verwendet. In Zeilenspeicherindizes implementiert SQL Server eine B+-Struktur. Dies gilt nicht für Columnstore-Indizes oder In-Memory-Datenspeicher. Weitere Informationen finden Sie im Leitfaden zur Architektur und zum Design von SQL Server-Indizes.

Zwei besondere Indextypen erfordern im Kontext einer speicheroptimierten Tabelle eine Erläuterung: Hashindizes und Columnstore-Indizes.

Eine Übersicht über Indizes bei speicheroptimierten Tabellen finden Sie unter:

Hashindizes

Hashindizes können das schnellste Format darstellen, um auf eine bestimmte Zeile mit ihrem exakten Primärschlüssel zuzugreifen, indem der „ = “-Operator verwendet wird.

  • Ungenaue Operatoren, z.B. „ != “, „ > “ oder „BETWEEN“ würden die Leistung beeinträchtigen, wenn Sie mit einem Hashindex verwendet werden.

  • Ein Hashindex stellt möglicherweise nicht die beste Wahl dar, wenn die Rate der Schlüsselwertduplizierung zu hoch wird.

  • Schützen Sie sich vor der Unterschätzung, wie viele Buckets Ihr Hashindex benötigen könnte, um lange Ketten innerhalb einzelner Buckets zu vermeiden. Einzelheiten dazu finden Sie unter:

Nicht gruppierte Columnstore-Indizes

Speicheroptimierte Tabellen bieten einen hohen Durchsatz von typischen Geschäftstransaktionsdaten, die wir im Paradigma als Onlinetransaktionsverarbeitung oder OLTPbezeichnen. Columnstore-Indizes bieten einen hohen Durchsatz von Aggregationen und ähnlichen Verarbeitungen, die wir als Analysenbezeichnen. In den vergangenen Jahren bestand die bestmögliche Methode, dem Bedarf von sowohl OLTP als auch Analysen gerecht zu werden, darin, über getrennte Tabellen mit intensiver Datenverschiebung und mit einem gewissen Grad an Datenduplizierung zu verfügen. Heutzutage ist eine einfachere Hybridlösung verfügbar, und zwar das Verfügen über einen Columnstore-Index in einer speicheroptimierten Tabelle.

  • Ein Columnstore-Index kann in einer datenträgerbasierten Tabelle erstellt werden, sogar als gruppierter Index. In einer speicheroptimierten Tabelle kann ein Columnstore-Index jedoch nicht gruppiert werden.

  • LOB-Spalten oder Spalten außerhalb von Zeilen verhindern in einer speicheroptimierten Tabelle die Erstellung eines Columnstore-Indizes in der Tabelle.

  • Es kann keine ALTER TABLE-Anweisung auf eine speicheroptimierte Tabelle ausgeführt werden, während ein Columnstore-Index in der Tabelle vorhanden ist.

    • Ab August 2016 plant Microsoft kurzfristig, die Leistung bei der Neuerstellung des Columnstore-Indizes zu verbessern.

D.2 LOB-Spalten und Spalten außerhalb von Zeilen

Large Objects (LOBs) sind Spalten von z.B. dem Typ varchar (max). Das Verfügen über eine Reihe von LOB-Spalten in einer speicheroptimierten Tabelle beeinträchtigt die Leistung wahrscheinlich nicht so sehr, dass es eine Rolle spielt. Verhindern Sie jedoch, mehr LOB-Spalten zu haben, als Ihre Daten benötigen. Der gleiche Rat gilt für Spalten außerhalb von Zeilen. Definieren Sie eine Spalte nicht als nvarchar(3072), wenn varchar(512) ausreichen würde.

Weitere Informationen zu LOB-Spalten und Spalten außerhalb von Zeilen finden Sie unter:

E. Einschränkungen von nativen Prozeduren

Bestimmte Elemente von Transact-SQL werden in nativ kompilierten T-SQL-Modulen, einschließlich gespeicherten Prozeduren, nicht unterstützt. Weitere Informationen darüber, welche Funktionen unterstützt werden, finden Sie im folgenden Artikel:

Überlegungen zur Migration eines Transact-SQL-Moduls, das nicht unterstützte Features verwendet, zu einem nativ kompilierten Transact-SQL-Modul, werden im folgenden Artikel erläutert:

Neben Einschränkungen für bestimmte Elemente von Transact-SQL gibt es auch Einschränkungen für Abfrageoperatoren, die in nativ kompilierten T-SQL-Modulen unterstützt werden. Aufgrund dieser Einschränkungen eignen sich nativ kompilierte gespeicherte Prozeduren nicht für analytische Abfragen, die große Datasets verarbeiten.

Keine parallele Verarbeitung in einer nativen Prozedur

Die Parallele Verarbeitung kann nicht Teil eines Abfrageplans für eine native Prozedur sein. Native Prozeduren sind immer auf einen Thread beschränkt.

Join-Typen

Weder ein Hashjoin noch ein Zusammenführungsjoin kann Teil eines Abfrageplans für eine native Prozedur sein. Joins geschachtelter Schleifen werden verwendet.

Keine Hashaggregation

Wenn der Abfrageplan für eine native Prozedur eine Aggregationsphase erfordert, steht nur die Stream-Aggregation zur Verfügung. Die Hashaggregation wird in einem Abfrageplan für eine native Prozedur nicht unterstützt.

  • Die Hashaggregation ist besser, wenn Daten aus einer großen Anzahl von Zeilen aggregiert werden müssen.

F. Anwendungsentwurf: Transaktionen und Wiederholungslogik

Eine Transaktion, die eine speicheroptimierte Tabelle umfasst, kann von einer anderen Transaktion abhängig werden, die die gleiche Tabelle umfasst. Wenn die Anzahl von abhängigen Transaktionen den zulässigen Höchstwert überschreitet, tritt bei allen abhängigen Transaktionen ein Fehler auf.

Bei SQL Server 2016:

  • beträgt das zulässige Maximum acht abhängige Transaktionen. Acht ist auch der Grenzwert von Transaktionen, von denen alle gegebenen Transaktionen abhängig sein können.
  • ist die Fehlernummer 41839 (In SQL Server 2014 ist die Fehlernummer 41301).

Sie können die Transact-SQL-Skripts stabiler gegenüber einem möglichen Transaktionsfehler machen, indem Sie die Wiederholungslogik zu Ihren Skripts hinzufügen. Die Wiederholungslogik hilft mit größerer Wahrscheinlichkeit, wenn UPDATE- und DELETE-Aufrufe häufig sind, oder wenn durch einen Fremdschlüssel in einer anderen Tabelle auf die speicheroptimierte Tabelle verwiesen wird. Einzelheiten dazu finden Sie unter: