멈추지 않고 끈질기게
[DB] 관계 데이터 모델 본문
※ 해당 포스팅은 개인의 공부 정리용 글입니다. 틀린 내용이 있다면 추후 수정될 수 있습니다.
※ 해당 포스팅은 하기 출처들을 참조하였습니다.
- 김연희, 데이터베이스 개론, 한빛아카데미, 2022
이번 포스팅에서는 데이터 모델 중 특히 널리 쓰이는 관계 데이터 모델에 대해 알아보겠습니다.
1. 관계 데이터 모델
1) 릴레이션 관련 용어
관계 데이터 모델에서는 하나의 객체에 관한 데이터를 릴레이션(relation) 하나에 담아 데이터베이스에 저장합니다. 그림 1은 게임에서 저장하고 있는 플레이어 정보를 표현한 릴레이션의 예시입니다.
- 속성(attribute)
릴레이션의 열을 속성이라고 하며, 각 속성은 서로 다른 이름을 사용하여 구별합니다. 그림 1에서 플레이어ID, 닉네임, 레벨, 전직, 보유 골드, 길드가 속성에 해당합니다.
- 투플(tuple)
릴레이션의 행을 투플이라고 하며, 실제 속성 값으로 이루어진 인스턴스가 됩니다. 그림 1의 릴레이션은 5명의 플레이어의 정보를 포함하고 있으며, 이는 곧 5개의 플레이어 인스턴스가 존재한다(5개의 투플로 이루어져 있다)는 뜻입니다.
- 도메인(domain)
어떤 속성 하나가 가질 수 있는 모든 값의 집합을 도메인이라 합니다. 그림 1의 예시에서 전직 속성에 검사, 법사, 수도사, 궁수, 도적의 5가지 직업만이 존재한다면, 이 5가지 집합이 전직 속성의 도메인입니다. 속성의 도메인을 정의해두면 유효성 검사가 편리해진다는 장점이 있습니다(도메인 외의 값은 불허).
다만 닉네임이나 보유 골드와 같은 속성은 도메인을 정의하기 어렵기 때문에, 이런 경우 도메인을 데이터 타입으로 정의합니다. 닉네임과 같은 문자열은 char(10), 즉 최대 10개의 문자로 구성된 문자열로 정의한다던가, 보유 골드는 int같은 정수 타입으로 정의하는 식입니다. 데이터 타입으로만 정의해두어도 닉네임과 보유 골드같이 도메인이 다른 속성끼리의 연산(문자열과 정수)을 막음으로써 잘못된 연산을 예방할 수 있습니다.
- 널 값(null)
특정 투플의 속성 값을 모르거나, 적합한 값이 없는 경우에는 null값을 사용합니다. 그림 1에서 player0517이 길드에 아직 가입하지 않았기 때문에, 해당 유저의 길드 속성 값은 null값이 됩니다. null값은 보통 공백으로 표현하나, DBMS에 따라 표현하는 방식은 달라질 수 있습니다.
- 차수(degree)
릴레이션에 존재하는 속성 전체의 개수를 차수라고 합니다. 그림 1의 경우 플레이어ID, 닉네임, 레벨, 전직, 보유 골드, 길드의 총 6가지 속성이 존재하므로, 해당 릴레이션의 차수는 6입니다. 릴레이션의 차수는 최소 1 이상이어야 하며(최소 1개의 속성 보유), 후술할 카디널리티에 비해 변화가 적은 정적인 값입니다.
- 카디널리티(cardinality)
릴레이션의 투플 전체의 개수를 카디널리티라고 합니다. 그림 1의 경우 플레이어 5명의 정보가 투플로 존재하므로 해당 릴레이션의 카디널리티는 5입니다. 투플은 차수와 달리 0일 수도 있습니다(아직 실제 데이터를 저장하지 않은 경우). 데이터의 삽입 및 삭제에 따라 기존 투플이 삭제되거나 새 투플이 생성되므로 변화가 잦은 동적인 값입니다.
2) 데이터베이스의 구성
릴레이션은 그림 2와 같이 릴레이션 스키마와 릴레이션 인스턴스로 구성됩니다.
- 릴레이션 스키마
릴레이션의 논리적 구조를 의미하며, 릴레이션의 이름 및 모든 속성 이름으로 정의합니다. 그림 2의 경우,
플레이어(플레이어ID, 닉네임, 레벨, 전직, 보유 골드, 길드) 로 릴레이션 스키마를 표현할 수 있습니다. 릴레이션 스키마를 통해 해당 릴레이션이 어떻게 구성되어 있는지 파악할 수 있습니다.
- 릴레이션 인스턴스
릴레이션에 존재하는 모든 투플들의 집합을 릴레이션 인스턴스라고 합니다. 각 투플은 릴레이션 스키마에 대응하는 실제 데이터들을 저장하고 있으며, 릴레이션 인스턴스를 통해 실제 데이터들을 확인할 수 있습니다. 그림 2의 경우 5명의 플레이어들의 데이터가 릴레이션 인스턴스를 구성하고 있습니다.
DBMS가 내부적으로 데이터 조작어를 통해 릴레이션 인스턴스의 투플을 검색 및 새로운 투플 삽입, 기존 투플 삭제를 수행합니다. 따라서 릴레이션 인스턴스는 그 구성이 자주 바뀔 수 있습니다.
- 데이터베이스 스키마 & 데이터베이스 인스턴스
데이터베이스는 다수의 릴레이션들로 구성되며, 데이터베이스 스키마는 이러한 모든 릴레이션들의 스키마의 집합을 의미합니다. 데이터베이스 인스턴스는 모든 릴레이션들의 인스턴스의 집합으로, 데이터베이스에 저장된 모든 데이터 내용의 전체 집합을 의미합니다.
3) 릴레이션의 특성
관계 데이터 모델의 릴레이션으로 인정되려면 하기의 4가지 특성을 만족해야 합니다.
- 투플의 무순서
하나의 릴레이션에서 투플 사이의 순서는 의미가 없어야 한다는 규칙입니다. 즉, 투플의 순서가 바뀐다고 해서 다른 릴레이션이 되지 않으며, 순서와 무관하게 같은 투플들을 담고 있으면 동일한 릴레이션이어야 합니다. 그림 2에서 player0516과 player0517의 투플 순서를 바꿔도 동일한 릴레이션인 것과 같습니다. 데이터베이스에서 연산 수행 시 효율적인 처리를 위해 투플의 순서를 임의로 변경할 수도 있으므로, 릴레이션이 해당 규칙을 꼭 지켜야 합니다.
- 속성의 무순서
하나의 릴레이션에서 속성 사이의 순서는 의미가 없어야 한다는 규칙입니다. 즉, 속성의 순서를 바꾼다고 해서 다른 릴레이션이 되지 않으며, 순서와 무관하게 같은 속성들로 구성되어 있다면 동일한 릴레이션이어야 합니다. 그림 2와 같이 릴레이션 스키마가 플레이어(플레이어ID, 닉네임, 레벨, 전직, 보유 골드, 길드)인 릴레이션과 플레이어(플레이어ID, 레벨, 길드, 전직, 보유 골드, 닉네임)인 릴레이션은 동일한 릴레이션으로 봐야합니다. 속성 값에는 속성의 이름을 통해 접근하므로 한 릴레이션 내에 같은 이름의 속성이 존재해서는 안되고, 이름도 명확하게 구분할 수 있도록 짓는 것이 좋습니다.
- 투플의 유일성
하나의 릴레이션에는 동일한 투플이 존재해서는 안된다는 규칙입니다. 반대로 말하면 모든 투플에는 다른 투플과 구별되는 유일한 특성이 있어야 하며, 이를 위해 선정하는 속성(들)을 키(key)라고 합니다. 그림 2에서 플레이어ID가 키 속성이라면 해당 속성 값은 투플마다 반드시 달라야 하며, 이를 위해 플레이어ID 생성 시 중복 방지 로직을 넣어야 할 것입니다. 투플의 유일성은 릴레이션에서 원하는 투플에 접근하기 위해 반드시 지켜져야 합니다.
- 속성의 원자성
속성 값은 반드시 원자값(더이상 분해할 수 없는 하나의 값)이어야 한다는 규칙입니다. 관계 데이터 모델은 릴레이션을 단순한 구조로 정의하고 유지하고자 하므로 다중 값을 허용하지 않습니다. 그림 2의 릴레이션에서 특정 캐릭터가 이중 직업(다중 값)을 가질 수 있다면, 해당 릴레이션은 관계 데이터 모델에는 적합하지 않다고 봐야 합니다.
4) 키의 종류
릴레이션의 투플들을 유일하게 구별해주는 역할을 해주는 것이 키(key)입니다. 키는 관계 데이터 모델에서 제약조건을 정의하며, 투플 처리에 관여하는 중요한 개념입니다. 관계 데이터 모델에서는 슈퍼키, 후보키, 기본키, 대체키, 외래키의 5가지 키가 존재합니다.
- 슈퍼키
하나의 릴레이션에서 키로 지정된 속성 값은 투플마다 달라야 한다는 것을 유일성이라 하며, 슈퍼키는 이 유일성의 특성을 만족하는 속성(들)입니다. 그림 2의 경우 플레이어ID가 슈퍼키에 해당합니다. 보유 골드의 경우 현재 기준으로는 같은 값을 가지는 투플이 없지만, 해당 속성값은 다른 투플과 같은 값으로 수정될 수 있고 같은 값을 가진 투플이 추가될 수도 있으므로 슈퍼키가 될 수 없습니다.
슈퍼키는 2개 이상의 속성 집합으로 이루어질 수도 있으며, 슈퍼키를 포함하는 속성 집합은 모두 슈퍼키에 속합니다. 예를 들어 (플레이어ID, 보유 골드) 집합은 플레이어ID가 슈퍼키이므로 슈퍼키가 될 수 있습니다. 다만 불필요한 속성이 포함된 속성 집합을 슈퍼키로 할 경우 효율성이 떨어집니다.
- 후보키
최소성은 꼭 필요한 최소한의 속성들로만 키를 구성하는 것을 의미하며, 후보키는 유일성과 최소성을 동시에 만족하는 속성(들)입니다. 그림 2의 경우 플레이어ID는 후보키가 될 수 있지만, (플레이어ID, 보유 골드) 집합은 최소성을 만족하지 않으므로 후보키가 될 수 없습니다. 후보키는 새로운 투플 삽입, 기존 투플 삭제 시에도 유일성과 최소성을 만족하는 속성이어야 하므로, 후보키 선정 시 앞으로 추가될 수 있는 데이터까지 염두에 두고 선별해야 합니다.
- 기본키
기본키는 후보키 중에서 기본적으로 사용할 키를 선택한 것으로, 릴레이션은 반드시 1개의 기본키를 선택해야 합니다. 후보키가 여러개 존재한다면 데이터베이스 사용 환경을 고려하여 적합한 기본키를 선택해야 합니다. 릴레이션에서 기본키는 이름에 밑줄을 그어 표현합니다. 그림 3은 그림 2에서 플레이어ID를 기본키로 선택한 예시입니다.
그림 3에서 닉네임도 중복을 허용하지 않는다면, 플레이어ID와 닉네임 모두 후보키에 속하며 데이터베이스 관리자는 이 중에서 기본키를 선택해야 합니다. 기본키를 선택할 때 사용할 수 있는 판단 기준으로는 다음과 같은 조건들이 있습니다.
값이 자주 변경될 수 있는가?
기본키는 항상 유일성과 최소성을 만족해야 하므로, 값이 수정될 때마다 해당 특성을 만족하는지 검사해야 합니다. 따라서 값이 자주 변경되는 속성을 기본키로 선택하면 검사 비용이 많이 들게 되므로, 되도록 값이 변경될일이 없는 속성을 선택하는 것이 좋습니다. 그림 3의 경우 닉네임도 중복을 불허한다면 기본키로 선택할 수 있지만, 인게임에서 닉네임 변경을 허용한다면 닉네임보다는 변경될 일이 없는 플레이어ID를 기본키로 선택하는 것이 좋습니다.
널 값을 가질 수 있는 속성인가?
기본키는 투플을 식별하는데 사용하므로 기본키 속성이 널 값을 포함할 경우 그 의미를 상실하게 됩니다. 그림 3에서 만약에 길드 속성이 중복 값을 허용하지 않는다면(1인 1길드 시스템이라면) 기본키 후보로 생각해 볼 수 있겠지만, 널 값을 허용하기 때문에 기본키로는 부적합합니다.
컴퓨터가 처리하기 좋은 단순한 속성인가?
기본키는 특정 투플에 접근하는데 사용되므로, 연산을 실행하는 컴퓨터가 쉽게 다룰 수 있는 단순한 속성일수록 좋습니다. 즉 두 개의 속성 집합보다는 단일 속성이, 문자열 보다는 단순 정수 타입의 속성을 기본키로 선택하는 것이 좋습니다. 모바일 게임에서는 유저들이 작성한 아이디나 닉네임과는 별개로 자동 생성되는 정수 타입의 pid(uid)를 기준으로 유저 데이터를 구분하며, 이 경우 pid가 기본키가 될 것입니다.
- 대체키
대체키는 기본키로 선택되지 못한 후보키로, 기본키가 될 조건은 만족했지만 상기 판단 기준 등에서 다른 후보키에 밀려난 속성입니다. 그림 3의 경우 플레이어ID와 닉네임이 후보키이며, 여기서 플레이어ID를 기본키로 선택했으므로 닉네임이 대체키가 됩니다.
- 외래키
외래키는 어떤 릴레이션에 소속된 속성(들)이 다른 릴레이션의 기본키가 되는 키를 말합니다. 즉 다른 릴레이션의 기본키를 참조하는 속성의 집합으로, 릴레이션간의 관계를 표현하기 위해 필요합니다.
그림 4는 앞에서 사용하던 플레이어 릴레이션과 새로 작성한 과금 상품 구매 릴레이션을 통해 외래키를 보여주는 예시입니다. 구매 릴레이션에서 구매자 속성을 보면 플레이어 릴레이션의 기본키인 플레이어ID를 참조함을 알 수 있습니다. 따라서 구매 릴레이션의 구매자 속성이 플레이어 릴레이션을 참조하는 외래키가 됩니다. 해당 예시와 같이 속성 이름은 달라도 상관없으나, 외래키와 외래키가 참조하는 기본키의 도메인은 같아야 합니다(도메인이 같아야 비교 연산이 가능). 해당 외래키를 통해 2023년 1월 1일에 ID가 10011인 상품을 구매한 유저의 인게임 닉네임이 ArC_Mage 임을 알 수 있습니다.
외래키는 이처럼 다른 릴레이션에서 관련있는 투플을 검색하기 위한 키이므로, 반드시 기본키를 가리켜야 합니다. 만약에 길드와 같이 중복값과 널 값이 허용되는 속성을 참조할 경우, 연관성 있는 투플을 정확하게 검색하기 어렵기 때문에 외래키의 의미가 없어지게 됩니다.
다만 외래키가 이름처럼 반드시 외부의 릴레이션을 참조해야 하는 것은 아닙니다. 한 릴레이션 내 일반 속성이 같은 릴레이션의 기본키를 참조하는 외래키가 될 수도 있습니다. 그림 5는 결혼 시스템이 있는 온라인 게임을 상정하여 플레이어 릴레이션에 배우자 속성을 추가한 모습입니다. 플레이어ID와 같은 도메인에 서로 연관이 있으므로 배우자 속성은 플레이어ID를 가리키는 외래키가 될 수 있습니다. 이 때 배우자 속성은 결혼하지 않은 경우 널 값이 될 수 있지만, 외래키는 기본키와 달리 유일성을 만족할 필요는 없기 때문에 상관 없습니다. 외래키에는 기본키와는 다른 별도의 제약 조건이 존재하며, 이는 밑에서 설명하겠습니다.
2. 관계 데이터 모델의 제약 조건
관계 데이터 모델에서는 키와 관련한 무결성 제약 조건(integrity constraint)을 기본 제약 사항으로 정의합니다. 무결성 제약 조건은 데이터베이스에 저장된 데이터의 무결성을 보장하고, 데이터베이스를 일관된 상태로 유지하기 위한 조건입니다. 이는 데이터베이스가 삽입, 수정, 삭제 연산 등을 실행하여 상태가 바뀐 후에도 항상 지켜져야 합니다.
관계 데이터 모델의 무결성 제약 조건은 개체 무결성 제약 조건과 참조 무결성 제약 조건으로 구분되며, 무결성을 보장하려면 두가지 모두 만족시켜야 합니다.
1) 개체 무결성 제약 조건(entity integrity constraint)
기본키를 구성하는 모든 속성은 널 값을 가지면 안된다는 제약 조건입니다. 기본키를 구성하는 속성에 널 값이 포함되는 순간, 투플의 유일성을 판단하게 해주는 기본키의 본래 목적을 상실하게 되기 때문입니다.
개체 무결성 제약 조건을 만족하려면 새로운 투플 삽입 및 기존 투플 수정 시, 기본키의 값이 널 값이 되는 연산의 수행을 거부하면 됩니다. 이는 보통 DBMS에서 자동으로 관리하는 부분으로, 사용자는 신규 릴레이션 생성 시 기본키를 적합한 속성으로 고르는데 신경써야 합니다.
2) 참조 무결성 제약 조건(referential integrity constraint)
외래키가 참조할 수 없는 값을 가지면 안된다는 제약 조건입니다. 외래키가 자신이 참조하는 기본키와 상관없는 값을 가지는 순간, 두 릴레이션을 연관시킬 수가 없어지므로 릴레이션 간의 관계를 표현하는 외래키의 의미가 상실되기 때문입니다.
그림 6은 참조 무결성 제약 조건을 위반하는 외래키의 예시입니다. 구매 릴레이션의 외래키(구매자)에 player0531이라는 값이 있으나, 해당 ID는 플레이어 릴레이션의 플레이어ID에 존재하지 않는 값입니다. 즉, 외래키가 참조하는 기본키와 관련이 없는 값을 가지고 있으므로 이는 참조 무결성 제약 조건을 위반한 것이 됩니다. 다만, 외래키가 널 값을 포함하는 것은 참조 무결성 제약 조건 위반이 아닙니다. 해당 릴레이션에서 대상을 모르는 것이지, 참조하는 릴레이션에 없는 대상을 참조하는 것은 아니기 때문입니다.
참조 무결성 제약 조건은 데이터베이스의 상태가 변해도 계속 유지되어야 합니다. 예를 들어 그림 6에서 구매 릴레이션에 구매번호 1003까지의 투플만 있었다고 했을 때, 구매번호 1004 투플의 삽입 요청은 DBMS에서 거부해야 합니다. 또한 플레이어 릴레이션에서 구매 릴레이션에서 참조중인 기본키 값(player0517 등)을 가진 투플을 삭제해선 안됩니다. 대신 플레이어 릴레이션의 새 투플 삽입이나 구매 릴레이션의 기존 투플 삭제는 참조 무결성 제약 조건에 영향을 미치지 않습니다.
참조 무결성 제약 조건 또한 DBMS에서 자동으로 관리하며, 사용자는 외래키가 될 속성과 참조할 기본키를 조심히 설정해주면 됩니다. 참조 무결성 제약 조건을 위반하는 경우의 처리 방법도 설정할 수 있으며, 이는 SQL문 관련 포스팅에서 자세히 다루도록 하겠습니다.
3. 관계 대수 연산
관계 데이터 모델의 연산은 즉 원하는 데이터를 얻기 위해 릴레이션에 필요한 처리 요구를 수행하는 것이며, 데이터베이스 시스템의 구성에서 데이터 언어의 역할에 속합니다. 자주 사용되는 관계 데이터 연산에는 대표적으로 관계 대수가 있습니다.
관계 대수는 원하는 결과를 얻기 위한 데이터 처리 과정을 순서대로 기술하는 절차 언어(procedural language)로, 일반 집합 연산자와 순수 관계 연산자를 포함합니다. 관계 대수는 피연산자가 릴레이션이며, 연산 결과도 릴레이션입니다. 이러한 특성을 폐쇄 특성(closure property)이라 합니다.
일반 집합 연산자
일반 집합 연산자에는 합집합(∪), 교집합(∩), 차집합(-), 카티션 프로덕트(X)의 4가지 종류가 있으며, 2개의 피연산자를 필요로 합니다. 한마디로 일반 집합 연산자는 두개의 릴레이션을 사용하는 연산입니다. 카티션 프로덕트를 제외한 3가지 연산자들은 수학에서 사용하는 용어와 비슷하게 동작하며, 합병 가능한 조건을 만족하는 릴레이션 간에만 연산 가능합니다. 합병 가능 조건은 다음과 같습니다.
1) 두 릴레이션의 차수가 동일할 것(속성 개수가 동일할 것)
2) 두 릴레이션에서 서로 대응되는 속성의 도메인이 일치할 것(속성의 이름은 상관 無)
그림 7은 합병 가능한 경우와 불가능한 경우의 예시입니다. 차수는 3으로 모두 동일하며, 위쪽의 릴레이션은 도메인이 각각 [char20, char20, int]로 일치하므로 병합 가능한 릴레이션들입니다. 아래쪽은 차수는 동일하지만 도메인이 [char20, char20, int]와 [char20, char10, int]로 불일치하기 때문에 병합할 수 없으며, 카티션 프로덕트를 제외한 일반 집합 연산자를 사용할 수 없습니다.
합집합(∪)
두 릴레이션 A와 B의 합집합은 A∪B로 표현하며, 릴레이션 결과는 A나 B 둘 중 하나라도 속하는 모든 투플로 이루어진 릴레이션입니다.
그림 8은 합집한 연산의 예시입니다. player0520의 경우 A와 B에 모두 포함되지만 결과에는 한번만 포함되었습니다. 연산 결과 또한 하나의 릴레이션이므로 투플의 유일성을 지켜야 하기 때문입니다. 합집합 결과는 차수는 동일하며 카디널리티는 A와 B의 카디널리티의 합과 같거나 작아집니다(중복 제외로 인해). 또한 합집합 연산은 합집합의 수학적인 특성도 그대로 따라갑니다. 즉, 교환법칙( A∪B = B∪A)과 결합법칙((A∪B)∪C = A∪(B∪C))이 성립합니다.
교집합(∩)
두 릴레이션 A와 B의 교집합은 A∩B로 표현하며, 릴레이션 결과는 A와 B에 모두 속하는 투플로 이루어진 릴레이션입니다.
그림 9는 교집합 연산의 예시입니다. A와 B 모두에 속하는 player0520만이 결과에 포함되었습니다. 교집합 결과는 차수는 동일하며 카디널리티는 A나 B의 어떤 카디널리티보다도 같거나 작아집니다. 또한 교집합 연산도 합집합과 마찬가지로 수학적인 특성이 그대로 적용됩니다. 즉, 교환법칙( A∩B = B∩A)과 결합법칙((A∩B)∩C = A∩(B∩C))이 성립합니다.
차집합(-)
두 릴레이션 A와 B의 차집합은 A-B로 표현하며, 릴레이션 결과는 A에는 존재하고 B에는 존재하지 않는 투플로 이루어진 릴레이션입니다.
그림 10은 차집합 연산의 예시입니다. A-B는 A에서 양쪽에 속하는 player0520이 제거된 릴레이션이고, B-A는 B에서 player0520이 제거된 릴레이션입니다. 이처럼 차집합은 피연산자의 순서에 영향을 받기 때문에 교환법칙 및 결합법칙이 성립하지 않습니다. 결과 릴레이션의 차수는 A와 B의 차수와 동일하며, 카디널리티는 원본과 같거나 작습니다. 즉, A-B의 카디널리티는 A보다 작거나 같고, B-A의 카디널리티는 B보다 작거나 같습니다.
카티션 프로덕트(×)
두 릴레이션 A와 B의 카티션 프로덕트는 A × B로 표현하며, 릴레이션 결과는 A의 투플과 B의 투플을 모두 연결하여 만들어진 릴레이션입니다.
그림 11은 카티션 프로덕트의 예시입니다. A의 10516 투플과 B의 20301 투플이 합쳐진 투플, A의 10516 투플과 B의 20302 투플이 합쳐진 투플, ... 과 같이 총 6개의 투플이 결과에 포함되어 있습니다. A와 B의 도메인이 일치하지 않지만, 위에서 언급했듯이 카티션 프로덕트는 병합 기준을 만족하지 않아도 가능합니다. 결과 릴레이션에서 속성의 이름에 릴레이션 이름을 붙여 A.ID, B.ID와 같이 표현하였으며, 이는 원래 어느 릴레이션에서 온 속성인지 구분하기 위한 표기법입니다. 다만 A.닉네임이나 B.레벨과 같이 양쪽에 동일한 이름의 속성이 있는 경우가 아니라면 릴레이션 명을 생략할 수 있습니다.
카티션 프로덕트의 결과 릴레이션의 차수는 A와 B의 차수를 더한 것과 같으며, 카디널리티는 A와 B의 카디널리티를 곱한 값이 됩니다. 또한 카티션 프로덕트 연산은 피연산자의 순서에 영향을 받지 않습니다(투플의 무순서). 합집합, 교집합과 마찬가지로 교환법칙(A × B = B × A)과 결합법칙((A × B) × C = A × (B × C))이 성립합니다.
순수 관계 연산자
순수 관계 연산자는 릴레이션의 구조와 특성을 이용하는 연산자로 셀렉트(σ), 프로젝트(π), 조인(⋈), 디비전(÷)의 4가지가 존재합니다. 일반 집합 연산자와 달리 관계 데이터 모델에서 새로 제시된 연산들이며 셀렉트와 프로젝트는 단일 릴레이션 연산, 조인과 디비전은 두 릴레이션 간의 연산입니다.
셀렉트
셀렉트 연산은 σ조건식(릴레이션)으로 표현하며, 연산 결과는 피연산자에서 조건식을 만족하는 투플들로 구성한 릴레이션입니다. 일반 집합 연사자와 달리 피연산자가 하나인 연산이며, 조건식은 비교 연산자(<, >, ≤, ≥, =, ≠)와 논리 연산자(∧(and), ∨(or), ¬(not))를 통해 구성합니다. 단, 조건식에서 비교 대상은 서로 도메인이 일치해야 합니다.
그림 12는 셀렉트 연산의 예시입니다. 상기 플레이어 릴레이션에서 셀렉트 연산을 통해 레벨이 20보다 높은 투플들만 추출했습니다. 이렇듯 셀렉트 연산의 결과는 피연산자의 수평적 부분집합이 됩니다. 또한 셀렉트 연산에도 다음과 같은 교환적 특징이 성립합니다.
σ조건식1(σ조건식2(릴레이션)) = σ조건식2(σ조건식1(릴레이션)) = σ조건식1∧조건식2(릴레이션)
프로젝트
프로젝트 연산은 π속성리스트(릴레이션)으로 표현하며, 연산 결과는 피연산자에서 선택한 속성들만으로 구성한 릴레이션입니다. 셀렉트와 마찬가지로 피연산자가 하나인 연산입니다.
그림 13은 프로젝트 연산의 예시입니다. 플레이어 릴레이션에서 플레이어ID,레벨,전직,길드 4가지 속성을 추출하는 프로젝트 연산과 전직 속성 하나만을 추출하는 프로젝트 연산을 실행하였습니다. 단일 속성을 추출한 결과를 보면 중복값이 제거된 것을 알 수 있습니다. 프로젝트 연산의 결과 또한 릴레이션이므로 투플의 유일성을 만족해야 하기 때문입니다. 이러한 경우를 제외하면 프로젝트 연산의 결과는 피연산자의 수직적 부분집합이 됩니다.
조인
두 릴레이션 A, B의 조인 연산은 A ⋈ B로 표현하며, 연산 결과는 두 릴레이션을 조합한 하나의 릴레이션입니다. 두 릴레이션을 조합하기 위해 두 릴레이션이 공통으로 가지고 있는 속성을 이용하는데, 이를 조인 속성(join attribute)이라 합니다. 즉, 조인 연산의 결과는 A, B에서 조인 속성이 같은 투플만 연결하여 만든 새로운 투플의 집합입니다.
그림 14는 조인 연산의 예시입니다. 사실 조인 연산에도 종류가 있으며, A ⋈ B로 표기하는 조인은 동등 조인입니다. 동등 조인의 경우 두 릴레이션의 모든 속성을 포함하므로, 조인 속성이 중복되어 나타나게 됩니다. 따라서 위쪽의 동등 조인의 결과에서는 중복 속성을 구분하기 위해 플레이어.ID, 구매.ID와 같이 릴레이션명을 붙여 표기하였습니다. 자연 조인 연산의 경우 조인 속성을 한번만 포함합니다. 자연 조인은 A ⋈N B 로 표현하며, 아래쪽 자연 조인 연산의 결과를 보면 ID 속성이 한번만 포함된 것을 볼 수 있습니다.
조인의 종류에 상관없이 조인 속성의 값이 같은 투플만이 연결되어 결과물에 포함됩니다. 상기 예시의 경우 조인 속성인 ID에서 양쪽에 모두 존재하는 값은 player0516, player0517, player0518 이며, 따라서 플레이어 릴레이션에서는 player0519, player0520이, 구매 릴레이션에서는 player0531이 조인 결과에서 제외되었습니다.
디비전
두 릴레이션 A, B의 디비전 연산은 A ÷ B로 표현하며, 연산 결과는 B의 모든 투플과 관련이 있는 A의 투플로 구성된 릴레이션입니다. 바꿔 말하자면 A ÷ B 연산은 A가 B의 모든 속성을 포함해야 합니다.
그림 15는 디비전 연산의 예시입니다. 위 예시의 경우, A ÷ B 연산은 A 릴레이션에서 서버종결자 길드에 속한 검사 직업의 플레이어를 찾는다는 의미로 해석할 수 있습니다. 따라서 해당 연산의 결과에 서버종결자 소속 검사인 player0516의 데이터가 포함되었습니다. 참고로 결과 릴레이션에는 B의 속성인 전직, 길드 속성은 포함하지 않습니다. 만약 해당 속성들을 포함한다면 결과 릴레이션에서 모든 전직, 길드 속성의 값은 동일할 것이므로 굳이 포함하지 않는 것입니다.
'DB' 카테고리의 다른 글
[DB][SQL] 그룹화와 집계 함수 (0) | 2023.05.03 |
---|---|
[DB][SQL] 데이터의 검색 (0) | 2023.05.02 |
[DB] 데이터 모델링 (0) | 2023.04.17 |
[DB] 데이터베이스 관리 시스템(DBMS) (0) | 2023.04.09 |
[DB] 트랜잭션(Transaction) (0) | 2023.04.04 |