Einführung in speicheroptimierte Tabellen

Gilt für:SQL ServerAzure SQL-DatenbankAzure SQL Managed Instance

Speicheroptimierte Tabellen werden mit CREATE TABLE (Transact-SQL) erstellt.

Speicheroptimierte Tabellen sind standardmäßig vollständig dauerhaft und bieten, wie Transaktionen in (herkömmlichen) datenträgerbasierten Tabellen, vollständige ACID-Eigenschaften (Atomarität, Konsistenz, Isolation, Dauerhaftigkeit). Speicheroptimierte Tabellen und nativ kompilierte gespeicherte Prozeduren unterstützen nur eine Teilmenge der Transact-SQL-Features.

Ab SQL Server 2016 und in der Azure SQL-Datenbank gibt es keine Einschränkungen für Sortierungen oder Codepages , die spezifisch für In-Memory OLTP sind.

Beim Primärspeicher für speicheroptimierte Tabellen handelt es sich um den Hauptspeicher. Zeilen in der Tabelle werden aus dem Arbeitsspeicher gelesen und in diesen geschrieben. Eine zweite Kopie der Tabellendaten wird auf Festplatte gespeichert, aber nur zu Dauerhaftigkeitszwecken. Weitere Informationen zu dauerhaften Tabellen finden Sie unter Erstellen und Verwalten von Speicher für arbeitsspeicheroptimierte Objekte . Daten in speicheroptimierten Tabellen werden während der Datenbankwiederherstellung nur vom Datenträger gelesen (z. B. nach einem Serverneustart).

Noch deutlichere Leistungsverbesserungen werden bei In-Memory OLTP durch die Unterstützung von dauerhaften Tabellen mit verzögerter Transaktionsdauerhaftigkeit erzielt. Verzögerte dauerhafte Transaktionen werden kurz nach dem Commit der Transaktion und nach der Rückgabe der Steuerung an den Client auf dem Datenträger gespeichert. Im Austausch für die höhere Leistung besteht die Gefahr, dass Transaktionen, die noch nicht auf dem Datenträger gespeichert wurden, bei einem Absturz oder Failover des Servers verloren gehen.

Neben den standardmäßigen dauerhaften speicheroptimierten Tabellen unterstützt SQL Server auch nicht dauerhafte speicheroptimierte Tabellen, die nicht protokolliert werden und ihre Daten nicht auf dem Datenträger gespeichert werden. Das bedeutet, dass Transaktionen in diesen Tabellen keine Datenträger-E/A-Vorgänge erfordern, die Daten aber bei einem Serverabsturz oder einem Failover nicht wiederhergestellt werden können.

In-Memory OLTP ist in SQL Server integriert, um eine nahtlose Erfahrung in allen Bereichen wie Entwicklung, Bereitstellung, Verwaltbarkeit und Unterstützung zu bieten. Eine Datenbank kann speicherinterne wie auch datenträgerbasierte Objekte enthalten.

Für Zeilen in speicheroptimierten Tabellen wird die Versionsverwaltung verwendet. Dies bedeutet, dass für jede Zeile in der Tabelle möglicherweise mehrere Versionen vorliegen. Alle Zeilenversionen werden in derselben Tabellendatenstruktur verwaltet. Die Zeilenversionsverwaltung wird verwendet, um gleichzeitige Lese- und Schreibvorgänge für dieselbe Zeile zuzulassen. Weitere Informationen zu gleichzeitigen Lese- und Schreibvorgängen für die gleiche Zeile finden Sie unter Transactions with Memory-Optimized Tables(Transaktionen mit speicheroptimierten Tabellen).

Die folgende Abbildung veranschaulicht die Multiversionsverwaltung. Die Abbildung zeigt eine Tabelle mit drei Zeilen, und jede Zeile weist unterschiedliche Versionen auf.

Multi-versioning.

Die Tabelle enthält drei Zeilen: r1, r2 und r3. r1 verfügt über drei Versionen, r2 über zwei Versionen und r3 über vier Versionen. Beachten Sie, dass unterschiedliche Versionen derselben Zeile nicht unbedingt aufeinander folgende Speicheradressen belegen. Die unterschiedlichen Zielversionen können über die Tabellendatenstruktur verteilt sein.

