메모리 액세스에 최적화된 테이블 소개Introduction to Memory-Optimized Tables

이 항목은 다음에 적용됩니다. 예SQL Server(2016부터)예Azure SQL Database아니요Azure SQL Data Warehouse아니요병렬 데이터 웨어하우스 THIS TOPIC APPLIES TO: yesSQL Server (starting with 2016)yesAzure SQL DatabasenoAzure SQL Data Warehouse noParallel Data Warehouse

메모리 최적화 테이블은 CREATE TABLE (Transact-SQL)을 사용하여 만들어집니다.Memory-optimized tables are created using CREATE TABLE (Transact-SQL).

메모리 최적화 테이블은 기본적으로 완전 지속 가능하며, 기존 디스크 기반 테이블의 트랜잭션과 마찬가지로 메모리 최적화 테이블의 트랜잭션은 완전 ACID(원자성, 일관성, 격리 및 지속성)을 가집니다.Memory-optimized tables are fully durable by default, and, like transactions on (traditional) disk-based tables, transactions on memory-optimized tables are fully atomic, consistent, isolated, and durable (ACID). 메모리 최적화 테이블과 네이티브 컴파일 저장 프로시저는 Transact-SQLTransact-SQL의 하위 집합만 지원합니다.Memory-optimized tables and natively compiled stored procedures support only a subset of Transact-SQLTransact-SQL features.

SQL Server 2016부터 Azure SQL Database에는 메모리 내 OLTP에 한정되는 데이터 정렬 또는 코드 페이지 에 대한 제한이 없습니다.Starting with SQL Server 2016, and in Azure SQL Database, there are no limitations for collations or code pages that are specific to In-Memory OLTP.

메모리 최적화 테이블에 대한 기본 저장소는 주 메모리입니다.The primary storage for memory-optimized tables is the main memory. 테이블의 행은 메모리에서 읽고 메모리에 기록합니다.Rows in the table are read from and written to memory. 테이블 데이터의 보조 복사본이 디스크에서 유지 관리되는데, 이는 내구성 목적입니다.A second copy of the table data is maintained on disk, but only for durability purposes. 내구성이 있는 테이블에 대한 자세한 내용은 메모리 액세스에 최적화된 개체의 저장소 만들기 및 관리 를 참조하세요.See Creating and Managing Storage for Memory-Optimized Objects for more information about durable tables. 메모리 최적화 테이블의 데이터는 데이터베이스 복구 중에 디스크에서만 읽습니다(예:Data in memory-optimized tables is only read from disk during database recovery (eg. 서버를 다시 시작한 후).after a server restart).

보다 큰 성능 향상을 위해 메모리 내 OLTP는 트랜잭션 내구성이 지연된 영구 테이블을 지원합니다.For even greater performance gains, In-Memory OLTP supports durable tables with transaction durability delayed. 지연된 지속적 트랜잭션은 트랜잭션이 커밋되고 제어를 클라이언트에 반환한 후 곧바로 디스크에 저장됩니다.Delayed durable transactions are saved to disk soon after the transaction has committed and control was returned to the client. 성능이 향상되는 대신 디스크에 저장되지 않은 커밋된 트랜잭션이 서버 충돌 또는 장애 조치(Failover)에서 손실됩니다.In exchange for the increased performance, committed transactions that have not saved to disk are lost in a server crash or fail over.

기본 내구성 메모리 액세스에 최적화된 테이블 외에도 SQL ServerSQL Server 는 기록되지 않고 데이터가 디스크에 지속되지 않는 비 내구성 메모리 액세스에 최적화된 테이블도 지원합니다.Besides the default durable memory-optimized tables, SQL ServerSQL Server also supports non-durable memory-optimized tables, which are not logged and their data is not persisted on disk. 따라서 이러한 테이블의 트랜잭션에는 디스크 IO가 필요하지 않지만 서버 충돌이나 장애 조치가 있는 경우 데이터가 복구되지 않습니다.This means that transactions on these tables do not require any disk IO, but the data will not be recovered if there is a server crash or failover.

