메모리 액세스에 최적화된 테이블 소개
적용 대상: SQL Server Azure SQL 데이터베이스 Azure SQL Managed Instance
메모리 최적화 테이블은 CREATE TABLE(Transact-SQL)을 사용하여 만들어집니다.
메모리 최적화 테이블은 기본적으로 완전 내구성이 있으며(기존) 디스크 기반 테이블의 트랜잭션과 마찬가지로 메모리 최적화 테이블의 트랜잭션은 완전한 원자성, 일관성, 격리, 지속형(ACID)을 갖습니다. 메모리 최적화 테이블과 네이티브 컴파일된 저장 프로시저는 Transact-SQL 기능의 하위 집합만을 지원합니다.
SQL Server 2016부터 Azure SQL 데이터베이스에서는 메모리 내 OLTP와 관련된 데이터 정렬 또는 코드 페이지에 제한이 없습니다.
메모리 최적화 테이블의 기본 스토리지는 주 메모리입니다. 테이블의 행은 메모리에서 읽고 메모리에 기록됩니다. 테이블 데이터의 두 번째 복사본은 디스크에서 유지 관리되지만 내구성을 위해서만 유지됩니다. 내구성이 있는 테이블에 대한 자세한 내용은 메모리 액세스에 최적화된 개체의 스토리지 만들기 및 관리 를 참조하세요. 메모리 최적화 테이블의 데이터는 데이터베이스 복구 중(예: 서버 다시 시작)에만 디스크에서 읽습니다.
보다 큰 성능 향상을 위해 메모리 내 OLTP는 트랜잭션 내구성이 지연된 영구 테이블을 지원합니다. 지연된 지속형 트랜잭션은 트랜잭션이 커밋되고 컨트롤이 클라이언트에 반환된 후 곧바로 디스크에 저장됩니다. 성능이 향상되는 대신 디스크에 저장되지 않은 커밋된 트랜잭션이 서버 충돌 또는 장애 조치(Failover)에서 손실됩니다.
기본 내구성 메모리 최적화 테이블 외에도 SQL Server는 기록되지 않고 데이터가 디스크에 지속되지 않는 비 내구성 메모리 최적화 테이블도 지원합니다. 즉, 이러한 테이블의 트랜잭션에는 디스크 IO가 필요하지 않지만 서버 작동 중단 또는 장애 조치(failover)가 있는 경우 데이터가 복구되지 않습니다.
메모리 내 OLTP는 SQL Server와 통합되어 개발, 배포, 관리 효율성, 지원 가능성과 같은 모든 영역에서 원활한 환경을 제공합니다. 데이터베이스는 메모리 내 개체뿐만 아니라 디스크 기반 개체를 포함할 수 있습니다.
메모리 최적화 테이블의 행 버전이 지정됩니다. 즉, 테이블의 각 행에는 잠재적으로 여러 버전이 있습니다. 모든 행 버전은 동일한 테이블 데이터 구조에서 유지 관리됩니다. 행 버전 관리 기능을 사용하여 동일한 행에서 동시 읽기 및 쓰기를 허용합니다. 동일한 행의 동시 읽기 및 쓰기에 대한 자세한 내용은 메모리 최적화 테이블이 있는 트랜잭션을 참조하세요.
다음 그림에서는 다중 버전 관리를 보여 줍니다. 그림에서는 세 개의 행이 있는 테이블을 보여줍니다. 각 행은 버전이 다릅니다.
테이블에는 r1, r2, r3의 세 개의 행이 있습니다. r1에는 세 가지 버전, r2에는 두 가지 버전, r3에는 네 가지 버전이 있습니다. 동일한 행의 다른 버전이 연속 메모리 위치를 반드시 차지하지는 않습니다. 테이블 데이터 구조의 여러 위치에 분산하여 배치할 수 있습니다.
메모리 최적화 테이블 데이터 구조는 행 버전의 컬렉션으로 볼 수 있습니다. 디스크 기반 테이블의 행은 페이지 및 익스텐트로 구성되며 페이지 번호와 페이지 오프셋을 사용하여 주소가 지정된 개별 행은 메모리 최적화 테이블의 행 버전이 8바이트 메모리 포인터를 사용하여 처리됩니다.
메모리 최적화 테이블의 데이터는 다음 두 가지 방법으로 액세스됩니다.
네이티브 컴파일된 저장 프로시저 사용.
네이티브 컴파일된 저장 프로시저 외부의 해석된 Transact-SQL 사용. 이러한 Transact-SQL 문은 해석된 저장 프로시저 내에 있거나 임시 Transact-SQL 문일 수 있습니다.
메모리 최적화 테이블의 데이터 액세스
메모리 최적화 테이블은 네이티브 컴파일된 저장 프로시저에서 가장 효율적으로 액세스할 수 있습니다(네이티브 컴파일된 저장 프로시저). 메모리 최적화 테이블은 (기존의) 해석된 Transact-SQL을 사용하여 액세스할 수도 있습니다. 해석된 Transact-SQL은 네이티브 컴파일된 저장 프로시저 없이 메모리 최적화 테이블에 액세스하는 것을 의미합니다. 해석된 Transact-SQL 액세스의 몇 가지 예로는 DML 트리거, 임시 Transact-SQL 일괄 처리, 뷰 및 테이블 반환 함수에서 메모리 최적화 테이블에 액세스하는 것이 포함됩니다.
다음 표에는 다양한 개체에 대한 네이티브 및 해석된 Transact-SQL 액세스가 요약되어 있습니다.
기능 | 네이티브 컴파일된 저장 프로시저를 사용하여 액세스 | 해석된 Transact-SQL 액세스 | CLR 액세스 |
---|---|---|---|
메모리 최적화 테이블 | 예 | 예 | 아니요* |
메모리 액세스에 최적화된 테이블 형식 | 예 | 예 | 아니요 |
고유하게 컴파일된 저장 프로시저 | 고유하게 컴파일된 저장 프로시저 중첩은 지원되지 않습니다. 참조된 프로시저도 네이티브 컴파일되는 한 저장 프로시저 내에서 EXECUTE 구문을 사용할 수 있습니다. | 예 | 아니요* |
*컨텍스트 연결(CLR 모듈을 실행하는 경우 SQL Server의 연결)에서는 메모리 최적화 테이블이나 네이티브 컴파일된 저장 프로시저에 액세스할 수 없습니다. 하지만 메모리 최적화 테이블과 고유하게 컴파일된 저장 프로시저에 액세스할 수 있는 다른 연결을 만들어서 열 수 있습니다.
성능 및 스케일링 성능
다음과 같은 요인이 메모리 내 OLTP에서 얻을 수 있는 성능 향상에 영향을 미칩니다.
통신: 짧은 저장 프로시저에 대한 호출이 많은 애플리케이션은 호출 수가 적고 각 저장 프로시저에서 구현된 기능이 더 많은 애플리케이션에 비해 성능 향상 폭이 적을 수 있습니다.
Transact-SQL 실행: 메모리 내 OLTP는 해석된 저장 프로시저 또는 쿼리 실행 대신 네이티브 컴파일된 저장 프로시저를 사용할 때 최상의 성능을 달성합니다. 이러한 저장 프로시저에서 메모리 최적화 테이블에 액세스하면 이점이 있을 수 있습니다.
범위 검색 및 지점 조회: 메모리 액세스에 최적화된 비클러스터형 인덱스는 범위 검색 및 정렬된 검색을 지원합니다. 지점 조회의 경우 메모리 최적화 해시 인덱스는 메모리 최적화 비클러스터형 인덱스보다 성능이 우수합니다. 메모리 액세스에 최적화된 비클러스터형 인덱스는 디스크 기반 인덱스보다 성능이 우수합니다.
- SQL Server 2016부터 메모리 최적화 테이블에 대한 쿼리 계획은 테이블을 병렬로 검색할 수 있습니다. 이렇게 하면 분석 쿼리의 성능이 향상됩니다.
- 해시 인덱스도 SQL Server 2016에서 병렬로 검색할 수 있게 되었습니다.
- 또한 비클러스터형 인덱스도 SQL Server 2016에서 병렬로 검색할 수 있게 되었습니다.
- Columnstore 인덱스는 SQL Server 2014에서 시작된 이후 병렬로 검색할 수 있습니다.
인덱스 작업: 인덱스 작업은 기록되지 않으며 메모리에만 있습니다.
동시 실행: 성능이 래치 경합 또는 차단과 같은 엔진 수준 동시성의 영향을 받는 애플리케이션은 애플리케이션이 메모리 내 OLTP로 이동하면 성능이 크게 개선됩니다.
다음 표에서는 관계형 데이터베이스에서 일반적으로 발견되는 성능 및 확장성 문제와 메모리 내 OLTP를 사용하여 성능을 개선할 수 있는 방법을 나열합니다.
문제 | 메모리 내 OLTP 영향 |
---|---|
성능 많은 리소스(CPU, I/O, 네트워크 또는 메모리) 사용량 |
CPU 네이티브 컴파일된 저장 프로시저는 해석된 저장 프로시저에 비해 Transact-SQL 문을 실행하는 데 훨씬 적은 명령이 필요하기 때문에 CPU 사용량을 크게 줄일 수 있습니다. 메모리 내 OLTP는 한 서버가 잠재적으로 5~10대의 서버 처리량을 제공할 수 있기 때문에 스케일 아웃 워크로드에 대한 하드웨어 투자를 줄이는 데 도움이 될 수 있습니다. I/O I/O 병목 상태가 처리에서 데이터 또는 인덱스 페이지로 발생하는 경우 메모리 내 OLTP는 병목 상태를 줄일 수 있습니다. 또한 메모리 내 OLTP 개체의 검사점은 연속되며 I/O 작업이 갑자기 증가하지는 않습니다. 그러나 성능에 중요한 테이블의 작업 집합이 메모리에 맞지 않는 경우 메모리 내 OLTP는 데이터가 메모리에 상주해야 하므로 성능이 향상되지 않습니다. 로깅에서 I/O 병목 상태가 발생하는 경우 메모리 내 OLTP는 로깅을 줄이므로 병목 상태를 줄일 수 있습니다. 하나 이상의 메모리 최적화 테이블이 비지속 테이블로 구성된 경우 데이터에 대한 로깅을 제거할 수 있습니다. 메모리 메모리 내 OLTP는 성능 이점이 없습니다. 메모리 내 OLTP는 개체가 메모리에 상주해야 하므로 메모리에 추가적인 압력을 가할 수 있습니다. 네트워크 메모리 내 OLTP는 성능 이점이 없습니다. 데이터는 데이터 계층에서 애플리케이션 계층으로 통신해야 합니다. |
확장성 SQL Server 애플리케이션의 대부분의 크기 조정 문제는 잠금, 래치, 스핀 잠금의 경합과 같은 동시성 문제로 인해 발생합니다. |
래치 경합 일반적인 시나리오는 키 순서로 행을 동시에 삽입할 때 인덱스의 마지막 페이지에서 경합입니다. 메모리 내 OLTP는 데이터에 액세스할 때 래치를 사용하지 않으므로 래치 경합과 관련된 확장성 문제가 완전히 제거됩니다. 스핀 잠금 경합 메모리 내 OLTP는 데이터에 액세스할 때 래치를 사용하지 않으므로 스핀 잠금 경합과 관련된 확장성 문제가 완전히 제거됩니다. 잠금 관련 경합 데이터베이스 애플리케이션에서 읽기 및 쓰기 작업 간에 차단 문제가 발생하는 경우 메모리 내 OLTP는 새로운 형태의 낙관적 동시 실행 제어를 사용하여 모든 트랜잭션 격리 수준을 구현하기 때문에 차단 문제를 제거합니다. 메모리 내 OLTP는 TempDB를 사용하여 행 버전을 저장하지 않습니다. 같은 행을 업데이트하려는 두 개의 동시 트랜잭션과 같은 두 쓰기 작업 간의 충돌로 인해 크기 조정 문제가 발생하는 경우 메모리 내 OLTP는 한 트랜잭션이 성공하고 다른 트랜잭션에 실패합니다. 실패한 트랜잭션은 트랜잭션을 다시 시도하여 명시적으로 또는 암시적으로 다시 제출해야 합니다. 어느 경우나 애플리케이션을 변경해야 합니다. 애플리케이션의 두 쓰기 작업 간에 충돌이 자주 발생하는 경우 낙관적 잠금 값이 감소합니다. 애플리케이션은 메모리 내 OLTP에 적합하지 않습니다. 잠금 에스컬레이션으로 충돌이 유발되지 않는 한 대부분의 OLTP 애플리케이션에는 쓰기 충돌이 없습니다. |
메모리 액세스에 최적화된 테이블의 행 수준 보안
행 수준 보안은 메모리 메모리 최적화 테이블에서 지원됩니다. 메모리 최적화 테이블에 행 수준 보안 정책을 적용하는 것은 기본적으로 디스크 기반 테이블과 동일합니다. 단, 보안 조건자로 사용되는 인라인 테이블 반환 함수는 네이티브 컴파일되어야 합니다(WITH NATIVE_COMPILATION 옵션을 사용하여 생성됨). 자세한 내용은 행 수준 보안 항목의 기능 간 호환성 섹션을 참조하세요.
메모리 내 테이블에는 행 수준 보안에 필수적인 다양한 기본 제공 보안 함수가 사용하도록 설정되었습니다. 자세한 내용은 고유하게 컴파일된 모듈의 기본 제공 함수를 참조하세요.
EXECUTE AS CALLER - 힌트가 지정되지 않은 경우에도 모든 네이티브 모듈은 기본적으로 EXECUTE AS CALLER를 지원하고 사용합니다. 이는 모든 행 수준 보안 조건자 함수가 EXECUTE AS CALLER를 사용하여 함수(및 그 안에서 사용된 모든 기본 제공 함수)가 호출 사용자의 컨텍스트에서 평가될 것으로 예상되기 때문입니다.
EXECUTE AS CALLER에는 호출자에 대한 권한 검사로 인한 작은(약 10%) 성능 손실이 있습니다. 모듈에서 EXECUTE AS OWNER 또는 EXECUTE AS SELF를 명시적으로 지정하는 경우 이러한 권한 검사 및 관련 성능 비용은 방지됩니다. 그러나 위의 기본 제공 함수와 함께 이러한 옵션 중 하나를 사용하면 필요한 컨텍스트 전환으로 인해 성능이 크게 향상됩니다.
시나리오
메모리 내 OLTP가 성능을 향상시킬 수 있는 일반적인 시나리오에 대한 간략한 설명은 메모리 내 OLTP를 참조하세요.