SQL Server 2014 In-Memory OLTP Mikael Colliander Principal TSP - Application Platform Microsoft Enterprise & Partner Group
Session Objective(s): Understand the SQL Server 2014 In-Memory OLTP value proposition Understand how In-memory OLTP helps make applications faster, and what some of the limitations are Key Takeaway 1 SQL Server in-memory OLTP can make applications run very fast on commodity hardware Key Takeaway 2 SQL Server in-memory OLTP is designed for OLTP style workloads, and does require some code modifications.
Business Trends Market need in OLTP space Examples - Ever higher throughput - Lower latency - at a lower cost Examples - Credit-card transactions: validate, authorize and complete the transaction - Online-betting: Ability to place the bet quickly - Stock trading: microsecond - ETL/ELT high load scenarios - Handle volume spikes / Chock absorber
Hardware Trends Moore’s Law means more transistors and therefore cores, but… CPU clock rate stalled… Meanwhile RAM cost continues to drop Chart reference http://www.gotw.ca/publications/concurrency-ddj.htm
What is SQL Server In-Memory OLTP? 1. High performance 2. Main memory-optimized 3. OLTP scenarios 4. Integrated into SQL Server 5. Architected for modern hardware trends
In-Memory OLTP – Architectural Pillars Customer Benefits High performance data operations Efficient business-logic processing Frictionless scale-up Hybrid engine and integrated experience Architectural Pillars Main-Memory Optimized T-SQL Compiled to Machine Code High Concurrency SQL Server Integration Optimized for in-memory data Indexes (hash and range) exist only in memory No buffer pool, B-trees Stream-based storage T-SQL compiled to machine code via C code generator and VC Invoking a procedure is just a DLL entry-point Aggressive optimizations @ compile-time Multi-version optimistic concurrency control with full ACID support Core engine uses lock-free algorithms No lock manager, latches or spinlocks Same manageability, administration & development experience Integrated queries & transactions Integrated HA and backup/restore Drivers Hardware trends Business Steadily declining memory price, NVRAM Stalling CPU clock rate Many-core processors TCO
In-Memory OLTP Integration and Application Migration Client App TDS Handler and Session Management Key SQL Server.exe Parser, Catalog, Optimizer Existing SQL Component T-SQL Query Execution Natively Compiled SPs and Schema Native Compiler In-mem OLTP Component Non-durable table Query Interop Memory Optimized Tables & Indexes Buffer Pool for Tables & Indexes T1 T2 Generated .dll T3 Tables Indexes Memory Optimized Data Filegroup Transaction Log Data Filegroup T1 T2 T3 T1 T2 T3
Demo 1 – Traditional Table
Create Table DDL Hash Index Secondary Indexes are specified inline CREATE TABLE [Customer]( [CustomerID] INT NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 1000000), [Name] NVARCHAR(250) NOT NULL INDEX [IName] HASH WITH (BUCKET_COUNT = 1000000), [CustomerSince] DATETIME NULL ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA); Hash Index Secondary Indexes are specified inline This table is memory optimized This table is durable
Memory Optimized Table Creation CREATE TABLE DDL Code generation and compilation Table DLL produced Table DLL loaded
Create Procedure DDL CREATE PROCEDURE [dbo].[InsertOrder] @id INT, @date DATETIME WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER AS BEGIN ATOMIC (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'us_english') -- insert T-SQL here END This proc is natively compiled Native procs must be schema-bound Execution context is required Atomic blocks Create a transaction if there is none Otherwise, create a savepoint Session settings are fixed at create time
Procedure Creation CREATE PROC DDL Query optimization Code generation and compilation Procedure DLL produced Procedure DLL loaded
What is a latch? It’s all about “physical” protection Introduced in SQL 7.0 for database pages What is a latch? It’s all about “physical” protection Thread synchronization for important data structures or concurrency sensitive code No isolation level or transaction semantics Ownership and Waiters Compatibility Matrix (Modes) Not directly under user control EX, SH, …. There is no latch hint
Some page changes are just in header (Ex. Checksum, torn page bits) Why aren’t locks enough? Some page changes are just in header (Ex. Checksum, torn page bits) INSERT VALUES (3,300) Page 100 96 1 Page 100 m_freedata=126 100 2 200 111 EX_LATCH IX Page 100 m_freedata=126 156 141 1 100 2 200 3 4 400 300 4 400 INSERT VALUES (4,400) 141 126 111 96 EX_LATCH IX Page 100
Demo 2 – Introducing Mem. Opt. Tables
Demo 3 – Introducing Natively Com. Proc.
Performance Gains Client App SQL Server.exe TDS Handler and Session Management Key No improvements in communication stack, parameter passing, result set generation Existing SQL Component Parser, Catalog, Optimizer T-SQL Query Execution Native Compiler In-mem OLTP Component Natively Compiled SPs and Schema 10-30x more efficient Generated .dll Query Interop Removes lock and latch contention Engine for Memory_optimized Tables & Indexes Buffer Pool for Tables & Indexes Reduced bandwidth. Latency remains Memory-optimized Table Filegroup Transaction Log Data Filegroup Persistence uses sequential IO
In-Memory Data Structures Rows New row format Structure of the row is optimized for memory residency and access No page containers Rows are versioned (payload never updated in place) Indexes Nonclustered Indexes only Indexes point to rows, they do not duplicate them Nonclustered hash index for point lookups Memory-optimized nonclustered index for range and ordered scans (In CTP2) Not logged and do not exist on disk – maintained online or recreated during recovery
Payload (table columns) Memory-optimized Table: Row Format Row header Payload (table columns) Begin Ts End Ts StmtId IdxLinkCount 8 bytes 4 bytes 2 bytes 8 bytes * (IdxLinkCount) Key Points Begin/End timestamp determines row’s version validity and visibility No data pages; just rows Row size limited to 8060 bytes (@table create time) to allow data to be moved to disk-based table Not every SQL table schema is supported (for example LOB and sqlvariant)
Hash index with (bucket_count=8): Hash Indexes Hash index with (bucket_count=8): Hash function f: Maps values to buckets Built into the system Hash mapping: f(Jane) 4 5 6 7 1 2 3 Array of 8-byte Memory pointers f(John) f(Prague) Hash Collisions f(Susan) f(Bogota), f(Beijing)
Memory Optimized Tables and Indexes Timestamps Chain ptrs Name City Hash index on City Hash index on Name f(Jane) 50, ∞ Jane Prague f(Prague) f(Susan) f(Bogota) 90, ∞ Susan Bogota
Memory Optimized Tables and Indexes Timestamps Chain ptrs Name City Hash index on City Hash index on Name 50, ∞ Jane Prague f(Prague) f(John) 100, ∞ John Prague 90, ∞ Susan Bogota T100: INSERT (John, Prague)
Memory Optimized Tables and Indexes Timestamps Chain ptrs Name City Hash index on City Hash index on Name 50, ∞ Jane Prague 100, ∞ John Prague 90, ∞ Susan Bogota 90, 150 T150: DELETE (Susan, Bogota)
Memory Optimized Tables and Indexes Timestamps Chain ptrs Name City Hash index on City Hash index on Name 50, ∞ Jane Prague f(John) 100, 200 100, ∞ John Prague f(Beijing) 200, ∞ John Beijing 90, 150 Susan Bogota T200: UPDATE (John, Prague) to (John, Beijing)
Memory Optimized Tables and Indexes Timestamps Chain ptrs Name City Hash index on City Hash index on Name f(Jane) 50, ∞ Jane Prague f(Prague) f(John) 100, 200 John Prague f(Beijing) 200, ∞ John Beijing 90, 150 Susan Bogota T250: Garbage collection
Limitations on Tables in SQL 2014 Optimized for high-throughput OLTP No DML triggers No XML and no CLR data types Optimized for in-memory Rows are at most 8060 bytes – no off row data No Large Object (LOB) types like varchar(max) Scoping limitations No FOREIGN KEY and no CHECK constraints No IDENTITY No schema changes (ALTER TABLE) – need to drop/recreate table No add/remove index – need to drop/recreate table
Suitable Application Characteristics Application is suited for in-memory processing All performance critical data already fits in memory Transaction locking or physical latching causing stalls and blocking Application is “OLTP-Like” Relatively short-lived transactions High degree of concurrent transactions from many connections Examples: Stock trading, travel reservations, order processing Application migration simplified if Stored procedures used Performance problems isolated to subset of tables and SPs
Assess workload for migration Not all scenarios can take advantage of In-memory OLTP Resource Commitment/Ability to change code Hardware limitations Bottleneck cannot be addressed by migration (outside of In-memory OLTP Engine) Workload – Complete Data Warehouse, Long Running Reporting, XML/Full-Text Establish performance baseline and goals Identify perf bottlenecks Utilize AMR (Analyze, Migrate, Report) to help migration Targeted, staged migration Migrate only necessary pieces Start with tables, then T-SQL code and iterate Validate against perf goals
Summary: Key Takeaway 1 Key Takeaway 2 Understand the SQL Server 2014 In-Memory OLTP value proposition Understand how In-memory OLTP helps make applications faster, and what some of the limitations are Key Takeaway 1 SQL Server in-memory OLTP can make applications run very fast on commodity hardware Key Takeaway 2 SQL Server in-memory OLTP is designed for OLTP style workloads, and does require some code modifications.
Appendix
Internals Whitepaper: SQL Server In-Memory OLTP Internals Overview for CTP2
TechReady 17 9/14/2018 Retrieve BLOB CREATE PROCEDURE [dbo].[RetrieveBLOB] @id nvarchar(88), @TheBlob varbinary(max) OUTPUT AS BEGIN DECLARE @Part int=0 DECLARE @DoesPartExist bit=0 DECLARE @Chunk varbinary(7000)=0x01 -- Set output variable to NULL, so NULL returned if the item does not exist SET @TheBlob=NULL exec GetLongItemPart_Hekaton @id, @Part, @Chunk OUTPUT, @DoesPartExist OUTPUT SET @Part=7000 if @DoesPartExist=1 SET @TheBlob=convert(varbinary(max), @Chunk) WHILE @DoesPartExist=1 BEGIN exec GetLongItemPart_Hekaton @id,@Part,@Chunk OUTPUT, @DoesPartExist OUTPUT SET @Part+=7000 if @DoesPartExist=1 SET @TheBlob=@TheBlob+convert(varbinary(max), @Chunk) END GO © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.
Handling Referential Integrity TechReady 17 9/14/2018 Handling Referential Integrity CREATE PROCEDURE evs.usp_EventID_FKCHK @EventID INT WITH EXECUTE AS OWNER, NATIVE_COMPILATION, SCHEMABINDING AS BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = 'english') DECLARE @err nvarchar(200) BEGIN TRY IF (@EventID>=0) BEGIN DECLARE @refexists BIT = 0 SELECT @refexists = 1 FROM [evs].[event] WHERE [ID]=@EventID IF (@refexists = 0) SET @err = N'Foreign key violation for column EventID'; THROW 50001, @err, 1 END BEGIN CATCH THROW; END CATCH END TRY © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.
Workaround Example: IDENTITY Before migration: After migration: CREATE TABLE t1 ( c1 INT NOT NULL IDENTITY ..., c2 INT, c3 DATE) CREATE TABLE t1 ( c1 INT NOT NULL ..., c2 INT, c3 DATE) WITH (MEMORY_OPTIMIZED=ON) CREATE SEQUENCE usq_t1 AS INT START WITH 1 INCREMENT BY 1 CREATE PROC usp_insert @c2 INT, c3 DATE AS BEGIN INSERT INTO t1 VALUES (@c2, @c3) END CREATE PROC usp_insert @c2 INT, c3 DATE AS BEGIN DECLARE @c1 INT = NEXT VALUE FOR usq_t1 INSERT INTO t1 VALUES (@c1, @c2, @c3) END © 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.