메모리 내 OLTP는 개발, 배포, 관리 효율성 및 지원 가능성과 같은 모든 영역에서 원활한 환경을 제공하기 위해 SQL ServerSQL Server 와 통합되었습니다.In-Memory OLTP is integrated with SQL ServerSQL Server to provide a seamless experience in all areas such as development, deployment, manageability, and supportability. 데이터베이스는 메모리 내 개체뿐만 아니라 디스크 기반 개체를 포함할 수 있습니다.A database can contain in-memory as well as disk-based objects.

메모리 액세스에 최적화된 테이블의 행에는 버전이 있습니다.Rows in memory-optimized tables are versioned. 즉, 테이블의 각 행에 여러 버전이 있을 수 있습니다.This means that each row in the table potentially has multiple versions. 모든 행 버전은 동일한 테이블 데이터 구조에서 유지 관리됩니다.All row versions are maintained in the same table data structure. 행 버전 관리는 동일한 행에 대한 동시 읽기 및 쓰기를 가능하게 합니다.Row versioning is used to allow concurrent reads and writes on the same row. 동일한 행에 대한 동시 읽기 및 쓰기에 대한 자세한 내용은 Transactions with Memory-Optimized Tables(메모리 액세스에 최적화된 테이블 트랜잭션)를 참조하세요.For more information about concurrent reads and writes on the same row, see Transactions with Memory-Optimized Tables.

다음 그림에서는 다중 버전 관리를 보여 줍니다.The following figure illustrates multi-versioning. 이 그림에서는 세 개의 행이 있고 각 행에 서로 다른 버전이 있는 테이블을 보여 줍니다.The figure shows a table with three rows and each row has different versions.

다중 버전 관리Multi-versioning.

테이블에 3개의 행 즉, r1, r2, r3이 있습니다.The table has three rows: r1, r2, and r3. r1에는 세 개의 버전, r2에는 두 개의 버전, r3에는 네 개의 버전이 있습니다.r1 has three versions, r2 has two versions, and r3 has four versions. 동일한 행의 서로 다른 버전은 반드시 연속된 메모리 위치에 배치하지 않아도 되며,Note that different versions of the same row do not necessarily occupy consecutive memory locations. 테이블 데이터 구조의 여러 위치에 분산하여 배치할 수 있습니다.The different row versions can be dispersed throughout the table data structure.

메모리 액세스에 최적화된 테이블 데이터 구조는 행 버전의 컬렉션처럼 보일 수 있습니다.The memory-optimized table data structure can be seen as a collection of row versions. 디스크 기반 테이블의 행은 페이지 및 익스텐트에 구성되고 개별 행은 페이지 번호 및 페이지 오프셋을 사용하여 지정되는 반면 메모리 액세스에 최적화된 테이블의 행 버전은 8바이트 메모리 포인터를 사용하여 지정됩니다.Rows in disk-based tables are organized in pages and extents, and individual rows addressed using page number and page offset, row versions in memory-optimized tables are addressed using 8-byte memory pointers.

메모리 액세스에 최적화된 테이블의 데이터는 다음 두 가지 방법으로 액세스됩니다.Data in memory-optimized tables is accessed in two ways:

  • 고유하게 컴파일된 저장 프로시저를 통해Through natively compiled stored procedures.

  • 고유하게 컴파일된 저장 프로시저 외부의 해석된 Transact-SQLTransact-SQL을 통해Through interpreted Transact-SQLTransact-SQL, outside of a natively-compiled stored procedure. 이러한 Transact-SQLTransact-SQL 문은 해석된 저장 프로시저 내부에 있거나 임시 Transact-SQLTransact-SQL 문이 될 수 있습니다.These Transact-SQLTransact-SQL statements may be either inside interpreted stored procedures or they may be ad-hoc Transact-SQLTransact-SQL statements.

메모리 액세스에 최적화된 테이블에서 데이터 액세스Accessing Data in Memory-Optimized Tables

