메모리 내 OLTP의 초기 영역 조사
적용 대상: SQL Server Azure SQL 데이터베이스 Azure SQL Managed Instance
이 문서는 Microsoft SQL Server 및 Azure SQL 데이터베이스의 메모리 내 OLTP 성능 기능의 기본 사항을 알아보기 위해 서두르는 개발자를 위한 것입니다.
메모리 내 OLTP 관련, 이 문서에서는 다음을 제공합니다.
- 기능에 대한 간략한 설명.
- 기능을 구현하는 핵심 코드 샘플.
SQL Server 및 SQL Database는 메모리 내 기술을 지원하는 데 약간의 변형만 있습니다.
일부 블로거들은 비공식적으로 메모리 내 OLTP를 Hekaton이라고도 합니다.
메모리 내 기능의 이점
SQL Server는 많은 애플리케이션 시스템의 성능을 크게 향상시킬 수 있는 메모리 내 기능을 제공합니다. 이 섹션에서는 가장 간단한 고려 사항에 대해 설명합니다.
OLTP(온라인 트랜잭션 처리) 기능
동시에 다수의 SQL INSERT를 처리해야 하는 시스템이 OLTP 기능에 가장 적합합니다.
- 벤치마크는 메모리 내 기능을 채택하여 속도 향상을 5배에서 20배 더 빠르게 달성할 수 있음을 보여 줍니다.
Transact-SQL 계산을 많이 처리하는 시스템도 적합합니다.
- 무거운 계산 전용 저장 프로시저는 최대 99배 더 빠르게 실행할 수 있습니다.
나중에 메모리 내 OLTP의 성능 향상에 대한 데모를 제공하는 다음 문서를 참조할 수 있습니다.
- Demonstration: Performance Improvement of In-Memory OLTP (데모: 메모리 내 OLTP의 성능 향상)에서는 더 큰 잠재적 성능 향상에 대한 소규모 데모를 제공합니다.
- 메모리 내 OLTP 용 샘플 데이터베이스는 더 큰 규모의 데모를 제공합니다.
운영 분석을 위한 기능
메모리 내 분석은 일반적으로 GROUP BY 절을 포함하여 트랜잭션 데이터를 집계하는 SQL SELECT를 나타냅니다. columnstore라는 인덱스 형식은 운영 분석의 핵심입니다.
다음 두 가지 주요 시나리오가 있습니다.
- 운영 분석 일괄 처리는 업무 시간 이후에 또는 트랜잭션 데이터의 복사본이 있는 보조 하드웨어에서 실행되는 집계 프로세스를 나타냅니다.
- Azure Synapse Analytics는 일괄 처리 운영 분석과도 관련이 있습니다.
- 실시간 운영 분석은 업무 시간 및 트랜잭션 워크로드에 사용되는 기본 하드웨어에서 실행되는 집계 프로세스를 나타냅니다.
현재 문서에서는 분석이 아닌 OLTP에 중점을 둡니다. columnstore 인덱스가 분석을 SQL로 가져오는 방법에 대한 자세한 내용은 다음을 참조하세요.
columnstore
훌륭한 블로그 게시물의 시퀀스는 여러 관점에서 columnstore 인덱스를 우아하게 설명합니다. 대부분의 게시물은 columnstore에서 지원하는 실시간 운영 분석의 개념에 대해 추가로 설명합니다. 이 게시물은 2016년 3월 Microsoft의 프로그램 관리자인 수닐 아가왈이 작성했습니다.
실시간 운영 분석
- 메모리 내 기술을 사용한 실시간 운영 분석
- 실시간 운영 분석 - 비클러스터형 Columnstore 인덱스(NCCI) 개요
- 실시간 운영 분석: SQL Server 2016에서 비클러스터형 클러스터형 Columnstore 인덱스(NCCI)를 사용하는 간단한 예제
- 실시간 운영 분석: SQL Server 2016의 DML 작업 및 비클러스터형 Columnstore 인덱스(NCCI)
- 실시간 운영 분석: 필터링된 비클러스터형 Columnstore 인덱스(NCCI)
- 실시간 운영 분석: 비클러스터형 Columnstore 인덱스(NCCI)의 압축 연기 옵션
- 실시간 운영 분석: NCCI의 압축 연기 옵션 및 성능
- 실시간 운영 분석: 메모리 최적화 테이블 및 Columnstore 인덱스
columnstore 인덱스 조각 모음
데이터의 대량 가져오기
- 클러스터형 열 저장소: 대량 로드
- 클러스터형 Columnstore 인덱스: 데이터 로드 최적화 - 최소 로깅
- 클러스터형 columnstore 인덱스: 데이터 로드 최적화 - 병렬 대량 가져오기
메모리 내 OLTP의 기능
메모리 내 OLTP의 기본 기능을 살펴보겠습니다.
메모리 최적화 테이블
CREATE TABLE 문의 T-SQL 키워드 MEMORY_OPTIMIZED는 디스크가 아닌 활성 메모리에 테이블을 만드는 방법입니다.
메모리 액세스에 최적화된 테이블 은 활성 메모리에 포함될 뿐 아니라 디스크에도 보조 복사본이 있습니다.
- 디스크 복사는 서버 또는 데이터베이스를 종료하고 다시 시작한 후 일상적인 복구를 위한 것입니다. 이 메모리 및 디스크의 중복성은 사용자와 코드에서 완전히 숨겨집니다.
고유하게 컴파일된 모듈
CREATE PROCEDURE 문의 T-SQL 키워드 NATIVE_COMPILATION은 고유하게 컴파일된 저장 프로시저를 만드는 방법입니다. 온라인에서 데이터베이스를 순환할 때마다 네이티브 프로시저를 처음 사용할 때 T-SQL 문이 기계어 코드로 컴파일됩니다. T-SQL 명령어는 더 이상 각 명령의 느린 해석을 견디지 못합니다.
- 네이티브 컴파일은 해석된 시간의 1/100에 해당하는 시간이라는 것을 확인했습니다.
원시 모듈은 메모리 최적화 테이블만 참조할 수 있으며 디스크 기반 테이블을 참조할 수 없습니다.
고유하게 컴파일된 모듈에는 다음 세 가지 유형이 있습니다.
- 고유하게 컴파일된 저장 프로시저.
- 고유하게 컴파일된 사용자 정의 스칼라 함수(UDF).
- 고유하게 컴파일된 트리거.
Azure SQL 데이터베이스 가용성
메모리 내 OLTP 및 Columnstore는 Azure SQL 데이터베이스에서 사용할 수 있습니다. 자세한 내용은 SQL Database에서 메모리 내 기술을 사용하여 성능 최적화를 참조하세요.
1. 호환성 수준 >= 130 설정
이 섹션의 앞부분에 나오는 번호가 지정된 일련의 섹션에서는 메모리 내 OLTP 기능을 구현하는 데 사용할 수 있는 Transact-SQL 구문을 보여 줍니다.
먼저 데이터베이스의 호환성 수준을 적어도 130 이상으로 설정하는 것이 중요합니다. 다음은 현재 데이터베이스에 설정된 현재 호환성 수준을 보여 주는 T-SQL 코드입니다.
SELECT d.compatibility_level
FROM sys.databases as d
WHERE d.name = Db_Name();
다음은 필요한 경우 수준을 업데이트하는 T-SQL 코드입니다.
ALTER DATABASE CURRENT
SET COMPATIBILITY_LEVEL = 130;
2. 스냅샷으로 상승
트랜잭션에 디스크 기반 테이블과 메모리 최적화 테이블이 모두 포함되어 있을 경우 컨테이너 간 트랜잭션이라고 합니다. 이러한 트랜잭션에서 메모리 최적화 트랜잭션 부분은 SNAPSHOT이라고 하는 트랜잭션 격리 수준에서 작동해야 합니다.
컨테이너 간 트랜잭션에서 메모리 최적화 테이블에 대해 이 수준을 안정적으로 적용하려면 다음 T-SQL을 실행하여 데이터베이스 설정을 변경합니다.
ALTER DATABASE CURRENT
SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON;
3. 최적화된 FILEGROUP 생성
Microsoft SQL Server에서 메모리 최적화 테이블을 만들려면 먼저 CONTAINS MEMORY_OPTIMIZED_DATA를 선언하는 FILEGROUP을 만들어야 합니다. FILEGROUP이 데이터베이스에 할당됩니다. 자세한 내용은 다음을 참조하십시오.
Azure SQL 데이터베이스에서는 이러한 FILEGROUP을 만들 필요가 없으며 만들 수도 없습니다.
다음 샘플 T-SQL 스크립트는 메모리 내 OLTP에 대한 데이터베이스를 사용하도록 설정하고 모든 권장 설정을 구성합니다. enable-in-memory-oltp.sql는 SQL Server 및 Azure SQL 데이터베이스 모두와 작동합니다.
MEMORY_OPTIMIZED_DATA 파일 그룹이 있는 데이터베이스에 대해 모든 SQL Server 기능이 지원되는 것은 아닙니다. 제한 사항에 대한 자세한 내용은 메모리 내 OLTP에 대한 지원되지 않는 SQL Server 기능을 참조하세요.
4. 메모리 최적화 테이블 생성
중요한 Transact-SQL 키워드는 MEMORY_OPTIMIZED 키워드입니다.
CREATE TABLE dbo.SalesOrder
(
SalesOrderId integer not null IDENTITY
PRIMARY KEY NONCLUSTERED,
CustomerId integer not null,
OrderDate datetime not null
)
WITH
(MEMORY_OPTIMIZED = ON,
DURABILITY = SCHEMA_AND_DATA);
메모리 최적화 테이블에 대한 Transact-SQL INSERT 및 SELECT 문은 정규 테이블과 동일합니다.
메모리 액세스에 최적화된 테이블에 대한 ALTER TABLE
ALTER TABLE...ADD/DROP은 메모리 최적화 테이블 또는 인덱스에서 열을 추가하거나 제거할 수 있습니다.
- CREATE INDEX 및 DROP INDEX는 메모리 최적화 테이블에 대해 실행할 수 없으니, 대신 ALTER TABLE ... ADD/DROP INDEX를 사용하세요.
- 자세한 내용은 메모리 최적화 테이블 변경을 참조하세요.
메모리 최적화 테이블 및 인덱스 계획
5. 고유하게 컴파일된 저장 프로시저(기본 프로시저) 생성
중요한 키워드는 NATIVE_COMPILATION입니다.
CREATE PROCEDURE ncspRetrieveLatestSalesOrderIdForCustomerId
@_CustomerId INT
WITH
NATIVE_COMPILATION,
SCHEMABINDING
AS
BEGIN ATOMIC
WITH
(TRANSACTION ISOLATION LEVEL = SNAPSHOT,
LANGUAGE = N'us_english')
DECLARE @SalesOrderId int, @OrderDate datetime;
SELECT TOP 1
@SalesOrderId = s.SalesOrderId,
@OrderDate = s.OrderDate
FROM dbo.SalesOrder AS s
WHERE s.CustomerId = @_CustomerId
ORDER BY s.OrderDate DESC;
RETURN @SalesOrderId;
END;
키워드 SCHEMABINDING은 기본 프로시저가 먼저 삭제되지 않으면 기본 프로시저에서 참조하는 테이블을 삭제할 수 없음을 의미합니다. 자세한 내용은 네이티브 컴파일 저장 프로시저 만들기를 참조하세요.
메모리 최적화 테이블에 액세스하기 위해 고유하게 컴파일된 저장 프로시저를 만들 필요가 없습니다. 기존 저장 프로시저 및 임시 일괄 처리에서 메모리 최적화 테이블을 참조할 수도 있습니다.
6. 기본 프로시저 실행
테이블을 두 개의 데이터 행으로 채웁니다.
INSERT into dbo.SalesOrder
( CustomerId, OrderDate )
VALUES
( 42, '2013-01-13 03:35:59' ),
( 42, '2015-01-15 15:35:59' );
고유하게 컴파일된 저장 프로시저에 대한 EXECUTE 호출은 다음과 같습니다.
DECLARE @LatestSalesOrderId int, @mesg nvarchar(128);
EXECUTE @LatestSalesOrderId =
ncspRetrieveLatestSalesOrderIdForCustomerId 42;
SET @mesg = CONCAT(@LatestSalesOrderId,
' = Latest SalesOrderId, for CustomerId = ', 42);
PRINT @mesg;
실제 PRINT 출력은 다음과 같습니다.
-- 2 = Latest SalesOrderId, for CustomerId = 42
설명서와 다음 단계에 대한 가이드
위의 일반 예제에서는 메모리 내 OLTP의 고급 기능을 학습할 수 있는 기반을 제공합니다. 다음 섹션은 알아야 할 수 있는 특별한 고려 사항과 각 항목에 대한 세부 정보를 볼 수 있는 위치에 대한 가이드입니다.
메모리 내 OLTP 기능이 훨씬 더 빠르게 작동하는 방법
다음 하위 섹션에서는 향상된 성능을 제공하기 위해 메모리 내 OLTP 기능이 내부적으로 작동하는 방식을 간략하게 설명합니다.
메모리 최적화 테이블의 성능 향상 방법
이중 특성: 메모리 최적화 테이블은 활성 메모리에서 표현되고, 하드 디스크에도 표현되는 이중 특성이 있습니다. 각 트랜잭션은 테이블의 두 표현 방식으로 모두 커밋됩니다. 트랜잭션은 훨씬 더 빠른 활성 메모리 표현에 대해 작동합니다. 메모리 최적화 테이블은 디스크에 비해 활성 메모리 속도가 더 빠르다는 이점이 있습니다. 또한 활성 메모리의 민첩성이 높아질수록 속도에 최적화된 고급 테이블 구조가 실용화됩니다. 또한 고급 구조는 페이지가 없으므로 래치와 스핀 잠금의 오버헤드 및 경합을 방지합니다.
잠금 없음: 메모리 최적화 테이블은 데이터 무결성과 동시성 및 높은 처리량 간 경쟁하는 목표에 대한 최적의 접근 방법을 사용합니다. 트랜잭션 중에 테이블은 업데이트된 데이터 행의 버전에 잠금을 배치하지 않습니다. 이렇게 하면 일부 대용량 시스템에서 경합이 크게 감소할 수 있습니다.
행 버전: 잠금 대신 메모리 최적화 테이블은 tempdb가 아닌 테이블 자체에 업데이트된 행의 새 버전을 추가합니다. 원래 행은 트랜잭션이 커밋될 때까지 유지됩니다. 트랜잭션 중에 다른 프로세스는 행의 원래 버전을 읽을 수 있습니다.
- 디스크 기반 테이블의 경우 행 버전이 여러 개 만들어 지면 행 버전은 tempdb에 임시로 저장됩니다.
로깅 감소: 업데이트된 행의 이전 버전과 이후 버전은 메모리 최적화 테이블에서 유지됩니다. 행 쌍은 일반적으로 로그 파일에 기록되는 정보 대부분을 제공합니다. 이렇게 하면 시스템에서 로그에 더 적은 정보를 덜 자주 쓸 수 있습니다. 여전히 트랜잭션 무결성이 보장됩니다.
기본 프로시저의 성능 향상 방법
일반 해석 저장 프로시저를 고유하게 컴파일된 저장 프로시저로 변환하면 런타임에 실행할 명령 수가 크게 줄어듭니다.
메모리 내 기능의 상충 관계
전산학에서 일반적인 경우와 마찬가지로 메모리 내 기능을 통해 제공되는 성능 향상은 절충안입니다. 더 나은 기능일수록 해당 기능의 추가 비용보다 더 가치가 있다는 이점이 있습니다. 다음에서 상충 관계에 대한 포괄적인 지침을 확인할 수 있습니다.
이 섹션의 나머지 부분에서는 몇 가지 주요 계획 및 장단점 고려 사항을 나열합니다.
메모리 최적화 테이블의 장단점
메모리 추정: 메모리 최적화 테이블이 사용하는 활성 메모리 양을 추정할 수 있습니다. 컴퓨터 시스템에 메모리 최적화 테이블을 호스트할 수 있는 충분한 메모리 용량이 있어야 합니다. 자세한 내용은 다음을 참조하십시오.
큰 테이블 분할: 많은 활성 메모리에 대한 요구를 충족하는 한 가지 방법은 큰 테이블을 최신 데이터 행을 저장하는 메모리 내 부분과, 콜드 레거시 행(예: 전체가 배송되어 완료된 판매 주문)을 저장하는 디스크 부분으로 분할하는 것입니다. 이 분할은 디자인 및 구현 단계에서 수동으로 처리됩니다. 참조
기본 프로시저의 장단점
- 네이티브 컴파일된 저장 프로시저는 디스크 기반 테이블에 액세스할 수 없습니다. 기본 프로시저는 메모리 최적화 테이블에만 액세스할 수 있습니다.
- 서버 또는 데이터베이스가 가장 최근에 다시 온라인 상태가 된 후 기본 프로시저가 처음으로 실행되면 기본 프로시저를 한 번 다시 컴파일해야 합니다. 이 작업으로 인해 기본 프로시저 실행이 시작되기 전에 지연이 발생합니다.
메모리 최적화 테이블에 대한 고급 고려 사항
메모리 최적화 테이블의 인덱스는 기존 디스크 기반 테이블의 인덱스와는 몇 가지 면에서 다릅니다. 해시 인덱스는 메모리 최적화 테이블에서만 사용할 수 있습니다.
계획 중인 메모리 최적화 테이블 및 인덱스에 대해 활성 메모리가 충분한지 확인할 계획을 세워야 합니다. 참조
메모리 최적화 테이블은 DURABILITY = SCHEMA_ONLY를 사용하여 선언할 수 있습니다.
- 이 구문은 데이터베이스를 오프라인으로 전환할 때 메모리 최적화 테이블의 모든 데이터를 삭제하도록 시스템에 지시합니다. 테이블 정의만 유지됩니다.
- 데이터베이스를 다시 온라인 상태로 전환하면 메모리 최적화 테이블이 데이터가 비어 있는 활성 메모리로 다시 로드됩니다.
- 수천 개의 행이 관련된 경우 SCHEMA_ONLY 테이블이 tempdb의 #temporary 테이블 보다 더 효율적일 수 있습니다.
테이블 변수는 메모리 최적화로 선언할 수도 있습니다. 참조
네이티브 컴파일 모듈에 대한 고급 고려 사항
Transact-SQL을 통해 사용할 수 있는 고유하게 컴파일된 모듈 유형은 다음과 같습니다.
- 네이티브 컴파일 저장 프로시저(기본 프프로시저)
- 네이티브 컴파일 스칼라 사용자 정의 함수
- 네이티브 컴파일 트리거(기본 트리거).
- 메모리 최적화 테이블에는 고유하게 컴파일되는 트리거만 허용됩니다.
- 네이티브 컴파일 테이블 반환 함수.
고유하게 컴파일된 사용자 정의 함수(UDF)는 해석된 UDF보다 빠르게 실행됩니다. UDF에 대해 고려할 사항은 다음과 같습니다.
- T-SQL SELECT에서 UDF를 사용하는 경우 UDF가 반환된 행마다 한 번씩 항상 호출됩니다.
- UDF는 인라인으로 실행되지 않고 항상 호출됩니다.
- 컴파일된 구분은 각 UDF에 내재된 반복 호출의 오버헤드보다 덜 중요합니다.
- 하지만 실용적인 수준에서 UDF 호출의 오버헤드가 허용되는 경우도 많습니다.
테스트 데이터 및 네이티브 UDF의 성능에 대한 설명은 다음을 참조하세요.
메모리 최적화 테이블에 대한 설명서 가이드
메모리 최적화 테이블에 대한 특별한 고려 사항을 설명하는 다른 문서를 참조하세요.
- 메모리 내 OLTP로 마이그레이션
- 테이블 또는 저장 프로시저가 메모리 내 OLTP로 이식되어야 하는지 결정
- SQL Server Management Studio의 트랜잭션 성능 분석 보고서를 사용하면 메모리 내 OLTP로 데이터베이스 애플리케이션의 성능이 향상될지 평가할 수 있습니다.
- 메모리 최적화 어드바이저를 사용하여 디스크 기반 데이터베이스 테이블을 메모리 내 OLTP로 마이그레이션할 수 있습니다.
- 메모리 최적화 테이블의 백업, 복원 및 복구
- 메모리 최적화 테이블에서 사용하는 스토리지는 메모리 크기보다 훨씬 클 수 있으며 데이터베이스 백업의 크기에 영향을 줍니다.
- Transactions with Memory-Optimized Tables
- 메모리 최적화 테이블의 트랜잭션에 대한 T-SQL의 재시도 논리 관련 정보를 포함합니다.
- 메모리 내 OLTP에 대한 Transact-SQL 지원
- 메모리 최적화 테이블 및 기본 프로시저을 지원하고 지원하지 않는 T-SQL 및 데이터 형식.
- 메모리 최적화 테이블이 있는 데이터베이스를 리소스 풀에 바인딩하기에는 선택적 고급 고려 사항이 설명되어 있습니다.
기본 프로시저에 대한 설명서 가이드
다음 문서 및 그 목차에 나오는 하위 문서에서는 네이티브 컴파일 저장 프로시저에 대해 자세히 설명합니다.
관련 링크
- 초기 문서: 메모리 내 OLTP(메모리 내 최적화)
메모리 내 OLTP를 사용하여 얻을 수 있는 성능 향상을 보여 주는 코드를 제공하는 문서는 다음과 같습니다.
- Demonstration: Performance Improvement of In-Memory OLTP (데모: 메모리 내 OLTP의 성능 향상)에서는 더 큰 잠재적 성능 향상에 대한 소규모 데모를 제공합니다.
- 메모리 내 OLTP 용 샘플 데이터베이스는 더 큰 규모의 데모를 제공합니다.