Die speicheroptimierte Tabellendatenstruktur kann als Auflistung von Zeilenversionen gesehen werden. Während Zeilen in datenträgerbasierten Tabellen in Seiten und Blöcken angeordnet sind und einzelne Zeilen mithilfe der Seitenzahl und des Seitenoffsets adressiert werden, werden Zeilenversionen in speicheroptimierten Tabellen mithilfe von 8-Byte-Speicherzeigern adressiert.

Der Datenzugriff in speicheroptimierten Tabellen erfolgt auf zwei Arten:

  • Durch systemintern kompilierte gespeicherte Prozeduren

  • Durch interpretierte Transact-SQL außerhalb einer nativ kompilierten gespeicherten Prozedur. Diese Transact-SQL-Anweisungen können entweder innerhalb interpretierter gespeicherter Prozeduren oder ad-hoc Transact-SQL-Anweisungen sein.

Zugriff auf Daten in speicheroptimierten Tabellen

Auf speicheroptimierte Tabellen kann am effizientesten mit systemintern kompilierten gespeicherten Prozeduren (Systemintern kompilierte gespeicherte Prozeduren) zugegriffen werden. Auf speicheroptimierte Tabellen kann auch mit (traditionell) interpretierten Transact-SQL zugegriffen werden. Interpretierte Transact-SQL bezieht sich auf den Zugriff auf speicheroptimierte Tabellen ohne eine systemeigene kompilierte gespeicherte Prozedur. Einige Beispiele für interpretierten Transact-SQL-Zugriff sind der Zugriff auf eine speicheroptimierte Tabelle über einen DML-Trigger, ad-hoc Transact-SQL-Batch, ansichts- und tabellenwertige Funktion.

In der folgenden Tabelle sind systemeigene und interpretierte Transact-SQL-Zugriffe für verschiedene Objekte zusammengefasst.

Feature Zugriff mithilfe einer systemintern kompilierten gespeicherten Prozedur Interpretierter Transact-SQL-Zugriff CLR-Zugriff
Speicheroptimierte Tabelle Ja Ja Nein*
Speicheroptimierter Tabellentyp Ja Ja Nein
Systemintern kompilierte gespeicherte Prozedur Das Schachteln von systemintern kompilierten gespeicherten Prozeduren wird jetzt unterstützt. Sie können in gespeicherten Prozeduren die EXECUTE-Syntax verwenden, solange die Prozedur, auf die verwiesen wird, ebenfalls systemintern kompiliert wird. Ja Nein*

*Sie können nicht über die Kontextverbindung (die Verbindung von SQL Server beim Ausführen eines CLR-Moduls) auf eine speicheroptimierte Tabelle oder eine systemeigene gespeicherte Prozedur zugreifen. Sie können jedoch eine andere Verbindung erstellen und öffnen, über die Sie auf speicheroptimierte Tabellen und systemintern kompilierte gespeicherte Prozeduren zugreifen können.

Leistung und Skalierbarkeit

Die folgenden Faktoren beeinflussen die Leistungsvorteile, die mit In-Memory OLTP erreicht werden können:

Kommunikation: Eine Anwendung mit vielen Aufrufen kurzer gespeicherter Prozeduren erzielt möglicherweise einen kleineren Leistungszuwachs als eine Anwendung, bei der weniger Aufrufe und zusätzliche Funktionen in jeder gespeicherten Prozedur implementiert sind.

Transact-SQL-Ausführung: In-Memory OLTP erzielt die beste Leistung, wenn sie systemeigene gespeicherte Prozeduren anstelle interpretierter gespeicherter Prozeduren oder Abfrageausführung verwendet. Dies kann einen Vorteil gegenüber dem Zugriff auf speicheroptimierte Tabellen aus solchen gespeicherten Prozeduren bieten.