메모리 액세스에 최적화된 테이블은 고유하게 컴파일된 저장 프로시저(고유하게 컴파일된 저장 프로시저)에서 가장 효율적으로 액세스할 수 있습니다.Memory-optimized tables can be accessed most efficiently from natively compiled stored procedures (Natively Compiled Stored Procedures). (기존의) 해석된 Transact-SQLTransact-SQL로 메모리 액세스에 최적화된 테이블에 액세스할 수도 있습니다.Memory-optimized tables can also be accessed with (traditional) interpreted Transact-SQLTransact-SQL. 해석된 Transact-SQLTransact-SQL 은 고유하게 컴파일된 저장 프로시저를 사용하지 않고 메모리 액세스에 최적화된 테이블에 액세스함을 나타냅니다.Interpreted Transact-SQLTransact-SQL refers to accessing memory-optimized tables without a natively compiled stored procedure. 해석된 Transact-SQLTransact-SQL 액세스의 예로는 DML 트리거, 임시 Transact-SQLTransact-SQL 일괄 처리, 뷰 및 테이블 반환 함수에서 메모리 액세스에 최적화된 테이블에 액세스 등이 있습니다.Some examples of interpreted Transact-SQLTransact-SQL access include accessing a memory-optimized table from a DML trigger, ad hoc Transact-SQLTransact-SQL batch, view, and table-valued function.

다음 표에서는 다양한 개체에 대한 고유 및 해석된 Transact-SQLTransact-SQL 액세스를 요약하여 보여 줍니다.The following table summarizes native and interpreted Transact-SQLTransact-SQL access for various objects.

기능Feature 고유하게 컴파일된 저장 프로시저를 통한 액세스Access Using a Natively Compiled Stored Procedure 해석된 Transact-SQLTransact-SQL 액세스Interpreted Transact-SQLTransact-SQL Access CLR 액세스CLR Access
메모리 액세스에 최적화된 테이블Memory-optimized table Yes Yes 아니요No
메모리 액세스에 최적화된 테이블 형식Memory-optimized table type Yes Yes 아니요No
고유하게 컴파일된 저장 프로시저Natively compiled stored procedure 고유하게 컴파일된 저장 프로시저 중첩은 지원되지 않습니다.Nesting of natively compiled stored procedures is now supported. 참조되는 프로시저도 고유하게 컴파일된 경우 저장 프로시저 내에서 EXECUTE 구문을 사용할 수 있습니다.You can use the EXECUTE syntax inside the stored procedures, as long as the referenced procedure is also natively compiled. Yes 아니요No

컨텍스트 연결(CLR 모듈을 실행하는 경우 SQL ServerSQL Server 의 연결)에서는 메모리 액세스에 최적화된 테이블이나 고유하게 컴파일된 저장 프로시저에 액세스할 수 없습니다.You cannot access a memory-optimized table or natively compiled stored procedure from the context connection (the connection from SQL ServerSQL Server when executing a CLR module). 하지만 메모리 액세스에 최적화된 테이블과 고유하게 컴파일된 저장 프로시저에 액세스할 수 있는 다른 연결을 만들어서 열 수 있습니다.You can, however, create and open another connection from which you can access memory-optimized tables and natively compiled stored procedures.

성능 및 확장성Performance and Scalability

다음과 같은 요인이 메모리 내 OLTP에서 얻을 수 있는 성능 향상에 영향을 미칩니다.The following factors will affect the performance gains that can be achieved with In-Memory OLTP:

통신: 짧은 저장 프로시저에 대해 여러 번 호출을 하는 응용 프로그램은 적은 호출을 하고 각 저장 프로시저에 더 많은 기능이 구현된 응용 프로그램이 비해 성능 향상이 적을 수 있습니다.Communication: An application with many calls to short stored procedures may see a smaller performance gain compared to an application with fewer calls and more functionality implemented in each stored procedure.

Transact-SQLTransact-SQL 실행: 메모리 내 OLTP는 해석된 저장 프로시저 또는 쿼리 실행보다는 고유하게 컴파일된 저장 프로시저를 사용할 때 최상의 성능을 얻을 수 있습니다. Transact-SQLTransact-SQL Execution: In-Memory OLTP achieves the best performance when using natively compiled stored procedures rather than interpreted stored procedures or query execution. 이러한 저장 프로시저에서 메모리 액세스에 최적화된 테이블에 액세스하면 효율적일 수 있습니다.There can be a benefit to accessing memory-optimized tables from such stored procedures.

