왜 NULL을 허용해서는 안됩니까? 필드 속성이 있어야한다고

데이터베이스 디자인에 대한이 기사를 읽은 것을 기억하고 NOT NULL의 필드 속성이 있어야한다고 기억합니다. 나는 이것이 왜 그런지 기억하지 못한다.

내가 생각할 수있는 것은 응용 프로그램 개발자로서 NULL 존재하지 않는 데이터 값 (예 : 문자열의 빈 문자열) 을 테스트 할 필요가 없다는 것 입니다.

그러나 날짜, 날짜 시간 및 시간 (SQL Server 2008)의 경우 어떻게합니까? 과거 또는 최저 날짜를 사용해야합니다.

이것에 대한 아이디어가 있습니까?



답변

나는 그 단어가 이미 NULL을 잘못 결정했다고 암시하기 때문에 질문이 잘못 표현되었다고 생각합니다. 아마도 “NULL을 허용해야합니까?”라는 의미 일 것입니다.

어쨌든, 여기에 내가 취하는 것이 있습니다 : NULL은 좋은 것 같습니다. “NULLs bad”또는 “NULLs hard”로 인해 NULL을 막기 시작하면 데이터를 만들기 시작합니다. 예를 들어, 생년월일을 모른다면 어떻게해야합니까? 알 때까지 란에 무엇을 넣을 것인가? NULL이 아닌 많은 사람들과 같은 사람이라면 1900-01-01을 입력하십시오. 이제 노인 병동에 갇히게 될 것입니다. 아마도 지역 뉴스 방송국에서 전화를 받아 장수를 축하하며 저의 긴 생애 등에 대한 비밀을 묻습니다.

열의 값을 모르는 곳에 행을 입력 할 수 있다면 NULL은 알 수없는 사실을 나타내는 임의의 토큰 값을 선택하는 것보다 훨씬 의미가 있다고 생각합니다. 이미 알고 있거나, 리버스 엔지니어링하거나, 그 의미를 파악하도록 요구해야합니다.

그러나 데이터 모델의 모든 열이 널 입력 가능하지는 않아야합니다. 폼에는 선택적인 필드가 있거나 행을 만들 때 수집되지 않은 정보가 종종 있습니다. 그렇다고해서 모든 데이터를 채우는 것을 연기 할 수있는 것은 아닙니다 . 🙂

또한 NULL을 사용하는 기능은 실제 생활에서 중요한 요구 사항에 의해 제한 될 수 있습니다. 예를 들어, 의료 분야에서 가치를 알 수없는 이유 를 아는 것은 생명과 죽음의 문제 일 수 있습니다. 맥박이 없었거나 아직 측정하지 않았기 때문에 심박수가 NULL입니까? 그러한 경우, 우리는 심박수 열에 NULL을 넣을 수 있고, NULL이기 때문에 메모 또는 다른 열을 가질 수 있습니까?

NULL을 두려워하지 말고 언제 어디서 사용해야하는지, 언제 어디서 사용하지 않아야하는지 배우거나 지시하십시오.


답변

확립 된 이유는 다음과 같습니다.

  • NULL은 값이 아니므로 고유 한 데이터 유형이 없습니다. 널 (null) 은 실제 유형에 의존하는 코드가 유형화되지 않은 널 (NULL)을 수신 할 때 모든 곳에서 특별한 처리 가 필요 합니다.

  • NULL은 2 값 (친숙한 True 또는 False) 논리를 위반하며 3 값 논리가 필요합니다. 이것은 심지어 올바르게 구현하기에는 훨씬 더 복잡하며, 대부분의 DBA와 거의 모든 비 DBA에 의해 잘 이해되지 않습니다. 결과적으로 응용 프로그램에서 많은 미묘한 버그 를 적극적으로 초대 합니다.

  • 특정 NULL의미 적 의미 는 실제 값과 달리 응용 프로그램에 남겨집니다 .

    “해당 사항 없음”및 “알 수 없음”및 “감시자”와 같은 의미론이 일반적이며 다른 사항도 있습니다. 동일한 관계 내에서도 동일한 데이터베이스 내에서 동시에 자주 사용됩니다. 물론 명백 하고 구별 할 수없고 양립 할 수없는 의미입니다.

  • 그들은 관계형 데이터베이스에 필요하지 않습니다 에 주장으로, “널 (null)없이 정보를 누락 처리하는 방법” . 추가 정규화는 NULL 테이블을 제거하는 명백한 첫 번째 단계입니다.

이것은 NULL이 절대 허용되지 않아야한다는 의미는 아닙니다. 그것은 않습니다 어디든지 가능 NULL을 허용하는 많은 좋은 이유가 있다고 주장한다.

중요한 것은 더 나은 스키마 디자인, 더 나은 데이터베이스 엔진 및 더 나은 데이터베이스 언어 를 통해 NULL을 더 자주 피할 수 있도록 노력 하는 것입니다.

