PRIMARY KEY (기본 키) 선택 -1탄

PRIMARY KEY (기본 키) 선택 -1탄

여러 시스템들을 컨설팅하면서 발견하는 문제점 중 하나는 primary key가 없거나 잘못 정의되어 있는 것입니다. Primary key를 제대로 정의하는 것은 데이터베이스 디자인에 있어서 매우 중요한 출발점입니다.
야밤에 잠도 안 오고 하여 기본 키(primary key)에 대해서 아주 기본적인(^^) 얘기를 몇 자 적어볼까 합니다.
Primary key란 행을 고유하게 구분해 주는 최소의 정보입니다. 모든 테이블에는 primary key가 있어야 하며, 오직 하나의 primary key만 존재할 수 있습니다. 그리고 그 하나의 primary key는 단일 컬럼으로 구성될 수도 있고 둘 이상의 다중의 컬럼들로 구성될 수도 있습니다. 만일 어떤 하나의 테이블에 primary key 역할을 할 수 있는 컬럼 또는 컬럼들의 그룹이 여러 개 있다면 그 컬럼 또는 컬럼들의 그룹을 candidate key라고 합니다. 하나의 테이블에 여러 개의 candidate key들이 존재할 수 있습니다. 가령 회원 테이블에 각각의 회원에게 고유하게 부여되는 (회원번호) 컬럼과 회원의 (주민등록번호) 컬럼, 그리고 회원이 회원가입 시에 선택하면서 회원별로 고유한 회원의 (로그인ID) 컬럼이 존재한다면 이 테이블에는 세 개의 candidate key가 존재하는 겁니다. 그렇지만 이 세 개의 candidate key 중에서 오직 하나의 candidate key 만이 primary key로 간택(^^) 받을 수 있답니다. 참고로 (회원번호) 컬럼을 primary key로 선택했다면 (회원번호) 컬럼은 회원 테이블의 primary key가 되는 것이고, primary key로 뽑히지 못한 (주민등록번호) 컬럼과 (로그인ID) 컬럼은 alternate key가 됩니다.
어떤 분의 블로그에 "다시 보자 기본키"라는 글이 있어서 한번 들어가 보았더니, 내용인즉슨 "무지 느려서 잘 보았더니 primary key가 없더라, 그래서 primary key를 만들어 주었더니 잘 수행되더라. Primary key의 유무가 무지한 성능 차이를 보이더라"는 내용의 글이었습니다. 여러분들 중에서도 테이블에 primary key를 만들어 주고 나니까 성능이 현저하게 향상되는 경우를 경험하신 분들이 계실 겁니다. 테이블에 primary key를 생성하면 성능이 현저하게 향상되는 것은, primary key를 정의하면 물리적으로 uniqueness를 보장하기 위하여 unique index가 만들어지기 때문입니다. 일반적으로 primary key를 기준으로 데이터를 selecct 한다거나 primary key를 기준으로 다른 컬럼(들)의 값을 update 또는 delete하는 작업이 흔히 수행되기 때문에 테이블에 primary key를 정의해 주면 where 조건절에 primary key가 SARGs(Search Arguments)로 사용된 쿼리들의 성능은 현저하게 향상됩니다.
불행히도, 테이블에 candidate key들이 2,3개나 있음에도 불구하고 primary key를 정의하지 않은 경우들을 간혹 볼 수 있습니다. 그런 경우 primary key를 생성하지 않아서 primary key를 사용하는 쿼리들의 성능이 나쁜 것은 물론이며, 테이블에 잘못된 중복 데이터들이 저장됨으로 인하여 데이터 무결성까지 손상되어 있는 비극적인 상황까지 발전한 경우도 있습니다. 테이블에서 각각의 행들을 고유하게 구분해 주는 컬럼 또는 컬럼들의 그룹을 찾아서 primary key를 만들어 주는 것은 반드시 빠뜨려서는 안되는 매우 기본적인 작업입니다.
여담으로, primary key 컬럼이 반드시 테이블의 첫 번째 컬럼이어야 하는 것은 아닙니다. 테이블을 만들고 나서 보니 테이블의 두 번째 컬럼이 primary key라고 해서 슬퍼하지 않으셔도 됩니다. ^ ^ 그렇지만 관례상 primary key 컬럼을 테이블의 첫 번째 컬럼으로 배치하는 것이 일반적입니다.
CREATE TABLE 명령어를 사용하여 테이블을 만들어 줄 때 꼭 잊지 마십시오. Candidate key 중 하나를 primary key로 정의해야 한다는 것을요. 그리고 다음과 같이 CONSTRAINT 절을 사용하여 primary key를 정의하면 됩니다. 이 때 이름은 여러분의 시스템에서 표준화한 명명 규칙이 있다면 그 명명 규칙을 따라서 여러분이 정하시면 되고, primary key 컬럼(들)을 clustered index로 정할지 아니면 nonclustered index로 정할지는 인덱스 튜닝 기준에 따라 정하면 됩니다.
CREATE TABLE dbo.SalesPerson 
(   EmpNo    smallint       NOT NULL,
    EmpName  varchar  (25)  NOT NULL 
CONSTRAINT  PK_SalesPerson  PRIMARY KEY CLUSTERED (EmpNo) )
GO
만일 테이블을 만들 때 깜빡하고 primary key 제약 조건을 만들어 주는 것을 잊어버리셨다 해도 슬퍼하지 마세요. ALTER TABLE이 있습니다.
ALTER TABLE SalesPerson
ADD CONSTRAINT PK_SalesPerson PRIMARY KEY CLUSTERED (EmpNo)
GO
그런데 가끔 primary key가 안 만들어진다고 하시는 분들이 계시는데, 이미 primary key 컬럼에 중복 값이 저장되어 있거나 아니면 primary key로 정의하고자 하는 컬럼 또는 컬럼들이 NULL 허용으로 정의되어 있기 때문입니다. Primary key 컬럼은 반드시 NOT NULL로 정의하셔야 합니다. Primary key 컬럼은 NOT NULL 이어야만 하며, (primary key를 만드는 데 장애물이 되지는 않습니다만) 길이가 짧고 변경이 발생하지 않는 컬럼이어야 합니다. Microsoft에 null 허용 컬럼에도 primary key를 만들 수 있도록 해 달라고 하셔도 소용없습니다. ^ ^  Primary key 값은 절대로 null이어서는 안된다는 규정은 ANSI에서 정의한 규정이기 때문입니다.
또 이런 경우도 있습니다. 테이블에 primary key가 만들어져 있기는 한데, 사족을 달고 있는 primaru key들도 종종 볼 수 있습니다. primary key는 행을 고유하게 구분하는데 필요한 최소의 컬럼만 포함시켜야 합니다. 그렇다면 primary key가 불필요한 사족을 달고 있으면 어떤 문제가 발생할까요? 가령 (로그인ID) 하나로도 primary key가 되는데 (로그인ID, 가입일자)라는 composite key를 primary key로 생성했다면 어떤 문제가 발생할지 한번 생각해 보셔요.


이 글을 공유하기

댓글

Designed by JB FACTORY