Beispieldatenbank für In-Memory OLTPSample Database for In-Memory OLTP

Anwendungsbereich:Applies to: JaSQL ServerSQL Server (alle unterstützten Versionen) yesSQL ServerSQL Server (all supported versions) JaAzure SQL-DatenbankAzure SQL DatabaseYesAzure SQL-DatenbankAzure SQL DatabaseAnwendungsbereich:Applies to: JaSQL ServerSQL Server (alle unterstützten Versionen) yesSQL ServerSQL Server (all supported versions) JaAzure SQL-DatenbankAzure SQL DatabaseYesAzure SQL-DatenbankAzure SQL Database

ÜbersichtOverview

In diesem Beispiel wird das In-Memory OLTP-Feature vorgestellt.This sample showcases the In-Memory OLTP feature. Es zeigt speicheroptimierte Tabellen sowie nativ kompilierte gespeicherte Prozeduren und kann verwendet werden, um die Leistungsvorteile von In-Memory OLTP zu veranschaulichen.It shows memory-optimized tables and natively compiled stored procedures, and can be used to demonstrate performance benefits of In-Memory OLTP.

Hinweis

Informationen zum Anzeigen dieses Themas für SQL Server 2014 (12.x)SQL Server 2014 (12.x)finden Sie unter Erweiterungen von AdventureWorks zur Veranschaulichung von In-Memory OLTP.To view this topic for SQL Server 2014 (12.x)SQL Server 2014 (12.x), see Extensions to AdventureWorks to Demonstrate In-Memory OLTP.

Im Beispiel werden fünf Tabellen aus der AdventureWorks-Datenbank zu speicheroptimierten Tabellen migriert. Zusätzlich enthält es eine exemplarische Arbeitsauslastung zur Abwicklung von Verkaufsaufträgen.The sample migrates five tables in the AdventureWorks database to memory-optimized, and it includes a demo workload for sales order processing. Die exemplarische Arbeitsauslastung veranschaulicht die Leistungsvorteile von In-Memory OLTP auf dem Server.You can use this demo workload to see the performance benefit of using In-Memory OLTP on your server.

In der Beschreibung des Beispiels wird erläutert, welche Features bei der Migration der Tabellen zu In-Memory OLTP nicht ausgeschöpft werden konnten, weil sie für speicheroptimierte Tabellen derzeit (noch) nicht unterstützt werden.In the description of the sample, we discuss the tradeoffs that were made in migrating the tables to In-Memory OLTP to account for the features that are not (yet) supported for memory-optimized tables.

Die Dokumentation dieses Beispiels ist wie folgt gegliedert:The documentation of this sample is structured as follows:

VoraussetzungenPrerequisites

  • SQL Server 2016 (13.x)SQL Server 2016 (13.x)

  • Für Leistungstests benötigen Sie einen Server, dessen Kapazität ungefähr der eines Servers in Ihrer Produktionsumgebung entspricht.For performance testing, a server with specifications similar to your production environment. Für dieses spezielle Beispiel sollten SQL Server mindestens 16 GB Arbeitsspeicher zur Verfügung stehen.For this particular sample, you should have at least 16 GB of memory available to SQL Server. Allgemeine Richtlinien zur Hardware für In-Memory-OLTP finden Sie in folgendem Blogbeitrag: Aspekte zur Hardware für In-Memory-OLTP in SQL Server 2014.For general guidelines on hardware for In-Memory OLTP, see the following blog post: Hardware considerations for In-Memory OLTP in SQL Server 2014

Installieren des auf AdventureWorks basierenden InMemory OLTP-BeispielsInstalling the In-Memory OLTP sample based on AdventureWorks

Führen Sie die folgenden Schritte aus, um das Beispiel zu installieren:Follow these steps to install the sample:

  1. Laden Sie „AdventureWorks2016CTP3.bak“ und „SQLServer2016CTP3Samples.zip“ von https://github.com/microsoft/sql-server-samples/releases/tag/adventureworks in einen lokalen Ordner herunter, z.B. C:\temp.Download AdventureWorks2016CTP3.bak and SQLServer2016CTP3Samples.zip from: https://github.com/microsoft/sql-server-samples/releases/tag/adventureworks to a local folder, for example 'c:\temp'.

  2. Stellen Sie die Datenbanksicherung mithilfe von Transact-SQLTransact-SQL oder SQL Server Management StudioSQL Server Management Studiowieder her:Restore the database backup using Transact-SQLTransact-SQL or SQL Server Management StudioSQL Server Management Studio:

    1. Geben Sie den Zielordner und Dateinamen für die Datendatei an, z. B.Identify the target folder and filename for the data file, for example

      „h:\DATA\AdventureWorks2016CTP3_Data.mdf“'h:\DATA\AdventureWorks2016CTP3_Data.mdf'

    2. Geben Sie den Zielordner und Dateinamen für die Protokolldatei an, z. B.Identify the target folder and filename for the log file, for example

      „i:\DATA\AdventureWorks2016CTP3_log.ldf“'i:\DATA\AdventureWorks2016CTP3_log.ldf'

      1. Um optimale Leistung zu gewährleisten, sollte die Protokolldatei auf einem anderen Laufwerk als die Datendatei gespeichert werden, idealerweise auf einem Laufwerk mit niedriger Latenz wie einem SSD- oder PCIe-Speichermedium.The log file should be placed on a different drive than the data file, ideally a low latency drive such as an SSD or PCIe storage, for maximum performance.

    T-SQL-Beispielskript:Example T-SQL script:

    RESTORE DATABASE [AdventureWorks2016CTP3]   
      FROM DISK = N'C:\temp\AdventureWorks2016CTP3.bak'   
        WITH FILE = 1,    
      MOVE N'AdventureWorks2016_Data' TO N'h:\DATA\AdventureWorks2016CTP3_Data.mdf',    
      MOVE N'AdventureWorks2016_Log' TO N'i:\DATA\AdventureWorks2016CTP3_log.ldf',  
      MOVE N'AdventureWorks2016CTP3_mod' TO N'h:\data\AdventureWorks2016CTP3_mod'  
     GO  
    
  3. Entpacken Sie die Datei „SQLServer2016CTP3Samples.zip“ in einen lokalen Ordner, um die Beispielskripts und die Arbeitsauslastung anzuzeigen.To view the sample scripts and workload, unpack the file SQLServer2016CTP3Samples.zip to a local folder. Informationen zum Ausführen der Arbeitsauslastung finden Sie in der Datei „In-Memory OLTP\readme.txt“.Consult the file In-Memory OLTP\readme.txt for instructions on running the workload.

Beschreibung der Beispieltabellen und -prozedurenDescription of the sample tables and procedures

Im Beispiel werden neue Tabellen für Produkte und Verkaufsaufträge auf Grundlage vorhandener AdventureWorks-Tabellen erstellt.The sample creates new tables for products and sales orders, based on existing tables in AdventureWorks. Das Schema der neuen Tabellen entspricht bis auf die nachfolgend beschriebenen Unterschiede dem der vorhandenen Tabellen.The schema of the new tables is similar to the existing tables, with a few differences, as explained below.

Die neuen speicheroptimierten Tabellen haben das Suffix „_inmem“.The new memory-optimized tables carry the suffix '_inmem'. Zusätzlich umfasst das Beispiel entsprechende Tabellen mit dem Suffix „_ondisk“. Mithilfe dieser Tabellen können 1:1-Vergleiche zwischen der Leistung speicheroptimierter und datenträgerbasierter Tabellen im System angestellt werden.The sample also includes corresponding tables carrying the suffix '_ondisk' - these tables can be used to make a one-to-one comparison between the performance of memory-optimized tables and disk-based tables on your system..

Die in der Arbeitsauslastung für Leistungsvergleiche verwendeten speicheroptimierten Tabellen sind vollständig dauerhaft und vollständig protokolliert,The memory-optimized tables used in the workload for performance comparison are fully durable and fully logged. d. h., dass Leistungsvorteile nicht auf Kosten der Dauerhaftigkeit oder Zuverlässigkeit erzielt werden.They do not sacrifice durability or reliability to attain the performance gain.

Die Zielarbeitsauslastung in diesem Beispiel dient der Abwicklung von Verkaufsaufträgen. Dabei fließen auch Produkt- und RabattinformationenThe target workload for this sample is sales order processing, where we consider also information about products and discounts. aus den Tabellen SalesOrderHeader, SalesOrderDetail, Product, SpecialOffer und SpecialOfferProduct ein.To this end, the table SalesOrderHeader, SalesOrderDetail, Product, SpecialOffer, and SpecialOfferProduct.

Mithilfe der beiden neuen gespeicherten Prozeduren Sales.usp_InsertSalesOrder_inmem und Sales.usp_UpdateSalesOrderShipInfo_inmem werden Verkaufsaufträge eingefügt bzw. Versandinformationen zu bestimmten Verkaufsaufträgen aktualisiert.Two new stored procedures, Sales.usp_InsertSalesOrder_inmem and Sales.usp_UpdateSalesOrderShipInfo_inmem, are used to insert sales orders and to update the shipping information of a given sales order.

Das neue Schema "Demo" enthält Hilfstabellen und gespeicherte Prozeduren zum Ausführen einer exemplarischen Arbeitsauslastung.The new schema 'Demo' contains helper tables and stored procedures to execute a demo workload.

Durch das In-Memory OLTP-Beispiel werden AdventureWorks im Einzelnen die folgenden Objekte hinzugefügt:Concretely, the In-Memory OLTP sample adds the following objects to AdventureWorks:

Tabellen, die durch das Beispiel hinzugefügt werdenTables added by the sample

Neue TabellenThe New Tables

Sales.SalesOrderHeader_inmemSales.SalesOrderHeader_inmem

  • Kopfzeileninformationen zu Verkaufsaufträgen.Header information about sales orders. Diese Tabelle enthält eine Zeile für jeden Verkaufsauftrag.Each sales order has one row in this table.

Sales.SalesOrderDetail_inmemSales.SalesOrderDetail_inmem

  • Detailinformationen zu Verkaufsaufträgen.Details of sales orders. Diese Tabelle enthält eine Zeile für jeden Einzelposten eines Verkaufsauftrags.Each line item of a sales order has one row in this table.

Sales.SpecialOffer_inmemSales.SpecialOffer_inmem

  • Informationen zu Sonderangeboten, einschließlich des prozentualen Rabatts, der den einzelnen Sonderangeboten zugeordnet ist.Information about special offers, including the discount percentage associated with each special offer.

Sales.SpecialOfferProduct_inmemSales.SpecialOfferProduct_inmem

  • Verweistabelle zwischen Sonderangeboten und Produkten.Reference table between special offers and products. Jedes Sonderangebot kann für 0 (null) oder mehrere Produkte gelten, und jedes Produkt kann in 0 oder mehreren Sonderangeboten vertreten sein.Each special offer can feature zero or more products, and each product can be featured in zero or more special offers.

Production.Product_inmemProduction.Product_inmem

  • Informationen zu Produkten, einschließlich der Listenpreise.Information about products, including their list price.

Demo.DemoSalesOrderDetailSeedDemo.DemoSalesOrderDetailSeed

  • Wird in der exemplarischen Arbeitsauslastung zum Erstellen von Beispielverkaufsaufträgen verwendet.Used in the demo workload to construct sample sales orders.

