SQL Server 2014 In-Memory OLTP Workload Patterns and Migration Considerations TDM White Paper
SQL Server 2014 In-Memory OLTP Workload Patterns and Migration Considerations TDM White Paper
Copyright
This document is provided as-is. Information and views expressed in this document, including URL and
other Internet Web site references, may change without notice. You bear the risk of using it.
Some examples depicted herein are provided for illustration only and are fictitious. No real association
or connection is intended or should be inferred.
This document does not provide you with any legal rights to any intellectual property in any Microsoft
product. You may copy and use this document for your internal, reference purposes.
2014 Microsoft. All rights reserved.
Content
Content ......................................................................................................................................................... 3
Introduction .................................................................................................................................................. 4
SQL Server In-Memory OLTP Overview ........................................................................................................ 4
OLTP Workload Challenges ........................................................................................................................... 5
High Data Ingestion Rate .......................................................................................................................... 6
Read/Write Contention ............................................................................................................................ 6
Low Latency .............................................................................................................................................. 6
Typical Bottlenecks ....................................................................................................................................... 7
Lock, Latch, and Spinlock Contention ....................................................................................................... 7
Transaction Log I/O ................................................................................................................................... 8
Hardware Resources ................................................................................................................................. 8
Overcoming Challenges Utilizing In-Memory OLTP ...................................................................................... 8
Locking and Latching ................................................................................................................................. 8
I/O and Transaction Logging ..................................................................................................................... 8
Latency and Scale ...................................................................................................................................... 9
In-Memory OLTP Common Implementation Scenarios ................................................................................ 9
High Data Insert Rate .............................................................................................................................. 10
Read Performance and Scale .................................................................................................................. 13
Compute Heavy Data Processing ............................................................................................................ 17
Low Latency Execution............................................................................................................................ 19
Session State Management .................................................................................................................... 20
Migrating applications to In-Memory OLTP ................................................................................................ 22
Assessing Workloads for Migration ........................................................................................................ 23
Further Implementation Considerations ................................................................................................ 28
Scenarios Less Suitable for Migration ..................................................................................................... 33
Conclusion ................................................................................................................................................... 34
For more information: ................................................................................................................................ 35
Introduction
The architectural considerations that drove the initial design of relational database management
systems in the early 1980s were largely based on the available hardware resources and the business
needs of the era. Most of these architectural paradigms are still dominant in todays modern database
engines. However, business needs and available hardware resources have changed dramatically since
that time. Therefore, some of these paradigms must be revised in order to keep up with the increasing
demands of today.
Organizations frequently encounter extremely challenging scenarios, which require them to significantly
scale their applications to process ever increasing data volumes and numbers of concurrent users. This
trend is evident across all industries including retail, online banking, online gaming, and so on. At the
same time, many modern business workloads require lower latencies at this scale. This is particularly
true for scenarios where only computer systems (i.e., not responding to a person) originate and process
data. Examples of this machine-born data include financial trading, sensor and smart-metering,
manufacturing, telemetry, security monitoring/analytics, and many others.
Hardware trends have also changed the characteristics of a typical database server. While there is a
continued increase in the number of multi-core processors, their clock speed has not changed
significantly in recent years. However, memory is now less of a constraint. Servers can now
accommodate much more memory into a commodity class server at a much lower price point. This gives
applications the ability to use more main memory instead of incurring disk IO. The past paradigm where
data sizes were far larger than available memory is not as applicable. Additionally, the complex logic for
paging that had to be implemented in RDBMS to support efficient memory utilization is no longer as
relevant.
Even in terms of IO, faster interfaces and the addition of solid-state devices provide greater IO
performance and minimize the IO bottleneck. This growth in multi-core systems allows for a larger
number of concurrent threads to execute. IO improvements also provide faster response times.
Together, these advances push the contention points within the classic relational database architecture
to its limits in many cases.
It is these trends, along with the recognition that typical OLTP behavior in these environments is focused
on a hot dataset ranging from a few GB to a few hundred GB in size which called for a fundamental reevaluation of the current relational database architecture. In-Memory OLTP is this new architecture
designed to alleviate the current database bottlenecks, and take advantage of modern hardware in a
dramatically new way while still integrating into the well-known SQL Server relational engine.
memory data. Data access and transaction isolation are handled through a multi-version, concurrency
control mechanism that provides an optimistic, non-blocking implementation. While implemented
differently from traditional RDBMS, In-Memory OLTP still provides ACID compliance.
The need for critical performance within the engine requires not only a change in the physical storage
architecture, but also optimization of the associated data access programming surface. Natively
compiled stored procedures offer a highly optimized querying mechanism for accessing in-memory data.
Unlike traditional, interpreted Transact-SQL, natively compiled stored procedures are optimized and
compiled into machine language when they are created. This allows a much shorter execution code
path, which in turn significantly reduces CPU utilization and overall latency.
The In-Memory OLTP engine is fully integrated in SQL Server. This provides an easy way for migration of
traditional disk-based tables to memory-optimized tables and interpreted stored procedures to natively
compiled stored procedures. These objects reside in the In-Memory OLTP engine along with traditional
disk-based tables and stored procedures. The integration allows access to data stored in memoryoptimized tables and in disk-based tables using standard Transact-SQL calls (interpreted T-SQL). This
integration can help minimize application changes in converting to In-Memory OLTP.
When migrating SQL Server applications to the In-Memory OLTP engine, you can move performance
critical data into memory-optimized tables and maintain the rest in disk-based tables. Similarly, you can
move the performance critical Transact-SQL code, which interacts with memory-optimized tables, into
natively compiled store procedures. Ad-hoc Transact-SQL or non-natively compiled stored procedures
can still interact with memory-optimized tables. SQL Server Management Studio, backup/restore,
AlwaysOn Failover Cluster Instances, and Availability Groups, among others, are integrated for simplified
management.
Companies with one or more of the following conditions should seriously consider the potential benefits
of migrating to In-Memory OLTP:
Existing SQL Server (or other relational database) applications that require performance and
scalability gains.
A RDBMS that is experiencing database bottlenecks most prevalently around locking/latching
or code execution.
Environments that do not use a relational database in the critical performance path due to the
perceived performance overhead.
Transaction throughput.
Number of concurrent users.
Transaction latency (time to complete a particular piece of code execution).
This document, in many cases, will also utilize the term business transaction to describe a unit of
measure to define application performance. This term refers to a unit of work from an application or
line-of-business perspective. It does not refer to something distinct to a tier. Also, it does not refer to a
piece of the application, such as a performance counter measuring database transactions.
Some of these workload characteristics can vary based on the specific implementation. However, in all
the scenarios in this paper, similar business and application requirements that push performance
bottlenecks into the database are exhibited. This is particularly relevant for applications that manage
business-critical workloads and require extremely demanding levels of performance.
Having an intermediate table that handles the initial load and some form of data movement into
a target table.
Loading directly into the final target table and scaling the concurrency of writes and reads.
The overall performance issue with data ingestion remains the same. To establish baseline
measurements for this environment, the metrics are typically characterized by transaction throughput
or the number of rows loaded per second.
Read/Write Contention
Another typical challenging characteristic of many OLTP workloads appears when many processes are
targeting small regions of data concurrently. Some processes need to read data while others are
modifying it. Although these data sets are typically small, the fact that multiple concurrent user sessions
perform high frequency read and write requests on these datasets, causes contention. This contention
becomes a significant barrier to scale. Some common patterns that display this bottleneck are:
In many cases, these operations are synchronous with the user interaction, and any delay has an
immediate, linear impact on the users experience. Overall, the contention adds significant challenges
for meeting many performance critical application requirements.
Low Latency
Many applications have specific duration requirements for the execution of a particular unit of work.
They may also have time requirements for the end-to-end execution of specific steps that constitute a
business transaction. The applications will measure their performance based on the time it takes to
execute some work in isolation or under load. The unit of measurement may be for a specific query
execution, business transaction, or process. The measurement consists of the time the client application
6
takes to processes the data to the end consumer and all steps in-between. This measurement of these
finer grained executions of work is, in many cases, referred to as latency. Typical latency bottlenecks
that can be attributed in some form to database execution would include:
From a business perspective, these bottlenecks are typically identified as a need for faster execution of a
business transaction. In many cases the latency is measured in milliseconds or lower. Improvements in
latency may also be expressed as greater (business) transaction throughput, greater scale or
concurrency, or more efficient processing of data.
Typical Bottlenecks
The workload patterns we discussed, in performance critical environments, often display similar
bottlenecks in OLTP database applications and architectures. In this section, we will briefly discuss the
primary bottlenecks that high performance OLTP SQL Server and database deployments experience.
Hardware Resources
In many cases, hardware components can become the primary barrier to scalability and performance in
the system. Some common OLTP bottlenecks involving hardware include:
CPU utilization that may be a bottleneck under a heavy OLTP workload. Many times applications
will utilize scale-out scenarios to spread the workload over multiple servers.
The I/O subsystem capabilities can often become a bottleneck. As mentioned earlier,
transaction log I/O may become a bottleneck in transaction execution. Similarly, throughput, as
a measure of IOPS, may contribute to the bottleneck for data/index page allocation and logging.
Throughput may also bottleneck SQL Server database checkpoint behavior.
There are many times when bottlenecks occur and a company attempts to overcome them by using
faster or more efficient hardware. This can be successful in limited cases such as I/O subsystem
bottlenecks. However, you cannot resolve many of the typical OLTP bottlenecks, for example, the
locking or latching contention, using hardware upgrades.
As well, the insert and delete transactions will require less space than disk-based transactions in the
transaction log. Finally, log records can be combined up to 24k to minimize the number of log writes.
Moreover, the system only writes log records at commit time. This limits the number of times a
transaction needs to write to the log buffer. Minimizing this log access reduces contention between
transactions that are trying to access the log buffer concurrently.
In-Memory OLTP also provides a few configurable options to help minimize I/O bottlenecks. The most
extreme option, when compared to fully logging transactions for recovery, is to create the memoryoptimized table with the syntax of DURABILITY = SCHEMA_ONLY. This option provides for recovery of
the schema, but not of the data. Therefore, the system does not need to write to the transaction log for
modifications to these tables. Scenarios where data is transient in nature may benefit greatly from this
option. Several examples where this option may be utilized are discussed later in the paper.
Another configuration option, configured at a database or transaction level, is delayed durability. This
feature is not specific to In-Memory OLTP because you can also implement it as a general configuration
in SQL Server 2014. With delayed durability, the system does not persist the log records to disk on
commit. Instead, the system flushes the log records to disk after a set time (not on every commit) or
when the log buffer fills up. This way, fewer, more efficient, and larger I/Os take place instead of many
small flushes per transaction. Moreover, the system can commit transactions before it writes the log
records to disk. This minimizes the transaction dependency on the physical I/O.
The application design should take into consideration that the Durability = SCHEMA_ONLY and delayed
durability options do not guarantee recovery of all inflight transactions in the event of sever failure. For
more details, see the Books Online section Control Transaction Durability
(http://msdn.microsoft.com/en-us/library/dn449490(v=sql.120).aspx).
Implementation Scenario
Eliminate contention
Minimize I/O logging
Eliminate contention
Efficient data retrieval
Minimize code execution time
CPU efficiency for scale
Insert/Update/Delete workload
Heavy computation inside database
Read and write contention
Eliminate contention
Minimize code execution time
Efficient data processing
Low Latency
Eliminate contention
Minimize code execution time
Efficient data retrieval
Eliminate contention
Efficient data retrieval
Optional I/O reduction/removal
For each scenario, a discussion is provided that describes the general business and application
challenges, and the bottlenecks. We also discuss the considerations for the architecture or design with
In-Memory OLTP that can help improve performance of these workloads. Customer adoption references
are provided for further context.
10
table, and (most likely) delete that data from the memory-optimized table. This data movement is
usually scheduled as a background or SQL Agent process that can execute in a timely fashion.
A typical data movement implementation will usually require a known key or reference value in order to
identify the data for movement. Examples that have been successfully implemented typically include:
A date.
A sequenced value to attribute to some type of time stamp.
A range of values.
This partitioning of both memory-optimized and disk-based tables is often referred to as manual
partitioning. There are no specific system functions similar to the table and index partitioning
operations for disk-based tables in SQL Server. An example of this is provided in the Books Online
section Application Pattern for Partitioning Memory-Optimized Tables (http://msdn.microsoft.com/enus/library/dn133171(v=sql.120).aspx).
Other attributes of the application deployment will impact what data is stored in memory-optimized
tables and how often you move the data to disk-based tables. Among others, these considerations may
include:
The amount of memory that can be allocated to memory-optimized data. The input data will
continue to grow, and there are limits on the amount of memory allocated to SQL Server.
Moving data to disk-based tables can free up some allocated memory. In most cases, this will
not be immediate because of asynchronous garbage collection. If the application has a need to
store a large amount of data, it may not need the entire data-set to be maintained in memoryoptimized tables. Be aware that queries on disk-based tables may also require memory to be
allocated for pages in the SQL Server buffer pool.
There are certain desired attributes for the data that memory-optimized tables do not support.
This may include data encryption, specialized index types, or other options that memoryoptimized tables do not support.
Consider the types of queries and performance requirements of certain queries which may be
best addressed using tables and indexes outside of In-Memory OLTP. For point-lookup queries,
hash indexes can be quite efficient and memory-optimized tables provide these. However, the
workload pattern may be a mix of OLTP and data warehouse style workloads. These data
warehouse style workloads might benefit from solutions like In-Memory Columnstore for Data
Warehouse, or from a parallel execution plan. Neither this index nor the parallel plan can be
utilized when memory-optimized tables are involved. In these cases, moving this data after a
period of time into disk-based tables may prove to be an optimal solution.
As a layer of abstraction between memory-optimized and disk-based tables, a view could also be utilized
to address both tables. In this case, interpreted Transact-SQL would be required to access the view.
Another scenario where In-Memory OLTP can be implemented, and requires the same considerations
around fast data load, is staging tables, typically for the initial data loading into a data warehouse. While
OLTP workloads are the target scenario for In-Memory OLTP optimizations can be realized in this
scenario as well. The system fully supports data imports into memory-optimized tables using bcp.exe,
Bulk Insert, or SSIS packages. However, TABLOCK hints or other locking behaviors, which may be
implemented for fast data loading, are not compatible with In-Memory OLTP and should be removed.
Staging tables are typically used as an intermediate holding area for loading data. Once the data is
processed and moved to its final the destination, the data in the staging table is no longer needed and
12
may be discarded. Additionally, the data can be recreated and reloaded if it was lost during the loading
process. Therefore, in many cases, the memory-optimized tables can be created with DURABILITY =
SCHEMA_ONLY to avoid all logging and I/O.
Also consider that you typically load and then delete, or truncate staging tables. In the case of a
memory-optimized table, you would delete the data because there is no truncate support. Deleting
from memory-optimized tables should be quite fast. However, unlike deleting data from disk-based
tables, row versions will still utilize memory until the garbage collection process cleans up the rows.
Understand that this will temporarily increase the memory requirement. This may have an adverse
effect when a large number of rows are deleted. Therefore, an alternative option would be to drop and
recreate the staging tables.
Finally, consider the location of the tables involved in the data movement. The In-Memory OLTP engine
does not support any transaction that interacts with multiple databases and involves a memoryoptimized table. Therefore, data sources for the staging table must be from an external client
connection, such as SSIS, or from a table within the database. Similarly, the destination table must be in
the same database as the staging tables.
In a number of cases, this configuration has proven successful for ingesting the high volume and
spikes of the workload. This configuration has also provided a successful overall data-tier design
solution to handle these demanding workloads. Customer success and testing with this pattern has also
shown, in many cases, that data loading and data movement back to disk-based tables are faster. That
is, there is less overall latency than directly inserting and querying from a disk-based table.
Customer Adoption
An internal Microsoft application, named Event Reporting, was deployed to provide near real-time
information, including performance data and event logging, from approximately 7,500 data generating
machines. The data streams through a Web API. During high spikes in the input rates, the database
cannot ingest all of the data. Utilizing In-Memory OLTP in the Shock Absorber scenario, the Event
Reporting application was able to increase its data ingestion rate six-fold. It increased the number of
transactions from 3,500 to over 23,000 transactions/sec. This resolved the data ingestion spikes that
inhibited the application from achieving the desired throughput.
Typical Bottleneck
There are a few types of bottlenecks that can be challenging in this scenario. Even with all data-pages
loaded in memory and optimized indexes, the execution of the Transact-SQL call may still be too slow. In
some cases, the overhead of parsing and compiling the query can add extra time to the execution as
well. At scale, latching and locking for concurrent read-write scenarios can also delay the query
execution.
A hardware bottleneck, such as CPU utilization, may limit scale and require the use of a number of readonly servers to service the user load.
Middle-tier caching solutions can add additional complexity and overhead in managing multiple tiers.
Performance overhead for data movement between tiers can also add to the overall time it takes to
place data in a cache.
Applying In-Memory OLTP
In-Memory OLTP memory-optimized tables and natively compiled stored procedures can be
implemented as a cache solution. Applications that require extremely-fast, read-only access to small
subsets of data can use this cache. In particular, natively compiled stored procedures can reduce the
execution time of targeted queries, which provides a faster overall query execution time. If the workload
contains singleton row lookups, using nonclustered hash indexes will provide additional performance
gains.
Implementing In-Memory OLTP with existing solutions that now require better read performance will
typically require minimal changes to the application or database code. Migrating the data to In-Memory
OLTP minimizes the latency associated with buffer cache management and allocation metadata
retrieval. This allows for faster data transfers. However, the main benefits in this case, are typically
realized by migrating the database code that accesses these data sets to natively compiled stored
procedures. This will minimize execution times by eliminating parsing, optimizing, compiling, plan
caching, etc. It will not affect some other aspects of the inherent latency such as communication
protocols, network overhead, login time, etc.
In-Memory OLTP also provides integrated support with AlwaysOn Availability Groups and memoryoptimized tables that serve as transactional replication subscriptions. Both of these scenarios would
integrate well into scale-out read solutions. They would provide further scalability and performance
gains for the read-replicas/subscribers. In these cases, the integration of In-Memory OLTP can also
potentially provide a mechanism for server consolidation through improved CPU efficiency or readscale. This improvement would allow each read-server to handle more load than it previously could.
14
15
In-Memory OLTP provides a familiar development and management experience. All access to
data is through Transact-SQL. There is no other programming interface required.
All the availability and management features are contained in a single source (the database and
SQL Server). This would require less overhead when trying to come up with an HA/DR strategy
across tiers and applications. In those situations, the implementation and management may be
unique to each application.
Creating a relational cache within the database would require less network round trips
between mid-tier and server data stores.
This would minimize the number of servers needed to maintain the environment. Users could
potentially consolidate and purchase more memory within a box to service the memoryoptimized tables and also utilize them for other resources at the data tier.
Performance is critically important. Therefore, In-Memory OLTP provides natively compiled
stored procedures and optimized indexes, such as the nonclustered hash, for point-lookups.
These objects provide very fast access to the critical data-sets.
Queries against memory-optimized tables execute using a single thread, with no support for parallel
plan execution. Therefore, targeting queries that can operate efficiently without a parallel plan is critical.
In many cases, users may consider pre-staging the data by doing calculations. In many cases, users
may consider pre-staging the data by doing calculations or large aggregations within the disk-based
tables as part of the load into the memory-optimized tables. Therefore executing targeted lookups that
do not involve as many joins or aggregations on the memory-optimized table. Even if certain queries do
execute in parallel, it is possible that conversion to natively compiled stored procedures will reduce the
execution time. This reduction may be enough to justify migration to In-Memory OLTP. Not all queries
against memory-optimized tables must be natively compiled stored procedures. Targeting only the
performance-critical queries for migration to natively compiled stored procedures allows applications to
keep executing Interpreted T-SQL against the memory-optimized table.
Memory-optimized tables that store key pieces of data for fast read access will still require a manual
update of the data within the cache. The update could be re-occurring and time based using a scheduled
job or through a user initiated ad-hoc Transact-SQL execution. This is similar to working with two table
objects within SQL Server. You can further optimize operations that only access memory-optimized
tables using natively compiled stored procedures.
Some scenarios require a second copy of the table data in whole or pieces. For this, In-Memory OLTP
integrates with scale-out architectures such as AlwaysOn Availability Groups with Readable Secondaries
and transactional replication read-only subscriptions. AlwaysOn Availability Groups is primarily a high
availability and disaster recovery implementation. It does allow up to 8 secondary replicas per
Availability Group and provides for reads to be serviced from those replicas. This ability provides an
architecture that supports pushing read workloads to the replicas for scale out as well.
The configuration of In-Memory OLTP for objects within an Availability Group is the same as for a diskbased table. Availability Groups use the SQL Server transaction log to synchronize replicas. If data is
needed on the secondary replica for reads, the tables must be created as SCHEMA_AND_DATA.
The initial configuration of In-Memory OLTP objects and transactional replication requires some specific
initial configuration steps. These steps are in the Books Online section Replication to MemoryOptimized Table Subscribers (http://msdn.microsoft.com/en-us/library/dn600379(v=sql.120).aspx).
Customer Adoption
Edgenet is a SaaS provider that develops solutions to provide optimized product data for suppliers,
retailers, and search engines including Bing and Google. Used online and in stores, Edgenet solutions
ensure that businesses and consumers can make decisions based on timely, accurate product
information. By implementing In-Memory OLTP, Edgenet was able to remove their dependency on an
application cache and consolidate its read workload in the same database to provide near-real-time
inventory updates to consumers. Refer to the Edgenet Case Study
(http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=710000003026) for
further details.
16
A workload pattern that involves some compute intensive behavior within the Transact-SQL
code.
The transformation will have more update and delete DML compared to mostly appended
inserts.
Loading directly into the end table and scaling the concurrent writes and reads are important
factors.
Some of the business scenarios that may use this solution would include manufacturing supply chains or
retailers providing near real-time product catalog information.
Typical Bottleneck
In this scenario there is the potential for a number of issues with regard to contention. Latching on
ingested data is a typical bottleneck. Subsequently, processing and transforming the data within the
engine is time consuming. Finally, scaling the concurrent read and write workload creates lock and latch
contention as barriers to scale.
Applying In-Memory OLTP
In this pattern, the final destination table is the memory-optimized table. Usually, this is the
replacement for the entire disk-based table and there are no staging or further destination tables within
the workload. Moving the performance sensitive tables to memory-optimized tables and Transact-SQL
code to natively compiled stored procedures can provide better performance for this workload scenario.
17
18
Customer Adoption
Edgenet is a SaaS provider which develops solutions to provide optimized product data for suppliers,
retailers, and search engines including Bing and Google. Used online and in stores, Edgenet solutions
ensure that businesses and consumers can make decisions based on timely, accurate product
information. By implementing In-Memory OLTP Edgenet was able to gain between 8x and 11x
transaction throughput into SQL Server, dramatically reducing their time to get updated data into the
database. Refer to the Edgenet Case Study
(http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=710000003026) for
further details.
Second, there is the behavior of the system under load. Here scenarios such as latching and locking or
resource utilization, such as CPU, may increase the execution time of particular units of work. All this
adds latency to the process.
Applying In-Memory OLTP
In-Memory OLTP can dramatically reduce overall latency in the following ways:
19
Minimize the code execution path and provide CPU efficiencies in code execution. It eliminates
the parsing, optimizing, and compiling of a query at execution by using natively compiled stored
procedures.
Improves the performance of point lookup queries by utilizing nonclustered hash indexes.
Improves I/O performance for logging as demonstrated in the previous scenarios.
Provides for non-latching and locking data access under load. This removes barriers to scale and
execution time for high concurrency workloads.
preferences, actions, and internal metadata need to persist across multiple HTTP requests. This
persistence is often implemented in a database. When using load balanced web servers, where many
servers may service the same session, centralizing the state storage can result in increased contention.
This workload behavior will result in a significant amount of updates to users session data and usually
utilizes lookup queries focused on a single row. Some web platforms, such as ASP.NET, provide the
option to maintain session state in-process or use a SQL Server relational database to persist this session
state data. The latter is typically used for high scale websites.
The overall size of the session state implementations is usually quite small. However, the data is very
dynamic in nature. Some threads are actively writing and modifying data while other threads read the
previously saved data. As the number of threads that try to access this relatively small region of data
increases, lock and latch contention bottlenecks begin to manifest. For heavily loaded systems utilizing a
large number of CPU cores, this can be a significant barrier to scale. The time it takes to update and
query these tables is critical to the user experience.
Typical Bottleneck
These patterns typically begin to suffer from the concurrent read/write contention challenge that
introduces latch and lock bottlenecks. In many cases, this scale bottleneck would cause application slowdowns or force the implementation of a logical scale-out. Both scenarios could be quite impactful to the
business.
Applying In-Memory OLTP
Memory-optimized tables do not suffer from latching because the core In-Memory OLTP engine uses
lock-free algorithms and structures that introduce no latching. Migrating the tables with latch hotspots
to memory-optimized tables eliminates this scale bottleneck. Of note, the optimistic concurrency model
provides a new paradigm that applications will have to consider. Typically, session state tables do not
suffer from conflicts between writers because each web session will only update its own rows. However,
similar patterns may have concurrent transactions that modify the same row, which can cause conflicts
without locks. If the conflict occurs, one of the transactions will fail. Preparing for conflicts, by using
try/catch logic in Transact-SQL or application retry code for example, is critical.
21
As shown in Figure 5, In-Memory OLTP addresses the engine components of the data access layer
(tables and index objects) and query execution. If the current bottleneck is in this space, moving those
data-sets or Transact-SQL into the In-Memory OLTP engine can enhance performance. In-Memory OLTP
may also produce less log volume than SQL Server transactions compared to disk-based tables because
no records are written for index allocations or UNDO requirements. In any case, the log latency on I/O to
the disk subsystem is still a part of the transaction commit. Features such as SCHEMA_ONLY tables (nondurable) and delayed durability can eliminate or minimize this overhead in unique situations.
Additionally, no enhancements are made to the client connectivity layer. There are ways of developing
to cope with this, but In-Memory OLTP does not directly address or resolve this bottleneck.
23
Establishing a baseline
Identifying a baseline is critical to understanding the current performance of a system and measuring
the improvement or degradation when you make changes. You can accomplish this in a variety of ways.
Many of the tools and methodologies are discussed in the Monitor and Tune for Performance
(http://msdn.microsoft.com/en-us/library/ms189081(v=sql.120).aspx) article. While many tools exist to
help determine a baseline, choosing a measurement that serves as the baseline is important. Some
examples of a baseline measurement are:
System components such as: disk, CPU, memory, network, for utilization and performance.
SQL Server code execution time.
Transaction throughput.
What the system is waiting on and for how long. Here Dynamic Management View such as
sys.dm_os_wait_stats can be helpful in identifying SQL Server resource waits.
The overall application performance should be considered as part of a baseline as well. When
determining a baseline also consider the following factors:
Using these measurements can help define the criteria for a successful migration.
Bottleneck Analysis
In some cases, factors outside the database engine may be causing the bottleneck within the
application. Therefore, migration to In-Memory OLTP may not improve the situation. Understanding the
current performance bottlenecks in the overall application architecture is critical. Once you identify the
bottleneck in the database, focus on these specific components for migration.
Using In-Memory OLTP Tools to Analyze Workloads and Help with Migration
The In-Memory OLTP offering provides tools to help with the migration process. The tools are integrated
into Management Studio. We sometimes refer to the toolset as the Analyze, Migrate, and Reporting
(AMR) toolset. To help with the bottleneck analysis, new data collectors (Transaction Performance
Collection Sets) are available. They help collect performance data and workload characteristics. They
also recommend heavily used or contentious tables and code for migration to In-Memory OLTP.
The data collectors do significantly more than run a single query to determine a good candidate for InMemory OLTP migration. The collectors use Management Data Warehouse (MDW) to execute
aggregations of the data over the time period in which they are collected. Collectors provide estimates
regarding performance gains from migration to In-Memory OLTP. This information appears in the
Transaction Performance Analysis reports that come with SQL Server 2014 Management Studio. For a
detailed discussion on configuring and utilizing the tools, please read the Migrating to In-Memory
OLTP (http://msdn.microsoft.com/en-us/library/dn247639(v=sql.120).aspx) page which has drill-down
sections on this functionality.
If you cannot utilize the data collection and reporting tools, there are other ways to help understand the
contention points within SQL Server. SQLDiag (http://technet.microsoft.com/enus/library/ms162833.aspx), PSSDiag (http://diagmanager.codeplex.com/), and SQL Nexus
(http://sqlnexus.codeplex.com/) are tools that you can use to determine contention issues related to
latching, locking, spinlocks and stored procedure execution statistics. SQL Nexus will identify wait
24
resources, latching, locking, and blocking. If a SQL Trace is run as part of the capture, SQL Nexus also
captures top stored procedure and Transact-SQL Statements.
If the overhead for monitoring and collecting this information over a time period is too costly you have
another option. You can execute manual queries to detect frequently accessed tables, latch contention,
or stored procedure execution statistics. The execution of these queries provides a snapshot of the
values that exist since the last server restart and in the case of queries, only of what is still in memory. In
some cases, it may be more accurate to capture the output at two points in time and determine the
delta between them. The queries to collect this information are in the sections that follow.
Frequently Accessed Tables
This query provides a list of the most frequently accessed tables in the database since the SQL Server
instance was reset or the performance data was cleared. When determining candidates for conversion,
consider top lookup counts and scan counts. They give you an idea of usage by evaluating
singleton_lookup_count and range_scan_count from the following query. For migration to In-Memory
OLTP, consider moving the heavily accessed tables or parts of the data within the tables into memoryoptimized objects.
SELECT TOP (5)
FROM
WHERE
ORDER BY
GO
b.name AS TableName,
a.database_id,
a.singleton_lookup_count,
a.range_scan_count
sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) AS a
INNER JOIN sys.objects b on a.object_id = b.object_id
b.type <> 'S'
AND
(a.singleton_lookup_count > 0 OR a.range_scan_count > 0)
a.singleton_lookup_count DESC
Latch Contention
Evaluate latch contention by reviewing the page_latch_wait_and page_lock_wait from the
sys.dm_db_index_operational_stats DMV. Consider migrating tables that have a high latch or lock
contention to In-Memory OLTP. The query below will provide the cumulative latch and lock waits since
the SQL instance was reset or the performance data was cleared.
SELECT TOP (5)
FROM
WHERE
ORDER BY
a.database_id,
so.object_id,
so.name AS TableName,
a.page_latch_wait_count
,
a.page_latch_wait_in_ms,
a.page_lock_wait_count,
a.page_lock_wait_in_ms
sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) a
INNER JOIN sys.objects AS so
ON a.object_id = so.object_id
so.type = 'U' AND a.page_io_latch_wait_count > 0
a.page_latch_wait_count DESC;
25
running these queries several times over the course of a day or week to determine if other candidates
exist.
The following query will provide the stored procedure name with the highest total worker time. If the
performance data has been recently cleared, the plan cache will be volatile or if the SQL server instance
has been reset the plan cache may not have enough information to be valuable at that time.
SELECT TOP (10)
sp.database_id,
so.name AS StoredProcName,
sp.total_worker_time,
sp.execution_count,
sp.total_logical_reads,
sp.total_logical_writes,
sp.total_logical_reads
FROM
sys.dm_exec_procedure_stats AS sp
INNER JOIN sys.objects AS so
ON (sp.object_id = so.object_id)
WHERE
so.type = 'P' AND sp.database_id = DB_ID()
ORDER BY sp.total_worker_time DESC;
The data retrieved from the following query is not available in the Management Studio tools. However,
it may help determine which statements within the stored procedure are the top consumers of
resources. When deciding which stored procedures to migrate to In-Memory OLTP, knowing which
statements are top consumers can be valuable. It may beneficial to only move a few high resource
consuming statements into a natively complied stored procedure instead of moving the entire stored
procedure.
SELECT TOP (50)
sp.database_id,
dbname= DB_NAME (qt.dbid),
so.name AS StoredProcName,
sp.total_worker_time,
sp.execution_count AS StoredProcedureExecCount,
qs.execution_count AS StatementExecCount,
SUBSTRING(qt.text,qs.statement_start_offset / 2 + 1,
(CASE WHEN qs.statement_end_offset = -1
THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
ELSE qs.statement_end_offset END - qs.statement_start_offset) / 2
) AS query_text
FROM
sys.dm_exec_query_stats AS qs
CROSS APPLY
sys.dm_exec_sql_text(qs.sql_handle) AS qt
INNER JOIN sys.dm_exec_procedure_stats AS sp
ON (sp.sql_handle = qs.sql_handle)
INNER JOIN sys.objects so
ON (sp.object_id = so.object_id) and sp.database_id = DB_ID()
ORDER BY sp.total_worker_time DESC, qs.execution_count DESC
26
Figure 6 was created utilizing an AdventureWorks sample database (http://msdn.microsoft.com/enus/library/dn511655(v=sql.120).aspx) that was converted to In-Memory OLTP. The image shows the
engine performance gains as a workload runs into contention at scale. You can only recognize these
benefits by simulating a test to the point where scale affects performance in a typical RDBMS. The circle
in the diagram shows where typical RDBMS execution takes significantly more time to execute the same
number of transactions. After this point, the In-Memory OLTP workload continues to scale almost
linearly while the disk-based workload reaches a scale barrier.
Finally, consider that, as you migrate the workload to In-Memory OLTP, it is possible some
characteristics of the workload may change. The ideal scenario is to measure the performance of the
overall application based on a stable, defined measurement of work. Figure 7, displays the ideal based
on N, as in the number of user threads (measured against time). Measurements, such as business
transactions or the number of concurrent users, are easier to correlate across tests compared to a
specific value whose scope may change between executions.
Targeted, Iterative Migration Approach
We recommend that you approach migration by focusing on specific areas within the workload that
exhibit bottlenecks that In-Memory OLTP can address. Often, you may only need to migrate a subset of
the data and objects to In-Memory OLTP to achieve significant gains.
Some migrations of critical tables to memory-optimized structures and Transact-SQL code to natively
compiled code are quite simple and require minimal changes. Other cases may require complex changes
because of surface area support or the ability to deploy these new database objects.
Two tools, integrated into SQL Server 2014 Management Studio, to help migrate objects are the
Memory Optimization Advisor and Native Compilation Advisor. Both tools help you to assess the
migrations difficulty. They evaluate table schema and stored procedure syntax to find possible
migration blockers, e.g., an unsupported data type. The tools can then provide information on ways to
resolve these migration blockers. If Memory Optimization Advisor detects no migration issues, its wizard
can help create the memory-optimized table and help with data migration.
27
Because In-Memory OLTP is integrated into SQL Server, it allows you to utilize memory-optimized tables
and disk-based tables together. In-Memory OLTP also allows Interpreted-Transact-SQL and natively
compiled stored procedures to access data stored in memory-optimized tables. If you must migrate
specific components over time, use the following incremental migration strategy:
These steps should alleviate most scalability issues associated with locking and latching. If you need
additional performance gains, especially with regard to Transact-SQL execution time, then implement
migration of Transact-SQL to natively compiled stored procedures.
Identify the performance critical Transact-SQL that accesses these tables and their dependent
objects.
Address unsupported language constructs and migrate these stored procedures to natively
compiled code.
As you migrate certain bottleneck areas to In-Memory OLTP, other parts of the system may become the
bottleneck. Consider an iterative approach to migration when addressing a particular bottleneck, and
then analyze where the next performance bottleneck for the solution may reside.
28
However, one of the most critical and variable considerations will be a function of understanding the
workload. Having an idea of how many versions of rows may reside in memory before garbage collection
is important because this will require additional memory allocations. Row versions must stay in memory
until all the transactions that would utilize older row versions are complete. Also, garbage collection of
these rows is asynchronous to the actual process. For example, after a deletion is executed, it can take
some time to remove the row versions from memory. Certainly there is variance based on the type of
transactions and queries executed in the workload. However, for fairly update heavy, or read/write calls
iterating over the same values in an OLTP workload, consider a value of around 2x. This means two row
versions for each row that exists in the table. Please note that, under memory pressure, this garbage
collection process is expedited. For further information on determining the size of memory-optimized
tables, see Table and Row Size in Memory-Optimized Tables (http://msdn.microsoft.com/enus/library/dn205318(v=sql.120).aspx).
If you have already migrated tables, there are also ways to view memory taken by memory-optimized
tables and indexes. Use the DMV: sys.dm_db_xtp_table_memory_stats, or use Perfmon SQL Server
Database counters: XTP Memory Used (kb).
Overall, considering how to utilize Resource Governance for memory pools can be helpful in allocating
memory for memory-optimized tables in a database. For a detailed discussion, refer to the Resource
Governor (http://msdn.microsoft.com/en-us/library/bb933866(v=sql.120).aspx) section of Books
Online.
Finally, it is important to consider the size of the dataset relative to durable tables in memory. The
amount of data will impact recovery time. Additionally, there is a relationship between the storage on
disk, which does have some size limits, and data in memory. The recommended limit for the total size of
29
all durable tables in a database is at or below 250 GB. Durable tables requiring 250 GB of space in
memory will require, on average, twice the storage space (500 GB) in the memory-optimized filegroup.
This estimate assumes a mix of insert, delete, and update operations. This would lead to approximately
4000 data/delta file pairs allocated in this group.
Bursts of activity in the database may cause checkpoint operations to fall behind for a period of time.
This lag will increase the number of required files. As a cushion for such bursts, the storage system
supports up to 8000 data/delta file pairs. When the system reaches that limit, it will prevent new
transactions in the database until checkpoint operations catch up. This cushion does provide for the
possibility of managing durable tables with a size greater than 250GB. However, we do not
recommended running above 250 GB for an extended period of time. The cushion only exists to handle
bursts of activity and stalls in checkpoint. Exceeding the recommendation can increase the risk of
throttling transaction activity on the memory-optimized tables in the database.
Storage/Disk Subsystem
For memory-optimized tables created with SCHEMA_AND_DATA, durability considerations for disk
layout and file placement are important. The storage requirements are also very different from those of
disk-based SQL Server tables.
Memory-optimized tables execute I/O to the database transaction log. Therefore, the I/O latency is still
a factor in the overall transaction execution time. For the log drive, it is important to consider the disk
subsystem latency characteristics.
Data and Delta Files - Checkpoint File Pairs (CFPs)
The system stores data for durable tables in data and delta files, also referred to as Checkpoint File Pairs
(CFPs). The system stores this data in an append-only manner using a background thread. Data files
contain inserted records, and delta files store deleted records. Storing data in this manner eliminates
random I/O. These files leverage a FILESTREAM based storage mechanism. File storage in the memoryoptimized filegroup for the SQL Server database is very different from the standard storage for diskbased tables. The overall size of the files on disk may be much larger than the amount of memory used
by in-memory objects. When creating memory-optimized tables, the system pre-allocates CFPs to
minimize any delays in allocating new files as transactions are executing. The data file size is 128 MB (or
16 MB on servers with fewer than 16 GB of memory). The delta files sizes are 8 MB and 1 MB
respectively, but they contain no data. The number of CFPs is computed as the number of logical
processors or schedulers, and there is a minimum of 8. This is a fixed storage overhead in databases with
memory-optimized tables. The overall storage space that CFPs use is a function of the workload,
checkpoint, and log truncation characteristics of the workload. The size can vary, however, as an initial
point of reference consider allocating disk space that is approximately four times (4x) the size of the
memory-optimized tables in memory. It is important to underscore the importance of a log backup plan
under the FULL or Bulk-Logged recovery models that meets the business recovery requirements and
addresses the storage behavior of memory-optimized tables. The backup plan will help determine log
truncation and impact the garbage collection and is therefore critical to maintaining an acceptable
number and size of checkpoint files on disk. For more information regarding the data and delta files and
checkpoints, see Durability for Memory-Optimized Tables (http://msdn.microsoft.com/enus/library/dn553125(v=sql.120).aspx) and Checkpoint Operations for Memory-Optimized Tables
(http://msdn.microsoft.com/en-us/library/dn553124(v=sql.120).aspx).
There are also performance considerations to manage when implementing durable memory-optimized
tables. The placement of data files is important for:
1. Offline checkpoint performance.
30
Checkpoint writes.
Reads from source files participating in merge operations.
Writes to the destination merge file.
Having a disk subsystem that can handle this I/O volume is important. In the case of recovery
performance, placement of the data and delta containers is important. Consider creating multiple
containers on the memory-optimized filegroup and spreading them over different drives. Doing this
provides more bandwidth for streaming the data into memory. When you do this, understand that the
system allocates data and delta files in a round-robin manner across the given files. The system
associates a data file to the first file it creates and associates a delta file to the second file it creates, and
so on. To obtain a balanced stream of I/O on recovery, consider placing pairs of files on the same
spindles/storage. For example, File 1 and File 2 on drive X and File 3 and File 4 on drive Y. Take into
account that both data and delta file pairs reside on drive X and drive Y.
Processor
It is vital to consider the deployment of the processors. In particular, you should think about the number
of cores and sockets for an In-Memory OLTP solution. We have collected observations from customer
and internal testing for the current release. We have observed that the overhead of cross-socket
communications in some of the larger socket machines may affect scalability. You should target two or
four sockets and under 60 cores to achieve the most successful implementation.
Multi-version Optimistic Concurrency Considerations
Memory-optimized tables do not suffer from locking, latching, or spinlocks. The reason for this is that
the core In-Memory OLTP engine uses lock-free optimistic isolation and latch-free and spinlock-free
internal structure protection. Migration of tables that experience latching, locking, or spinlock
contention to memory-optimized tables completely eliminates this scale bottleneck.
However, this new paradigm of concurrency control introduces changes in behavior and may require
adjustments to either the Transact-SQL error handling, such as try-catch blocks, or to the application
code in order to accommodate for conflicts. With the default pessimistic isolation, two transactions that
attempt to modify the same resource will block each other. One will get serialized because one will need
to wait for the other to release its locks. With optimistic isolation, transactions will not block each other,
but may fail to commit because of update or validation conflicts. In this case, the system must resubmit
the transaction. Resubmission effectively serializes the transaction order and incurs additional overhead
for rollback and resubmission. Writer-writer conflicts are not common in most OLTP environments. For
further discussion on retry logic for conflicts, read Guidelines for Retry Logic for Transactions on
Memory-Optimized Tables (http://msdn.microsoft.com/en-us/library/dn169141(v=sql.120).aspx).
In-Memory OLTP supports REPEATABLE READ, SERIALIZABLE, and SNAPSHOT isolation modes only. Many
applications were designed to work with the traditional SQL Server default READ COMMITTED isolation
level. Use the new MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT database option to map all
transactions that use READ COMMITTED automatically to SNAPSHOT. Using this option does not require
application code changes.
31
For more details, see the Guidelines for Transaction Isolation Levels with Memory-Optimized Tables
(http://msdn.microsoft.com/en-us/library/dn133187(v=sql.120).aspx) section in Books Online and SQL
Server 2014 In-Memory OLTP Internals Overview
(http://download.microsoft.com/download/5/F/8/5F8D223F-E08B-41CC-8CE595B79908A872/SQL_Server_2014_In-Memory_OLTP_TDM_White_Paper.pdf).
Indexing Guidelines
There are two new index types with In-Memory OLTP: memory-optimized nonclustered indexes and
nonclustered hash indexes. Both indexes, as mentioned earlier, are created and exist entirely in
memory.
Memory-optimized nonclustered indexes are similar in concept to standard B-tree indexes, but they are
implemented in a lock and latch free manner. The memory-optimized nonclustered indexes support
point/singleton row and range lookups for queries. Because they support ordered scans, they are the
index of choice for non-equality range searches. They can also be very useful for queries that require
ordering of the result sets and grouping and aggregation. Nonclustered indexes also support partial key
lookups. Nonclustered indexes are similar to indexes used for disk-based tables. When compared to
hash indexes, nonclustered indexes have a relative lack of requirements for creation. Therefore, we
recommend that you use these as a starting point when creating memory-optimized tables.
Memory-optimized hash indexes are very efficient for point-lookup style queries, such as retrieving or
modifying a row or a set of rows based on key value. With hash indexes, row pointers are stored in a
hash table. Each pointer points to a chain of rows that have the same hash value for the index key.
When creating a hash index, you must specify a hash bucket count. This will be used to build the hash
table. Specifying too few buckets will cause multiple key values to share a bucket, which could lead to
scanning of redundant data. Scanning redundant data will degrade performance. Specifying too many
buckets will result in an over allocation of memory because many buckets will be left empty. Generally,
creating buckets of up to 5X the number of unique key values for the index columns does not
significantly impact performance. Remember that the hash value is computed across all key values.
Therefore, a filter on only a subset of the keys (or none) cannot use the index. This will result in a scan of
all buckets.
You can create nonclustered hash and nonclustered indexes on the same set of columns to satisfy
different query patterns. Both index types are optimal for low density data distributions. With hash
indexes, hash collisions can negatively affect performance. With nonclustered memory-optimized
indexes, high density values make the index less efficient for lookups but still retains ordered scan
benefits.
You determine the bucket count when you create the table and you cannot modify the bucket count
afterwards. To change a hash indexs bucket count, you must create a new table, specify the new bucket
count, and decide how to migrate the data. This is a non-trivial process that will impact data availability.
Query Execution
Memory-optimized tables support data distribution statistics that are similar to disk-based tables. The
query optimizer uses these statistics to generate an optimal execution plan for queries involving
memory-optimized tables. Statistics are referenced at different times depending on the type of code
being executed. For interpreted Transact-SQL, the query plan is optimized and statistics are used during
the compilation process. For every execution of the statement, statistics may be used to optimize an
execution plan. For natively compiled stored procedures, the statistics are only utilized once when the
stored procedure is being compiled, at creation time. Further statistics updates will be only utilized
again whenever the database goes offline or there is a service restart.
32
Consider the following aspects of statistics creation and utilization when planning migration to InMemory OLTP:
Memory-optimized tables do not support statistics collection sampling and require a full scan of
the table. The full scan can have a significant impact on tables with a very large number of rows.
The default database setting is to have auto-create statistics ON. With this setting, when a query
executes, missing statistics may be created automatically to help produce an optimal plan. With
memory-optimized tables that require a full scan, this will result in a longer compile time for
queries. For Interpreted T-SQL, this impact will appear when the statement executes. For
natively compiled stored procedures, this will affect the time it takes to create the stored
procedure. However, it will not affect the execution time of natively compiled stored
procedures.
With natively compiled stored procedures, statistics are used only when the stored procedure is
created. This means that if you create the procedure before the table is populated with real
data, the execution plan may be suboptimal. The query optimizer will be working with wrong
assumptions regarding the data distribution. Therefore, we recommended that you create the
procedures only after the tables are fully populated with faithfully representative data and a
statistics update is executed.
Unlike disk-based tables, statistics on memory-optimized tables are not updated automatically.
Statistics updates will execute a full sampling of data. Be careful about the timing when you
execute the statistics updates, and consider the impact to the workload. Take into account the
type of workload that is executing in terms of the number of rows being inserted or modified.
Consider how stale the statistics may be and how sensitive the queries are to data distribution
changes. If you do not update statistics or update very infrequently, the query optimizer may
use wrong distribution statistics and come up with suboptimal plans. On the other hand,
updating too frequently will add an unnecessary overhead.
As mentioned earlier, consider the fact that queries that access memory-optimized tables cannot utilize
parallel plans. All queries containing memory-optimized tables will use serial plans exclusively. For
example, joins between disk-based tables that use B-tree or columnstore indexes can benefit greatly
from parallelism. Migrating any of the joined tables to In-Memory OLTP will block the query optimizer
from using this optimization. For cases where it is necessary to utilize parallelism for particular queries,
consider keeping the dataset servicing those queries in disk-based tables. This solution is similar to the
concept discussed in the Shock Absorber scenario.
may require code changes to handle transaction enlistment and connection string settings. Finally,
locking hints or isolation level incompatibilities with In-Memory OLTP supported isolation levels may
also require some application modifications.
Memory Limitations
As mentioned earlier, data structures that make up memory-optimized tables are all stored in memory,
and unlike traditional B-tree objects are not backed by durable storage. Scenarios where sufficient
memory is not available to store the memory-optimized rows can be problematic. When evaluating
migration, determine the size of memory required. It is also critical to consider the workload that may
produce multiple versions of rows, which requires additional memory allocations.
Workload Pattern is not OLTP
In-Memory OLTP is optimized for OLTP workloads. Long running transactions, queries and reports that
involve many tables or execute large aggregations of data are more likely to cause retention of several
row versions. These workloads are more likely to put pressure on memory to the point where it may be
unable to accommodate these transactions, queries, and reports. Similarly, disk-based tables and
indexes may be better for very large datasets and provider greater benefits for these longer query
executions. Alternative solutions such as a nonclustered or updatable clustered columnstore indexes
may be more appropriate for this part of the workload. Workloads and schemas that are very dynamic
may not be the best fit because altering table and index definitions will involve recreating the InMemory OLTP objects.
Workload types such as those that benefit from Full-Text Search or XML parsing can be better serviced
using specialized indexes and data structures created specifically for working with those data structures
and patterns.
Lock Behavior Dependent Applications
Within the In-Memory OLTP engine there is no locking. In many cases, the multi-version optimistic
concurrency implementation can provide significant scale benefits. However, in some applications there
are dependencies on locking constructs to restrict access to data. With the exception of an application
lock, In-Memory OLTP does not offer the ability to lock records like standard SQL Server does. If the
application logic depends on the physical locking of records (e.g., queues implemented with READPAST
lock-skip hints), this may not be a good migration candidate.
Instead of taking out locks to prevent concurrent access to data, memory-optimized tables use conflict
detection to enforce data modification isolation. Workloads that are write heavy and are modifying a
single row may experience a number of these conflicts. In some cases, it is possible to minimize these
conflicts. However, sometimes there are a significant number of conflicts that are unavoidable. In this
case, the overhead for handling the conflicts and retrying may eliminate most of the performance gains
from In-Memory OLTP. A queue pattern with a large number of concurrent users trying to update the
first row on the stack is an example of such a case. Under contentious workloads this suffered from a
large number of conflicts.
Conclusion
There are number of scenarios that require high performance systems that traditional relational
database management systems are unable to deliver. In-Memory OLTP can help workloads achieve and
exceed their required performance metrics while integrating with other familiar features of SQL Server
2014.
34
An understanding of the current bottlenecks and database contention in the application is critical to
determining how to best utilize the In-Memory OLTP components to achieve the overall application
performance goals. SQL Server provides a set of tools, including data collection sets and reports, to help
assess candidates for migration. SQL Server also provides advisor tools to help with the actual migration.
When migrating tables, data, and Transact-SQL code to In-Memory OLTP, target the performance critical
database sections of the application. Performing the migration in an iterative manner can result in less
overall application disruption.
Did this paper help you? Please give us your feedback. Tell us on a scale of 1 (poor) to 5 (excellent), how
would you rate this paper and why have you given it this rating? For example:
Are you rating it high because it has good examples, excellent screen shots, clear writing, or
another reason?
Are you rating it low because of poor examples, fuzzy screen shots, or unclear writing?
This feedback will help us improve the quality of the white papers we release.
Send feedback.
35