물리적 구조가 바뀌면 응용 프로그램도 수정해야 한다는 설명이 적절하지 않다. DBMS는 물리적 데이터 독립성을 제공하기 때문이다.
DBMS는 스키마 사이의 사상으로 저장 구조의 변경을 응용 프로그램으로부터 격리한다. 그래서 저장 방식이 바뀌어도 프로그램은 그대로 쓸 수 있다.
- 중복 저장 통제: 데이터를 통합 관리하므로 중복을 통제할 수 있어 적절하다.
- 동시 접근: 동시성 제어로 다수 사용자의 동시 접근을 지원하므로 적절하다.
- 일관성·무결성 유지: 회복 기능과 무결성 제약으로 장애가 나도 데이터를 보호하므로 적절하다.
투플의 순서가 다르면 서로 다른 릴레이션이라는 설명이 적절하지 않다. 릴레이션은 투플의 집합이므로 투플 사이에 순서가 없다.
내용이 같은 투플들로 구성되어 있으면 저장·출력 순서가 달라도 같은 릴레이션이다.
- 동일 투플 불가: 집합에는 중복 원소가 없으므로 적절하다.
- 서로 다른 속성의 같은 도메인: 예를 들어 집 전화와 회사 전화 속성은 도메인이 같을 수 있으므로 적절하다.
- 속성 순서 무관: 속성도 이름으로 구별하는 집합이므로 적절하다.
참조되는 릴레이션에 투플을 삽입하는 것은 참조 무결성을 위배하지 않는다. 기존 외래키 값이 참조하는 대상은 그대로 남아 있기 때문이다.
참조 무결성은 외래키 값이 참조되는 릴레이션의 기본키 값으로 존재하거나 NULL이어야 한다는 조건이다. 따라서 참조 대상이 없어지거나 없는 값을 가리킬 때만 위배된다.
- 참조하는 릴레이션에 삽입: 존재하지 않는 값을 외래키로 넣으면 위배될 수 있다.
- 참조하는 릴레이션에서 삭제: 외래키 값이 사라질 뿐 참조 대상에는 영향이 없어 위배되지 않는다.
- 참조되는 릴레이션에서 삭제: 그 투플을 참조하던 외래키가 대상을 잃을 수 있어 위배될 수 있다.
나. 내부 스키마는 데이터베이스에 데이터가 물리적으로 저장되는 방식을 표현한다.
다. 외부 스키마는 다수 사용자들이 각자 데이터베이스를 바라보는 뷰를 의미한다.
라. 데이터베이스마다 다수의 개념 스키마가 존재할 수 있다.
적절한 설명은 나, 다이다.
내부 스키마는 물리적 저장 방식을, 외부 스키마는 사용자별 뷰를, 개념 스키마는 조직 전체의 논리 구조를 표현한다.
- 가: 사용자 관점이 외부 스키마이고 저장구조 관점이 내부 스키마이므로 두 이름이 서로 바뀌었다.
- 라: 개념 스키마는 데이터베이스 전체를 나타내므로 데이터베이스마다 하나만 존재한다.
| A | B |
|---|---|
| a1 | b1 |
| a2 | b2 |
| a4 | b2 |
| a5 | NULL |
| B | C |
|---|---|
| b1 | c1 |
| b2 | c2 |
| b3 | c2 |
| b4 | c4 |
나. R ⟕ S
자연조인 결과는 3개, 왼쪽 외부조인 결과는 4개이다.
자연조인: B 값이 같은 투플만 남는다.
(a1, b1, c1), (a2, b2, c2), (a4, b2, c2)
a5는 B가 NULL이므로 어떤 값과도 같지 않아 제외된다.
왼쪽 외부조인: 자연조인 결과에 짝이 없는 R의 투플을 더한다.
(a5, NULL, NULL)이 추가되어 4개가 된다.
- 가: 2, 나: 4: a2와 a4가 모두 b2로 조인되므로 자연조인이 2개일 수 없다.
- 가: 3, 나: 3: 왼쪽 외부조인은 짝이 없는 a5 투플도 보존한다.
- 가: 4, 나: 3: NULL은 조인되지 않으며 왼쪽 외부조인 결과는 자연조인보다 적을 수 없다.
교집합은 다른 연산자로 표현할 수 있다. 기본 연산이 아니라 차집합에서 유도되는 연산이기 때문이다.
두 릴레이션의 교집합은 차집합을 두 번 적용해 얻는다.
- 합집합: 다른 연산으로 대체할 수 없는 기본 연산이다.
- 셀렉트: 행을 고르는 기본 연산이다.
- 프로젝트: 열을 고르는 기본 연산이다.
SELECT * FROM R, S;
결과 투플의 최대 개수는 25,000개이다. 조인 조건이 없는 FROM 절의 두 테이블은 카티션 곱이 되기 때문이다.
결과의 카디널리티는 두 카디널리티의 곱이다.
- 50: S의 카디널리티일 뿐이다.
- 500: R의 카디널리티일 뿐이다.
- 550: 두 값을 더한 값으로, 곱 연산의 결과가 아니다.
강한 개체와 약한 개체가 다대다 관계라는 설명이 적절하지 않다. 둘은 일대다 관계이다.
약한 개체는 소유 개체인 강한 개체에 존재가 종속된다. 약한 개체 인스턴스 하나는 소유 개체 하나에 속하고, 강한 개체 하나는 약한 개체 여럿을 가질 수 있다.
- 전체 참여: 모든 인스턴스가 관계에 참여해야 한다는 뜻으로 적절하다.
- 매핑 카디널리티: 상대 개체 집합과 연관되는 인스턴스 수를 나타내므로 적절하다.
- 순환 관계: 한 개체 타입이 자기 자신과 맺는 관계로 적절하다.
| A | B | C |
|---|---|---|
| 100 | a | s |
| 100 | a | t |
| 100 | b | s |
| 100 | b | t |
| 200 | c | x |
| 200 | c | y |
| 200 | c | z |
| A | B |
|---|---|
| 100 | a |
| 100 | b |
| 200 | c |
| A | C |
|---|---|
| 100 | s |
| 100 | t |
| 200 | x |
| 200 | y |
| 200 | z |
R1, R2가 만족하는 가장 높은 정규형은 제4정규형이다. R의 다치 종속이 분해로 제거되었기 때문이다.
R에서 A=100의 B 값 {a, b}와 C 값 {s, t}는 모든 조합으로 나타난다. 즉 와 가 성립하지만 A는 슈퍼키가 아니므로 R은 제4정규형이 아니다.
R1, R2는 각각 속성이 2개이고 속성 전체가 키이므로 자명한 다치 종속만 남는다.
- 제2정규형: 부분 함수 종속이 없다는 조건까지만 나타내므로 더 높은 수준을 만족하는 R1, R2에는 낮다.
- 제3정규형: 이행적 종속이 없다는 조건까지만 나타내므로 낮다.
- 보이스/코드 정규형: R도 이미 만족하던 수준이며, 분해로 다치 종속까지 제거되었으므로 낮다.