Datenträgerbasierte Tabellenvarianten:Disk-based variations of the tables:

  • Sales.SalesOrderHeader_ondiskSales.SalesOrderHeader_ondisk

  • Sales.SalesOrderDetail_ondiskSales.SalesOrderDetail_ondisk

  • Sales.SpecialOffer_ondiskSales.SpecialOffer_ondisk

  • Sales.SpecialOfferProduct_ondiskSales.SpecialOfferProduct_ondisk

  • Production.Product_ondiskProduction.Product_ondisk

Unterschiede zwischen ursprünglichen datenträgerbasierten und neuen speicheroptimierten TabellenDifferences between original disk-based and the and new memory-optimized tables

Meistens verwenden die neuen, in diesem Beispiel eingeführten Tabellen bis auf wenige Ausnahmen dieselben Spalten und DatentypenFor the most part, the new tables introduced by this sample use the same columns and the same data types as the original tables. wie die ursprünglichen Tabellen.However, there are a few differences. Die Unterschiede und der Grund für die Abweichung sind im Folgenden aufgeführt.We list the differences below, along with a rationale for the changes.

Sales.SalesOrderHeader_inmemSales.SalesOrderHeader_inmem

  • DaStandardeinschränkungen bei speicheroptimierten Tabellen unterstützt werden, wurden die meisten Standardeinschränkungen unverändert migriert.Default constraints are supported for memory-optimized tables, and most default constraints we migrated as is. Die ursprüngliche Tabelle Sales.SalesOrderHeader enthält jedoch zwei Standardeinschränkungen, durch die für die Spalten OrderDate und ModifiedDate das aktuelle Datum abgerufen wird.However, the original table Sales.SalesOrderHeader contains two default constraints that retrieve the current date, for the columns OrderDate and ModifiedDate. In einer Arbeitsauslastung für die Auftragsverarbeitung mit hohem Durchsatz und einem hohen Maß an Parallelität können globale Ressourcen zu Konflikten führen.In a high throughput order processing workload with much concurrency, any global resource can become a point of contention. Die Systemzeit ist beispielsweise eine solche globale Ressource und kann bei einer In-Memory OLTP-Arbeitsauslastung, durch die Verkaufsaufträge eingefügt werden, erfahrungsgemäß einen Engpass verursachen. Dies gilt insbesondere, wenn die Systemzeit für mehrere Spalten sowohl in der Auftragskopfzeile als auch in den Auftragsdetails abgerufen werden muss.System time is such a global resource, and we have observed that it can become a bottleneck when running an In-Memory OLTP workload that inserts sales orders, in particular if the system time needs to be retrieved for multiple columns in the sales order header, as well as the sales order details. In diesem Beispiel wird das Problem umgangen, indem die Systemzeit für jeden eingefügten Verkaufsauftrag nur einmal abgerufen und dieser Wert in der gespeicherten Prozedur Sales.usp_InsertSalesOrder_inmem für die datetime-Spalten in SalesOrderHeader_inmem und SalesOrderDetail_inmem verwendet wird.The problem is addressed in this sample by retrieving the system time only once for each sales order that is inserted, and use that value for the datetime columns in SalesOrderHeader_inmem and SalesOrderDetail_inmem, in the stored procedure Sales.usp_InsertSalesOrder_inmem.

  • Alias-UDTs: In der ursprünglichen Tabelle werden die beiden Alias-UDTs (User-defined Data Types, benutzerdefinierte Datentypen) „dbo.OrderNumber“ und „dbo.AccountNumber“ für die Spalten „PurchaseOrderNumber“ bzw. „AccountNumber“ verwendet.Alias user-defined data types (UDTs) - The original table uses two alias UDTs dbo.OrderNumber and dbo.AccountNumber, for the columns PurchaseOrderNumber and AccountNumber, respectively. SQL Server 2016 (13.x)SQL Server 2016 (13.x) unterstützt keine Alias-UDTs für speicheroptimierte Tabellen, daher verwenden die neuen Tabellen die Systemdatentypen nvarchar(25) bzw. nvarchar(15).does not support alias UDT for memory-optimized tables, thus the new tables use system data types nvarchar(25) and nvarchar(15), respectively.

  • Spalten mit NULL-Werten in Indexschlüsseln : In der ursprünglichen Tabelle sind für die Spalte „SalesPersonID“ NULL-Werte zulässig, während die Spalte in den neuen Tabellen keine NULL-Werte zulässt und über eine Standardeinschränkung mit dem Wert (-1) verfügt.Nullable columns in index keys - In the original table, the column SalesPersonID is nullable, while in the new tables the column is not nullable and has a default constraint with value (-1). Dieser Umstand ist darin begründet, dass Indizes für speicheroptimierte Tabellen im Indexschlüssel keine Spalten aufweisen dürfen, die Nullwerte zulassen. Daher dient -1 in diesem Fall als Ersatz für NULL.This circumstance is because indexes on memory-optimized tables cannot have nullable columns in the index key; -1 is a surrogate for NULL in this case.

  • Berechnete Spalten : Auf die berechneten Spalten SalesOrderNumber und TotalDue wurde verzichtet, da berechnete Spalten in speicheroptimierten Tabellen von SQL Server 2016 (13.x)SQL Server 2016 (13.x) nicht unterstützt werden.Computed columns - The computed columns SalesOrderNumber and TotalDue are omitted, as SQL Server 2016 (13.x)SQL Server 2016 (13.x) does not support computed columns in memory-optimized tables. In der neuen Sicht Sales.vSalesOrderHeader_extended_inmem sind die Spalten SalesOrderNumber und TotalDue enthalten.The new view Sales.vSalesOrderHeader_extended_inmem reflects the columns SalesOrderNumber and TotalDue. Falls diese Spalten benötigt werden, können Sie diese Sicht verwenden.Therefore, you can use this view if these columns are needed.

    • Anwendungsbereich: SQL Server 2017 (14.x)SQL Server 2017 (14.x) CTP 1.1.Applies to: SQL Server 2017 (14.x)SQL Server 2017 (14.x) CTP 1.1.
      Ab SQL Server 2017 (14.x)SQL Server 2017 (14.x) CTP 1.1 werden in speicheroptimierten Tabellen und Indizes berechnete Spalten unterstützt.Beginning with SQL Server 2017 (14.x)SQL Server 2017 (14.x) CTP 1.1, computed columns are supported in memory-optimized tables and indexes.
  • Fremdschlüsseleinschränkungen werden für speicheroptimierte Tabellen in SQL Server 2016 (13.x)SQL Server 2016 (13.x)nur dann unterstützt, wenn die referenzierten Tabellen ebenfalls speicheroptimiert sind.Foreign key constraints are supported for memory-optimized tables in SQL Server 2016 (13.x)SQL Server 2016 (13.x), but only if the referenced tables are also memory-optimized. Fremdschlüssel mit Verweis auf Tabellen, die ebenfalls zu speicheroptimierten Tabellen migriert werden, werden in den migrierten Tabellen beibehalten, während andere Fremdschlüssel ausgelassen werden.Foreign keys that reference tables that are also migrated to memory-optimized are kept in the migrated tables, while other foreign keys are omitted. SalesOrderHeader_inmem stellt in der exemplarischen Arbeitsauslastung eine aktive Tabelle dar. Darüber hinaus verursachen FOREIGN KEY-Einschränkungen für DML-Vorgänge zusätzlichen Verarbeitungsaufwand, da alle anderen Tabellen, auf die in diesen Einschränkungen verwiesen wird, durchsucht werden müssen.In addition, SalesOrderHeader_inmem is a hot table in the example workload, and foreign keys constraints require additional processing for all DML operations, as it requires lookups in all the other tables referenced in these constraints. Daher wird davon ausgegangen, dass die App referenzielle Integrität für die Tabelle „Sales.SalesOrderHeader_inmem“ gewährleistet, und eingefügte Zeilen werden nicht auf referenzielle Integrität überprüft.Therefore, the assumption is that the app ensures referential integrity for the Sales.SalesOrderHeader_inmem table, and referential integrity is not validated when rows are inserted.

  • Rowguid : Die rowguid-Spalte wird nicht verwendet.Rowguid - The rowguid column is omitted. Im Gegensatz zu uniqueidentifier wird die ROWGUIDCOL-Option für speicheroptimierte Tabellen in SQL Server 2016 (13.x)SQL Server 2016 (13.x)nicht unterstützt.While uniqueidentifier is support for memory-optimized tables, the option ROWGUIDCOL is not supported in SQL Server 2016 (13.x)SQL Server 2016 (13.x). Spalten dieses Typs werden normalerweise für Mergereplikationen oder für Tabellen mit FILESTREAM-Spalten verwendet,Columns of this kind are typically used for either merge replication or tables that have filestream columns. die in diesem Beispiel beide nicht zum Einsatz kommen.This sample includes neither.

Sales.SalesOrderDetailSales.SalesOrderDetail

  • Standardeinschränkungen: Ähnlich wie SalesOrderHeader wird die Standardeinschränkung, die das Systemdatum bzw. die Systemzeit erfordert, nicht migriert. Stattdessen wird das aktuelle Systemdatum bzw. die aktuelle Systemzeit von der gespeicherten Prozedur, die Verkaufsaufträge einfügt, beim ersten Einfügevorgang hinzugefügt.Default constraints - similar to SalesOrderHeader, the default constraint requiring the system date/time is not migrated, instead the stored procedure inserting sales orders takes care of inserting the current system date/time on first insert.

  • Berechnete Spalten: Die berechnete Spalte „LineTotal“ wurde nicht migriert, weil berechnete Spalten bei speicheroptimierten Tabellen in SQL Server 2016 (13.x)SQL Server 2016 (13.x)nicht unterstützt werden.Computed columns - the computed column LineTotal was not migrated as computed columns are not supported with memory-optimized tables in SQL Server 2016 (13.x)SQL Server 2016 (13.x). Um auf diese Spalte zuzugreifen, verwenden Sie die Sicht „Sales.vSalesOrderDetail_extended_inmem“.To access this column, use the view Sales.vSalesOrderDetail_extended_inmem.

  • Rowguid : Die rowguid-Spalte wird nicht verwendet.Rowguid - The rowguid column is omitted. Ausführliche Informationen finden Sie in der Beschreibung zur Tabelle SalesOrderHeader.For details see the description for the table SalesOrderHeader.

Production.ProductProduction.Product

  • Alias-UDTs: Die ursprüngliche Tabelle verwendet den benutzerdefinierten Datentyp „dbo.Flag“, der dem Systemdatentyp „bit“ entspricht.Alias UDTs - the original table uses the user-defined data type dbo.Flag, which is equivalent to the system data type bit. Die migrierte Tabelle verwendet stattdessen den Datentyp bit.The migrated table uses the bit data type instead.

  • Rowguid : Die rowguid-Spalte wird nicht verwendet.Rowguid - The rowguid column is omitted. Ausführliche Informationen finden Sie in der Beschreibung zur Tabelle SalesOrderHeader.For details see the description for the table SalesOrderHeader.

Sales.SpecialOfferSales.SpecialOffer

  • Rowguid : Die rowguid-Spalte wird nicht verwendet.Rowguid - The rowguid column is omitted. Ausführliche Informationen finden Sie in der Beschreibung zur Tabelle SalesOrderHeader.For details see the description for the table SalesOrderHeader.

