데이터베이스에서 고유 인덱스를 생성하는 것은 데이터 무결성을 보장하기 위해 중요한 작업입니다. 하지만 NULL 값이 포함된 컬럼에 대해 고유 인덱스를 생성할 때, SQL과 NoSQL이 어떻게 다르게 동작하는지 알고 계신가요? 이번 포스트에서는 MongoDB, PostgreSQL, Oracle 데이터베이스를 예로 들어 NULL 값 처리와 고유 인덱스 동작 방식을 비교해보겠습니다.
NoSQL의 NULL 처리: MongoDB
MongoDB에서는 NULL이 값의 부재(absence)를 나타냅니다. 고유 인덱스를 생성할 경우, 동일한 NULL 값을 가진 두 문서는 중복으로 간주되어 에러를 발생시킵니다. 예를 들어, 다음과 같은 고유 인덱스를 생성한다고 가정합니다:
db.calls.createIndex({ "time": 1, "callee": 1, "caller": 1 }, { unique: true });
이 인덱스는 time
, callee
, caller
필드 조합이 중복되지 않도록 보장합니다. 만약 caller
값이 NULL인 두 개의 문서를 삽입하려고 하면 중복 키 에러가 발생합니다. 이를 해결하기 위해 MongoDB에서는 부분 인덱스(Partial Index)를 사용하여 특정 조건을 만족하는 문서만 인덱싱할 수 있습니다.
SQL의 NULL 처리: PostgreSQL
SQL 표준에서는 NULL을 "알 수 없는 값"으로 간주합니다. PostgreSQL에서는 NULL 값이 포함된 컬럼은 고유 제약 조건을 위반하지 않습니다. 즉, NULL 값은 비교할 수 없는 값으로 간주되기 때문에, 동일한 NULL 값을 가진 여러 행을 삽입할 수 있습니다. 하지만 PostgreSQL 15 이상에서는 NULLS NOT DISTINCT
옵션을 사용해 NULL 값을 중복으로 간주하도록 고유 인덱스를 생성할 수 있습니다:
CREATE UNIQUE INDEX calls_unique_index ON calls (time, callee, caller) NULLS NOT DISTINCT;
이 옵션을 사용하면 NULL 값도 중복 검사를 받게 됩니다.
Oracle의 NULL 처리
Oracle은 MongoDB와 유사하게 NULL 값을 처리합니다. 즉, 동일한 NULL 값을 가진 두 행은 중복으로 간주되어 에러를 발생시킵니다. 하지만 Oracle은 SQL 표준과는 다르게 NULL 값이 포함된 인덱스를 기본적으로 부분 인덱스로 처리합니다. 이를 해결하기 위해 NVL 함수 등을 활용해 NULL 값을 대체하는 방식으로 고유 인덱스를 생성할 수 있습니다:
CREATE UNIQUE INDEX calls_time_callee_caller_idx ON calls (time, callee, NVL(caller, id));
이 방식은 NULL 값을 고유 제약 조건에서 제외하는 효과를 제공합니다.
데이터베이스 선택 시 고려 사항
각 데이터베이스는 NULL 값을 처리하는 방식과 고유 인덱스 동작이 다릅니다. 따라서 데이터베이스를 선택하거나 마이그레이션할 때 이러한 차이를 이해하고 적절히 대응하는 것이 중요합니다. MongoDB는 개발자 친화적인 API와 직관적인 NULL 처리 방식을 제공하지만, SQL 표준을 따르는 PostgreSQL은 더 정교한 제어 옵션을 제공합니다. 반면 Oracle은 전통적인 방식과 호환성을 유지하면서도 유연한 NULL 처리 옵션을 제공합니다.
결론
NULL 값 처리는 데이터베이스 설계에서 간과하기 쉬운 부분이지만, 데이터 무결성과 중복 방지에 큰 영향을 미칩니다. 각 데이터베이스의 NULL 처리 방식을 이해하고, 필요에 따라 고유 인덱스 설정을 조정하세요. 이를 통해 데이터베이스의 동작 방식을 예측 가능하게 만들고, 오류를 최소화할 수 있습니다.
관련 링크
'데이터베이스' 카테고리의 다른 글
LeetCode SQL 50 챌린지 리뷰 초보자를 위한 SQL 학습의 첫걸음 (0) | 2025.02.06 |
---|