CS/DB

기본키로 varchar2가 좋을까?

하이하이루루 2023. 7. 17. 12:32

가끔 DB 설계를 하다가 vachar2로 된 필드가 유니크 했으면 좋겠다는 생각에 varchar2 필드를 기본키로 하면 어떨까? 이런 생각이 든적이 있었습니다.

기본키로 varchar2가 좋을까?

varchar2와 number중 어떤 방법이 더 좋은지 알아보도록 하겠습니다.

 

일반적으로는 VARCHAR2 데이터 타입을 기본 키로 사용하는 것은 권장되지 않습니다. 기본 키는 각 행을 고유하게 식별하는 역할을 수행해야 하며, 대개 정수형 데이터 타입이나 GUID(UUID)와 같이 고유성과 성능 면에서 좋은 선택이 됩니다.

VARCHAR2 데이터 타입은 문자열을 저장하기 위한 데이터 타입으로, 길이가 가변적입니다. 이는 인덱스를 구성하는 데에 추가적인 오버헤드를 발생시킬 수 있고, 성능 저하를 가져올 수 있습니다. 또한, 문자열을 기반으로 한 정렬과 비교 연산에는 숫자형 데이터 타입보다 비용이 더 들기 때문에 검색 성능에도 영향을 줄 수 있습니다.

또한, VARCHAR2 기본 키의 길이가 큰 경우, 다른 테이블에서 해당 기본 키를 외래 키로 참조하는 경우에도 성능 문제가 발생할 수 있습니다.

따라서, 일반적으로는 문자열 형태의 데이터를 기본 키로 사용하기보다는 숫자형 기본 키나 GUID(UUID)를 고려하는 것이 좋습니다. 그러나 특정 상황이나 요구 사항에 따라 VARCHAR2 기본 키를 사용해야 하는 경우, 해당 열의 길이를 최소화하고 인덱스를 효율적으로 구성하여 성능 문제를 최소화해야 합니다.

 

그렇다면, '구분'이라는 컬럼에 's'라는 데이터가 1개 뿐만 존재해야 하는 경우는 어떡할까?

다음 3가지 방법을 들 수 있습니다.

 

1. 유니크 인덱스: 구분 열에 유니크 인덱스를 생성하여 중복된 값을 허용하지 않도록 합니다. 이렇게 하면 S 값이 한 번만 등장할 수 있게 됩니다.

CREATE UNIQUE INDEX YourIndexName ON YourTableName (구분) WHERE (구분 = 'S');

 

2. 체크 제약조건 및 함수 기반 인덱스: 체크 제약조건과 함수 기반 인덱스를 조합하여 S 값이 1개인지 확인할 수 있습니다. 체크 제약조건은 구분 열의 값이 'S'인 경우에만 적용되도록 설정하고, 함수 기반 인덱스를 사용하여 S 값이 1개인지 검색 성능을 향상시킬 수 있습니다.

ALTER TABLE YourTableName
ADD CONSTRAINT YourTableName_Check CHECK (구분 = 'S');

CREATE INDEX YourIndexName ON YourTableName (CASE WHEN 구분 = 'S' THEN 구분 ELSE NULL END);

 

3. 트리거: BEFORE INSERT 및 BEFORE UPDATE 트리거를 사용하여 구분 열에 S 값이 1개인지 확인하고, 추가 변경을 막을 수 있습니다. 이를 통해 S 값이 한 번만 존재하도록 제한할 수 있습니다.

CREATE OR REPLACE TRIGGER YourTriggerName
BEFORE INSERT OR UPDATE ON YourTableName
FOR EACH ROW
DECLARE
  cnt NUMBER;
BEGIN
  IF :NEW.구분 = 'S' THEN
    SELECT COUNT(*) INTO cnt FROM YourTableName WHERE 구분 = 'S';
    IF cnt >= 1 THEN
      RAISE_APPLICATION_ERROR(-20001, '구분 값 "S"는 이미 존재합니다.');
    END IF;
  END IF;
END;

위의 예시는 트리거를 사용하여 구분 열에 S 값이 이미 존재하는 경우, 추가 변경을 막는 방법을 보여줍니다.

각 방법은 목표를 달성하기 위한 다른 접근 방식을 제공합니다. 적합한 방법은 데이터베이스 설계와 요구 사항에 따라 다를 수 있으므로, 상황에 맞게 선택하십시오. 또한, 성능 및 관리 측면에서 영향을 주는 가능성도 고려해야 합니다.

 

3가지 방법 중 뭐가 제일 좋을까?

구분 열에 S 값이 1개만 존재하도록 하는 방법으로 유니크 인덱스, 체크 제약조건 및 함수 기반 인덱스, 트리거를 예시로 드렸는데, 보편적으로 가장 많이 사용되는 방법은 유니크 인덱스입니다. 유니크 인덱스는 중복된 값을 허용하지 않고, 효율적으로 중복 체크를 수행할 수 있기 때문에 많은 상황에서 선호되는 방식입니다.

체크 제약조건과 함수 기반 인덱스를 사용하는 방법도 유효한 방법이지만, 일반적으로는 유니크 인덱스가 더 많이 사용됩니다. 유니크 인덱스는 데이터베이스 시스템에서 기본 지원하는 기능이기 때문에 구현이 간단하고 성능 측면에서도 효율적입니다.

트리거는 데이터의 변경을 감지하고 제어하기 위해 사용되는 기능이지만, 사용에 주의해야 합니다. 트리거는 데이터베이스의 리소스를 사용하며, 트리거의 작동 로직에 따라 성능 저하나 잠재적인 오류가 발생할 수 있습니다. 따라서 트리거를 사용하기 전에 잘 고려하고 테스트해야 합니다.

리소스 낭비의 가능성이 있는 트리거보다는 유니크 인덱스를 사용하는 것이 일반적으로 더 효율적입니다. 그러나 특정 상황이나 요구 사항에 따라 트리거를 사용해야 할 수도 있습니다. 트리거를 사용할 경우에는 성능과 리소스 사용에 대한 주의가 필요하며, 신중하게 구현하고 테스트해야 합니다.