Sales.SpecialOfferProductSales.SpecialOfferProduct

  • Rowguid : Die rowguid-Spalte wird nicht verwendet.Rowguid - The rowguid column is omitted. Ausführliche Informationen finden Sie in der Beschreibung zur Tabelle SalesOrderHeader.For details see the description for the table SalesOrderHeader.

Überlegungen zu Indizes bei speicheroptimierten TabellenConsiderations for indexes on memory-optimized tables

Der Basisindex für speicheroptimierte Tabellen ist der NONCLUSTERED-Index, der Punktsuchen (Indexsuche in Gleichheitsprädikaten), Bereichsscans (Indexsuche in Ungleichheitsprädikaten), vollständige Indexscans und sortierte Scans unterstützt.The baseline index for memory-optimized tables is the NONCLUSTERED index, which supports point lookups (index seek on equality predicate), range scans (index seek in inequality predicate), full index scans, and ordered scans. Zusätzlich unterstützen NONCLUSTERED-Indizes Suchen in führenden Indexschlüsselspalten.In addition, NONCLUSTERED indexes support searching on leading columns of the index key. Bis auf Rückwärtsscans unterstützen speicheroptimierte NONCLUSTERED-Indizes alle Vorgänge, die auch von datenträgerbasierten NONCLUSTERED-Indizes unterstützt werden.In fact memory-optimized NONCLUSTERED indexes support all the operations supported by disk-based NONCLUSTERED indexes, with the only exception being backward scans. Daher sind NONCLUSTERED-Indizes eine sichere Wahl für Ihre Indizes.Therefore, using NONCLUSTERED indexes is a safe choice for your indexes.

Mit HASH-Indizes kann die Arbeitsauslastung weiter optimiert werden,HASH indexes are can be used to further optimize the workload. da sie speziell für Punktsuchen und Zeileneinfügungen optimiert sind.They are particularly optimized for point lookups and row inserts. Allerdings unterstützen sie keine Bereichsscans, sortierte Scans oder Suchen in führenden Indexschlüsselspalten.However, one must consider that they do not support range scans, ordered scans, or search on leading index key columns. Daher sollten diese Indizes mit Vorsicht verwendet werden.Therefore, care needs to be taken when using these indexes. Außerdem muss während der Erstellung der bucket_count-Wert angegeben werden.In addition, it is necessary to specify the bucket_count at create time. Die Bucketanzahl sollte normalerweise auf einen Wert zwischen der einfachen und doppelten Anzahl von Indexschlüsselwerten festgelegt werden. Ein zu hoher Wert stellt in der Regel aber auch kein Problem dar.It should usually be set at between one and two times the number of index key values, but overestimating is usually not a problem.

Weitere Informationen zu Indexrichtlinien und Richtlinien zum Auswählen des geeigneten bucket_count-Werts finden Sie in der Onlinedokumentation.For more information, see Books Online for more details about index guidelines and guidelines for choosing the right bucket_count.

Die Onlinedokumentation bietet weitere Informationen zu folgenden Themen:The Books Online provide more information about the following topics:

Die Indizes der migrierten Tabellen wurden für die exemplarische Arbeitsauslastung, die zur Abwicklung von Verkaufsaufträgen eingesetzt wird, optimiert.The indexes on the migrated tables have been tuned for the demo sales order processing workload. Die Arbeitsauslastung basiert auf Einfügungen und Punktsuchen in den Tabellen Sales.SalesOrderHeader_inmem und Sales.SalesOrderDetail_inmem sowie auf Punktsuchen in den Primärschlüsselspalten der Tabellen Production.Product_inmem und Sales.SpecialOffer_inmem.The workload relies on inserts and point lookups in the tables Sales.SalesOrderHeader_inmem and Sales.SalesOrderDetail_inmem, and it also relies on point lookups on the primary key columns in the tables Production.Product_inmem and Sales.SpecialOffer_inmem.

Sales.SalesOrderHeader_inmem verfügt über drei Indizes, die aus Leistungsgründen und weil für die Arbeitsauslastung keine sortierten oder Bereichsscans erforderlich sind, alle HASH-Indizes sind.Sales.SalesOrderHeader_inmem has three indexes, which are all HASH indexes for performance reasons, and because no ordered or range scans are needed for the workload.

  • HASH-Index für (SalesOrderID): bucket_count hat einen Wert von 10 Millionen (und wird auf 16 Millionen aufgerundet), da die erwartete Anzahl von Verkaufsaufträgen 10 Millionen beträgt.HASH index on (SalesOrderID): bucket_count is sized at 10 million (rounded up to 16 million), because the expected number of sales orders is 10 million

  • HASH-Index für (SalesPersonID): bucket_count beträgt 1 Million.HASH index on (SalesPersonID): bucket_count is 1 million. Das bereitgestellte Dataset enthält nicht viele Vertriebsmitarbeiter.The data set provided does not have many sales persons. Dieser große bucket_count-Wert bietet jedoch genügend Platz für zukünftiges Wachstum.But this large bucket_count allows for future growth. Und Sie müssen keine Leistungseinbußen für Punktsuchen in Kauf nehmen, wenn bucket_count überdimensioniert ist.Plus you don't pay a performance penalty for point lookups if the bucket_count is oversized.

  • HASH-Index für (CustomerID): bucket_count beträgt 1 Million.HASH index on (CustomerID): bucket_count is 1 million. Dem bereitgestellten Dataset ist nur eine geringe Anzahl von Kunden zugeordnet, sodass es zukünftig anwachsen kann.The data set provided does not have a lot of customers, but this allows for future growth.

Sales.SalesOrderDetail_inmem verfügt über drei Indizes, die aus Leistungsgründen und weil für die Arbeitsauslastung keine sortierten oder Bereichsscans erforderlich sind, alle HASH-Indizes sind.Sales.SalesOrderDetail_inmem has three indexes, which are all HASH indexes for performance reasons, and because no ordered or range scans are needed for the workload.

  • HASH-Index für (SalesOrderID, SalesOrderDetailID): Dies ist der Primärschlüsselindex. Obwohl für (SalesOrderID, SalesOrderDetailID) nur selten Suchen ausgeführt werden, lassen sich Zeileneinfügungen beschleunigen, indem ein HASH-Index für den Schlüssel verwendet wird.HASH index on (SalesOrderID, SalesOrderDetailID): this is the primary key index, and even though lookups on (SalesOrderID, SalesOrderDetailID) will be infrequent, using a hash index for the key speeds up row inserts. Der bucket_count-Wert ist auf 50 Millionen festgelegt (und wird auf 67 Millionen aufgerundet): Die erwartete Anzahl von Verkaufsaufträgen beträgt 10 Millionen mit durchschnittlich fünf Einzelposten pro Auftrag.The bucket_count is sized at 50 million (rounded up to 67 million): the expected number of sales orders is 10 million, and this is sized to have an average of five items per order

  • HASH-Index für (SalesOrderID): Es werden häufig Suchen nach Verkaufsaufträgen ausgeführt, und Sie möchten alle Einzelposten ermitteln, die sich auf einen einzelnen Auftrag beziehen.HASH index on (SalesOrderID): lookups by sales order are frequent: you will want to find all the line items corresponding to a single order. bucket_count hat einen Wert von 10 Millionen (und wird auf 16 Millionen aufgerundet), da die erwartete Anzahl von Verkaufsaufträgen 10 Millionen beträgt.bucket_count is sized at 10 million (rounded up to 16 million), because the expected number of sales orders is 10 million

  • HASH-Index für (ProductID): bucket_count beträgt 1 Million.HASH index on (ProductID): bucket_count is 1 million. Dem bereitgestellten Dataset ist nur eine geringe Anzahl von Produkten zugeordnet, sodass es zukünftig anwachsen kann.The data set provided does not have a lot of product, but this allows for future growth.

Production.Product_inmem verfügt über drei Indizes.Production.Product_inmem has three indexes

  • HASH-Index für (ProductID): Da Suchen nach ProductID ein wesentlicher Bestandteil der exemplarischen Arbeitsauslastung sind, wird hier ein HASH-Index verwendet.HASH index on (ProductID): lookups on ProductID are in the critical path for the demo workload, therefore this is a hash index

  • NONCLUSTERED-Index für (Name): ermöglicht sortierte Scans für Produktnamen.NONCLUSTERED index on (Name): this will allow ordered scans of product names

  • NONCLUSTERED-Index für (ProductNumber): ermöglicht sortierte Scans für Produktnummern.NONCLUSTERED index on (ProductNumber): this will allow ordered scans of product numbers

Sales.SpecialOffer_inmem verfügt über einen HASH-Index für (SpecialOfferID): Punktsuchen nach Sonderangeboten sind ein wesentlicher Bestandteil der exemplarischen Arbeitsauslastung.Sales.SpecialOffer_inmem has one HASH index on (SpecialOfferID): point lookups of special offers are in the critical part of the demo workload. bucket_count beträgt 1 Million und ist auf zukünftiges Wachstum ausgelegt.The bucket_count is sized at 1 million to allow for future growth.

Da in der exemplarischen Arbeitsauslastung nicht auf Sales.SpecialOfferProduct_inmem verwiesen wird, ist es nicht erforderlich, HASH-Indizes für die Tabelle zu verwenden, um die Arbeitsauslastung zu optimieren. Für (SpecialOfferID, ProductID) und (ProductID) werden NONCLUSTERED-Indizes verwendet.Sales.SpecialOfferProduct_inmem is not referenced in the demo workload, and thus there is no apparent need to use hash indexes on this table to optimize the workload - the indexes on (SpecialOfferID, ProductID) and (ProductID) are NONCLUSTERED.

Beachten Sie, dass einige der oben genannten Bucketanzahlen zu hoch angesetzt sind. Auf die Bucketanzahlen für die Indizes von SalesOrderHeader_inmem und SalesOrderDetail_inmem trifft dies jedoch nicht zu, da sie auf eine Anzahl von 10 Millionen Verkaufsaufträgen beschränkt sind.Notice that in the above some of the bucket_counts are over-sized, but not the bucket_counts for the indexes on SalesOrderHeader_inmem and SalesOrderDetail_inmem: they are sized for just 10 million sales orders. Auf diese Weise kann das Beispiel auch auf Systemen mit geringerer Arbeitsspeicherkapazität installiert werden. In diesen Fällen verursacht die exemplarische Arbeitsauslastung jedoch einen Fehler vom Typ "Nicht genügend Arbeitsspeicher".This was done to allow installing the sample on systems with low memory availability, although in those cases the demo workload will fail with out-of-memory. Wenn Sie einen Wert festlegen möchten, der 10 Millionen Verkaufsaufträge erheblich überschreitet, können Sie die Bucketanzahlen einfach entsprechend erhöhen.If you do want to scale well beyond 10 million sales orders, feel free to increase the bucket counts accordingly.

Überlegungen zur ArbeitsspeichernutzungConsiderations for memory utilization

Die Arbeitsspeichernutzung der Beispieldatenbank vor und nach der Ausführung der exemplarischen Arbeitsauslastung wird im Abschnitt Arbeitsspeichernutzung für speicheroptimierte Tabellenerörtert.Memory utilization in the sample database, both before and after running the demo workload, is discussed in the Section Memory utilization for the memory-optimized tables.