범위 검색 및 포인트 조회: 메모리 액세스에 최적화된 비클러스터형 인덱스는 범위 검색 및 정렬된 검색을 지원합니다.Range Scan vs Point Lookup: Memory-optimized nonclustered indexes support range scans and ordered scans. 메모리 액세스에 최적화된 비클러스터형 인덱스보다 메모리 액세스에 최적화된 해시 인덱스를 사용할 경우 포인트 조회 성능이 개선됩니다.For point lookups, memory-optimized hash indexes have better performance than memory-optimized nonclustered indexes. 메모리 액세스에 최적화된 비클러스터형 인덱스는 디스크 기반 인덱스보다 성능이 우수합니다.Memory-optimized nonclustered indexes have better performance than disk-based indexes.

  • SQL Server 2016부터 메모리 액세스에 최적화된 테이블에 대한 쿼리 계획은 테이블을 병렬로 검색할 수 있습니다.Starting in SQL Server 2016, the query plan for a memory-optimized table can scan the table in parallel. 그 결과로 분석 쿼리 성능이 향상됩니다.This improves the performance of analytical queries.
    • 해시 인덱스도 SQL Server 2016에서 병렬로 검색할 수 있게 되었습니다.Hash indexes also became scannable in parallel in SQL Server 2016.
    • 또한 비클러스터형 인덱스도 SQL Server 2016에서 병렬로 검색할 수 있게 되었습니다.Nonclustered indexes also became scannable in parallel in SQL Server 2016.
    • Columnstore 인덱스는 SQL Server 2014 이래로 병렬로 검색 가능합니다.Columnstore indexes have been scannable in parallel since their inception in SQL Server 2014.

인덱스 작업: 인덱스 작업은 기록되지 않으며 메모리에만 있습니다.Index operations: Index operations are not logged, and they exist only in memory.

동시성: 성능이 래치 경합 또는 차단과 같은 엔진 수준 동시성의 영향을 받는 응용 프로그램은 응용 프로그램이 메모리 내 OLTP로 이동하면 성능이 크게 개선됩니다.Concurrency: Applications whose performance is affected by engine-level concurrency, such as latch contention or blocking, improves significantly when the application moves to In-Memory OLTP.

다음 표에서는 관계형 데이터베이스에서 일반적으로 발견되는 성능 및 확장성 문제와 메모리 내 OLTP를 사용하여 성능을 개선할 수 있는 방법을 나열합니다.The following table lists the performance and scalability issues that are commonly found in relational databases and how In-Memory OLTP can improve performance.

문제점Issue 메모리 내 OLTP 영향In-Memory OLTP Impact
성능Performance

많은 리소스(CPU, I/O, 네트워크 또는 메모리) 사용량High resource (CPU, I/O, network or memory) usage.
CPUCPU
고유하게 컴파일된 저장 프로시저를 사용할 경우 Transact-SQLTransact-SQL 문을 실행하는 데 필요한 명령이 해석된 저장 프로시저에 비해 매우 적기 때문에 CPU 사용량도 크게 줄어들 수 있습니다.Natively compiled stored procedures can lower CPU usage significantly because they require significantly fewer instructions to execute a Transact-SQLTransact-SQL statement compared to interpreted stored procedures.

메모리 내 OLTP는 서버 한 대가 서버 5 - 10대의 처리량을 발휘할 수 있기 때문에 확장된 작업에서 하드웨어 투자를 줄일 수 있습니다.In-Memory OLTP can help reduce the hardware investment in scaled-out workloads because one server can potentially deliver the throughput of five to ten servers.