Bereichsscan im Vergleich zu Punktsuche: Speicheroptimierte, nicht gruppierte Indizes unterstützen Bereichsscans und sortierte Scans. Bei Punktsuchen erzielen Sie mit speicheroptimierten Hashindizes eine bessere Leistung als mit speicheroptimierten, nicht gruppierten Indizes. Speicheroptimierte, nicht gruppierte Indizes weisen eine bessere Leistung auf als datenträgerbasierte Indizes.

  • Ab SQL Server 2016 kann der Abfrageplan für eine speicheroptimierte Tabelle die Tabelle parallel scannen. Dies verbessert die Leistung von Analyseabfragen.
    • Hashindizes können seit SQL Server 2016 auch parallel gescannt werden.
    • Nicht gruppierte Indizes können seit SQL Server 2016 auch parallel gescannt werden.
    • Columnstore-Indizes können seit ihrer Einführung in SQL Server 2014 parallel gescannt werden.

Indexvorgänge: Indexvorgänge werden nicht protokolliert und sind nur im Arbeitsspeicher vorhanden.

Parallelität: Anwendungen, deren Leistung durch Parallelität auf Engine-Ebene wie Latchkonflikte oder Blockierungen beeinträchtigt wird, verzeichnen eine erhebliche Leistungssteigerung, wenn die Anwendung auf In-Memory-OLTP umgestellt wird.

In der folgenden Tabelle werden die Leistungs- und Skalierbarkeitsprobleme, die häufig in relationalen Datenbanken auftreten, zusammen mit einer möglichen Leistungssteigerung durch In-Memory OLTP aufgeführt.

Problem Einfluss durch In-Memory OLTP
Leistung

Intensive Ressourcennutzung (CPU, E/A, Netzwerk oder Arbeitsspeicher)
CPU
Nativ kompilierte gespeicherte Prozeduren können die CPU-Auslastung erheblich verringern, da sie im Vergleich zu interpretierten gespeicherten Prozeduren deutlich weniger Anweisungen zum Ausführen einer Transact-SQL-Anweisung erfordern.

In-Memory OLTP kann die erforderlichen Hardwareinvestitionen bei horizontal skalierten Arbeitsauslastungen reduzieren, da ein Server so potenziell den Durchsatz von fünf bis 10 Servern erzielen kann.

E/A
Wenn bei der Verarbeitung ein E/A-Engpass aufgrund der Verarbeitung von Daten oder Indexseiten auftritt, lässt sich dieser durch In-Memory OLTP u. U. reduzieren. Zudem wird der Prüfpunktalgorithmus von In-Memory OLTP-Objekten kontinuierlich durchgeführt und führt nicht zu einem plötzlichen Anstieg von E/A-Vorgängen. Wenn jedoch das Workingset der leistungskritischen Tabellen zu groß für den Arbeitsspeicher ist, steigert In-Memory OLTP nicht die Leistung, da dieser Datenbanktyp speicherresidente Daten benötigt. Wenn bei der Protokollierung ein E/A-Engpass auftritt, kann In-Memory OLTP diesen Engpass verringern, da weniger Protokollierungsaktivität durchgeführt wird. Wenn eine oder mehrere speicheroptimierte Tabellen als nicht dauerhafte Tabellen konfiguriert sind, können Sie dadurch die Protokollierung für Daten eliminieren.

Gedächtnis
In-Memory OLTP bietet keine Leistungssteigerung. In-Memory OLTP kann den Arbeitsspeicher zusätzlich belasten, da die Objekte speicherresident sein müssen.

Netzwerk
In-Memory OLTP bietet keine Leistungssteigerung. Die Daten müssen von der Datenebene an die Anwendungsebene übertragen werden.
Skalierbarkeit

Die meisten Skalierungsprobleme in SQL Server-Anwendungen werden durch Parallelitätsprobleme verursacht, z. B. Konflikte in Sperren, Latches und Spinlocks.
Latchkonflikte
Ein typisches Szenario ist ein Konflikt auf der letzten Seite eines Indexes, wenn Zeilen gleichzeitig in Schlüsselreihenfolge einfügt werden. Da In-Memory OLTP beim Datenzugriff keine Latches verwendet, werden Skalierbarkeitsprobleme aufgrund von Latchkonflikten vollständig eliminiert.