Gespeicherte Prozeduren, die durch das Beispiel hinzugefügt wurdenStored Procedures added by the sample

Die beiden wichtigsten gespeicherten Prozeduren zum Einfügen von Verkaufsaufträgen und Aktualisieren von Versanddetails lauten:The two key stored procedures for inserting sales order and updating shipping details are as follows:

  • Sales.usp_InsertSalesOrder_inmemSales.usp_InsertSalesOrder_inmem

    • Fügt einen neuen Verkaufsauftrag in die Datenbank ein und gibt SalesOrderID für den Verkaufsauftrag aus.Inserts a new sales order in the database and outputs the SalesOrderID for that sales order. Als Eingabeparameter werden Details zur Auftragskopfzeile sowie die Einzelposten im Auftrag akzeptiert.As input parameters it takes details for the sales order header, as well as the line items in the order.

    • Ausgabeparameter:Output parameter:

      • @SalesOrderID int: SalesOrderID für den gerade eingefügten Verkaufsauftrag@SalesOrderID int - the SalesOrderID for the sales order that was just inserted
    • Eingabeparameter (erforderlich):Input parameters (required):

      • @DueDate datetime2@DueDate datetime2

      • @CustomerID int@CustomerID int

      • @BillToAddressID [int]@BillToAddressID [int]

      • @ShipToAddressID [int]@ShipToAddressID [int]

      • @ShipMethodID [int]@ShipMethodID [int]

      • @SalesOrderDetails Sales.SalesOrderDetailType_inmem: Tabellenwertparameter, der die Einzelposten des Auftrags enthält@SalesOrderDetails Sales.SalesOrderDetailType_inmem - table-valued parameter (TVP) that contains the line items of the order

    • Eingabeparameter (optional):Input parameters (optional):

      • @Status [tinyint]@Status [tinyint]

      • @OnlineOrderFlag [bit]@OnlineOrderFlag [bit]

      • @PurchaseOrderNumber [nvarchar](25)@PurchaseOrderNumber [nvarchar](25)

      • @AccountNumber [nvarchar](15)@AccountNumber [nvarchar](15)

      • @SalesPersonID [int]@SalesPersonID [int]

      • @TerritoryID [int]@TerritoryID [int]

      • @CreditCardID [int]@CreditCardID [int]

      • @CreditCardApprovalCode [varchar](15)@CreditCardApprovalCode [varchar](15)

      • @CurrencyRateID [int]@CurrencyRateID [int]

      • @Comment nvarchar(128)@Comment nvarchar(128)

  • Sales.usp_UpdateSalesOrderShipInfo_inmemSales.usp_UpdateSalesOrderShipInfo_inmem

    • Aktualisiert die Versandinformationen für einen bestimmten Verkaufsauftrag.Update the shipping information for a given sales order. Gleichzeitig werden auch die Versandinformationen für alle Einzelposten des Verkaufsauftrags aktualisiert.This will also update the shipping information for all line items of the sales order.

    • Dies ist eine Wrapperprozedur für die systemintern kompilierte gespeicherte Prozedur Sales.usp_UpdateSalesOrderShipInfo_native. Sie verfügt über eine Wiederholungslogik zur Behandlung (unerwarteter) potenzieller Konflikte mit Transaktionen, die gleichzeitig ausgeführt werden und denselben Auftrag aktualisieren.This is a wrapper procedure for the natively compiled stored procedures Sales.usp_UpdateSalesOrderShipInfo_native with retry logic to deal with (unexpected) potential conflicts with concurrent transactions updating the same order. Weitere Informationen zur Wiederholungslogik finden Sie in diesem Themain der Onlinedokumentation.For more information about retry logic see the Books Online topic here.

  • Sales.usp_UpdateSalesOrderShipInfo_nativeSales.usp_UpdateSalesOrderShipInfo_native

    • Dies ist die systemintern kompilierte gespeicherte Prozedur, durch die das Update der Versandinformationen tatsächlich verarbeitet wird.This is the natively compiled stored procedure that actually processes the update to the shipping information. Sie sollte normalerweise von der gespeicherten Wrapperprozedur Sales.usp_UpdateSalesOrderShipInfo_inmem aufgerufen werden.It is means to be called from the wrapper stored procedure Sales.usp_UpdateSalesOrderShipInfo_inmem. Wenn der Client Fehler behandeln kann und eine Wiederholungslogik implementiert wurde, können Sie diese Prozedur direkt aufrufen, anstatt die gespeicherte Wrapperprozedur zu verwenden.If the client can deal with failures and implements retry logic, you can call this procedure directly, rather than using the wrapper stored procedure.

Die folgende gespeicherte Prozedur wird für die exemplarische Arbeitsauslastung verwendet.The following stored procedure is used for the demo workload.

  • Demo.usp_DemoResetDemo.usp_DemoReset

    • Setzt die exemplarische Arbeitsauslastung zurück, indem für die Tabellen SalesOrderHeader und SalesOrderDetail ein erneutes Seeding ausgeführt wird, nachdem sie geleert wurden.Resets the demo by emptying and reseeding the SalesOrderHeader and SalesOrderDetail tables.

Mit den folgenden gespeicherten Prozeduren werden Daten in speicheroptimierten Tabellen eingefügt und daraus gelöscht, ohne die Domänenintegrität und referenzielle Integrität zu gefährden.The following stored procedures are used for inserting in and deleting from memory-optimized tables while guaranteeing domain and referential integrity.

  • Production.usp_InsertProduct_inmemProduction.usp_InsertProduct_inmem

  • Production.usp_DeleteProduct_inmemProduction.usp_DeleteProduct_inmem

  • Sales.usp_InsertSpecialOffer_inmemSales.usp_InsertSpecialOffer_inmem

  • Sales.usp_DeleteSpecialOffer_inmemSales.usp_DeleteSpecialOffer_inmem

  • Sales.usp_InsertSpecialOfferProduct_inmemSales.usp_InsertSpecialOfferProduct_inmem

Zum Schluss werden Domänenintegrität und referenzielle Integrität mit der folgenden gespeicherten Prozedur überprüft.Finally the following stored procedure is used to verify domain and referential integrity.

  1. dbo.usp_ValidateIntegritydbo.usp_ValidateIntegrity

    • Optionaler Parameter: @object_id: ID des Objekts, dessen Integrität überprüft werden sollOptional parameter: @object_id - ID of the object to validate integrity for

    • Diese Prozedur ermittelt anhand der Tabellen dbo.DomainIntegrity, dbo.ReferentialIntegrity und dbo.UniqueIntegrity, welche Integritätsregeln überprüft werden müssen. Im Beispiel werden diese Tabellen auf der Grundlage der CHECK-, FOREIGN KEY- und UNIQUE-Einschränkungen der ursprünglichen Tabellen in der AdventureWorks-Datenbank aufgefüllt.This procedure relies on the tables dbo.DomainIntegrity, dbo.ReferentialIntegrity, and dbo.UniqueIntegrity for the integrity rules that need to be verified - the sample populates these tables based on the check, foreign key, and unique constraints that exist for the original tables in the AdventureWorks database.

    • Die zum Ausführen der Integritätsprüfungen erforderliche T-SQL-Anweisung wird mithilfe der Hilfsprozeduren dbo.usp_GenerateCKCheck, dbo.usp_GenerateFKCheck und dbo.GenerateUQCheck generiert.It relies on the helper procedures dbo.usp_GenerateCKCheck, dbo.usp_GenerateFKCheck, and dbo.GenerateUQCheck to generate the T-SQL needed for performing the integrity checks.

Leistungsmessungen anhand der exemplarischen ArbeitsauslastungPerformance Measurements using the Demo Workload

OSTRESS ist ein Befehlszeilentool, das vom Microsoft CSS SQL Server-Supportteam entwickelt wurde.Ostress is a command-line tool that was developed by the Microsoft CSS SQL Server support team. Mit diesem Tool können Abfragen ausgeführt oder gespeicherte Prozeduren parallel aufgerufen werden.This tool can be used to execute queries or run stored procedures in parallel. Sie können die Anzahl der Threads zur parallelen Ausführung einer bestimmten T-SQL-Anweisung konfigurieren und angeben, wie oft die Anweisung in diesem Thread ausgeführt werden soll. OSTRESS bündelt die Threads und führt die Anweisung in allen Threads gleichzeitig aus.You can configure the number of threads to run a given T-SQL statement in parallel, and you can specify how many times the statement should be executed on this thread; ostress will spin up the threads and execute the statement on all threads in parallel. Nachdem die Ausführung aller Threads beendet wurde, meldet OSTRESS die zur Beendigung sämtlicher Threads benötigte Dauer.After execution finishes for all threads, ostress will report the time taken for all threads to finish execution.

Installieren von OSTRESSInstalling ostress

OSTRESS wird nicht eigenständig, sondern als Teil der RML-Hilfsprogramme (Remote Markup Language) installiert.Ostress is installed as part of the Report Markup Language (RML) Utilities; there is no standalone installation for ostress.

Installationsschritte:Installation steps:

  1. Laden Sie die x64-Version des Installationspakets für die RML-Hilfsprogramme von folgender Seite herunter, und führen Sie das Paket aus: Herunterladen von RML für SQL ServerDownload and run the x64 installation package for the RML utilities from the following page: Download RML for SQL Server

  2. Falls Sie in einem Dialogfeld darauf hingewiesen werden, dass bestimmte Dateien gerade verwendet werden, klicken Sie auf „Weiter“.If there is a dialog box saying certain files are in use, click 'Continue'

Ausführen von OSTRESSRunning ostress

OSTRESS wird an der Eingabeaufforderung ausgeführt.Ostress is run from the command-line prompt. Am einfachsten lässt sich das Tool über die RML-Eingabeaufforderung ausführen, die mit den RML-Hilfsprogrammen installiert wird.It is most convenient to run the tool from the "RML Cmd Prompt", which is installed as part of the RML Utilities.

Führen Sie die folgenden Schritte aus, um die RML-Eingabeaufforderung zu öffnen:To open the RML Cmd Prompt follow these instructions:

Öffnen Sie in Windows Server 2012 [R2] sowie in Windows 8 und 8.1 das Startmenü, indem Sie die Windows-Taste drücken, und geben Sie „rml“ ein.In Windows Server 2012 [R2] and in Windows 8 and 8.1, open the start menu by clicking the Windows key, and type 'rml'. Klicken Sie auf die in der Liste der Suchergebnisse angezeigte RML-Eingabeaufforderung (RML Cmd Prompt).Click on "RML Cmd Prompt", which will be in the list of search results.

Vergewissern Sie sich, dass sich die Eingabeaufforderung im Installationsordner für die RML-Hilfsprogramme befindet.Ensure that the command prompt is located in the RML Utilities installation folder.