입력/출력I/O
데이터 또는 인덱스 페이지 처리에 I/O 병목 현상이 발생하는 경우 메모리 내 OLTP를 사용하면 병목 현상을 줄일 수 있습니다.If you encounter an I/O bottleneck from processing to data or index pages, In-Memory OLTP may reduce the bottleneck. 또한 메모리 내 OLTP 개체의 검사점은 연속되며 I/O 작업의 갑작스러운 증가를 초래하지 않습니다.Additionally, the checkpointing of In-Memory OLTP objects is continuous and does not lead to sudden increases in I/O operations. 그러나 성능에 중요한 영향을 미치는 테이블의 작업 집합이 메모리에 맞지 않을 경우 데이터가 메모리에 상주할 필요가 없기 때문에 메모리 내 OLTP는 성능을 개선하지 않습니다.However, if the working set of the performance critical tables does not fit in memory, In-Memory OLTP will not improve performance because it requires data to be memory resident. 로깅에서 I/O 병목 현상이 발생하는 경우 메모리 내 OLTP를 사용하면 로깅이 적게 수행되므로 병목 현상을 줄일 수 있습니다.If you encounter an I/O bottleneck in logging, In-Memory OLTP can reduce the bottleneck because it does less logging. 하나 이상의 메모리 액세스에 최적화된 테이블을 비내구성 테이블로 구성한 경우 데이터에 대한 로깅을 제거할 수 있습니다.If one or more memory-optimized tables are configured as non-durable tables, you can eliminate logging for data.

메모리Memory
메모리 내 OLTP는 성능 이점을 제공하지 않습니다.In-Memory OLTP does not offer any performance benefit. 개체가 메모리에 상주해야 하기 때문에 메모리 내 OLTP는 메모리에 추가 부담을 줄 수 있습니다.In-Memory OLTP can put extra pressure on memory as the objects need to be memory resident.

네트워크Network
메모리 내 OLTP는 성능 이점을 제공하지 않습니다.In-Memory OLTP does not offer any performance benefit. 데이터는 데이터 계층에서 응용 프로그램 계층으로 통신해야 합니다.The data needs to be communicated from data tier to application tier.
확장성Scalability

SQL ServerSQL Server 응용 프로그램에서 발생하는 대부분의 확장 문제는 잠금, 래치 및 spinlock의 경합 같은 동시성 문제로 인한 것입니다.Most scaling issues in SQL ServerSQL Server applications are caused by concurrency issues such as contention in locks, latches, and spinlocks.
래치 경합Latch Contention
일반적인 시나리오는 키 순서로 행을 동시에 삽입할 때 인덱스의 마지막 페이지에서의 경합입니다.A typical scenario is contention on the last page of an index when inserting rows concurrently in key order. 메모리 내 OLTP는 데이터에 액세스할 때 래치를 수행하지 않으므로 래치 경합과 관련한 확장성 문제가 완전히 제거됩니다.Because In-Memory OLTP does not take latches when accessing data, the scalability issues related to latch contentions are fully removed.

Spinlock 경합Spinlock Contention
메모리 내 OLTP는 데이터에 액세스할 때 래치를 수행하지 않으므로 spinlock 경합과 관련한 확장성 문제가 완전히 제거됩니다.Because In-Memory OLTP does not take latches when accessing data, the scalability issues related to spinlock contentions are fully removed.

잠금 관련 경합Locking Related Contention
데이터베이스 응용 프로그램의 읽기와 쓰기 작업 간에 잠금 문제가 발생하는 경우 새로운 형태의 낙관적 동시성 제어를 사용하여 모든 트랜잭션 격리 수준을 구현하기 때문에 메모리 내 OLTP는 차단 문제를 제거합니다.If your database application encounters blocking issues between read and write operations, In-Memory OLTP removes the blocking issues because it uses a new form of optimistic concurrency control to implement all transaction isolation levels. 메모리 내 OLTP는 행 버전을 저장하는 데 TempDB를 사용하지 않습니다.In-Memory OLTP does not use TempDB to store row versions.

같은 행을 업데이트하려는 두 동시 트랜잭션 같이 두 쓰기 작업 간의 충돌로 인해 확장 문제가 발생하는 경우 메모리 내 OLTP를 사용하면 한 트랜잭션은 성공하고 다른 트랜잭션은 실패합니다.If the scaling issue is caused by conflict between two write operations, such as two concurrent transactions trying to update the same row, In-Memory OLTP lets one transaction succeed and fails the other transaction. 실패한 트랜잭션은 명시적으로 또는 암시적으로 다시 제출해야 하며 트랜잭션을 다시 시도해야 합니다.The failed transaction must be re-submitted either explicitly or implicitly, re-trying the transaction. 어느 경우나 응용 프로그램을 변경해야 합니다.In either case, you need to make changes to the application.