Spinlock-Konflikt
Da In-Memory OLTP beim Datenzugriff keine Latches verwendet, werden Skalierbarkeitsprobleme aufgrund von Spinlock-Konflikten vollständig eliminiert.

Konflikte aufgrund von Sperren
Wenn in der Datenbankanwendung Blockierungen zwischen Lese- und Schreibvorgängen auftreten, werden diese Blockierungsprobleme durch In-Memory OLTP beseitigt, da es eine neue Art der optimistischen Nebenläufigkeitssteuerung für die Implementierung der Transaktionsisolationsstufen verwendet. In-Memory OLTP verwendet nicht TempDB, um Zeilenversionen zu speichern.

Wenn das Skalierungsproblem durch einen Konflikt zwischen zwei Schreibvorgängen verursacht wird, etwa zwei Transaktionen, die gleichzeitig dieselbe Zeile zu aktualisieren versuchen, führt In-Memory OLTP eine Transaktion erfolgreich durch und beendet die andere. Die fehlgeschlagene Transaktion muss zur Wiederholung explizit oder implizit erneut gesendet werden. In beiden Fällen müssen Sie Änderungen an der Anwendung vornehmen.

Wenn in der Anwendung häufig Konflikte zwischen zwei Schreibvorgängen auftreten, wird der Wert der optimistischen Sperre verringert. Die Anwendung ist für In-Memory OLTP nicht geeignet. Die meisten OLTP-Anwendungen weisen keine Schreibkonflikte auf, sofern diese nicht durch Sperrenausweitung verursacht werden.

Sicherheit auf Zeilenebene in speicheroptimierten Tabellen

Sicherheit auf Zeilenebene wird für speicheroptimierte Tabellen unterstützt. Richtlinien für die Sicherheit auf Zeilenebene werden auf speicheroptimierte Tabellen im Wesentlichen auf die gleiche Weise wie auf datenträgerbasierte Tabellen angewendet. Der einzige Unterschied ist, dass die als Sicherheitsprädikate verwendeten Inline-Tabellenwertfunktionen systemintern kompiliert (mit der Option WITH NATIVE_COMPILATION erstellt) werden müssen. Weitere Informationen finden Sie unter Row-Level Security (Sicherheit auf Zeilenebene) im Abschnitt Cross-Feature Compatibility (Funktionsübergreifende Kompatibilität).

Für speicherinterne Tabellen wurden verschiedene integrierte Sicherheitsfunktionen aktiviert, die für Sicherheit auf Zeilenebene wesentlich sind. Weitere Informationen finden Sie unter Integrierte Funktionen in nativ kompilierten Modulen.

EXECUTE AS CALLER: Alle nativen Module unterstützen und verwenden jetzt standardmäßig EXECUTE AS CALLER, auch ohne entsprechenden Hinweis. Der Grund dafür ist, dass von allen Sicherheitsprädikatfunktionen auf Zeilenebene die Verwendung von EXECUTE AS CALLER erwartet wird, sodass die Funktion (und alle integrierten Funktionen, die in ihr verwendet werden) im Kontext des aufrufenden Benutzers ausgewertet wird.
EXECUTE AS CALLER ist mit einer geringen Leistungseinbuße (ungefähr 10 %) verbunden, die durch das Überprüfen der Berechtigung des Aufrufers verursacht wird. Wenn das Modul explizit EXECUTE AS OWNER oder EXECUTE AS SELF angibt, werden diese Berechtigungsüberprüfungen und die entsprechenden Leistungseinbußen vermieden. Wenn jedoch eine dieser Optionen zusammen mit den oben beschriebenen integrierten Funktionen verwendet wird, kommt es aufgrund des erforderlichen Kontextwechsels zu einer erheblich höheren Leistungseinbuße.

Szenarien

Eine kurze Erläuterung der typischen Szenarien, in denen In-Memory OLTP die Leistung verbessern kann, finden Sie unter In-Memory OLTP.

Weitere Informationen

In-Memory OLTP (In-Memory Optimization)