Um die Befehlszeilenoptionen für OSTRESS anzuzeigen, führen Sie ostress.exe einfach ohne Angabe von Befehlszeilenoptionen aus.The command-line options for ostress can be seen when simply running ostress.exe without any command-line options. Im Folgenden die wichtigsten Optionen, die beim Ausführen von OSTRESS für dieses Beispiel angegeben werden:The main options to consider for running ostress with this sample are:

  • -S: Der Name der Microsoft SQL Server-Instanz, mit der eine Verbindung hergestellt werden soll.-S name of Microsoft SQL Server instance to connect to

  • -E: Verwendet die Windows-Authentifizierung für Verbindungen (Standard). Bei Verwendung der SQL Server-Authentifizierung können Sie mit den Optionen -U und -P den Benutzernamen bzw. das Kennwort angeben.-E use Windows authentication to connect (default); if you use SQL Server authentication, use the options -U and -P to specify the username and password, respectively

  • -d: Der Name der Datenbank, in diesem Beispiel "AdventureWorks2014".-d name of the database, for this example AdventureWorks2014

  • -Q: Die auszuführende T-SQL-Anweisung.-Q the T-SQL statement to be executed

  • -n: Die Anzahl der Verbindungen, über die die einzelnen Eingabedateien/Abfragen verarbeitet werden.-n number of connections processing each input file/query

  • -r: Die Anzahl der Iterationen für jede Verbindung, über die die einzelnen Eingabedateien/Abfragen verarbeitet werden.-r the number of iterations for each connection to execute each input file/query

Exemplarische ArbeitsauslastungDemo Workload

Die wichtigste in der exemplarischen Arbeitsauslastung verwendete gespeicherte Prozedur ist Sales.usp_InsertSalesOrder_inmem/ondisk.The main stored procedure used in the demo workload is Sales.usp_InsertSalesOrder_inmem/ondisk. Das folgende Skript erstellt einen Tabellenwertparameter (Table-valued Parameter, TVP) mit Beispieldaten und ruft anschließend die Prozedur auf, um einen Verkaufsauftrag mit fünf Einzelpositionen einzufügen.The script in the below constructs a table-valued parameter (TVP) with sample data, and calls the procedure to insert a sales order with five line items.

Das OSTRESS-Tool wird verwendet, um die Aufrufe der gespeicherten Prozedur parallel auszuführen und Clients zu simulieren, die zeitgleich Verkaufsaufträge einfügen.The ostress tool is used to execute the stored procedure calls in parallel, to simulate clients inserting sales orders concurrently.

Setzen Sie die exemplarische Arbeitsauslastung nach jedem Belastungstest zurück, indem Sie Demo.usp_DemoReset ausführen.Reset the demo after each stress run executing Demo.usp_DemoReset. Durch diese Prozedur werden die Zeilen in den speicheroptimierten Tabellen gelöscht, die datenträgerbasierten Tabellen abgeschnitten und ein Datenbankprüfpunkt ausgeführt.This procedure deletes the rows in the memory-optimized tables, truncates the disk-based tables, and executes a database checkpoint.

Das folgende Skript wird gleichzeitig ausgeführt, um eine Arbeitsauslastung zur Auftragsabwicklung zu simulieren:The following script is executed concurrently to simulate a sales order processing workload:

DECLARE   
      @i int = 0,   
      @od Sales.SalesOrderDetailType_inmem,   
      @SalesOrderID int,   
      @DueDate datetime2 = sysdatetime(),   
      @CustomerID int = rand() * 8000,   
      @BillToAddressID int = rand() * 10000,   
      @ShipToAddressID int = rand() * 10000,   
      @ShipMethodID int = (rand() * 5) + 1;   
  
INSERT INTO @od   
SELECT OrderQty, ProductID, SpecialOfferID   
FROM Demo.DemoSalesOrderDetailSeed   
WHERE OrderID= cast((rand()*106) + 1 as int);   
  
WHILE (@i < 20)   
BEGIN;   
      EXEC Sales.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @ShipMethodID, @od;   
      SET @i += 1   
END

Mit diesem Skript wird jeder erstellte Beispielauftrag durch 20 in einer WHILE-Schleife ausgeführte gespeicherte Prozeduren 20 Mal eingefügt.With this script, each sample order that is constructed is inserted 20 times, through 20 stored procedures executed in a WHILE loop. Die Schleife wird verwendet, weil die Datenbank zum Erstellen des Beispielauftrags verwendet wird.The loop is used to account for the fact that the database is used to construct the sample order. In einer typischen Produktionsumgebung wird der einzufügende Verkaufsauftrag durch die Mid-Tier-Anwendung erstellt.In typical production environments, the mid-tier application will construct the sales order to be inserted.

Durch das oben angegebene Skript werden Verkaufsaufträge in speicheroptimierte Tabellen eingefügt.The above script inserts sales orders into memory-optimized tables. Sie erhalten das Skript zum Einfügen von Verkaufsaufträgen in datenträgerbasierte Tabellen, indem Sie die beiden Suffixe „_inmem in _ondisk“ ändern.The script to insert sales orders into disk-based tables is derived by replacing the two occurrences of '_inmem' with '_ondisk'.

Wir verwenden das OSTRESS-Tool, um die Skripts unter Verwendung mehrerer gleichzeitiger Verbindungen auszuführen.We will use the ostress tool to execute the scripts using several concurrent connections. Dabei wird mit dem Parameter „-n“ gesteuert, wie viele Verbindungen verwendet werden, und mit dem Parameter „-r“, wie oft das Skript für jede Verbindung ausgeführt wird.We will use the parameter '-n' to control the number of connections, and the parameter 'r' to control how many times the script is executed on each connection.

Ausführen der ArbeitsauslastungRunning the Workload

Um das Verhalten in einem größeren Szenario zu testen, fügen wir unter Verwendung von 100 Verbindungen 10 Millionen Verkaufsaufträge ein.To test at scale we insert 10 million sales orders, using 100 connections. Bei einem einfach ausgestatteten Server (z. B. mit 8 physischen und 16 logischen Kernen) und SSD-Basisspeicher für das Protokoll liefert der Test zufriedenstellende Ergebnisse.This test performs reasonably on a modest server (e.g., 8 physical, 16 logical cores), and basic SSD storage for the log. Falls der Test mit Ihrer Hardware nicht gut abschneidet, sollten Sie sich im Abschnitt Problembehandlung bei langsamer Testausführung informieren. Wenn Sie das Belastungsniveau für diesen Test verringern möchten, reduzieren Sie die Anzahl der Verbindungen, indem Sie den Parameter „-n“ ändern.If the test does not perform well on your hardware, take look at the Section Troubleshooting slow-running tests.If you want to reduce the level of stress for this test, lower the number of connections by changing the parameter '-n'. Um die Anzahl der Verbindungen z. B. auf 40 zu verringern, ändern Sie den Parameter „-n100“ in „-n40“.For example to lower the connection count to 40, change the parameter '-n100' to '-n40'.

Als Leistungskennzahl für die Arbeitsauslastung wird die Zeitspanne verwendet, die von ostress.exe nach Ausführung der Arbeitsauslastung gemeldet wird.As a performance measure for the workload we use the elapsed time as reported by ostress.exe after running the workload.

Den unten angegebenen Anweisungen und Messungen liegt eine Arbeitsauslastung zugrunde, bei der 10 Millionen Verkaufsaufträge eingefügt werden.The below instructions and measurements use a workload that inserts 10 million sales orders. Eine Anleitung zum Ausführen einer herunterskalierten Arbeitsauslastung zum Einfügen von 1 Million Verkaufsaufträgen finden in der Datei „In-Memory OLTP\readme.txt“, die im Archiv „SQLServer2016CTP3Samples.zip“ enthalten ist.For instructions to run a scaled-down workload inserting 1 million sales orders, see the instructions in 'In-Memory OLTP\readme.txt' that is part of the SQLServer2016CTP3Samples.zip archive.

Speicheroptimierte TabellenMemory-optimized tables

Zuerst führen wir die Arbeitsauslastung für speicheroptimierte Tabellen aus.We will start by running the workload on memory-optimized tables. Mit dem folgenden Befehl werden 100 Threads geöffnet, die jeweils für 5.000 Iterationen ausgeführt werden.The following command opens 100 threads, each running for 5,000 iterations. Pro Iteration werden 20 Verkaufsaufträge in getrennten Transaktionen eingefügt.Each iteration inserts 20 sales orders in separate transactions. Die 20 Einfügungen pro Iteration sind darauf zurückzuführen, dass die einzufügenden Daten unter Verwendung der Datenbank generiert werden.There are 20 inserts per iteration to compensate for the fact that the database is used to generate the data to be inserted. Daraus ergeben sich insgesamt 20 * 5.000 * 100 = 10.000.000 eingefügte Verkaufsaufträge.This yield a total of 20 * 5,000 * 100 = 10,000,000 sales order inserts.

Öffnen Sie die RML-Eingabeaufforderung, und führen Sie folgenden Befehl aus:Open the RML Cmd Prompt, and execute the following command:

Klicken Sie auf die Schaltfläche zum Kopieren, um den Befehl zu kopieren, und fügen Sie ihn in die Eingabeaufforderung der RML-Hilfsprogramme ein.Click the Copy button to copy the command, and paste it into the RML Utilities command prompt.

ostress.exe -n100 -r5000 -S. -E -dAdventureWorks2016CTP3 -q -Q"DECLARE @i int = 0, @od Sales.SalesOrderDetailType_inmem, @SalesOrderID int, @DueDate datetime2 = sysdatetime(), @CustomerID int = rand() * 8000, @BillToAddressID int = rand() * 10000, @ShipToAddressID int = rand() * 10000, @ShipMethodID int = (rand() * 5) + 1; INSERT INTO @od SELECT OrderQty, ProductID, SpecialOfferID FROM Demo.DemoSalesOrderDetailSeed WHERE OrderID= cast((rand()*106) + 1 as int); while (@i < 20) begin; EXEC Sales.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @ShipMethodID, @od; set @i += 1 end"  

Auf einem Testserver mit insgesamt 8 physischen (16 logischen) Kernen betrug die Dauer zwei Minuten und fünf Sekunden.On one test server with a total number of 8 physical (16 logical) cores, this took 2 minutes and 5 seconds. Auf einem zweiten Testserver mit 24 physischen (48 logischen) Kernen dauerte der Vorgang eine Minute und 0 (null) Sekunden.On a second test server with 24 physical (48 logical) cores, this took 1 minute and 0 seconds.

Beobachten Sie bei der Ausführung der Arbeitsauslastung die CPU-Auslastung, beispielsweise mit dem Task-Manager.Observe the CPU utilization while the workload is running, for example using task manager. Sie werden feststellen, dass die CPU-Auslastung bei fast 100 % liegt.You will see that CPU utilization is close to 100%. Andernfalls verursachen E/A-Protokollvorgänge einen Engpass. Weitere Informationen finden Sie auch unter Problembehandlung bei langsamer Testausführung.If this is not the case, you have a log IO bottleneck see also Troubleshooting slow-running tests.

Datenträgerbasierte TabellenDisk-based tables

Mit dem folgenden Befehl wird die Arbeitsauslastung für datenträgerbasierte Tabellen ausgeführt.The following command will run the workload on disk-based tables. Die Ausführung dieser Arbeitsauslastung kann einige Zeit dauern, was hauptsächlich auf Latchkonflikte im System zurückzuführen ist.This workload may take a while to execute, which is largely due to latch contention in the system. Dieses Problem tritt bei speicheroptimierten Tabellen nicht auf, da sie ohne Latches auskommen.Memory-optimized table are latch-free and thus do not suffer from this problem.

Öffnen Sie die RML-Eingabeaufforderung, und führen Sie folgenden Befehl aus:Open the RML Cmd Prompt, and execute the following command:

Klicken Sie auf die Schaltfläche zum Kopieren, um den Befehl zu kopieren, und fügen Sie ihn in die Eingabeaufforderung der RML-Hilfsprogramme ein.Click the Copy button to copy the command, and paste it into the RML Utilities command prompt.

ostress.exe -n100 -r5000 -S. -E -dAdventureWorks2016CTP3 -q -Q"DECLARE @i int = 0, @od Sales.SalesOrderDetailType_ondisk, @SalesOrderID int, @DueDate datetime2 = sysdatetime(), @CustomerID int = rand() * 8000, @BillToAddressID int = rand() * 10000, @ShipToAddressID int = rand() * 10000, @ShipMethodID int = (rand() * 5) + 1; INSERT INTO @od SELECT OrderQty, ProductID, SpecialOfferID FROM Demo.DemoSalesOrderDetailSeed WHERE OrderID= cast((rand()*106) + 1 as int); while (@i < 20) begin; EXEC Sales.usp_InsertSalesOrder_ondisk @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @ShipMethodID, @od; set @i += 1 end"  

Auf einem Testserver mit insgesamt 8 physischen (16 logischen) Kernen betrugt die Dauer 41 Minuten und 25 Sekunden.On one test server with a total number of 8 physical (16 logical) cores, this took 41 minutes and 25 seconds. Auf einem zweiten Testserver mit 24 physischen (48 logischen) Kernen dauerte der Vorgang 52 Minuten und 16 Sekunden.On a second test server with 24 physical (48 logical) cores, this took 52 minutes and 16 seconds.

Der Hauptunterschied zwischen der Leistung speicheroptimierter und datenträgerbasierter Tabellen in diesem Test besteht darin, dass die CPU bei Verwendung datenträgerbasierter Tabellen von SQL Server nicht voll ausgenutzt werden kann.The main factor in the performance difference between memory-optimized tables and disk-based tables in this test is the fact that when using disk-based tables, SQL Server cannot not fully utilize the CPU. Die Ursache sind Latchkonflikte: Wenn gleichzeitige Transaktionen versuchen, Daten in dieselbe Datenseite zu schreiben, wird mithilfe von Latches sichergestellt, dass jeweils nur eine Transaktion Schreibzugriff auf eine Seite hat.The reason is latch contention: concurrent transactions are attempting to write to the same data page; latches are used to ensure only one transaction at a time can write to a page. Die In-Memory-OLTP-Engine verwendet keine Latches, und Datenzeilen sind nicht seitenweise angeordnet.The In-Memory OLTP engine is latch-free, and data rows are not organized in pages. Da sich Einfügungen gleichzeitiger Transaktionen nicht gegenseitig blockieren, kann die CPU-Leistung von SQL Server voll ausgeschöpft werden.Thus, concurrent transactions do not block each other's inserts, thus enabling SQL Server to fully utilize the CPU.

Sie können die CPU-Auslastung bei der Ausführung der Arbeitsauslastung beispielsweise mit dem Task-Manager beobachten.You can observe the CPU utilization while the workload is running, for example using task manager. Sie werden feststellen, dass die CPU-Auslastung bei Verwendung datenträgerbasierter Tabellen weit von 100 % entfernt ist.You will see with disk-based tables the CPU utilization is far from 100%. In einer Testkonfiguration mit 16 logischen Prozessoren würde sich die Auslastung um 24 % bewegen.On a test configuration with 16 logical processors, the utilization would hover around 24%.

Optional können Sie den Leistungsindikator „\SQL Server:Latches\Latchwartevorgänge/Sekunde“ im Systemmonitor verwenden, um die Anzahl der Latchwartevorgänge pro Sekunde anzuzeigen.Optionally, you can view the number of latch waits per second using Performance Monitor, with the performance counter '\SQL Server:Latches\Latch Waits/sec'.

Zurücksetzen der exemplarischen ArbeitsauslastungResetting the demo

Um die exemplarische Arbeitsauslastung zurückzusetzen, öffnen Sie die RML-Eingabeaufforderung und führen folgenden Befehl aus:To reset the demo, open the RML Cmd Prompt, and execute the following command:

ostress.exe -S. -E -dAdventureWorks2016CTP3 -Q"EXEC Demo.usp_DemoReset"  

Je nach Hardware kann die Ausführung einige Minuten dauern.Depending on the hardware, this may take a few minutes to run.

Es wird empfohlen, die Arbeitsauslastung nach jedem Durchgang zurückzusetzen.We recommend a reset after every demo run. Da bei dieser Arbeitsauslastung nur Einfügungen stattfinden, wird bei jedem Durchgang mehr Arbeitsspeicher belegt. Durch das Zurücksetzen wird verhindert, dass der Arbeitsspeicher knapp wird.Because this workload is insert-only, each run will consume more memory, and thus a reset is required to prevent running out of memory. Der Abschnitt Arbeitsspeichernutzung nach dem Ausführen der Arbeitsauslastungenthält Informationen darüber, wie viel Arbeitsspeicher nach einer Ausführung belegt ist.The amount of memory consumed after a run is discussed in Section Memory utilization after running the workload.

Problembehandlung bei langsamer TestausführungTroubleshooting slow-running tests

Die Testergebnisse variieren normalerweise je nach Hardware und dem im Testlauf verwendeten Parallelitätsgrad.Test results will typically vary with hardware, and also the level of concurrency used in the test run. Wenn die Ergebnisse nicht wie erwartet ausfallen, sollten Sie folgende Punkte überprüfen:A couple of things to look for if the results are not as expected:

  • Anzahl gleichzeitiger Transaktionen: Wenn die Arbeitsauslastung in einem einzelnen Thread ausgeführt wird, liegt der Leistungsgewinn bei In-Memory OLTP wahrscheinlich unter dem zweifachen Wert.Number of concurrent transactions: When running the workload on a single thread, performance gain with In-Memory OLTP will likely be less than 2X. Latchkonflikte stellen nur bei einem hohen Parallelitätsgrad ein wirkliches Problem dar.Latch contention is only a big problem if there is a high level of concurrency.

  • SQL Server arbeitet mit einer geringen Anzahl von Kernen: Dies bedeutet, dass das System einen geringen Parallelitätsgrad aufweist, da nur so viele Transaktionen gleichzeitig ausgeführt werden können, wie Kerne für SQL verfügbar sind.Low number of cores available to SQL Server: This means there will be a low level of concurrency in the system, as there can only be as many concurrently executing transactions as there are cores available to SQL.

    • Symptom: Wenn die CPU-Auslastung beim Ausführen der Arbeitsauslastung für datenträgerbasierte Tabellen hoch ist, liegen normalerweise wenig Konflikte vor, was auf eine fehlende Parallelität hinweist.Symptom: if the CPU utilization is high when running the workload on disk-based tables, this means there is not a lot of contention, pointing to a lack of concurrency.
  • Geschwindigkeit des Protokolllaufwerks: Wenn das Protokolllaufwerk für den Transaktionsdurchsatz im System zu langsam ist, verursacht die Arbeitsauslastung bei E/A-Protokollvorgängen einen Engpass.Speed of the log drive: If the log drive cannot keep up with the level of transaction throughput in the system, the workload becomes bottlenecked on log IO. Obwohl die Protokollierung mit In-Memory OLTP effizienter ist, wenn E/A-Protokollvorgänge einen Engpass verursachen, ist der potenzielle Leistungsgewinn begrenzt.Although logging is more efficient with In-Memory OLTP, if log IO is a bottleneck, the potential performance gain is limited.

    • Symptom: Wenn die CPU-Auslastung beim Ausführen der Arbeitsauslastung für speicheroptimierte Tabellen nicht nahe 100 % liegt oder unregelmäßige Spitzen aufweist, kann ein Engpass bei E/A-Protokollvorgängen vorliegen.Symptom: if the CPU utilization is not close to 100% or is very spiky when running the workload on memory-optimized tables, it is possible there is a log IO bottleneck. Sie können die Ursache im Ressourcenmonitor anhand der Warteschlangenlänge für das Protokolllaufwerk ermitteln.This can be confirmed by opening Resource Monitor and looking at the queue length for the log drive.

Arbeitsspeicher- und Datenträgernutzung im BeispielMemory and Disk Space Utilization in the Sample

Im Folgenden wird beschrieben, wie viel Arbeitsspeicher und Datenträgerspeicher für die Beispieldatenbank benötigt wird.In the below we describe what to expect in terms of memory and disk space utilization for the sample database. Außerdem sind die Ergebnisse aufgeführt, die auf einem Testserver mit 16 logischen Kernen ermittelt wurden.We also show the results we have seen in on a test server with 16 logical cores.

Arbeitsspeichernutzung für speicheroptimierte TabellenMemory utilization for the memory-optimized tables

Gesamtnutzung der DatenbankOverall utilization of the database

Mithilfe der folgenden Abfrage kann die gesamte Arbeitsspeichernutzung für In-Memory OLTP im System ermittelt werden.The following query can be used to obtain the total memory utilization for In-Memory OLTP in the system.

SELECT type  
   , name  
, pages_kb/1024 AS pages_MB   
FROM sys.dm_os_memory_clerks WHERE type LIKE '%xtp%'  

Momentaufnahme direkt nach der Erstellung der Datenbank:Snapshot after the database has just been created:

typetype namename pages_MBpages_MB
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 9494
MEMORYCLERK_XTPMEMORYCLERK_XTP DB_ID_5DB_ID_5 877877
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00

Die standardmäßigen Arbeitsspeicherclerks basieren auf systemweiten Strukturen und sind relativ klein.The default memory clerks contain system-wide memory structures and are relatively small. Der Arbeitsspeicherclerk für die Benutzerdatenbank, d. h. die Datenbank mit der ID 5, umfasst etwa 900 MB.The memory clerk for the user database, in this case database with ID 5, is about 900 MB.

Arbeitsspeichernutzung pro TabelleMemory utilization per table

Mithilfe der folgenden Abfrage kann ein Drilldown ausgeführt werden, um die Arbeitsspeichernutzung der einzelnen Tabellen und ihrer Indizes zu ermitteln:The following query can be used to drill down into the memory utilization of the individual tables and their indexes:

SELECT object_name(t.object_id) AS [Table Name]  
     , memory_allocated_for_table_kb  
 , memory_allocated_for_indexes_kb  
FROM sys.dm_db_xtp_table_memory_stats dms JOIN sys.tables t   
ON dms.object_id=t.object_id  
WHERE t.type='U'  

Die folgende Tabelle zeigt die Ergebnisse, die diese Abfrage bei einer Neuinstallation des Beispiels zurückgibt:The following table displays the results of this query for a fresh installation of the sample:

TabellennameTable Name memory_allocated_for_table_kbmemory_allocated_for_table_kb memory_allocated_for_indexes_kbmemory_allocated_for_indexes_kb
SpecialOfferProduct_inmemSpecialOfferProduct_inmem 6464 38403840
DemoSalesOrderHeaderSeedDemoSalesOrderHeaderSeed 19841984 55045504
SalesOrderDetail_inmemSalesOrderDetail_inmem 1531615316 663552663552
DemoSalesOrderDetailSeedDemoSalesOrderDetailSeed 6464 1043210432
SpecialOffer_inmemSpecialOffer_inmem 33 81928192
SalesOrderHeader_inmemSalesOrderHeader_inmem 71687168 147456147456
Product_inmemProduct_inmem 124124 1235212352