관계 RR은 RR(PK1, PK3, PK2, D) 한 릴레이션으로 변환하는 것이 가장 적절하다.
RR은 E1(M), E3(N), E2(1)가 참여하는 삼항 관계이다. 카디널리티가 1인 E2는 E1과 E3의 조합마다 하나로 정해지므로, M·N 쪽의 키 PK1과 PK3만 기본키가 되고 PK2는 외래키, 관계의 속성 D는 일반 속성으로 함께 둔다.
- RR1(PK1, PK3)과 RR2(PK2, D)로 나누는 구성: 두 릴레이션을 이어 줄 공통 속성이 없어 어떤 조합에 어떤 PK2와 D가 대응하는지 알 수 없다.
- RR1(PK1, PK2, PK3)과 RR2(PK2, D)로 나누는 구성: PK2까지 기본키에 넣으면 1 쪽을 N 쪽처럼 다루게 되고, D가 PK2에만 종속되어 관계의 속성을 표현하지 못한다.
- RR1(PK2, PK3)과 RR2(PK1, PK3, D)로 나누는 구성: PK2가 PK1과 PK3의 조합이 아니라 PK3와만 묶여 세 개체가 함께 맺는 관계가 보존되지 않는다.
나. 교집합(intersect)
다. 완전 외부 조인(full outer join)
라. 차집합(set difference)
마. 프로젝트(project)
합병 가능 조건이 필요한 연산은 교집합과 차집합으로 모두 2개이다.
합병 가능 조건은 두 릴레이션의 속성 수가 같고 대응 속성의 도메인이 같아야 한다는 뜻으로, 합집합·교집합·차집합 같은 집합 연산에 필요하다.
- 카티션 곱: 차수가 달라도 두 릴레이션의 투플을 이어 붙일 수 있다.
- 완전 외부 조인: 조인 속성을 기준으로 결합하므로 스키마 전체가 같을 필요가 없다.
- 프로젝트: 릴레이션 하나에 적용하는 단항 연산이다.
| CAR_ID | SEATS |
|---|---|
| 1 | 10 |
| 2 | 20 |
| 3 | NULL |
Q1. SELECT SEATS + 1 FROM CAR
WHERE CAR_ID = 3;
Q2. SELECT AVG(SEATS) FROM CAR;
Q3. SELECT COUNT(*) FROM CAR;
수행 결과는 Q1: NULL, Q2: 15, Q3: 3이다.
Q1: NULL과의 산술 연산 결과는 NULL이다.
Q2: AVG는 NULL을 제외하고 계산한다.
Q3: COUNT(*)는 NULL 포함 여부와 무관하게 행 수를 세므로 3이다.
- Q1: NULL, Q2: NULL, Q3: 2: 집계 함수는 NULL을 무시하므로 AVG가 NULL이 되지 않으며, 행 수도 3이다.
- Q1: 1, Q2: 10, Q3: 3: NULL을 0으로 취급한 결과이다.
- Q1: 1, Q2: 10, Q3: 2: NULL을 0으로 취급했고 COUNT(*)에서 NULL 행까지 뺀 결과이다.
| TID 시간 | T1 | T2 |
|---|---|---|
| 1 | read(X); X ← X + 1000; write(X); | |
| 2 | read(X); X ← X * 2; write(X); | |
| 3 | read(Y); rollback; |
발생하는 문제는 연쇄 복귀이다. T2가 읽은 값을 쓴 T1이 철회되므로 T2도 함께 철회해야 한다.
T2는 T1이 완료하지 않은 X 값을 읽어 다시 썼다. 이후 T1이 rollback하면 T2는 무효가 된 값에 근거한 것이 된다.
- 모순성: 한 트랜잭션이 여러 항목을 읽는 도중 다른 트랜잭션의 갱신이 끼어들어 불일치가 생기는 문제로, 철회가 핵심인 이 상황과 다르다.
- 갱신 분실: 같은 값을 읽은 두 트랜잭션 중 뒤의 쓰기가 앞의 쓰기를 덮는 문제인데, T2는 T1의 갱신값을 읽었다.
- 반복 불가능 읽기: 한 트랜잭션이 같은 항목을 두 번 읽어야 생기는데, 어느 트랜잭션도 X를 두 번 읽지 않았다.
나. SALARY는 700 미만의 값만 가질 수 있다.
다. DNO는 NULL을 허용하지 않는다.
라. DNO는 DEPARTMENT 테이블의 DEPTNO를 참조하기 위한 외래키이다.
CREATE TABLE EMPLOYEE (
EMPNO INT,
SALARY INT ( ㉠ ) (SALARY < 700),
DNO INT ( ㉡ ),
PRIMARY KEY EMPNO,
FOREIGN KEY(DNO) ( ㉢ ) DEPARTMENT(DEPTNO) );
빈칸에는 ㉠ CHECK, ㉡ NOT NULL, ㉢ REFERENCES가 들어간다.
값의 범위 제한은 CHECK, NULL 금지는 NOT NULL로 지정한다. 외래키는 FOREIGN KEY(속성) REFERENCES 테이블(속성) 형식으로 쓴다.
- BETWEEN, DEFAULT, REFERENCES: BETWEEN은 조건식의 연산자이고 DEFAULT는 기본값 지정이므로 제약 조건을 나타내지 못한다.
- BETWEEN, NOT NULL, CASCADE: BETWEEN은 제약 키워드가 아니고 CASCADE는 참조 동작 옵션이다.
- CHECK, UNIQUE, CASCADE: UNIQUE는 중복 금지일 뿐 NULL을 막지 않으며, CASCADE는 REFERENCES를 대신할 수 없다.
ORDER(ORDID, DID, CCID, ODATE)
SELECT CID, CNAME
FROM CUSTOMER
WHERE CID ( ㉠ )
(SELECT CCID FROM ORDER WHERE ( ㉡ ) );
빈칸에는 ㉠ NOT IN, ㉡ DID = ‘B041’이 들어간다.
부속 질의로 ‘B041’을 구매한 고객번호를 구한 뒤, 고객 중 그 집합에 없는 사람만 남긴다.
- IN, CCID = CID: 주문한 적이 있는 고객을 찾을 뿐 도서 조건이 없다.
- IN, DID = ‘B041’: ‘B041’을 구매한 고객을 찾으므로 정반대이다.
- NOT IN, CCID = CID: 주문이 전혀 없는 고객만 남아, 다른 도서를 산 고객이 빠진다.
삽입을 마친 뒤 루트 노드의 키는 13이다. 차수 3이면 노드당 키가 최대 2개이고, 3개가 되면 가운데 키가 위로 올라간다.
10, 22 삽입: [10, 22]
13 삽입: 분할되어 루트 [13], 자식 [10], [22]
17, 1 삽입: 자식 [1, 10], [17, 22]
3 삽입: [1, 3, 10]이 분할되어 루트 [3, 13], 자식 [1], [10], [17, 22]
12 삽입: [10, 12]
29 삽입: [17, 22, 29]가 분할되어 루트가 [3, 13, 22]로 넘친다. 다시 분할되어 새 루트 [13]이 되고 그 자식은 [3], [22]이다.
5 삽입: [5, 10, 12]가 분할되어 10이 [3]으로 올라가 [3, 10]이 된다. 루트는 그대로이다.
- 10: 루트 왼쪽 자식인 내부 노드에 있다.
- 12: 리프 노드에 있다.
- 17: 리프 노드에 있다.
나. 뷰는 일반 테이블과 같이 항상 삽입과 삭제가 가능하다.
다. 기존 뷰를 사용하여 새로운 뷰를 생성하는 것이 불가능하다.
라. 뷰가 정의된 기본 테이블이 제거되면 뷰도 자동적으로 제거된다.
마. 사용자별로 필요한 데이터를 제공하기 때문에 뷰에 권한 설정이 불가능하다.
적절한 설명은 가, 라이다.
뷰는 여러 테이블의 조인으로 만들 수 있고, 기본 테이블에 의존하는 가상 테이블이므로 기본 테이블이 제거되면 뷰도 함께 제거되는 것으로 본다.
- 나: 조인·집계 등으로 만든 뷰는 삽입·삭제가 제한되므로 항상 가능한 것이 아니다.
- 다: 기존 뷰를 기반으로 새 뷰를 정의할 수 있다.
- 마: 뷰에도 권한을 부여할 수 있으며, 뷰는 접근 제어 수단으로 쓰인다.
나. COMMIT
다. RENAME
라. REVOKE
마. TRUNCATE
바. DROP
데이터 정의어는 ALTER, RENAME, TRUNCATE, DROP으로 모두 4개이다.
데이터 정의어는 테이블 같은 데이터베이스 객체의 구조를 만들고 변경·제거하는 명령이다. TRUNCATE도 테이블을 비우는 DDL로 분류한다.
- COMMIT: 트랜잭션을 완료하는 트랜잭션 제어어이다.
- REVOKE: 권한을 회수하는 데이터 제어어이다.
DEPARTMENT(DID, DNAME, ADDRESS)
SELECT E.EID AS EMPID, E.ENAME AS EMPNAME,
D.DNAME AS DEPTNAME
FROM EMPLOYEE E, DEPARTMENT D
WHERE ( ㉠ ) = ‘총무팀’ AND ( ㉡ );
빈칸에는 ㉠ D.DNAME, ㉡ E.DNO = D.DID가 들어간다.
부서이름 비교는 부서 테이블의 DNAME으로 하고, 조인 조건은 외래키 DNO와 참조 대상 DID를 같게 놓는다.
- D.DNAME, E.EID = D.DID: 직원아이디와 부서아이디는 참조 관계가 없다.
- D.DID, E.DNO = D.DNAME: 부서아이디를 부서이름과 비교하고, 외래키도 이름과 비교한다.
- D.DID, E.DNO = D.DID: 조인 조건은 맞지만 부서아이디를 ‘총무팀’과 비교한다.
<T1, C, 100, 20>
<commit, T1>
<checkpoint>
<start_transaction, T4>
<T4, B, 20, 15>
<T4, A, 30, 20>
<commit, T4>
<start_transaction, T2>
<T2, B, 15, 25>
<start_transaction, T3>
<T3, A, 20, 40>
<T2, C, 20, 30>
... 시스템 장애 발생 ...
회복 후 최종 값은 A: 20, B: 15, C: 20이다. 체크포인트 이후 완료된 T4는 REDO, 미완료인 T2와 T3는 UNDO한다.
T1: 체크포인트 전에 완료되어 회복 대상이 아니다. C는 20이다.
T4 REDO: B = 15, A = 20
T2, T3 UNDO(로그 역순): C를 20으로, A를 20으로, B를 15로 되돌린다.
- A: 20, B: 25, C: 30: T2의 갱신을 되돌리지 않은 결과이다.
- A: 40, B: 25, C: 30: T2와 T3의 갱신을 모두 되돌리지 않은 결과이다.
- A: 20, B: 25, C: 20: T2의 B 갱신을 되돌리지 않은 결과이다.
나. 역정규화는 개념적 설계 단계에서 수행한다.
다. 릴레이션의 데이터 중복이 감소되고 데이터베이스의 크기도 작아진다.
라. 둘 이상의 릴레이션에 대한 조인 결과를 자주 이용하는 경우 역정규화를 통해 질의응답 시간을 단축할 수 있다.
적절한 설명은 라 하나뿐이므로 1개이다.
역정규화는 조회 성능을 위해 정규화된 릴레이션을 합치는 등 의도적으로 중복을 허용하는 작업이다. 자주 쓰는 조인 결과를 미리 저장하면 질의응답 시간이 줄어든다.
- 가: 정규형 수준을 높이는 것이 아니라 낮추는 방향이다.
- 나: 개념적 설계가 아니라 성능 요구를 고려하는 후반 설계 단계에서 수행한다.
- 다: 중복이 늘어나고 데이터베이스 크기도 커질 수 있다.
나. 요구조건 분석
다. 데이터베이스 튜닝
라. 물리적 설계
마. 논리적 설계
세 번째로 수행되는 단계는 논리적 설계이다.
설계 순서는 요구조건 분석 → 개념적 설계 → 논리적 설계 → 물리적 설계 → 데이터베이스 튜닝이다.
- 개념적 설계: 요구조건 분석 다음인 두 번째 단계이다.
- 데이터베이스 튜닝: 구현 이후 성능을 조정하는 마지막 단계이다.
- 물리적 설계: 논리적 설계 다음인 네 번째 단계이다.
X → Y이고 X → Z이면 Y → Z라는 규칙이 적절하지 않다. 같은 X로 결정된다고 해서 Y와 Z 사이에 종속이 생기지는 않는다.
예를 들어 학번이 이름과 학과를 각각 결정해도 이름이 학과를 결정하지는 않는다. X → YZ로 합칠 수 있을 뿐이다.
- X → Y, Y → Z이면 X → Z: 이행 규칙이다.
- X → Y이면 XZ → YZ: 부가 규칙이다.
- X → Y, WY → Z이면 WX → Z: 의사 이행 규칙이다.
R1(A, B, C), R2(A, D), R3(B, E, F)로 분해한 것이 가장 적절하다. 후보키 AB에 대한 부분 함수 종속이 모두 제거되기 때문이다.
AB로 모든 속성이 결정되므로 후보키는 AB이다. D는 A에만, E와 F는 B에만 종속되므로 이들을 각각 분리하고 C만 AB와 남긴다.
- R1(A, B, C, D), R2(B, E, F): R1에 A → D 부분 종속이 남아 있다.
- R1(A, B, E, F), R2(A, D): R1에 B → E, B → F 부분 종속이 남고 속성 C가 사라졌다.
- R1(A, B, C, D), R2(B, E), R3(B, F): R1에 A → D 부분 종속이 남아 있다.
SELECT E.ENAME, C.CNAME
FROM EMP E, CUSTOMER C
WHERE E.CID = C.CUSTID AND C.AGE = 20;
E.CID 인덱스와 C.AGE 인덱스를 함께 두는 것이 가장 효과적이다.
C.AGE 인덱스로 나이가 20인 고객만 먼저 찾고, 찾은 CUSTID로 E.CID 인덱스를 탐색하면 EMP 전체를 읽지 않고 조인할 수 있다.
- E의 이름 속성 인덱스: 출력에만 쓰이는 속성이라 검색 조건에 도움이 되지 않는다.
- E.CID와 C.CUSTID 인덱스: 조인 속성만 있고 AGE 조건 처리에 필요한 인덱스가 없다.
- (C.AGE, C.CUSTID) 복합 인덱스: CUSTOMER 쪽만 빨라질 뿐 EMP에서 조인 대상을 찾는 경로가 없다.
| TID 시간 | T1 | T2 | T3 |
|---|---|---|---|
| 1 | read(X); | ||
| 2 | read(Y); | ||
| 3 | read(Y); | ||
| 4 | read(X); | ||
| 5 | read(Z); | ||
| 6 | write(X); | ||
| 7 | write(Z); | ||
| 8 | read(Z); | ||
| 9 | write(Y); |
동등한 직렬 스케쥴은 T3 → T1 → T2이다. 충돌 연산의 순서로 그린 선행 그래프에 사이클이 없다.
X: T3의 read(시간 4)가 T1의 write(시간 6)보다 앞서므로 T3 → T1
Y: T1의 read(시간 3)가 T2의 write(시간 9)보다 앞서므로 T1 → T2
Z: T3의 write(시간 7)가 T2의 read(시간 8)보다 앞서므로 T3 → T2
간선 T3 → T1, T1 → T2, T3 → T2를 위상 정렬하면 순서가 하나로 정해진다.
- 없음: 그래프에 사이클이 없으므로 충돌 직렬가능하다.
- T1 → T2 → T3: T3 → T1, T3 → T2 간선에 어긋난다.
- T2 → T3 → T1: T1 → T2, T3 → T2 간선에 어긋난다.
각 레코드의 크기가 모두 같아야 한다는 설명이 적절하지 않다. 파일에는 가변 길이 레코드도 저장할 수 있다.
가변 길이 속성이나 서로 다른 형식의 레코드가 있으면 크기가 달라지며, 이를 관리하는 별도 표현 방식이 쓰인다.
- 블록의 비인접 저장: 블록을 포인터 등으로 연결할 수 있어 적절하다.
- 블록의 인접 재배치: 탐색 시간이 줄어 입출력이 빨라지므로 적절하다.
- 여러 블록에 걸친 저장: 블록보다 긴 레코드를 나누어 저장하는 방식으로 적절하다.
나. 트랜잭션 T는 항목 X에 대한 모든 읽기 연산과 쓰기 연산을 끝낸 후 반드시 로크를 해제해야 한다.
다. 트랜잭션 T는 항목 X에 쓰기 연산을 수행하기 전에는 반드시 배타 로크를 수행해야 한다.
라. 트랜잭션 T가 항목 X에 배타 로크를 보유하고 있다면 다른 트랜잭션 S의 공유 로크를 허용한다.
적절한 설명은 가, 나, 다이다.
읽기에는 공유 로크 또는 배타 로크가, 쓰기에는 배타 로크가 필요하고, 연산을 마친 뒤에는 로크를 해제해야 한다.
- 라: 배타 로크는 공유 로크와 양립할 수 없으므로 다른 트랜잭션의 공유 로크를 허용하지 않는다.
블로킹 인수는 5, 필요한 블록은 4,000개이다.
블로킹 인수는 한 블록에 들어가는 레코드 수로, 소수점을 버린다.
블록 개수는 레코드 수를 블로킹 인수로 나눈다.
- 블로킹 인수 5, 블록 2,000: 레코드 수에 맞는 블록 수의 절반밖에 되지 않는다.
- 블로킹 인수 10, 블록 2,000: 200바이트 레코드 10개는 1,024바이트 블록에 들어가지 않는다.
- 블로킹 인수 10, 블록 4,000: 블로킹 인수가 틀렸고, 그 값과 블록 수도 서로 맞지 않는다.
로그 레코드 버퍼링을 쓰면 안정적 관리가 보장된다는 설명이 적절하지 않다. 주 메모리의 버퍼는 휘발성이므로 장애 시 내용이 사라질 수 있다.
버퍼링은 출력 횟수를 줄이는 기법일 뿐이다. 안정성은 로그를 먼저 안전한 저장장치에 출력하는 규칙을 지켜야 확보된다.
- commit 로그 출력 후 완료: 그 레코드가 안전하게 저장되어야 트랜잭션이 완료 상태가 되므로 적절하다.
- commit 로그 전 관련 로그 출력: 트랜잭션의 로그를 앞서 저장해야 하므로 적절하다.
- 버퍼 블록 출력 전 로그 출력: 로그 우선 기록의 핵심 규칙으로 적절하다.
나. READ COMMITTED
다. REPEATABLE READ
라. SERIALIZABLE
팬텀 문제가 발생할 수 있는 수준은 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ이다.
SQL 표준의 고립 수준 중 팬텀까지 막는 것은 가장 높은 SERIALIZABLE뿐이다.
- READ UNCOMMITTED: 오손 읽기까지 허용하므로 팬텀도 발생한다.
- READ COMMITTED: 오손 읽기만 막으므로 팬텀이 발생한다.
- REPEATABLE READ: 읽은 투플의 변경은 막지만 새 투플 삽입은 막지 못해 팬텀이 발생한다.
- SERIALIZABLE: 팬텀을 포함한 이상 현상을 막으므로 해당하지 않는다.
| TID 시간 | T1 | T2 |
|---|---|---|
| 1 | START TRANSACTION SELECT ENAME FROM EMP WHERE DNO = 1; | |
| 2 | START TRANSACTION INSERT INTO EMP VALUES(10, ‘홍길동’, 1); COMMIT; | |
| 3 | SELECT ENAME FROM EMP WHERE DNO = 1; COMMIT; |
2단계 로킹 프로토콜 준수는 해결 방법으로 적절하지 않다. 이 스케쥴의 문제는 팬텀이고, 존재하지 않는 투플에는 로크를 걸 수 없기 때문이다.
T1의 두 번째 SELECT에서 T2가 삽입한 행이 나타난다. 2단계 로킹은 투플 단위 로크로는 새로 삽입되는 투플을 막지 못한다.
- DNO 인덱스 엔트리의 공유 로크: 삽입에 필요한 인덱스 갱신이 대기하므로 팬텀을 막는다.
- EMP 테이블의 공유 로크: 테이블 전체가 잠겨 T2의 삽입이 대기한다.
- SERIALIZABLE 설정: 팬텀까지 방지하는 고립 수준이다.
결과가 많은 셀렉트를 먼저 실행한다는 설명이 적절하지 않다. 경험적 최적화는 결과 투플이 가장 적은 제한적인 셀렉트를 먼저 수행한다.
앞 단계의 결과가 작을수록 뒤이은 조인 등의 처리 비용이 줄어든다.
- 셀렉트를 아래로 이동: 조인 전에 행을 줄이므로 적절하다.
- 카티션 곱과 조인 조건 결합: 곱의 큰 중간 결과를 피하므로 적절하다.
- 프로젝트를 나눠 아래로 이동: 불필요한 속성을 일찍 제거하므로 적절하다.
나. 즉시 갱신(immediate update) 회복 기법
다. 검사 시점(checkpoint) 회복 기법
라. 그림자 페이징(shadow paging) 회복 기법
로그를 이용하는 회복 기법은 지연 갱신, 즉시 갱신, 검사 시점 기법이다.
세 기법은 모두 로그를 기록해 두고 장애 시 이를 근거로 REDO나 UNDO를 수행한다.
- 라: 그림자 페이징은 로그 없이 현재 페이지 테이블과 그림자 페이지 테이블을 유지해 회복한다.
데이터베이스 관리자가 카탈로그를 생성·갱신한다는 설명이 적절하지 않다. 시스템 카탈로그는 DBMS가 자동으로 생성하고 유지한다.
테이블을 만들거나 변경하면 DBMS가 해당 메타데이터를 카탈로그에 반영한다. 사용자는 직접 수정하지 않고 조회한다.
- SELECT로 검색: 카탈로그도 테이블 형태이므로 조회할 수 있다.
- 통계 정보 포함: 옵티마이저가 비용을 추정할 때 활용하므로 적절하다.
- 데이터 사전: 시스템 카탈로그의 다른 이름으로 적절하다.
하나의 수직 단편에만 기본키를 포함해야 한다는 설명이 적절하지 않다. 재구성을 위해서는 모든 수직 단편에 기본키가 있어야 한다.
수직 단편은 공통 기본키를 기준으로 조인해야 원래 릴레이션으로 복원된다. 기본키가 없는 단편은 다른 단편의 어느 행과 연결되는지 알 수 없다.
- 어느 한 단편에 속함: 단편화의 완전성 조건으로 적절하다.
- 원상회복 가능: 재구성 조건으로 적절하다.
- 수평 단편화: 행 단위로 나누는 방식이므로 적절하다.
나. ( ㉡ )은 큐브 데이터에 대해 차원의 값을 어떤 범위로 제한해서 부분 큐브 데이터를 생성한다.
빈칸에는 ㉠ 롤업, ㉡ 다이싱이 들어간다.
롤업은 상세 데이터를 더 요약된 수준으로 올리는 연산이고, 다이싱은 차원 값의 범위를 제한해 부분 큐브를 만드는 연산이다.
- 드릴 다운: 요약에서 상세로 내려가는 연산으로 ㉠의 설명과 반대이다.
- 슬라이싱: 한 차원을 특정 값 하나로 고정하는 연산으로 범위 제한과 다르다.
은행 시스템이 BASE 특성을 만족해야 한다는 설명이 적절하지 않다. 은행 거래는 강한 일관성이 필요하므로 ACID 특성을 요구한다.
BASE는 가용성을 위해 일시적인 불일치를 허용하는 모델이다. 계좌 잔액처럼 불일치가 허용되지 않는 데이터에는 맞지 않는다.
- CAP의 의미: 일관성, 가용성, 분할감내를 뜻하므로 적절하다.
- 세 특성 중 두 개만 보장: CAP 이론의 내용으로 적절하다.
- 이중 예약 허용: 일관성을 양보하고 서비스를 계속하는 것이므로 가용성 우선으로 적절하다.
의미 검사는 조인 구현 기법이 아니다. 조인은 두 릴레이션에서 값이 맞는 투플을 찾는 물리적 처리이고, 의미 검사는 그런 탐색 방법이 아니다.
조인 구현은 투플을 비교하거나 접근 구조로 짝을 찾는 방식으로 이루어진다.
- 중첩 루프: 바깥 릴레이션의 각 투플마다 안쪽 릴레이션을 비교하는 기법이다.
- 인덱스 검사: 안쪽 릴레이션의 인덱스로 짝이 되는 투플을 찾는 기법이다.
- 해시 검사: 해시로 조인 키가 같은 투플을 찾는 기법이다.
| 트랜잭션 ID | 구매품목 |
|---|---|
| 1 | 양파, 감자, 마늘 |
| 2 | 감자, 양파 |
| 3 | 맥주, 감자, 두부 |
| 4 | 맥주, 감자, 마늘 |
| 5 | 양파, 맥주 |
빈발항목으로만 구성된 것은 {양파}, {맥주}이다.
트랜잭션이 5건이므로 최소 지지 횟수는 3건이다.
감자 4건, 양파 3건, 맥주 3건은 기준을 넘고, 마늘은 2건, 두부는 1건이다.
- {감자}, {마늘}: 마늘이 2건으로 기준에 못 미친다.
- {맥주}, {감자, 양파}: 감자와 양파를 함께 산 트랜잭션은 2건뿐이다.
- {감자, 마늘, 맥주}: 세 품목이 함께 나온 트랜잭션은 1건뿐이다.