응용 프로그램의 두 쓰기 작업 간에 충돌이 자주 발생하는 경우 낙관적 잠금 값이 감소합니다.If your application experiences frequent conflicts between two write operations, the value of optimistic locking is diminished. 응용 프로그램은 메모리 내 OLTP에 적합하지 않습니다.The application is not suitable for In-Memory OLTP. 충돌이 잠금 에스컬레이션으로 인해 발생하지 않는다면 대부분의 OLTP 응용 프로그램에는 쓰기 충돌이 없습니다.Most OLTP applications don’t have a write conflicts unless the conflict is induced by lock escalation.

메모리 액세스에 최적화된 테이블의 행 수준 보안 Row-Level Security in Memory-Optimized Tables

행 수준 보안 은 메모리 액세스에 최적화된 테이블에서 지원됩니다.Row-Level Security is supported in memory-optimized tables. 메모리 액세스에 최적화된 테이블에 행 수준 보안 정책을 적용하는 작업은 디스크 기반 테이블에서와 기본적으로 동일합니다. 단, 메모리 액세스에 최적화된 테이블의 경우에는 보안 조건자로 사용되는 인라인 테이블 반환 함수를 고유하게 컴파일해야 합니다(WITH NATIVE_COMPILATION 옵션을 사용하여 함수를 작성해야 함).Applying Row-Level Security policies to memory-optimized tables is essentially the same as disk-based tables, except that the inline table-valued functions used as security predicates must be natively compiled (created using the WITH NATIVE_COMPILATION option). 자세한 내용은 행 수준 보안 항목의 기능 간 호환성 섹션을 참조하세요.For details, see the Cross-Feature Compatibility section in the Row-Level Security topic.

행 수준 보안에 반드시 필요한 여러 기본 제공 보안 함수가 메모리 내 테이블에 사용할 수 있도록 설정되었습니다.Various built-in security functions that are essential to row-level security have been enabled for in-memory tables. 자세한 내용은 고유하게 컴파일된 모듈의 기본 제공 함수를 참조하세요.For details, see Built-in Functions in Natively Compiled Modules.

EXECUTE AS CALLER - 이제 모든 네이티브 모듈에서는 힌트를 지정하지 않더라도 EXECUTE AS CALLER를 기본적으로 지원하며 사용합니다.EXECUTE AS CALLER - All native modules now support and use EXECUTE AS CALLER by default, even if the hint is not specified. 호출하는 사용자의 컨텍스트에서 함수와 함수 내에서 사용되는 모든 기본 제공 함수를 평가할 수 있도록, 모든 행 수준 보안 조건자 함수는 EXECUTE AS CALLER를 사용하기 때문입니다.This is because it is expected that all row-level security predicate functions will use EXECUTE AS CALLER so that the function (and any built-in functions used within it) will be evaluated in the context of the calling user.
EXECUTE AS CALLER 사용 시에는 호출자의 권한 확인으로 인해 성능이 약간(약 10%) 저하됩니다.EXECUTE AS CALLER has a small (approximately10%) performance hit caused by permission checks on the caller. 모듈에서 EXECUTE AS OWNER 또는 EXECUTE AS SELF를 명시적으로 지정하는 경우에는 이러한 권한 검사 및 관련 성능 비용을 방지할 수 있습니다.If the module specifies EXECUTE AS OWNER or EXECUTE AS SELF explicitly, these permission checks and their associated performance cost will be avoided. 그러나 이 두 옵션 중 하나를 위의 기본 제공 함수와 함께 사용하면 필요한 컨텍스트 전환으로 인해 성능이 훨씬 더 많이 저하됩니다.However, using either of these options together with the built-in functions above will incur a significantly higher performance hit due to the necessary context-switching.

시나리오Scenarios

SQL Server 메모리 내 OLTPSQL Server In-Memory OLTP 를 사용하여 성능을 향상시킬 수 있는 일반적인 시나리오에 대한 간단한 설명은 메모리 내 OLTP를 참조하세요.For a brief discussion of typical scenarios where SQL Server 메모리 내 OLTPSQL Server In-Memory OLTP can improve performance, see In-Memory OLTP.

관련 항목:See Also

메모리 내 OLTP(메모리 내 최적화)In-Memory OLTP (In-Memory Optimization)