Sie sehen, dass die Tabellen relativ klein sind: „SalesOrderHeader_inmem“ umfasst ca. 7 MB und „SalesOrderDetail_inmem“ ca. 15 MB.As you can see the tables are fairly small: SalesOrderHeader_inmem is about 7 MB, and SalesOrderDetail_inmem is about 15 MB in size.

Hier fällt auf, dass die den Indizes zugeordnete Arbeitsspeicherkapazität deutlich über der Kapazität der Tabellendaten liegt.What is striking here is the size of the memory allocated for indexes, compared to the size of the table data. Dies liegt daran, dass die Datengröße für die Hashindizes im Beispiel vorab auf einen höheren Wert festgelegt wurde.That is because the hash indexes in the sample are pre-sized for a larger data size. Da Hashindizes über eine feste Größe verfügen, wachsen sie nicht mit der Größe der Daten in der Tabelle mit.Note that hash indexes have a fixed size, and thus their size will not grow with the size of data in the table.

Arbeitsspeichernutzung nach dem Ausführen der ArbeitsauslastungMemory utilization after running the workload

Nach 10 Millionen eingefügten Verkaufsaufträgen stellt sich die Arbeitsspeichernutzung insgesamt wie folgt dar:After insert 10 million sales orders, the all-up memory utilization looks similar to the following:

SELECT type  
, name  
, pages_kb/1024 AS pages_MB   
FROM sys.dm_os_memory_clerks WHERE type LIKE '%xtp%'  
typetype namename pages_MBpages_MB
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 146146
MEMORYCLERK_XTPMEMORYCLERK_XTP DB_ID_5DB_ID_5 73747374
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00

Wie Sie sehen, belegt SQL Server etwas weniger als 8 GB für die speicheroptimierten Tabellen und Indizes in der Beispieldatenbank.As you can see, SQL Server is using a bit under 8 GB for the memory-optimized tables and indexes in the sample database.

Nach einem Testlauf ergibt sich die folgende Arbeitsspeichernutzung nach Tabellen:Looking at the detailed memory usage per table after one example run:

SELECT object_name(t.object_id) AS [Table Name]  
     , memory_allocated_for_table_kb  
 , memory_allocated_for_indexes_kb  
FROM sys.dm_db_xtp_table_memory_stats dms JOIN sys.tables t   
ON dms.object_id=t.object_id  
WHERE t.type='U'  
TabellennameTable Name memory_allocated_for_table_kbmemory_allocated_for_table_kb memory_allocated_for_indexes_kbmemory_allocated_for_indexes_kb
SalesOrderDetail_inmemSalesOrderDetail_inmem 51137615113761 663552663552
DemoSalesOrderDetailSeedDemoSalesOrderDetailSeed 6464 1036810368
SpecialOffer_inmemSpecialOffer_inmem 22 81928192
SalesOrderHeader_inmemSalesOrderHeader_inmem 15756791575679 147456147456
Product_inmemProduct_inmem 111111 1203212032
SpecialOfferProduct_inmemSpecialOfferProduct_inmem 6464 37123712
DemoSalesOrderHeaderSeedDemoSalesOrderHeaderSeed 19841984 55045504

Die Gesamtmenge an Daten beträgt etwa 6,5 GB.We can see a total of about 6.5 GB of data. Beachten Sie, dass die Größe der Indizes für die Tabellen SalesOrderHeader_inmem und SalesOrderDetail_inmem der Größe der Indizes vor dem Einfügen der Verkaufsaufträge entspricht.Notice that the size of the indexes on the table SalesOrderHeader_inmem and SalesOrderDetail_inmem is the same as the size of the indexes before inserting the sales orders. Die Indexgröße hat sich nicht geändert, weil beide Tabellen Hashindizes verwenden, die wiederum statisch sind.The index size did not change because both tables are using hash indexes, and hash indexes are static.

Nach dem Zurücksetzen der exemplarischen ArbeitauslastungAfter demo reset

Die gespeicherte Prozedur Demo.usp_DemoReset kann verwendet werden, um die exemplarische Arbeitsauslastung zurückzusetzen.The stored procedure Demo.usp_DemoReset can be used to reset the demo. Durch sie werden die Daten in den Tabellen SalesOrderHeader_inmem und SalesOrderDetail_inmem gelöscht und mit neuen Ausgangsdaten aus den urspünglichen Tabellen SalesOrderHeader und SalesOrderDetail aufgefüllt.It deletes the data in the tables SalesOrderHeader_inmem and SalesOrderDetail_inmem, and re-seeds the data from the original tables SalesOrderHeader and SalesOrderDetail.

Obwohl die Zeilen in den Tabellen gelöscht wurden, bedeutet dies nicht, dass der Arbeitsspeicher sofort freigegeben wird.Now, even though the rows in the tables have been deleted, this does not mean that memory is reclaimed immediately. SQL Server gibt den Arbeitsspeicher, der von den aus speicheroptimierten Tabellen gelöschten Zeilen belegt wurde, nach Bedarf im Hintergrund frei.SQL Server reclaims memory from deleted rows in memory-optimized tables in the background, as needed. Wenn im System keine Transaktionen ausgeführt werden, werden Sie feststellen, dass der von den gelöschten Zeilen belegte Arbeitsspeicher unmittelbar nach dem Zurücksetzen der exemplarischen Arbeitsauslastung noch nicht freigegeben wurde:You will see that immediately after demo reset, with no transactional workload on the system, memory from deleted rows is not yet reclaimed:

SELECT type  
, name  
, pages_kb/1024 AS pages_MB   
FROM sys.dm_os_memory_clerks WHERE type LIKE '%xtp%'  
typetype namename pages_MBpages_MB
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 22612261
MEMORYCLERK_XTPMEMORYCLERK_XTP DB_ID_5DB_ID_5 73967396
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00

Erwartetes Verhalten: Der Arbeitsspeicher wird beim Ausführen der Transaktionsarbeitsauslastung freigegeben.This is expected: memory will be reclaimed when the transactional workload is running.

Wenn Sie die exemplarische Arbeitsauslastung ein zweites Mal ausführen, werden Sie anfänglich einen Rückgang der Arbeitsspeichernutzung feststellen, da die zuvor gelöschten Zeilen bereinigt werden.If you start a second run of the demo workload you will see the memory utilization decrease initially, as the previously deleted rows are cleaned up. Gleichzeitig nimmt die Arbeitsspeichergröße wieder zu, bis die Arbeitsauslastung abgeschlossen wurde.At some point the memory size will increase again, until the workload finishes. Nachdem die exemplarische Arbeitsauslastung zurückgesetzt und 10 Millionen Zeilen eingefügt wurden, entspricht die Arbeitsspeichernutzung weitestgehend der Nutzung nach der ersten Ausführung.After inserting 10 million rows after demo reset, the memory utilization will be very similar to the utilization after the first run. Beispiel:For example:

SELECT type  
, name  
, pages_kb/1024 AS pages_MB   
FROM sys.dm_os_memory_clerks WHERE type LIKE '%xtp%'  
typetype namename pages_MBpages_MB
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 18631863
MEMORYCLERK_XTPMEMORYCLERK_XTP DB_ID_5DB_ID_5 73907390
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00
MEMORYCLERK_XTPMEMORYCLERK_XTP StandardDefault 00

Datenträgernutzung für speicheroptimierte TabellenDisk utilization for memory-optimized tables

Mithilfe der folgenden Abfrage können Sie ermitteln, wie viel Gesamtspeicherplatz die Prüfpunktdateien einer Datenbank zu einem bestimmten Zeitpunkt auf dem Datenträger belegen:The overall on-disk size for the checkpoint files of a database at a given time can be found using the query:

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]  
FROM sys.filegroups f JOIN sys.database_files df   
   ON f.data_space_id=df.data_space_id  
WHERE f.type=N'FX'  
  

AnfangszustandInitial state

Bei der Erstellung der Beispieldateigruppe und der speicheroptimierten Beispieltabellen werden eine Reihe von Prüfpunktdateien vorab erstellt, und das System beginnt, die Dateien mit Daten aufzufüllen. Wie viele Prüfpunktdateien vorab erstellt werden, hängt von der Anzahl der logischen Prozessoren im System ab.When the sample filegroup and sample memory-optimized tables are created initially, a number of checkpoint files are pre-created and the system starts filling the files - the number of checkpoint files pre-created depends on the number of logical processors in the system. Da das Beispiel zunächst noch sehr klein ist, sind die vorab erstellten Dateien anfänglich überwiegend leer.As the sample is initially very small, the pre-created files will be mostly empty after initial create.

Der folgende Code zeigt die anfängliche Größe des Beispiels auf dem Datenträger eines Computers mit 16 logischen Prozessoren:The following code shows the initial on-disk size for the sample on a machine with 16 logical processors:

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]  
FROM sys.filegroups f JOIN sys.database_files df   
   ON f.data_space_id=df.data_space_id  
WHERE f.type=N'FX'  
Größe auf dem Datenträger (MB)On-disk size in MB
23122312

Wie Sie sehen, besteht eine große Diskrepanz zwischen der Größe der Prüfpunktdateien auf dem Datenträger, die 2,3 GB beträgt, und der tatsächlichen Datengröße, die eher bei 30 MB liegt.As you can see, there is a big discrepancy between the on-disk size of the checkpoint files, which is 2.3 GB, and the actual data size, which is closer to 30 MB.

Mithilfe der folgenden Abfrage können Sie untersuchen, worauf die Datenträgerbelegung zurückzuführen ist.Looking closer at where the disk-space utilization comes from, you can use the following query. Die Größe auf dem Datenträger, die von dieser Abfrage zurückgegeben wird, stellt bei Dateien mit Status 5 (REQUIRED FOR BACKUP/HA), 6 (IN TRANSITION TO TOMBSTONE) oder 7 (TOMBSTONE) einen Schätzwert dar.The size on disk returned by this query is approximate for files with state in 5 (REQUIRED FOR BACKUP/HA), 6 (IN TRANSITION TO TOMBSTONE), or 7 (TOMBSTONE).

SELECT state_desc  
 , file_type_desc  
 , COUNT(*) AS [count]  
 , SUM(CASE  
   WHEN state = 5 AND file_type=0 THEN 128*1024*1024  
   WHEN state = 5 AND file_type=1 THEN 8*1024*1024  
   WHEN state IN (6,7) THEN 68*1024*1024  
   ELSE file_size_in_bytes  
    END) / 1024 / 1024 AS [on-disk size MB]   
FROM sys.dm_db_xtp_checkpoint_files  
GROUP BY state, state_desc, file_type, file_type_desc  
ORDER BY state, file_type  

Im Anfangszustand erzielt das Beispiel Ergebnisse, die in etwa denen eines Servers mit 16 logischen Prozessoren entsprechen:For the initial state of the sample, the result will look something like for a server with 16 logical processors:

state_descstate_desc file_type_descfile_type_desc countcount Größe auf dem Datenträger (MB)on-disk size MB
PRECREATEDPRECREATED DATADATA 1616 20482048
PRECREATEDPRECREATED DELTADELTA 1616 128128
UNDER CONSTRUCTIONUNDER CONSTRUCTION DATADATA 11 128128
UNDER CONSTRUCTIONUNDER CONSTRUCTION DELTADELTA 11 88

