물리적 데이터베이스 설계
: 논리적인 설계의 데이터 구조를 보조 기억 장치 상의 화일(물리적인 데이터 모델)로 사상
예상 빈도를 포함하여 데이터베이스 질의와 트랜잭션 분석
데이터에 대한 효율적 접근 제공 위해 저장 구조, 접근 방법들을 다룸 -> 조인 연산 속도 향상
DBMS 종류 고려하여 진행
질의를 효율적으로 지원하기 위해 인덱스 구조 적절히 사용
- 인덱스 너무 많을 시, 데이터베이스 갱신에 시간 많이 걸림
- 인덱스 너무 적을 시, 검색 연산 효율적으로 적용되지 않음
: 사용자가 원하는 데이터 검색 위해 DBMS는 디스크 상의 데이터베이스로부터 사용자가 원하는 데이터를 포함하고 있는 블록을 읽어서 주기억 장치로 가져옴
데이터 변경 시, 디스크에 블록 다시 기록
블록 크기: 512bytes~ 운영체제에 따라 다름. 일반적으로 4096bytes
주기억장치: RAM. 빠르지만 용량 작음
디스크: 직접 접근
테이프: 순차 접근만 가능. 느림. 백업용으로만 사용
디스크 접속 소요 시간을 줄이기 위해서?
=> 평균 회전지연시간 감소, 블록 전송 횟수 감소
모든 데이터를 주기억장치에 올릴 수 없기 때문에 한정된 버퍼 공간에 어떤 블록들을 주기억장치에 유지할 것인가
릴레이션의 애트리뷰트: 고정 길이 or 가변 길이의 필드
연관된 필드들 => 고정 길이 or 가변 길이의 레코드
한 릴레이션을 구성하는 레코드들의 모임 => 화일 (블록들의 모임)
한 화일에 속하는 블록들이 반드시 인접해 있을 필요 X
인접한 블록들을 읽는 경우: 탐구 시간과 회전 지연 시간 X. 입출력 속도 Fast.
BLOB(Binary Large Object): 이미지, 동영상 등 대규모 크기의 데이터 저장
8TB ~ 128TB
(블록 크기: 일반적으로 레코드보다 훨씬 big. IF 레코드 길이 > 블록 크기: 한 레코드 여러 블록에 저장해야 함)
채우기 인수: 각 블록에 레코드를 채우는 공간의 비율
나중에 레코드 삽입될 때, 기존의 레코드들을 이동하는 가능성을 줄이기 위해서 빈 공간을 남겨두기.
고정 길이 레코드
: 레코드 i를 접근하기 위해 n*(i-1)+1 위치에서 레코드 읽기 (n: 바이트)
* 가변 길이: 위치 파악 어려움. 레코드 끝 나타내는 특별 문자 사용.
* 고정 길이: 레코드 배치, 관리 단순
18*(3-1)+1 = 37byte부터 읽으면 세 번째 레코드 읽을 수 있음.
2번 레코드 삭제 시, 4번 레코드를 2번 자리로 옮겨서 빈 자리를 채우면 한 개의 레코드만 이동해도 재배치 가능.
화일 내의 클러스터링 (Intra-File Clustering)
: 한 화일 내에서 함께 검색될 가능성이 높은 레코드들을 디스크 상에서 물리적으로 가까운 곳에 모아두는 것
화일 간의 클러스터링 (Inter-File Clustering)
: 논리적으로 연관되어 함께 검색될 가능성이 높은 두 개 이상의 화일에 속한 레코드들을 디스크 상에서 물리적으로 가까운 곳에 저장하는 것
: 화일 내의 데이터를 보조기억장치인 디스크에서 블록과 레코드들로 배치
: 레코드들이 삽입된 순서대로 화일에 저장
* 공간 재사용하지 않고 끝에 계속 새로 넣기 때문에 화일 크기 증가 => 주기적 재조직 필요 (릴레이션 쭉 적재할 때 사용)
- 성능
SELECT *
FROM EMPLOYEE;
// 히프 화일에 b개의 블록이 있을 때
// 원하는 블록을 찾기 위해 평균적으로 b/2개의 블록을 읽어야 함
SELECT TITLE
FROM EMPLOYEE
WHERE EMPNO = 1365;
// 몇 개의 레코드들 검색.
// 조건에 맞는 레코드 이미 한 개 이상 검색했더라도
// 화일의 마지막 블록까지 읽어서 원하는 레코드 존재하는가 확인해야 함
// b개의 블록 모두 읽어야 함
SELECT EMPNAME, TITLE
FROM EMPLOYEE
WHERE DNO = 2;
// 급여의 범위를 만족하는 레코드들 모두 검색
// EMPLOYEE 릴레이션의 모든 레코드들을 접근해야 함
SELECT EMPNAME, TITLE
FROM EMPLOYEE
WHERE SALARY >= 3000000 AND SALARY <= 4000000;
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
- 블록 수: 10,000,000 / 20 = 500,000개
- 특정 레코드를 찾기 위해 읽어야 하는 디스크 블록 수: 500,000 / 2 = 250,000개
- 총 걸리는 시간: 250,000 * 10ms = 2,500,000ms = 2500s (약 42m)
효율적: 삽입
비효율적: 삭제, 탐색, 순서대로 검색, 특정 레코드 검색
: 레코드들이 하나 이상의 필드 값에 따라 순서대로 저장된 화일 (탐색 키값의 순서에 따라 저장)
*탐색 키(Search Key): 순차 화일을 정렬하는데 사용되는 필드
* 레코드 순차적 접근 응용에 적합. 화일의 레코드들이 정렬된 필드를 사용해서 특정 레코드 검색 효율적
- 성능
SELECT TITLE
FROM EMPLOYEE
WHERE EMPNO = 1365;
SELECT EMPNAME, TITLE
FROM EMPLOYEE
WHERE SALARY >= 3000000 AND SALARY <= 4000000;
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
이진 탐색
- 블록 수: 10,000,000 / 2 = 500,000개
- 특정 레코드 찾기 위해 읽어야 하는 디스크 블록 수: = 19개
- 총 걸리는 시간: 19 * 10ms = 190ms
효율적: 탐색 키 기반 탐색
비효율적: 삽입, 삭제, 탐색 키가 아닌 필드를 사용하여 탐색
인덱스된 순차 화일: 인덱스를 통해서 임의의 레코드를 접근할 수 있는 화일
: 탐색 키가 데이터 화일의 기본 키인 인덱스
기본 키의 값에 따라 정렬된 데이터 화일에 대해 정의됨
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
- 블록 포인터: 4byte, 키 필드 길이: 20byte
- 블록 수: 10,000,000 / 20 = 500,000개
데이터 화일의 각 블록마다 하나의 인덱스 엔트리가 인덱스에 들어 있음 (인덱스 엔트리 개수 = 데이터 블록 개수)
- 인덱스 엔트리 길이: 24byte
- 인덱스 블록킹 인수: 4096/24 = 170 (인덱스 블록 당 170개의 인덱스 엔트리 들어감)
- 인덱스 크기: 500,000/170 = 2942블록
- 인덱스로 하나의 레코드를 찾는데 필요한 블록 접근 횟수: (인덱스 블록 접근 횟수) + 1(데이터 블록 접근 횟수) = 13
- 총 걸리는 시간: 13*10ms = 130ms
: 탐색 키 값에 따라 정렬된 데이터 화일에 대해 정의됨
각각의 상이한 키 값마다 하나의 인덱스 엔트리가 인덱스에 포함
범위 질의에 유용
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
- 블록 포인터: 4byte, 키 필드 길이: 20byte
- 블록 수: 10,000,000 / 20 = 500,000개
데이터 화일의 각 블록마다 하나의 인덱스 엔트리가 인덱스에 들어 있음 (인덱스 엔트리 개수 = 데이터 블록 개수)- 서로 상이한 탐색 키 값들의 수: 800,000
- 인덱스 엔트리 길이: 24byte
- 인덱스 블록킹 인수: 4096/24 = 170
- 인덱스 크기: 800,000/170 = 4706블록
- 인덱스로 하나의 레코드를 찾는데 필요한 블록 접근 횟수: + 1 = 14
- 총 걸리는 시간: 14 * 10ms = 140ms
: 탐색 키 값에 따라 정렬되지 않은 데이터 화일에 대해 정의
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
- 블록 포인터: 4byte, 키 필드 길이: 20byte
- 블록 수: 10,000,000 / 20 = 500,000개
데이터 화일의 각 블록마다 하나의 인덱스 엔트리가 인덱스에 들어 있음 (인덱스 엔트리 개수 = 데이터 블록 개수)
- 인덱스 엔트리 길이: 24byte
- 인덱스 블록킹 인수: 4096/24 = 170
- 인덱스 블록 수: 10,000,000/170 = 58,824블록
- 인덱스로 하나의 레코드를 찾는데 필요한 블록 접근 횟수: + 1 = 17
- 총 걸리는 시간: 17 * 10ms = 170ms
희소 인덱스 VS 밀집 인덱스
희소 인덱스 | 밀집 인덱스 |
---|---|
블록마다 한 개의 엔트리 | 레코드마다 한 개의 엔트리 |
엔트리 수 ⬇️ | 엔트리 수 ⬆️ |
디스크 접근 수 1만큼 ⬇️ | |
갱신, 질의에 대해 효율적 | 인덱스 정의된 애트리뷰트만 검색(ex. COUNT) 시, 인덱스만 접근해서 질의 수행 가능 => 효율적 |
한 화일에 한 개 | 한 화일에 여러 개 |
클러스터링 인덱스 VS 보조 인덱스
클러스터링 인덱스 | 보조 인덱스 |
---|---|
희소 인덱스 | 밀집 인덱스 |
범위 질의에 효율적 | 일부 질의에 대해 화일 접근 필요 없이 처리 가능 |
*클러스터링 인덱스: 채우기 인수에 낮은 값 지정해서 추가 삽입되는 레코드 대비하는 게 바람직
: 인덱스 엔트리 탐색 시간 단축 위해, 단일 단계 인덱스를 디스크 상의 하나의 순서 화일로 간주, 단일 단계 인덱스에 대해 다시 인덱스 정의.
가장 상위 단계의 모든 인덱스 엔트리들이 한 블록에 들어갈 수 있을 때까지 위 과정 반복.
- 레코드: 10,000,000개, 레코드 길이: 200byte
- 블록 크기: 4096byte
- 블록킹 인수: 4096/200 = 20 (한 블록에 포함되는 레코드 수)
- 한 블록 읽는 데 걸리는 시간: 10ms
- 블록 포인터: 4byte, 키 필드 길이: 20byte
- 블록 수: 10,000,000 / 20 = 500,000개
데이터 화일의 각 블록마다 하나의 인덱스 엔트리가 인덱스에 들어 있음 (인덱스 엔트리 개수 = 데이터 블록 개수)
- 인덱스 엔트리 길이: 24byte
- 인덱스 블록킹 인수: 4096/24 = 170
- 1단계 인덱스 블록 수: 500,000/170 = 2942블록
- 2단계 인덱스 블록 수: 2942/170 = 18블록
- 3단계 인덱스 블록 수: 18/170 = 1블록 => 주기억장치 상주 가능
- 2단계 인덱스 한 블록, 1단계 인덱스 한 블록, 데이터 화일 한 블록: 3
- 총 걸리는 시간: 3 * 10ms =30ms
CREATE INDEX EMPDNO_IDX ON EMPLOYEE(DNO);
CREATE INDEX EmpIndex ON EMPLOYEE (DNO, SALARY);
// 활용 가능
SELECT *
FROM EMPLOYEE
WHERE DNO = 3 AND SALARY = 4000000;
// 활용 가능
SELECT *
FROM EMPLOYEE
WHERE DNO >= 2 AND DNO <= 3 AND SALARY >= 3000000 AND SALARY <= 4000000;
// 활용 가능
SELECT *
FROM EMPLOYEE
WHERE DNO = 2; // 또는 DNO에 대한 범위 질의
// **활용 불가능**
SELECT *
FROM EMPLOYEE
WHERE SALARY >= 3000000 AND SALARY <= 4000000; // 또는 SALARY에 대한 동등 조건
: 가장 중요한 질의, 수행 빈도 & 가장 중요한 갱신, 수행 빈도에 대한 성능 고려하여 인덱스 선정
- 인덱스 결정 지침
- 기본 키: 클러스터링 인덱스 정의 후보
- 외래 키: 인덱스 정의 후보 (조인 연산에 도움)
- 한 애트리뷰트에 들어있는 상이한 값들의 개수 ~= 전체 레코드 수, 그 애트리뷰트가 동등 조건에 사용 시, 비클러스터링 인덱스 생성
- 튜플이 많이 들어있는 릴레이션에서 대부분의 질의가 검색하는 튜플이 2~4% 미만인 경우에는 인덱스 생성
- 자주 갱신되는 애트리뷰트에는 인덱스 정의 X
- 자주 갱신되는 릴레이션에는 인덱스 정의 X
- 후보 키: 기본 키의 특성을 가짐. 인덱스 생성 후보
- 인덱스는 화일의 레코드들 충분히 분할 가능
- 정수형 애트리뷰트에 인덱스 생성
- VARCHAR, 날짜형, 실수형 애트리뷰트 인덱스 생성 X
- 작은 화일에는 인덱스 생성 X
- 대량 데이터 삽입 시, 모든 인덱스 제거 후, 데이터 삽입 완료 후, 인덱스 다시 생성
SELECT *
FROM EMPLOYEE
WHERE SALARY * 12 > 40000000;
SELECT *
FROM EMPLOYEE
WHERE SUBSTR(EMPNAME, 1, 1) = '김';
SELECT *
FROM EMPLOYEE
WHERE MANAGER IS NULL;