널은 속성의 값을 알수 없을때 사용하는 데이터 값이다. 데이터가 입력되는 시점을 기준으로, 값을 알 수 없을때 널을 사용한다. 널을 허용한 속성은 선택속성이다.
모른다는 의미에서 사용된 널값이지만, 언제가 알게될수도 있는것이다.
속성을 정확하게 모델링하기 위해서는 '모르는 것'과 '해당사항이 없는것' 을 구분할 필요가 있다.
'해당사항이 없는것'으로 널을 저장하는 속성은 해당엔터티에서 분리되는 것이 바람직하다. 나중에라도 값이 채워질수 없는 속성이라면 엔터티에서 제외해 1:1 관계로 분리하는 것이 원칙이다.
속성이 코드값을 사용할때는 적용할 수 없는 값과 알수 없는 값을 구분해 코드값 의미를 명확하게 설계해야 한다. '적용할 수 없음'이나 '해당사항없음'을 의미하는 코드값을 추가해서 사용해야 한다.
#주문번호 | 주문일자 | 주문상태유형코드 | 주문취소사유종류코드 |
1000 | 2023-01-01 | 1(주문취소) | 1(변심) |
1001 | 2023-03-01 | 2(배송중) | 0(해당없음) |
1002 | 2023-05-01 | 3(주문취소) | 9(모름) |
1003 | 2023-07-08 | 4(배송완료) | 0(해당없음) |
1004 | 2023-11-23 | 1(주문취소) | 2(불량) |
정상주문 '1001','1003' 번 주문은 취소상태가 아니므로 해당하는 주문취소사유종류코드 값이 존재할 수 없다.
주문취소사유종류코드값을 '0' 으로 정해 해당사항이 없다는 의미로 사용한다. 반면에 '1002'번 주문취소는 되었는데 사유를 모르는 경우다. 취소사유를 반드시 취득할 수 있는 것은 아니므로 모르는 값을 '9' 로 정해서 사용할 수 있다. 이렇게 '0'(해당없음) '9'(모름)는 의미하는 바가 다르므로 구분하여 사용하는 것이 바람직하다.널이 존재하는 속성이 많을때는 원천 엔터티에서 분리해서 별도의 엔터티에서 관리하는 것도 고려해야 한다. 특히 '해당없음'에 속성은 분리하는 것이 좋다.
널과 DBMS와 인덱스
속성의 널값은 값을 모를때/ 값이 없을때 구분하여 설계할 필요가 있다. DBMS에서는 가능하면 널값을 사용하지 않는 것이 좋다. 널값도 하나의 고유한 값이어서 쿼리에서 뜻하지 않게 사용될 수 있다. 특히 연산때!
대부분의 그룹함수는 널값을 연산대상으로 고려하지 않는다. 널값은 보통 인덱스에 포함되지 않는다. 널값에 대한 조회가 많고 널값이 저장된 인스턴스가 적다면, 속성에 널값을 허용하지 않고, 널값을 대신하는 기본값을 사용해야 한다. 기본값을 사용해 인덱스 스캔을 사용할수 있다. 반면에 널값이 저장된 인스턴스가 많다면 테이블 풀스캔을 유도하기 위해 실제 널값을 사용하는 것이 유리하다. 분포도가 낮은 속성은 테이블 풀스캔이 되도록 널값을 사용하는 것을 고려하고, 분포도가 높은 속성은 널값을 사용하지 않고 기본값을 사용해 인덱스 스캔이 되도록 해야 한다.
널값이 허용된 속성을 조회하는 쿼리에서 NVL구문을 사용하면 인덱스를 사용할 수 없게 된다. 초기에 데이터양 적을때는 문제가 없지만 데이터가 많아지면 치명적인 성능 결합이 발생 할수 있어 NVL 구문의 사용은 최소화 해야 한다.
NVL 구문은 CPU에도 영향을 미치므로 성능관점에서만 본다면 널값은 사용하지 않는 것이 최선의 선택이다.
널은 참조무결성 제약을 사용할 때도 주의를 해야 한다.
사원엔터티에 데이터가 입력될때 사원의 소속부서를 모른다고 가정하면, 소속부서번호 속성은 널 허용이 돼야 한다. 소속부서번호 속성에 참조무결성 제약을 생성했다고 널값을 사용하지 못하는 것은 아니다. 오히려 널을 허용하지 않고 기본값을 사용하면 문제가 생긴다. 상위엔터티에 존재하지 않는 ' '빈공간 같은 기본값을 사용할 수가 없다. 기본값을 생성하면 문제가 해결되겠지만 의미가 맞지 않다. 참조무결성제약을 사용한 관계속성이 업무적으로 널이 가능하면 널을 허용해야 한다.
외래식별자 속성에 널값이 존재할때는 아웃터 조인을 항상염두해두어야 한다. 널값이 조인에 참여하면 일반조인과 아웃터조인이 다른결과를 나타낸다는 점을 유의해야한다.
널값은 마이그레이션에서도 고려되어야한다. as-is 널값허용인데 to-be를 not null로 변경한다면 널값을 기본값으로 변경해야 한다.
널사용원칙은 운영중이 DBMS에서도 고려할 내용이이다. 널값 허용하지 않고, 기본값을 사용하는 원칙에 때라 운영중이 대용량 엔터티에 속성이 추가되는 상황을 고려해야 한다. 속성을 추가한 후 기본값으로 업데이트할때 많은 시간이 소요될 수 있고, 엔터티를 재생성햐여 할 수도 있으므로 운영측면을 고려해야 한다.
본질적인 면과 물리적인 면, 환경적인면을 고려하여 널허용여부를 결정해야 한다. 기본적으로 널을 허용하여 본질적으로 접근하고 물리적특성을 고려해야 할때는 널을 허용하지 않는 것이 바람직하다.
널 특징과 사용법
코드속성은 Not Null 로 지정하는 것이 좋다.
모르는 값이나 적용할 수 없는 상태를 나타낼때도 코드값을 지정해 사용하는 것이 좋다.
코드속성에 널값을 허용하면 쿼리구분에 널을 항상 고려해야한다.코드조인할 때도 널값을 고려하여 아웃터조인을 해야하고, 아웃터조인을 누락할수도 있어 불가피할때만 사용해야 한다. 코드값으로 집계 시 널값의 존재를 고려하지 않으면 집계가 틀릴수도 있고, 데이터무결성에 치명적일수 있다.
집계대상이 되는 속성은 널값을 사용하지 않는것이 바람직하다.
외래식별자속성은 널값 허용여부가 업무요건에 따라 결정된다. 만약 널 허용일때는 기본값을 사용하지 않아야 한다. 그 기본값은 참조되는 엔터티에 없을 것이므로 참조무결성관계가 성립하지 않기 때문이다.
금액을 저장하는 속성도 널값 사용을 주의해야 한다. 금액속성은 널허용하지 않는 것이 원칙인데, 기본값이 모호해질수있다. 논리적으로 모르는 값으 '0'으로 사용하면 실제 '0' 과 혼동된다. 그렇다고 널값을 허용하면 집계할때 원치않는 결과가 발생할 수 있다.
일자속성도 연산이 필요할 수 있다. 널으 ㄹ허용하지 않고 기본값을 사용할때는 '9999-12-31' 을 사용하자. 실제 일자를 의미하고 직관적으로 알수 있으며 연산도 가능하다.
이름 전화번호 주소등의 텍스트를 저장하는 속성은 널값을 사용해도 대게 문제가 없다. 업무요건에 따라 자유롭게 널값을 사용하면 된다.
엔터티에 널값을 가지는 속성은 가능한 없는것이 좋다. 널이 발생하는 속성은 일대일 엔터티로 분리한다. 인스턴스의 종류별로 속성집단이 널값을 가지거나 특히 해당없을 의미하는 값을 가진다면 서브타입을 도출해 널값이 생기지 않게 하는 것이 바람직하다. 널속성은 대체로 엔터티 하단에 위치시키는 것이 좋다.
·
구분 | 특징 | |
Null 허용 | 장점 | ·현행데이터그대로 마이그레이션기능 ·Null값이 인덱스에 포함안됨(Not null이면 기본값이 인덱스에 포함) ·분포도가 낮은 속성은 테이블 풀스캔이 되도록 함 ·Not Null제약이 없으므로 성능에 약간유리함 ·운영중 추가 속성이 발생해도 기본값에 대한 처리방안은 고려하지 않아도 됌 |
단점 | ·속성의 상세업무 요건 파악으로 모델링 시간이 증가(null 속성정의not null 속성정의, default값정의등 고려사항이 많음) ·속성의 null 처리 프로그래밍 혼선발생 ·NVL구문사용으로 성능문제발생 ·연산 집계요건이 있을때 원치 않는 결과 나올가능성 존대 |
|
Not Null | 장점 | ·일관된 모델을 유지할 수 있으며 모델링 시간이 단축됨 ·null값이 없으므로 null처리 프로그램이 수월 ·NVL처리로 인덱스 사용 못하게 되는 문제나 CPU를 많이 사용하는 문제없음 ·기본값 사용으로 인덱스 효용성 증대 |
단점 | ·업무요건에 최적화되지 않은 일관된 모델 ·현행데이터가 null인데 to-be not null일때 기본값사용으로 마이그레이션 복잡도 증가 ·운영중 추가속성이 발생했을때 기본값고려해야 하고, 운영부하 부담발생 |
모든속성에 널을 허용하거나 전부 널을 금지하는 것보다는 도메인이나 개별속성에 대한 판단으로 널 사용 원칙을 정하는것이 바람직하다.
'관계형데이터모데링노트 요약' 카테고리의 다른 글
관계 이야기 (0) | 2023.12.09 |
---|---|
속성 식별자 검증 (0) | 2023.12.05 |
데이터 타입 선정 원칙과 절차 (0) | 2023.12.03 |
도메인 (1) | 2023.12.03 |
속성명 (0) | 2023.12.02 |