Wie Sie sehen, wird der meiste Speicherplatz durch vorab erstellte Daten- und Änderungsdateien belegt.As you can see, most of the space is used by precreated data and delta files. SQL Server hat vorab ein Dateipaar (bestehend aus Daten- und Änderungsdatei) pro logischem Prozessor erstellt.SQL Server pre-created one pair of (data, delta) files per logical processor. Darüber hinaus wird für Datendateien vorab eine Größe von 128 MB und für Änderungsdateien eine Größe von 8 MB festgelegt. So können Daten effizienter in diese Dateien eingefügt werden.In addition, data files are pre-sized at 128 MB, and delta files at 8 MB, in order to make inserting data into these files more efficient.

Die tatsächlichen Daten der speicheroptimierten Tabellen sind in einer einzelnen Datendatei gespeichert.The actual data in the memory-optimized tables is in the single data file.

Nach dem Ausführen der ArbeitsauslastungAfter running the workload

Nach einem einzelnen Testlauf, bei dem 10 Millionen Verkaufsaufträge eingefügt wurden, wird in etwa folgender Gesamtspeicherplatz auf dem Datenträger belegt (Testserver mit 16 Kernen):After a single test run that inserts 10 million sales orders, the overall on-disk size looks something like this (for a 16-core test server):

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]  
FROM sys.filegroups f JOIN sys.database_files df   
   ON f.data_space_id=df.data_space_id  
WHERE f.type=N'FX'  
Größe auf dem Datenträger (MB)On-disk size in MB
88288828

Die Größe auf dem Datenträger liegt bei etwa 9 GB. Dies entspricht weitestgehend der Größe der Daten im Arbeitsspeicher.The on-disk size is close to 9 GB, which comes close to the in-memory size of the data.

Im Folgenden sind die Größen der Prüfpunktdateien in den einzelnen Phasen aufgeschlüsselt:Looking more closely at the sizes of the checkpoint files across the various states:

SELECT state_desc  
 , file_type_desc  
 , COUNT(*) AS [count]  
 , SUM(CASE  
   WHEN state = 5 AND file_type=0 THEN 128*1024*1024  
   WHEN state = 5 AND file_type=1 THEN 8*1024*1024  
   WHEN state IN (6,7) THEN 68*1024*1024  
   ELSE file_size_in_bytes  
    END) / 1024 / 1024 AS [on-disk size MB]   
FROM sys.dm_db_xtp_checkpoint_files  
GROUP BY state, state_desc, file_type, file_type_desc  
ORDER BY state, file_type  
state_descstate_desc file_type_descfile_type_desc countcount Größe auf dem Datenträger (MB)on-disk size MB
PRECREATEDPRECREATED DATADATA 1616 20482048
PRECREATEDPRECREATED DELTADELTA 1616 128128
UNDER CONSTRUCTIONUNDER CONSTRUCTION DATADATA 11 128128
UNDER CONSTRUCTIONUNDER CONSTRUCTION DELTADELTA 11 88

Es sind weiterhin 16 vorab erstellte Dateipaare verfügbar, die nach dem Schließen der Prüfpunkte sofort einsatzbereit sind.We still have 16 pairs of pre-created files, ready to go as checkpoints are closed.

Ein Paar wird gerade erstellt, das bis zum Schließen des aktuellen Prüfpunkts verwendet wird.There is one pair under construction, which is used until the current checkpoint is closed. Zusammen mit den aktiven Prüfpunktdateien ergeben 6,5 GB Daten im Arbeitsspeicher eine Datenträgernutzung von ca. 6,5 GB.Along with the active checkpoint files this gives about 6.5 GB of disk utilization for 6.5 GB of data in memory. Wie Sie wissen, werden Indizes nicht dauerhaft auf dem Datenträger gespeichert. Folglich ist die Gesamtgröße auf dem Datenträger in diesem Fall kleiner als die Datengröße im Arbeitsspeicher.Recall that indexes are not persisted on disk, and thus the overall size on disk is smaller than the size in memory in this case.

Nach dem Zurücksetzen der exemplarischen ArbeitauslastungAfter demo reset

Nach dem Zurücksetzen der exemplarischen Arbeitsauslastung wird der Speicherplatz auf dem Datenträger nicht sofort freigegeben, wenn das System keine Transaktionen ausführt und keine Datenbank-Prüfpunkte vorhanden sind.After demo reset, disk space is not reclaimed immediately if there is no transactional workload on the system, and there are not database checkpoints. Damit Prüfpunktdateien die verschiedenen Phasen durchlaufen und schließlich entfernt werden können, müssen eine Reihe von Prüfpunkten sowie Protokollkürzungen vorangegangen sein. Das ist erforderlich, um die Zusammenführung von Prüfpunktdateien sowie die Garbage Collection zu initiieren.For checkpoint files to be moved through their various stages and eventually be discarded, a number of checkpoints and log truncation events need to happen, to initiate merge of checkpoint files, as well as to initiate garbage collection. Wenn das System Transaktionen ausführt (und Sie bei Verwendung des vollständigen Wiederherstellungsmodells regelmäßige Protokollsicherungen vornehmen), erfolgt dieser Schritt automatisch. Befindet sich das System wie im Beispielszenario jedoch im Leerlauf, wird dieser Schritt nicht ausgeführt.These will happen automatically if you have a transactional workload in the system [and take regular log backups, in case you are using the FULL recovery model], but not when the system is idle, as in a demo scenario.

Nach dem Zurücksetzen der exemplarischen Arbeitauslastung sehen Sie in etwa folgende ErgebnisseIn the example, after demo reset, you may see something like

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]  
FROM sys.filegroups f JOIN sys.database_files df   
   ON f.data_space_id=df.data_space_id  
WHERE f.type=N'FX'  
Größe auf dem Datenträger (MB)On-disk size in MB
1183911839

Mit fast 12 GB liegen die Ergebnisse deutlich über den 9 GB vor dem Zurücksetzen der exemplarischen Arbeitsauslastung.At nearly 12 GB, this is significantly more than the 9 GB we had before the demo reset. Dies ist darauf zurückzuführen, dass die Zusammenführung einiger Prüfpunktdateien zwar bereits gestartet, einige der Zusammenführungsziele jedoch noch nicht installiert wurden. Darüber hinaus wurden einige der zusammengeführten Quelldateien noch nicht bereinigt, wie im Folgenden ersichtlich:This is because some checkpoint file merges have been started, but some of the merge targets have not yet been installed, and some of the merge source files have not yet been cleaned up, as can be seen from the following:

SELECT state_desc  
 , file_type_desc  
 , COUNT(*) AS [count]  
 , SUM(CASE  
   WHEN state = 5 AND file_type=0 THEN 128*1024*1024  
   WHEN state = 5 AND file_type=1 THEN 8*1024*1024  
   WHEN state IN (6,7) THEN 68*1024*1024  
   ELSE file_size_in_bytes  
    END) / 1024 / 1024 AS [on-disk size MB]   
FROM sys.dm_db_xtp_checkpoint_files  
GROUP BY state, state_desc, file_type, file_type_desc  
ORDER BY state, file_type  
state_descstate_desc file_type_descfile_type_desc countcount Größe auf dem Datenträger (MB)on-disk size MB
PRECREATEDPRECREATED DATADATA 1616 20482048
PRECREATEDPRECREATED DELTADELTA 1616 128128
ACTIVEACTIVE DATADATA 3838 51525152
ACTIVEACTIVE DELTADELTA 3838 13311331
MERGE TARGETMERGE TARGET DATADATA 77 896896
MERGE TARGETMERGE TARGET DELTADELTA 77 5656
MERGED SOURCEMERGED SOURCE DATADATA 1313 17721772
MERGED SOURCEMERGED SOURCE DELTADELTA 1313 455455

Sobald Transaktionsaktivitäten im System auftreten, werden Zusammenführungsziele installiert und zusammengeführte Quelldateien bereinigt.Merge targets are installed and merged source are cleaned up as transactional activity happens in the system.

Nachdem die exemplarische Arbeitsauslastung ein zweites Mal ausgeführt, zurückgesetzt und 10 Millionen Verkaufsaufträge eingefügt wurden, werden Sie feststellen, dass die während der ersten Ausführung der Arbeitsauslastung erstellten Dateien bereinigt wurden.After a second run of the demo workload, inserting 10 million sales orders after the demo reset, you will see that the files constructed during the first run of the workload have been cleaned up. Wenn Sie die vorangehende Abfrage bei aktiver Arbeitsauslastung mehrere Male ausführen, können Sie beobachten, wie die Prüfpunktdateien die verschiedenen Phasen durchlaufen.If you run the above query several times while the workload is running, you can see the checkpoint files make their way through the various stages.

Nachdem die Arbeitsauslastung zum zweiten Mal ausgeführt und 10 Millionen Verkaufsaufträge eingefügt wurden, ist die Datenträgernutzung ähnlich (wenn auch nicht identisch) mit der Nutzung nach der ersten Ausführung. Dies liegt an der Dynamik des Systems.After the second run of the workload insert 10 million sales orders you will see disk utilization very similar to, though not necessarily the same as after the first run, as the system is dynamic in nature. Beispiel:For example:

SELECT state_desc  
 , file_type_desc  
 , COUNT(*) AS [count]  
 , SUM(CASE  
   WHEN state = 5 AND file_type=0 THEN 128*1024*1024  
   WHEN state = 5 AND file_type=1 THEN 8*1024*1024  
   WHEN state IN (6,7) THEN 68*1024*1024  
   ELSE file_size_in_bytes  
    END) / 1024 / 1024 AS [on-disk size MB]   
FROM sys.dm_db_xtp_checkpoint_files  
GROUP BY state, state_desc, file_type, file_type_desc  
ORDER BY state, file_type  
state_descstate_desc file_type_descfile_type_desc countcount Größe auf dem Datenträger (MB)on-disk size MB
PRECREATEDPRECREATED DATADATA 1616 20482048
PRECREATEDPRECREATED DELTADELTA 1616 128128
UNDER CONSTRUCTIONUNDER CONSTRUCTION DATADATA 22 268268
UNDER CONSTRUCTIONUNDER CONSTRUCTION DELTADELTA 22 1616
ACTIVEACTIVE DATADATA 4141 56085608
ACTIVEACTIVE DELTADELTA 4141 328328

In diesem Fall gibt es zwei Prüfpunktdateipaare mit dem Status „under construction“. Das legt die Vermutung nahe, dass aufgrund des hohen Parallelitätsgrads der Arbeitsauslastung mehrere Dateipaare in den Status „under construction“ versetzt wurden.In this case, there are two checkpoint file pairs in the 'under construction' state, which means multiple file pairs were moved to the 'under construction' state, likely due to the high level of concurrency in the workload. Mehrere gleichzeitige Threads erforderten also zur selben Zeit ein neues Dateipaar, wodurch sich der Status eines Paares von „precreated“ in „under construction“ geändert hat.Multiple concurrent threads required a new file pair at the same time, and thus moved a pair from 'precreated' to 'under construction'.

Weitere InformationenSee Also

In-Memory-OLTP (Arbeitsspeicheroptimierung)In-Memory OLTP (In-Memory Optimization)