확장 가능한 저장소 엔진
| 다른 이름 | JET Blue |
|---|---|
| 개발자 | 마이크로소프트 |
| 발표일 | 1994년 |
| 저장소 | |
| 프로그래밍 언어 | C++ |
| 운영 체제 | 마이크로소프트 윈도우 |
| 플랫폼 | IA-32, X86-64, ARM, 아이테니엄 (역사적으로는 DEC 알파, MIPS, 파워PC) |
| 종류 | 데이터베이스 엔진 |
| 라이선스 | MIT 허가서 |
| 웹사이트 | docs |
확장 가능한 저장소 엔진(Extensible Storage Engine)(ESE), 일명 JET Blue는 마이크로소프트에서 개발한 ISAM(색인 순차 접근 방식) 데이터 저장 기술이다. ESE는 마이크로소프트 익스체인지 서버, 액티브 디렉터리, 윈도우 검색의 핵심이다. 또한 윈도우 업데이트 클라이언트 및 도움말 및 지원 센터를 포함한 여러 윈도우 구성 요소에서도 사용된다. 이 기술의 목적은 애플리케이션이 색인 및 순차적 접근을 통해 데이터를 저장하고 검색할 수 있도록 하는 것이다.
ESE는 데이터베이스 트랜잭션 업데이트 및 검색을 제공한다. 시스템 충돌 시에도 데이터 일관성이 유지되도록 충돌 복구 메커니즘이 제공된다. ESE의 트랜잭션은 높은 동시성을 지원하여 서버 애플리케이션에 적합하다. ESE는 데이터를 지능적으로 캐싱하여 고성능 데이터 접근을 보장한다. 또한 가벼운 설계 덕분에 보조 애플리케이션에도 적합하다.
ESE 런타임(ESENT.DLL)은 윈도우 2000 이후 모든 윈도우 릴리스에 포함되어 있으며, x64 버전의 ESE 런타임은 윈도우 XP 및 윈도우 서버 2003의 x64 버전부터 제공되었다. 마이크로소프트 익스체인지는 익스체인지 서버 2003까지는 32비트 에디션만 지원되는 플랫폼이었기에 32비트 에디션으로 제공되었다. 익스체인지 서버 2007부터는 64비트 에디션으로 제공된다.
데이터베이스
[편집]데이터베이스는 데이터의 물리적 및 논리적 그룹화이다. ESE 데이터베이스는 윈도우에서 단일 파일로 보인다. 내부적으로 데이터베이스는 2, 4, 8, 16 또는 32 킬로바이트 페이지(16 및 32 KB 페이지 옵션은 윈도우 7 및 익스체인지 2010에서만 사용 가능)의 모음이며,[1] 균형 잡힌 B 트리 구조로 배열되어 있다.[2] 이러한 페이지에는 데이터베이스 내의 데이터를 설명하는 메타데이터, 데이터 자체, 유용한 데이터 순서를 유지하기 위한 인덱스 및 기타 정보가 포함된다. 이 정보는 데이터베이스 파일 내에 혼합되어 있으나, 함께 사용되는 데이터는 데이터베이스 내에서 군집을 이루도록 노력한다. ESE 데이터베이스는 8 킬로바이트 페이지 크기 기준으로 최대 232 페이지, 즉 16 테라바이트의 데이터를 포함할 수 있다.[3]
ESE 데이터베이스는 인스턴스라는 그룹으로 구성된다. 대부분의 애플리케이션은 단일 인스턴스를 사용하지만, 모든 애플리케이션은 여러 인스턴스를 사용할 수도 있다. 인스턴스의 중요성은 단일 복구 로그 시리즈를 하나 이상의 데이터베이스와 연관시킨다는 점에 있다. 현재 ESE 인스턴스에는 언제든지 최대 6개의 사용자 데이터베이스를 연결할 수 있다. ESE를 사용하는 각각의 별도 프로세스는 최대 1024개의 ESE 인스턴스를 가질 수 있다.
데이터베이스는 실행 중인 하나의 ESE 인스턴스에서 분리되어 나중에 동일하거나 다른 실행 중인 인스턴스에 연결될 수 있다는 점에서 이식성이 있다. 분리된 상태에서는 표준 윈도우 유틸리티를 사용하여 데이터베이스를 복사할 수 있다. ESE가 데이터베이스 파일을 독점적으로 열기 때문에 활발하게 사용 중인 데이터베이스는 복사할 수 없다. 데이터베이스는 윈도우에서 직접 주소 지정이 가능한 I/O 작업을 지원하는 모든 장치에 물리적으로 상주할 수 있다.
테이블
[편집]테이블은 동일한 열 세트를 가진 레코드들의 동질적 모음이다. 각 테이블은 테이블 이름으로 식별되며, 그 범위는 해당 테이블이 포함된 데이터베이스 내로 국한된다. 데이터베이스 내에서 테이블에 할당된 디스크 공간의 양은 CreateTable 작업 시 부여되는 매개변수에 의해 결정된다. 테이블은 데이터 생성에 따라 자동으로 확장된다.
테이블에는 하나 이상의 인덱스가 있다. 레코드 데이터를 위한 클러스터형 인덱스가 최소 하나는 있어야 한다. 애플리케이션이 클러스터형 인덱스를 정의하지 않으면, 레코드 삽입의 시간순에 따라 레코드를 정렬하고 클러스터링하는 인공 인덱스가 사용된다. 인덱스는 유용한 데이터 순서를 유지하기 위해 정의되며, 인덱스 순서대로 레코드에 대한 순차적 접근과 인덱스 열 값을 통한 직접 접근을 모두 허용한다. ESE의 클러스터형 인덱스는 반드시 기본(primary)이어야 하며, 이는 인덱스 키가 고유해야 함을 의미한다.
클러스터형 및 비클러스터형 인덱스는 B+ 트리를 사용하여 표현된다. 삽입 또는 업데이트 작업으로 인해 페이지가 넘치면 페이지 분할이 발생한다. 즉, 새 페이지가 할당되고 이전에 인접했던 두 페이지 사이에 논리적으로 연결된다. 이 새 페이지는 물리적으로는 논리적 이웃과 인접하지 않기 때문에 접근 효율성이 떨어진다. ESE에는 데이터를 재압축하는 온라인 압축 기능이 있다. 테이블이 자주 업데이트될 것으로 예상되는 경우, 테이블이나 인덱스를 생성할 때 적절한 페이지 밀도를 지정하여 향후 삽입을 위한 공간을 예약할 수 있다. 이를 통해 분할 작업을 방지하거나 연기할 수 있다.
레코드와 열
[편집]레코드는 연관된 열 값들의 세트이다. 레코드는 업데이트 작업을 통해 삽입 및 업데이트되며 삭제 작업을 통해 삭제할 수 있다. 열은 각각 SetColumns 및 RetrieveColumns 작업을 통해 설정 및 검색된다. 레코드의 최대 크기는 긴 값(long value) 열을 제외하고 8킬로바이트 페이지당 8110바이트이다. LongText 및 LongBinary 열 유형은 이 크기 제한에 크게 기여하지 않으며, 긴 값 열에 데이터가 저장될 때 레코드는 데이터베이스 페이지 크기보다 훨씬 큰 데이터를 보유할 수 있다. 레코드에 긴 값 참조가 저장될 때는 레코드 내 데이터가 9바이트만 필요하다. 이러한 긴 값 자체는 최대 2 기가바이트(GB) 크기일 수 있다.
레코드는 일반적으로 각 레코드가 동일한 열 세트에 대한 값 세트를 가진다는 점에서 균일하다. ESE에서는 테이블에 대해 많은 열을 정의할 수 있으면서도 특정 레코드가 소수의 비NULL 열 값만 포함하도록 할 수도 있다. 이런 의미에서 테이블은 이질적인 레코드의 모음이 될 수도 있다.
ESE는 1비트에서 2GB에 이르는 광범위한 열 값을 지원한다. 올바른 열 유형을 선택하는 것은 중요하다. 열 유형이 인덱스 정렬을 포함한 많은 속성을 결정하기 때문이다. ESE는 다음과 같은 데이터 유형을 지원한다.
열 유형
[편집]| 이름 | 설명 |
|---|---|
| Bit | 3진 값(NULL, 0, 또는 1) |
| Unsigned Byte | 1바이트 부호 없는 정수 |
| Short | 2바이트 부호 있는 정수 |
| Unsigned Short | 2바이트 부호 없는 정수 |
| Long | 4바이트 부호 있는 정수 |
| Unsigned Long | 4바이트 부호 없는 정수 |
| LongLong | 8바이트 부호 있는 정수 |
| UnsignedLongLong | 8바이트 부호 없는 정수 |
| Currency | 8바이트 부호 있는 정수 |
| IEEE Single | 4바이트 부동 소수점 수 |
| IEEE Double | 8바이트 부동 소수점 수 |
| DateTime | 8바이트 날짜-시간 (정수형 날짜, 소수형 시간) |
| GUID | 16바이트 고유 식별자 |
| Binary | 이진 문자열, 길이 <= 255바이트 |
| Text | ANSI 또는 유니코드 문자열, 길이 <= 255바이트 |
| Long Binary | 대형 이진 문자열, 길이 < 2 GB |
| Long Text | 대형 ANSI 또는 유니코드 문자열, 길이 < 2 GB |
고정, 가변 및 태그 지정된 열
[편집]각 ESE 테이블은 최대 127개의 고정 길이 열, 128개의 가변 길이 열, 64,993개의 태그 지정된 열을 정의할 수 있다.
- 고정 열은 기본적으로 값에 관계없이 각 레코드에서 동일한 양의 공간을 차지하는 열이다. 고정 열은 열 값의 NULL 여부를 나타내는 1비트와 해당 열이나 이후에 정의된 고정 열이 설정된 각 레코드에서 고정된 양의 공간을 차지한다.
- 가변 열은 기본적으로 특정 열 값의 크기에 따라 설정되는 각 레코드에서 가변적인 양의 공간을 차지하는 열이다. 가변 열은 NULL 여부와 크기를 결정하기 위해 2바이트를 차지하며, 해당 열이 설정된 각 레코드에서 가변적인 양의 공간을 차지한다.
- 태그 지정된 열은 레코드에 설정되지 않으면 공간을 전혀 차지하지 않는 열이다. 단일 값일 수도 있고 다중 값일 수도 있다. 동일한 태그 지정된 열이 단일 레코드에 여러 값을 가질 수 있다. 태그 지정된 열이 레코드에 설정되면, 각 태그 지정된 열 인스턴스는 태그 지정된 열 인스턴스 값의 크기 외에도 약 4바이트의 공간을 차지한다. 단일 태그 지정된 열의 인스턴스 수가 많을 때는 태그 지정된 열 인스턴스당 오버헤드가 약 2바이트이다. 태그 지정된 열은 설정되지 않으면 공간을 전혀 차지하지 않으므로 희소 열에 이상적이다. 다중 값 태그 지정된 열이 인덱싱되면, 인덱스는 태그 지정된 열의 각 값에 대해 레코드당 하나의 항목을 포함하게 된다.
주어진 테이블에 대해 열은 두 가지 범주 중 하나에 속한다. 각 레코드에 정확히 한 번 나타나며 NULL 값을 가질 수 있는 열, 그리고 드물게 나타나거나 단일 레코드에 여러 번 나타날 수 있는 열이다. 고정 및 가변 열은 전자에 속하고, 태그 지정된 열은 후자에 속한다. 두 열 범주의 내부 표현 방식은 다르며, 열 범주 간의 장단점을 이해하는 것이 중요하다. 고정 및 가변 열은 일반적으로 NULL 값을 가지는 경우에도 모든 레코드에 표현된다. 이러한 열은 오프셋 테이블을 통해 빠르게 주소를 지정할 수 있다. 태그 지정된 열 인스턴스 앞에는 열 식별자가 있으며, 해당 열은 태그 지정된 열 세트를 이진 검색하여 위치를 찾는다.
긴 값
[편집]Long Text 및 Long Binary 열 유형은 대형 이진 객체이다. 이들은 긴 값 ID와 바이트 오프셋을 기준으로 클러스터형 인덱스와 별도의 B+ 트리 구조에 저장된다. ESE는 이러한 열에 대한 추가, 바이트 범위 덮어쓰기 및 크기 설정을 지원한다. 또한 ESE에는 여러 레코드가 동일한 대형 이진 객체를 참조할 수 있는 단일 인스턴스 저장 기능이 있어, 각 레코드가 정보의 자체 복사본을 가지고 있는 것처럼 작동하며 레코드 간 잠금 충돌이 없다. Long Text 또는 Long Binary 열 값의 최대 크기는 2GB이다.
버전, 자동 증가 및 에스크로 열
[편집]버전 열은 이 열을 포함하는 레코드가 업데이트 작업을 통해 수정될 때마다 ESE에 의해 자동으로 증가된다. 이 열은 애플리케이션에서 설정할 수 없으며 읽기만 가능하다. 버전 열의 애플리케이션 사용 예로는 주어진 레코드의 메모리 내 복사본을 새로 고쳐야 하는지 결정하는 용도가 있다. 테이블 레코드의 값이 캐시된 복사본의 값보다 크면 캐시된 복사본은 오래된 것으로 간주된다. 버전 열은 Long 유형이어야 한다.
자동 증가 열은 열에 포함된 값이 테이블의 모든 레코드에 대해 고유하도록 ESE에 의해 자동으로 설정된다. 이 열은 버전 열과 마찬가지로 애플리케이션에서 설정할 수 없다. 자동 증가 열은 읽기 전용이며 업데이트 작업을 통해 테이블에 새 레코드가 삽입될 때 자동으로 설정된다. 열의 값은 레코드 수명 동안 일정하게 유지되며, 테이블당 하나의 자동 증가 열만 허용된다. 자동 증가 열은 Long 또는 Currency 유형일 수 있다.
에스크로 열은 EscrowUpdate 작업을 통해 수정할 수 있다. 에스크로 업데이트는 수치적 델타 연산이다. 에스크로 열은 Long 유형이어야 한다. 수치적 델타 연산의 예로는 값에 2를 더하거나 1을 빼는 것이 있다. ESE는 업데이트의 최종 값보다는 값의 변화를 추적한다. ESE가 어떤 트랜잭션이 커밋되고 어떤 트랜잭션이 롤백되는지에 관계없이 실제 최종 값을 결정할 수 있으므로, 여러 세션이 동일한 값에 대해 EscrowUpdate를 통해 미해결 변경 사항을 가질 수 있다. 이를 통해 여러 사용자가 수치적 델타 변경을 수행하여 동시에 열을 업데이트할 수 있다. 선택적으로 데이터베이스 엔진은 열 값이 0인 레코드를 삭제할 수 있다. 이러한 에스크로 열의 일반적인 용도는 참조 카운터이다. 많은 스레드가 잠금 없이 값을 증가/감소시키고 카운터가 0에 도달하면 레코드가 자동으로 삭제된다.
인덱스
[편집]인덱스는 테이블 내 레코드의 지속적인 순서이다. 인덱스는 정의된 순서대로 행에 대한 순차적 접근과 인덱싱된 열 값을 기반으로 하는 직접적인 레코드 탐색 모두에 사용된다. 인덱스에 의해 정의된 순서는 우선순위 순서대로 열 배열로 설명된다. 이 열 배열을 인덱스 키라고도 한다. 각 열을 인덱스 세그먼트라고 한다. 각 인덱스 세그먼트는 정렬 기여도 측면에서 오름차순 또는 내림차순일 수 있다. 테이블에 대해 원하는 만큼 많은 인덱스를 정의할 수 있다. ESE는 풍부한 인덱싱 기능을 제공한다.
클러스터형 인덱스
[편집]하나의 인덱스를 클러스터형 또는 기본(primary) 인덱스로 지정할 수 있다. ESE에서 클러스터형 인덱스는 고유해야 하며 기본 인덱스로 참조된다. 다른 인덱스는 비클러스터형 또는 보조(secondary) 인덱스로 설명된다. 기본 인덱스는 인덱스 항목이 레코드에 대한 논리적 포인터가 아니라 레코드 자체라는 점에서 보조 인덱스와 다르다. 보조 인덱스는 기본 인덱스의 레코드에 논리적으로 연결하기 위해 잎 노드에 기본 키를 가진다. 즉, 테이블은 기본 인덱스 순서대로 물리적으로 클러스터링된다. 기본 인덱스 순서로 인덱싱되지 않은 레코드 데이터를 검색하는 것은 일반적으로 보조 인덱스 순서보다 훨씬 빠르다. 이는 단일 디스크 접근이 시간상 가깝게 접근될 여러 레코드를 메모리로 가져올 수 있기 때문이다. 동일한 디스크 접근으로 여러 레코드 접근 작업을 만족시킨다. 그러나 기본 인덱스 순서에 따라 인덱스 중간에 레코드를 삽입하는 것은 인덱스 끝에 추가하는 것보다 훨씬 느릴 수 있다. 테이블 설계 시 검색 패턴과 업데이트 빈도를 신중하게 고려해야 한다. 테이블에 기본 인덱스가 정의되어 있지 않으면, 데이터베이스 키(DBK) 인덱스라는 암시적 기본 인덱스가 생성된다. DBK는 레코드가 삽입될 때마다 증가하는 고유한 오름차순 번호이다. 결과적으로 DBK 인덱스에서 레코드의 물리적 순서는 시간순 삽입 순서이며, 새 레코드는 항상 테이블 끝에 추가된다. 애플리케이션이 고유하지 않은 인덱스에 데이터를 클러스터링하려는 경우, 고유하지 않은 인덱스 정의 끝에 자동 증가 열을 추가하여 이를 수행할 수 있다.
다중 값 열에 대한 인덱싱
[편집]인덱스는 다중 값 열에 대해 정의할 수 있다. 인덱싱된 열에 대해 여러 값을 가진 레코드의 경우 이러한 인덱스에 여러 항목이 존재할 수 있다. 다중 값 열은 단일 값 열과 함께 인덱싱될 수 있다. 두 개 이상의 다중 값 열이 함께 인덱싱되면 다중 값 속성은 인덱스에서 첫 번째 다중 값 열에 대해서만 적용된다. 우선순위가 낮은 열은 단일 값인 것처럼 처리된다.
희소 인덱스
[편집]인덱스는 희소(sparse)하도록 정의될 수도 있다. 희소 인덱스는 테이블의 각 레코드에 대해 최소한 하나의 항목을 가지지 않는다. 희소 인덱스를 정의하는 옵션은 여러 가지가 있다. 전체 인덱스 키가 NULL일 때, 어떤 키 세그먼트가 NULL일 때, 또는 첫 번째 키 세그먼트만 NULL일 때 인덱스에서 레코드를 제외하는 옵션이 있다. 인덱스는 조건부 열을 가질 수도 있다. 이러한 열은 인덱스 내에 나타나지는 않지만 조건부 열이 NULL이거나 NULL이 아닐 때 레코드가 인덱싱되지 않게 할 수 있다.
튜플 인덱스
[편집]인덱스는 Text 또는 Long Text 열의 각 부분 문자열에 대해 하나의 항목을 포함하도록 정의할 수 있다. 이러한 인덱스를 튜플 인덱스라고 한다. 이들은 부분 문자열 일치 술어를 사용하는 쿼리 속도를 높이는 데 사용된다. 튜플 인덱스는 Text 열에 대해서만 정의할 수 있다. 예를 들어, Text 열 값이 “I love JET Blue”이고 인덱스가 최소 튜플 크기 4자, 최대 튜플 길이 10자로 구성된 경우 다음과 같은 부분 문자열이 인덱싱된다.
| “I love JET” “ love JET ” |
튜플 인덱스는 매우 클 수 있지만, “JET Blue”를 포함하는 모든 레코드 찾기와 같은 쿼리 속도를 상당히 높일 수 있다. 검색 부분 문자열을 최대 튜플 길이 검색 문자열로 나누고 결과를 교차시켜 최대 튜플 길이보다 긴 부분 문자열에도 사용할 수 있다. 인덱스 교차 없이 최소 튜플 길이만큼 짧거나 최대 튜플 길이만큼 긴 문자열에 대한 정확한 일치에 사용할 수 있다. ESE에서 인덱스 교차를 수행하는 방법에 대한 자세한 내용은 인덱스 교차를 참조하라. 튜플 인덱스는 검색 문자열이 최소 튜플 길이보다 짧은 경우에는 쿼리 속도를 높일 수 없다.
트랜잭션
[편집]트랜잭션은 BeginTransaction과 CommitTransaction 또는 Rollback 작업으로 구분되는 논리적 처리 단위이다. 트랜잭션 중에 수행되는 모든 업데이트는 원자적이다. 즉, 데이터베이스에 동시에 모두 나타나거나 전혀 나타나지 않는다. 다른 트랜잭션에 의한 후속 업데이트는 트랜잭션에 보이지 않는다. 그러나 트랜잭션은 그 사이에 변경되지 않은 데이터만 업데이트할 수 있으며, 그렇지 않으면 작업이 기다리지 않고 즉시 실패한다. 읽기 전용 트랜잭션은 기다릴 필요가 없으며, 업데이트 트랜잭션은 서로 간에만 간섭할 수 있다. Rollback으로 종료되거나 시스템 충돌로 종료된 트랜잭션은 데이터베이스에 흔적을 남기지 않는다. 일반적으로 데이터 상태는 Rollback 시 BeginTransaction 이전 상태로 복원된다.
트랜잭션은 ESE 내부용으로 예약된 하나의 추가 레벨을 포함하여 최대 7레벨까지 중첩될 수 있다. 이는 트랜잭션의 일부를 전체 트랜잭션을 롤백할 필요 없이 롤백할 수 있음을 의미한다. 중첩 트랜잭션의 CommitTransaction은 처리 단계의 성공을 의미할 뿐이며, 외부 트랜잭션은 여전히 실패할 수 있다. 변경 사항은 가장 바깥쪽 트랜잭션이 커밋될 때만 데이터베이스에 커밋된다. 이를 트랜잭션 레벨 0으로 커밋한다고 한다. 트랜잭션이 트랜잭션 레벨 0으로 커밋되면 트랜잭션을 설명하는 데이터가 로그에 동기식으로 플러시되어 후속 시스템 충돌 시에도 트랜잭션이 완료되도록 보장한다. 로그를 동기식으로 플러시하면 ESE 트랜잭션은 지속성을 갖게 된다. 그러나 경우에 따라 애플리케이션이 업데이트 순서를 지정하기를 원하지만 변경 사항이 즉시 완료될 것이라고 보장하지는 않을 수 있다. 이 경우 애플리케이션은 JET_bitIndexLazyFlush를 사용하여 변경 사항을 커밋할 수 있다.
ESE는 다중 버전 관리(multi-versioning)라는 동시성 제어 메커니즘을 지원한다. 다중 버전 관리에서 모든 트랜잭션은 트랜잭션이 시작된 시점의 전체 데이터베이스의 일관된 뷰를 쿼리한다. 발생하는 유일한 업데이트는 자신이 수행한 업데이트뿐이다. 이런 방식으로 각 트랜잭션은 쓰기 충돌의 경우를 제외하고 시스템에서 실행 중인 유일한 활성 트랜잭션인 것처럼 작동한다. 트랜잭션은 다른 트랜잭션에서 이미 업데이트된 읽기 데이터를 기반으로 변경할 수 있으므로, 다중 버전 관리 자체로는 직렬화 가능 트랜잭션을 보장하지 않는다. 그러나 업데이트 기반이 되는 읽기 데이터를 잠그기 위해 명시적 레코드 읽기 잠금을 사용하여 원하는 경우 직렬화 가능성을 달성할 수 있다. 읽기 및 쓰기 잠금은 GetLock 작업을 통해 명시적으로 요청할 수 있다.
또한 ESE는 에스크로 잠금이라고 하는 고급 동시성 제어 기능을 지원한다. 에스크로 잠금은 수치 값이 상대적인 방식, 즉 다른 수치 값을 더하거나 빼는 방식으로 변경되는 매우 동시적인 업데이트이다. 에스크로 업데이트는 동일한 데이터에 대한 다른 동시 에스크로 업데이트와도 충돌하지 않는다. 지원되는 작업이 교환 가능하며 독립적으로 커밋되거나 롤백될 수 있기 때문에 가능하다. 결과적으로 이들은 동시 업데이트 트랜잭션을 방해하지 않는다. 이 기능은 유지 관리되는 집계에 자주 사용된다.
ESE는 트랜잭션 의미론을 데이터 조작 작업에서 데이터 정의 작업까지 확장한다. 트랜잭션 잠금 경합 없이 테이블에 인덱스를 추가하고 동시에 실행 중인 트랜잭션이 동일한 테이블을 업데이트하도록 할 수 있다. 나중에 이러한 트랜잭션이 완료되면 새로 생성된 인덱스를 모든 트랜잭션에서 사용할 수 있으며, 업데이트가 발생했을 때 인덱스의 존재를 인식하지 못한 다른 트랜잭션에 의해 이루어진 레코드 업데이트 항목을 포함하게 된다. 데이터 정의 작업은 레코드 업데이트에 대한 트랜잭션 메커니즘에서 기대되는 모든 기능을 갖추고 수행될 수 있다. 이런 방식으로 지원되는 데이터 정의 작업에는 AddColumn, DeleteColumn, CreateIndex, DeleteIndex, CreateTable 및 DeleteTable이 포함된다.
커서 탐색 및 복사 버퍼
[편집]커서는 테이블 인덱스 내의 논리적 포인터이다. 커서는 레코드 위, 첫 번째 레코드 앞, 마지막 레코드 뒤 또는 레코드 사이에 위치할 수 있다. 커서가 레코드 앞이나 뒤에 위치하면 현재 레코드는 없다. 동일한 테이블 인덱스에 여러 커서를 가질 수 있다. 많은 레코드 및 열 작업은 커서 위치를 기반으로 한다. 커서 위치는 Move 작업을 통해 순차적으로 이동하거나 인덱스 키를 사용하여 Seek 작업으로 직접 이동할 수 있다. 커서는 인덱스 내의 분수 위치로 이동할 수도 있다. 이런 방식으로 커서를 썸바(thumb bar) 위치로 빠르게 이동할 수 있다. 이 작업은 Seek 작업과 동일한 속도로 수행된다. 중간 데이터를 접근할 필요가 없다.
각 커서에는 열 단위로 새 레코드를 생성하거나 기존 레코드를 수정하기 위한 복사 버퍼가 있다. 이는 SetColumns 작업을 통해 내용을 변경할 수 있는 내부 버퍼이다. 복사 버퍼를 수정해도 저장된 데이터가 자동으로 변경되지는 않는다. PrepareUpdate 작업을 사용하여 현재 레코드의 내용을 복사 버퍼에 복사할 수 있으며, Update 작업은 복사 버퍼의 내용을 레코드로 저장한다. 복사 버퍼는 트랜잭션 커밋 또는 롤백 시, 그리고 탐색 작업 시 암시적으로 지워진다. RetrieveColumns는 레코드 또는 복사 버퍼(존재하는 경우)에서 열 데이터를 검색하는 데 사용할 수 있다.
쿼리 처리
[편집]ESE 애플리케이션은 항상 데이터를 쿼리한다. 이 문서의 이 섹션에서는 애플리케이션이 ESE에서 쿼리 처리 로직을 작성하기 위한 기능과 기술을 설명한다.
정렬 및 임시 테이블
[편집]ESE는 임시 테이블 형태의 정렬 기능을 제공한다. 애플리케이션은 정렬 프로세스에 한 번에 하나씩 데이터 레코드를 삽입한 다음, 정렬된 순서대로 한 번에 하나씩 검색한다. 정렬은 실제로 마지막 레코드 삽입과 첫 번째 레코드 검색 사이에 수행된다. 임시 테이블은 부분 및 전체 결과 세트에도 사용할 수 있다. 이러한 테이블은 정렬 정의와 일치하는 인덱스 키를 사용하여 행을 순차적으로 또는 직접 탐색하는 기능을 포함하여 기본 테이블과 동일한 기능을 제공할 수 있다. 임시 테이블은 복잡한 집계 계산을 위해 업데이트할 수도 있다. 간단한 집계는 정렬 프로세스의 자연스러운 결과로 원하는 집계가 도출되는 정렬과 유사한 기능을 통해 자동으로 계산될 수 있다.
커버링 인덱스
[편집]보조 인덱스에서 직접 열 데이터를 검색하는 것은 중요한 성능 최적화이다. RetrieveColumns 작업의 RetrieveFromIndex 플래그를 통해 데이터 레코드를 접근하지 않고도 보조 인덱스에서 열을 직접 검색할 수 있다. 인덱스로 탐색할 때 레코드보다는 보조 인덱스에서 열을 검색하는 것이 훨씬 효율적이다. 레코드에서 열 데이터를 검색하면 기본 키로 레코드 위치를 찾기 위해 추가 탐색이 필요하다. 이는 추가 디스크 접근을 초래할 수 있다. 필요한 모든 열을 인덱스가 제공하면 이를 커버링 인덱스라고 한다. 테이블 기본 인덱스에 정의된 열도 보조 인덱스에서 찾을 수 있으며 JET_bitRetrieveFromPrimaryBookmark를 사용하여 유사하게 검색할 수 있다는 점에 유의하라.
인덱스 키는 많은 경우 원래 열 값으로 비정규화될 수 있는 정규화된 형식으로 저장된다. 정규화는 항상 역전 가능한 것은 아니다. 예를 들어, Text 및 Long Text 열 유형은 비정규화할 수 없다. 또한 열 데이터가 매우 길면 인덱스 키가 잘릴 수 있다. 보조 인덱스에서 열을 직접 검색할 수 없는 경우, 항상 레코드를 접근하여 필요한 데이터를 검색할 수 있다.
인덱스 교차
[편집]쿼리에는 종종 데이터에 대한 제약 조건 조합이 포함된다. 제약 조건을 처리하는 효율적인 방법은 사용 가능한 인덱스를 사용하는 것이다. 그러나 쿼리에 여러 제약 조건이 포함된 경우 애플리케이션은 종종 단일 인덱스에 의해 만족되는 가장 제한적인 술어의 전체 인덱스 범위를 탐색하여 제약 조건을 처리한다. 잔류 술어(residual predicate)라고 하는 나머지 술어는 레코드 자체에 술어를 적용하여 처리된다. 이 방법은 간단하지만 잔류 술어를 적용하기 위해 레코드를 메모리로 가져오는 데 많은 디스크 접근을 수행해야 할 수도 있다는 단점이 있다.
인덱스 교차는 복잡한 제약 조건을 더 효율적으로 처리하기 위해 여러 인덱스를 함께 사용하는 중요한 쿼리 메커니즘이다. 단일 인덱스만 사용하는 대신 여러 인덱스의 인덱스 범위를 결합하여 잔류 술어를 적용할 수 있는 훨씬 적은 수의 레코드를 도출한다. ESE는 IntersectIndexes 작업을 제공하여 이를 쉽게 만든다. 이 작업은 동일한 테이블의 인덱스에 대한 일련의 인덱스 범위를 받아들이고, 모든 인덱스 술어를 만족하는 기본 테이블 레코드를 탐색하는 데 사용할 수 있는 기본 키의 임시 테이블을 반환한다.
사전 조인 테이블
[편집]조인은 정규화된 테이블 설계에서 논리적으로 관련된 데이터를 애플리케이션에서 사용하기 위해 다시 모으는 일반적인 작업이다. 관련 데이터를 메모리로 가져오는 데 많은 데이터 접근이 필요할 수 있기 때문에 조인은 비용이 많이 드는 작업이 될 수 있다. 이 작업은 두 개 이상의 논리적 테이블에 대한 데이터를 포함하는 단일 기본 테이블을 정의하여 경우에 따라 최적화될 수 있다. 기본 테이블의 열 세트는 이러한 논리적 테이블의 열 세트의 합집합이다. 태그 지정된 열은 다중 값 데이터와 희소 값 데이터를 모두 잘 처리하기 때문에 이를 가능하게 한다. 관련 데이터가 동일한 레코드에 함께 저장되므로 함께 접근되어 조인을 수행하기 위한 디스크 접근 횟수가 최소화된다. ESE는 최대 64,993개의 태그 지정된 열을 지원할 수 있으므로 이 프로세스는 많은 수의 논리적 테이블로 확장될 수 있다. 인덱스는 다중 값 열에 대해 정의될 수 있으므로 ‘내부’ 테이블을 인덱싱하는 것도 여전히 가능하다. 그러나 몇 가지 제한 사항이 있으므로 애플리케이션은 이 기술을 사용하기 전에 사전 조인을 신중하게 고려해야 한다.
로깅 및 충돌 복구
[편집]ESE의 로깅 및 복구 기능은 시스템 충돌 시 데이터 무결성과 일관성을 보장한다. 로깅은 로그 파일에 데이터베이스 업데이트 작업을 중복 기록하는 프로세스이다. 로그 파일 구조는 시스템 충돌에 매우 강력하다. 복구는 시스템 충돌 후 로그를 사용하여 데이터베이스를 일관된 상태로 복원하는 프로세스이다.
트랜잭션 작업은 기록되며 로그는 트랜잭션 레벨 0으로 커밋될 때마다 디스크에 플러시된다. 이를 통해 복구 프로세스는 트랜잭션 레벨 0으로 커밋된 트랜잭션에 의해 수행된 업데이트를 다시 실행하고, 트랜잭션 레벨 0으로 커밋되지 않은 트랜잭션에 의해 수행된 변경 사항을 취소할 수 있다. 이러한 유형의 복구 체계를 종종 ‘롤 포워드/롤 백워드(roll-forward/roll-backward)’ 복구 체계라고 한다. 로그는 아래 설명된 백업 프로세스를 통해 데이터가 안전하게 복사될 때까지 보관되거나, 시스템 충돌 복구에 더 이상 필요하지 않게 되는 즉시 순환 방식으로 재사용될 수 있다. 순환 로깅은 로그에 필요한 디스크 공간을 최소화하지만, 미디어 장애 시 데이터 상태를 재현하는 기능에는 영향을 미친다.
백업 및 복원
[편집]로깅 및 복구는 미디어 장애로부터 데이터를 보호하는 데도 역할을 한다. ESE는 하나 이상의 데이터베이스가 데이터베이스 작업에 영향을 주지 않는 방식으로 로그 파일과 함께 복사되는 온라인 백업을 지원한다. 백업이 진행되는 동안에도 데이터베이스를 계속 쿼리하고 업데이트할 수 있다. 이 백업은 ‘퍼지 백업(fuzzy backup)’이라고 불리는데, 일관된 데이터베이스 세트를 복원하기 위해 백업 복원 과정의 일부로 복구 프로세스를 실행해야 하기 때문이다. 스트리밍 백업과 섀도 복사본 백업이 모두 지원된다.
스트리밍 백업은 백업 프로세스 중에 모든 원하는 데이터베이스 파일과 필요한 로그 파일의 복사본을 만드는 백업 방법이다. 파일 복사본은 테이프에 직접 저장되거나 다른 저장 장치에 저장될 수 있다. 스트리밍 백업에는 어떤 종류의 작업 중단도 필요하지 않다. 데이터베이스와 로그 파일 모두 백업 프로세스 중에 데이터 세트 내에 데이터 손상이 없는지 확인하기 위해 체크섬이 수행된다. 스트리밍 백업은 증분 백업일 수도 있다. 증분 백업은 로그 파일만 복사되는 백업이며, 이전 전체 백업과 함께 복원하여 모든 데이터베이스를 최신 상태로 가져올 수 있다.
섀도 복사본 백업은 새로운 고속 백업 방법이다. 섀도 복사본 백업은 애플리케이션을 잠시 중단한 후 가상으로 복사본을 만들기 때문에 훨씬 빠르다. 데이터에 대한 후속 업데이트가 이루어지면 가상 복사본이 실체화된다. 경우에 따라 섀도 복사본 백업에 대한 하드웨어 지원은 가상 복사본을 실제로 저장할 필요가 없음을 의미한다. 섀도 복사본 백업은 항상 전체 백업이다.
복원은 단일 백업을 적용하거나, 단일 전체 백업과 하나 이상의 증분 백업의 조합을 적용하는 데 사용할 수 있다. 또한 기존 로그 파일을 재생하여 트랜잭션 레벨 0으로 커밋된 것으로 기록된 마지막 트랜잭션까지 전체 데이터 세트를 재현할 수 있다. 백업 복원은 원래 애플리케이션을 지원할 수 있는 모든 시스템에서 수행할 수 있다. 동일한 컴퓨터이거나 동일한 컴퓨터 구성일 필요는 없다. 복원 프로세스의 일부로 파일 위치를 변경할 수 있다.
다른 하드웨어로의 백업 및 복원
[편집]ESENT 데이터베이스가 생성되면 물리적 디스크 섹터 크기가 데이터베이스와 함께 저장된다. 물리적 섹터 크기는 세션 간에 일관되게 유지되어야 하며, 그렇지 않으면 오류가 보고된다. 물리적 드라이브를 복제하거나 드라이브 이미지에서 다른 물리적 섹터 크기(어드밴스트 포맷 드라이브)를 사용하는 드라이브로 복원할 때 ESENT는 오류를 보고한다.[4]
이는 알려진 문제이며 마이크로소프트는 핫픽스를 제공한다. 윈도우 비스타 또는 윈도우 서버 2008의 경우 KB2470478을 참조하라.[5] 윈도우 7 또는 윈도우 서버 2008 R2의 경우 KB982018을 참조하라.[6]
역사
[편집]JET Blue는 원래 마이크로소프트 액세스의 JET Red 데이터베이스 엔진에 대한 잠재적 업그레이드로 마이크로소프트에서 개발했으나, 이 역할로 사용된 적은 없다. 대신 익스체인지 서버, 액티브 디렉터리, 파일 복제 서비스(FRS), 보안 구성 편집기, 인증서 서비스, 윈도우 인터넷 네임 서비스(WINS) 및 기타 수많은 마이크로소프트 서비스, 애플리케이션 및 윈도우 구성 요소에 사용되었다.[7] 수년간 마이크로소프트 내부에서만 사용되는 비공개 API였으나, 이후 누구나 사용할 수 있는 공개 API가 되었다.
데이터 접근 엔진(DAE) 작업은 1989년 3월 앨런 레이터(Allen Reiter)가 마이크로소프트에 합류하면서 시작되었다. 다음 해에 4명의 개발자로 구성된 팀이 앨런을 위해 일하며 ISAM을 거의 완성했다. 마이크로소프트는 이미 BC7 ISAM(JET Red)을 보유하고 있었지만, 당시 새로운 클라이언트-서버 아키텍처 분야의 진입을 위해 더 강력한 데이터베이스 엔진을 구축하고자 데이터 접근 엔진(DAE) 노력을 시작했다. 1990년 봄, BC7 ISAM과 DAE 팀은 합동 엔진 기술(JET) 노력으로 통합되었다. 이는 동일한 API 사양(JET API)을 따르는 두 개의 엔진, 즉 v1(JET Red)과 v2(JET Blue)를 생산하는 책임을 맡았다. DAE는 이스라엘 국기의 색상을 따서 JET Blue가 되었다. BC7 ISAM은 러시아 국기의 색상을 따서 JET Red가 되었다. JET Blue와 JET Red는 동일한 API 사양으로 작성되었지만, ISAM 코드는 전혀 공유하지 않았다. 두 엔진 모두 공통 쿼리 프로세서인 QJET을 지원했으며, 이는 나중에 BC7 ISAM과 함께 JET Red와 동의어가 되었다.
JET Blue는 1994년 윈도우 NT 3.5의 WINS, DHCP 및 현재는 사라진 RPL 서비스를 위한 ISAM으로 처음 출시되었다. 1996년 마이크로소프트 익스체인지의 저장 엔진으로 다시 출시되었다. 추가적인 윈도우 서비스들이 저장 기술로 JET Blue를 선택했고, 2000년에는 모든 윈도우 버전이 JET Blue와 함께 출시되기 시작했다. JET Blue는 액티브 디렉터리에 사용되었으며, 신뢰할 수 있는 컴퓨팅 기반(TCB)이라는 특별한 윈도우 코드 세트의 일부가 되었다. JET Blue를 사용하는 마이크로소프트 애플리케이션의 수는 계속 증가하고 있으며, 윈도우 내부 및 외부의 점점 더 많은 애플리케이션과 서비스의 사용을 촉진하기 위해 2005년에 JET Blue API가 공개되었다.
마이크로소프트 익스체인지 웹 블로그 항목[8]에 따르면 JET Blue에 기여한 개발자는 치엔 랴오(Cheen Liao), 스티븐 헥트(Stephen Hecht), 매슈 벨로우(Matthew Bellew), 이언 호세(Ian Jose), 에드워드 "에디" 길버트(Edward "Eddie" Gilbert), 케네스 킨 럼(Kenneth Kin Lum), 발라수브라마니안 스리람(Balasubramanian Sriram), 조너선 리엠(Jonathan Liem), 앤드루 굿셀(Andrew Goodsell), 로리언 버철(Laurion Burchall), 안드레이 마리네스쿠(Andrei Marinescu), 애덤 폭스맨(Adam Foxman), 이반 트린데프(Ivan Trindev), 스펜서 로우(Spencer Low) 및 브렛 셜리(Brett Shirley)이다.
2021년 1월 마이크로소프트는 ESE를 오픈 소스로 공개했다.[9] 이는 허용적인 MIT 허가서와 함께 깃허브에 게시되었다.
JET Red와 비교
[편집]공통된 혈통을 공유하지만 JET Red와 ESE 사이에는 큰 차이가 있다.
- JET Red는 파일 공유 기술인 반면, ESE는 서버 애플리케이션에 내장되도록 설계되었으며 파일을 공유하지 않는다.
- JET Red는 최선의 파일 복구를 시도하지만, ESE는 보장된 충돌 복구를 위해 선행 기록 로깅(write-ahead logging)과 스냅숏 격리를 지원한다.
- 4.0 버전 이전의 JET Red는 페이지 수준 잠금만 지원하지만, ESE와 JET Red 버전 4.0은 레코드 수준 잠금을 지원한다.
- JET Red는 ODBC 및 OLE DB를 포함한 다양한 쿼리 인터페이스를 지원한다. ESE는 쿼리 엔진과 함께 제공되지 않으며, 애플리케이션이 C ISAM 코드로 직접 쿼리를 작성해야 한다.
- JET Red의 최대 데이터베이스 파일 크기는 2 GiB이지만, ESE는 4 KiB 페이지 사용 시 최대 8 TiB, 8 KiB 페이지 사용 시 16 TiB의 최대 데이터베이스 파일 크기를 가진다.
각주
[편집]- ↑ 이 문맥에서 1 KB = 1024 B
- ↑ “Extensible Storage Engine Architecture”. TechNet. 2007년 6월 18일에 확인함.
- ↑ 이 문맥에서 1 TB = 10244 B
- ↑ “Acronis Products: Applications Build on ESENT Running on Windows Vista, Windows Server 2008 and Windows 7 may not work correctly after restoring or cloning to a drive with different physical sector | Knowledge Base”. 《kb.acronis.com》.
- ↑ “Applications that are built on ESENT and that run on a Windows Vista-based or Windows Server 2008-based computer may not work correctly after the reported physical sector size of the storage device changes”. 2015년 2월 28일에 원본 문서에서 보존된 문서. 2014년 11월 19일에 확인함.
- ↑ “An update that improves the compatibility of Windows 7 and Windows Server 2008 R2 with Advanced Format Disks is available”. 《support.microsoft.com》.
- ↑ “Extensible Storage Engine”. 《마이크로소프트》.
- ↑ “Extensible Storage Engine”. 2008년 12월 19일에 확인함.
- ↑ “Microsoft Open Sources ESE, the Extensible Storage Engine”. 2021년 2월 3일. 2021년 2월 5일에 확인함.
- “Exchange Terminology”. 2008년 11월 9일에 원본 문서에서 보존된 문서. 2015년 8월 20일에 확인함.
- “Understanding Information Store Essentials”. 2007년 6월 9일에 원본 문서에서 보존된 문서. 2007년 6월 18일에 확인함.
외부 링크
[편집]- 확장 가능한 저장소 엔진 - 공식 웹사이트
- (영어) Extensible-Storage-Engine - 깃허브
- Extensible Storage Engine - CodeProject