Fabian Pascal은 “Nulls Nullified” 에서 여러 가지 인수에 응답합니다 .


답변

동의하지 않습니다. null은 데이터베이스 디자인의 필수 요소입니다. 대안은 당신이 언급 한 바와 같이, 누락되거나 알려지지 않은 알려진 값의 확산 일 것입니다. 문제는 널 (null)이 너무 널리 오해되어 부적절하게 사용되는 것입니다.

IIRC, Codd는 현재 존재하지 않는 (현재 존재하지 않거나 누락 된) 구현은 “존재하지 않지만 적용 가능하지 않음”과 “존재하지 않고 적용 할 수 없음”이 아닌 두 개의 널 마커를 사용함으로써 개선 될 수 있다고 제안했다. 이를 통해 관계형 디자인이 어떻게 향상 될지 상상할 수 없습니다.


답변

DBA가 아니라, 개발자이며, 필요에 따라 데이터베이스를 유지 관리하고 업데이트한다고 말하면서 시작하겠습니다. 즉, 몇 가지 이유로 같은 질문이있었습니다.

  1. 값이 널이면 개발이 더 어려워지고 버그가 발생하기 쉽습니다.
  2. Null 값은 쿼리, 저장 프로 시저 및 뷰를보다 복잡하고 버그가 발생하기 쉽습니다.
  3. 널값은 공간을 차지합니다 (고정 열 길이에 따라? 바이트 또는 가변 열 길이에 대해 2 바이트).
  4. 널값은 색인 작성 및 수학에 영향을 줄 수 있으며 종종 영향을줍니다.

인터넷을 통해 많은 답변, 의견, 기사 및 조언을 조사하는 데 오랜 시간을 소비했습니다. 말할 필요도없이 대부분의 정보는 @AaronBertrand의 답변과 거의 동일했습니다. 그렇기 때문에이 질문에 대답해야한다고 생각했습니다.

먼저 미래의 모든 독자를 위해 무언가를 똑바로 설정하고 싶습니다 … NULL 값은 사용되지 않은 데이터가 아닌 알 수없는 데이터를 나타냅니다. 종료 날짜 필드가있는 직원 테이블이있는 경우 종료일의 널값은 현재 알려지지 않은 미래의 필수 필드이기 때문입니다. 모든 직원이 활동 중이거나 해고되면 어느 시점에서 해당 필드에 날짜가 추가됩니다. 그것이 제 생각에는 널 입력 가능 필드의 유일한 이유입니다.

동일한 직원 테이블에 일종의 인증 데이터가있을 가능성이 높습니다. 엔터프라이즈 환경에서 직원이 HR 및 회계 용 데이터베이스에 나열되는 것이 일반적이지만 인증 세부 정보가 항상 있거나 필요하지는 않습니다. 대부분의 응답으로 해당 필드를 무효화하거나 계정을 만들지 만 자격 증명을 보내지 않는 것이 좋습니다. 전자는 개발 팀이 NULL을 확인하고 그에 따라 처리하는 코드를 작성하게하므로 후자는 큰 보안 위험을 초래합니다! 시스템에서 아직 사용되지 않은 계정은 해커의 가능한 액세스 지점 수만 증가 시키며, 사용하지 않은 무언가를 위해 귀중한 데이터베이스 공간을 차지합니다.

위의 정보를 감안할 때 사용되는 널 입력 가능 데이터를 처리하는 가장 좋은 방법은 널 입력 가능 값을 허용하는 것입니다. 슬프지만 사실이며 개발자가 당신을 미워할 것입니다. 두 번째 유형의 널 입력 가능 데이터는 관련 테이블 (IE : 계정, 신임 정보 등)에 넣고 일대일 관계를 가져야합니다. 이를 통해 사용자는 필요하지 않은 경우 자격 증명없이 존재할 수 있습니다. 이는 추가 보안 위험과 귀중한 데이터베이스 공간을 제거하고 훨씬 더 깨끗한 데이터베이스를 제공합니다.

아래는 필요한 nullable 열과 일대일 관계를 모두 보여주는 매우 간단한 테이블 구조입니다.

알 수없는 Nullable 및 일대일 관계

나는이 질문이 몇 년 전에 요청 된 이후로 파티에 조금 늦었다는 것을 알고 있지만, 이것이이 문제와 그 문제를 다루는 가장 좋은 방법을 밝히는 데 도움이되기를 바랍니다.


답변

NULL 혼란스러운 개발자의 모든 문제 외에도 NULL은 또 다른 심각한 단점이 있습니다.

NULL을 허용하는 열은 성능 측면에서 재앙입니다. 예를 들어 정수 산술을 고려하십시오. NULL이없는 제정신 세계에서는 SIMD 명령어를 사용하여 데이터베이스 엔진 코드에서 정수 산술을 벡터화하여 CPU 사이클 당 1 행보다 빠른 속도로 거의 모든 계산을 수행하는 것이 “쉽습니다”. 그러나 NULL을 도입하는 순간 NULL이 생성하는 모든 특수한 경우를 처리해야합니다. 최신 CPU 명령어 세트 (읽기 : x86 / x64 / ARM 및 GPU 논리도)는이 작업을 효율적으로 수행 할 수 없습니다.

예를 들어 나누기를 고려하십시오. 매우 높은 수준에서 이것은 null이 아닌 정수로 필요한 논리입니다.

if (b == 0)
  do something when dividing by error
else
  return a / b

NULL을 사용하면 조금 까다로워집니다. 함께 null에 대해 비슷하게 b표시가 필요합니다 . 이제 수표가됩니다 :ba

if (b_null_bit == NULL)
   return NULL
else if (b == 0) 
   do something when dividing by error
else if (a_null_bit == NULL)
   return NULL
else 
   return a / b

널 (null) 산술은 널이 아닌 산술 (약 2-3 배의 계수)보다 최신 CPU에서 실행하는 것이 훨씬 느립니다.

SIMD를 도입하면 상황이 악화됩니다. SIMD를 사용하면 최신 Intel CPU는 다음과 같이 단일 명령으로 4 x ​​32 비트 정수 나누기를 수행 할 수 있습니다.

x_vector = a_vector / b_vector
if (fetestexception(FE_DIVBYZERO))
   do something when dividing by zero
return x_vector;

SIMD 랜드에서도 NULL을 처리하는 방법이 있지만 더 많은 벡터와 CPU 레지스터를 사용하고 영리한 비트 마스킹을 수행해야합니다. 좋은 트릭을 사용하더라도 NULL 정수 산술의 성능 패널티는 비교적 간단한 표현을 위해 5-10 배 느린 범위로 들어갑니다.

위와 같은 것은 집계와 어느 정도의 조인에도 적용됩니다.

다시 말해, SQL에서 NULL이 존재한다는 것은 데이터베이스 이론과 현대 컴퓨터의 실제 디자인 사이의 임피던스 불일치입니다. NULL이 개발자를 혼란스럽게하는 데는 꽤 좋은 이유가 있습니다. 대부분의 정상적인 프로그래밍 언어에서는 정수가 NULL 일 수 없기 때문에 컴퓨터가 작동하는 방식이 아닙니다.


답변

흥미로운 질문들.

내가 생각할 수있는 것은 응용 프로그램 개발자로서 NULL 및 존재하지 않는 가능한 데이터 값 (예 : 문자열의 빈 문자열)을 테스트 할 필요가 없다는 것입니다.

그것보다 더 복잡합니다. Null에는 여러 가지 고유 한 의미가 있으며 많은 열에서 null을 허용하지 않는 중요한 이유는 열이 null 일 때 단 하나만 의미하기 때문입니다 (즉, 외부 조인에 표시되지 않음). 또한 매우 유용한 데이터 입력 표준을 설정할 수 있습니다.

그러나 날짜, 날짜 시간 및 시간 (SQL Server 2008)의 경우 어떻게합니까? 과거 또는 최저 날짜를 사용해야합니다.

즉, 테이블에 저장된 값이 “이 값이 적용되지 않음”또는 “알지 못함”을 의미 할 수있는 널 (null) 문제가 있음을 나타냅니다. 문자열을 사용하면 빈 문자열은 “적용되지 않음”으로 사용할 수 있지만 날짜와 시간에는 일반적으로이를 의미하는 유효한 값이 없기 때문에 이러한 규칙이 없습니다. 일반적으로 NULL을 사용하여 고정됩니다.

더 많은 관계를 추가하고 조인 하여이 문제를 해결할 수있는 방법이 있지만 데이터베이스에 NULL을 갖는 것과 동일한 의미 론적 명확성 문제가 있습니다. 이 데이터베이스의 경우 걱정하지 않아도됩니다. 실제로 할 수있는 일은 없습니다.

편집 : NULL 없어야 영역 중 하나 는 외래 키입니다. 여기서는 일반적으로 외부 조인 의미의 null과 동일한 하나의 의미를 갖습니다. 이것은 물론 문제에 대한 예외입니다.


답변

SQL Null에 대한 Wikipedia의 기사 에는 NULL 값에 대한 흥미로운 설명이 있으며 특정 RDBMS에 NULL 값을 갖는 잠재적 영향을 알고있는 한 데이터베이스에 무관 한 답으로 설계에 적용 할 수 있습니다. 그렇지 않은 경우 열을 널 입력 가능으로 지정할 수 없습니다.

RDBMS가 수학과 같은 SELECT 작업과 인덱스에서 RDBMS를 처리하는 방법을 알고 있어야합니다.