Почему мы не должны разрешать NULL?

Я помню, как читал эту статью о дизайне базы данных, и я также помню, что он сказал, что у вас должны быть полевые свойства NOT NULL. Я не помню, почему это было так.

Все, что я могу представить, это то, что в качестве разработчика приложений вам не нужно было бы проверять для NULL и возможное несуществующее значение данных (например, пустую строку для строк) .

Но что вы делаете в случае дат, времени и времени (SQL Server 2008)? Вам придется использовать историческую или нижнюю дату.

Любые идеи по этому поводу?

103 голоса | спросил Thomas Stringer 31 AM00000010000003931 2011, 01:11:39

8 ответов


204

Я думаю, что этот вопрос плохо сформулирован, поскольку формулировка подразумевает, что вы уже решили, что NULL - это плохо. Возможно, вы имели в виду «Должны ли мы разрешать NULL?»

В любом случае, вот мой пример: я думаю, что NULL - это хорошо. Когда вы начинаете предотвращать NULL только потому, что «NULL are bad» или «NULLs are hard», вы начинаете составлять данные. Например, что, если вы не знаете дату своего рождения? Что вы собираетесь вставить в колонку, пока не узнаете? Если вы похожи на множество людей с анти-NULL, вы собираетесь ввести 1900-01-01. Теперь меня посадят в гериатрическую палату и, вероятно, позвоните из моей местной новостной станции, поздравляя меня с моей долгой жизнью, спрашивая у меня мои секреты жизни такой долгой жизни и т. Д.

Если строка может быть введена там, где возможно, что вы не знаете значение столбца, я думаю, что NULL имеет гораздо больше смысла, чем выбор некоторых произвольное значение токена, чтобы представить тот факт, что он неизвестен - значение, которое другие должны будут знать, реконструировать или спросить, чтобы выяснить, что это значит.

Существует баланс, однако - не каждый столбец в вашей модели данных должен иметь значение NULL. Часто есть необязательные поля в форме или части информации, которые в противном случае не собираются в момент создания строки. Но это не означает, что вы можете отложить заполнение данных all . : -)

Также возможность использования NULL может быть ограничена критическими требованиями в реальной жизни. Например, в медицинской области может быть вопрос жизни или смерти, чтобы знать , почему значение неизвестно. Является ли частота сердечных сокращений NULL, потому что не было пульса, или потому, что мы еще не измерили его? В таком случае мы можем положить NULL в столбце сердечного ритма и записать заметки или другой столбец с NULL-причиной?

Не бойтесь NULL, но будьте готовы учиться или диктовать, когда и где их следует использовать, и когда и где они не должны.

ответил Aaron Bertrand 31 AM00000030000000231 2011, 03:01:02
46

Установленные причины:

  • NULL не является значением и поэтому не имеет встроенного типа данных. Нумерам нужна специальная обработка по всему месту , когда код, который в противном случае полагается на фактические типы, может также получить непечатаемый NULL.

  • NULL ломает двухзначную (знакомая True или False) логику и требует трехзначную логику. Это намного сложнее даже для правильной реализации и, безусловно, плохо понимается большинством администраторов баз данных и практически всех не-администраторов баз данных. Как следствие, он положительно приглашает множество тонких ошибок в приложении.

  • Значение семантического значения любого конкретного NULL остается в приложении , в отличие от фактических значений.

    Семантики, такие как «неприменимо» и «неизвестные» и «центральные», являются общими, и есть и другие. Они часто используются одновременно в одной и той же базе данных, даже в том же отношении; и, конечно, неявные и неразличимые и несовместимые значения .

  • Они не нужны реляционным базам данных , как указано в « Как обращаться с отсутствующей информацией без нулей ». Дальнейшая нормализация является очевидным первым шагом, чтобы попытаться избавиться от таблицы NULL.

Это не означает, что NULL никогда не допускается. Он делает утверждают, что есть много веских причин, чтобы запретить NULL, где это возможно.

Важно отметить, что он пытается изо всех сил стараться - лучше разработать схему и улучшить работу с базами данных, а еще лучше использовать языки баз данных - сделать , чтобы избежать NULL чаще.

Фабиан Паскаль отвечает на ряд аргументов, в «Nulls Nullified» .

ответил bignose 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 07:08:00 +0400 2011, 07:08:00
27

Я не согласен, нули являются важным элементом проектирования базы данных. Альтернатива, как вы уже говорили, будет распространением известных ценностей, представляющих недостающие или неизвестные. Проблема заключается в том, что нуль становится настолько непонятным и в результате используется ненадлежащим образом.

IIRC, Кодд предположил, что текущая реализация null (то есть отсутствие /отсутствие) может быть улучшена за счет наличия двух нулевых маркеров, а не одного, «нет, но применимо» и «нет и не применимо». Невозможно предусмотреть, каким образом реляционные проекты будут улучшены этим лично.

ответил Mark Storey-Smith 31 AM00000010000005731 2011, 01:32:57
11

Позвольте мне начать с того, что я не являюсь администратором баз данных, я разработчик наизусть, и я поддерживаю и обновляю наши базы данных на основе наших потребностей. При этом у меня был тот же вопрос по нескольким причинам.

  
  1. Нулевые значения затрудняют разработку и подверженность ошибкам.
  2.   
  3. Нулевые значения делают запросы, хранимые процедуры и представления более сложными и подвержены ошибкам.
  4.   
  5. Нулевые значения занимают пространство (? байты на основе фиксированной длины столбца или 2 байта для переменной длины столбца).
  6.   
  7. Нулевые значения могут и часто влияют на индексирование и математику.
  8.   

Я провожу очень много времени, просеивая множество ответов, комментариев, статей и советов по всему Интернету. Излишне говорить, что большая часть информации была примерно такой же, как ответ @ AaronBertrand. Вот почему я почувствовал необходимость ответить на этот вопрос.

Во-первых, я хочу установить что-то прямое для всех будущих читателей ... Значения NULL представляют неизвестные данные НЕ неиспользуемые данные. Если у вас есть таблица сотрудников, у которой есть поле даты окончания. Нулевое значение в дате окончания - это то, что оно является будущим обязательным полем, которое в настоящее время неизвестно. Каждый сотрудник, будь он активным или прекращенным, в какой-то момент добавит дату в это поле. Это, на мой взгляд, единственная причина для поля Nullable.

При этом одна и та же таблица сотрудников, скорее всего, проведет какие-то данные аутентификации. Обычно в корпоративной среде сотрудники будут перечислены в базе данных для управления персоналом и учета, но не всегда имеют или нуждаются в деталях аутентификации. Большинство ответов заставили бы вас поверить, что это нормально, чтобы удалить эти поля или в некоторых случаях создать учетную запись для них, но никогда не отправлять им учетные данные. Первая заставит вашу команду разработчиков написать код, чтобы проверить NULL и соответствующим образом разобраться с ним, а последний представляет собой огромный риск для безопасности! Учетные записи, которые еще никогда не используются в системе, только увеличивают количество возможных точек доступа для хакера, плюс они занимают ценное пространство базы данных для того, что никогда не используется.

Учитывая приведенную выше информацию, лучший способ справиться с нулевыми данными, которые будут использоваться, - это разрешить значения с нулевым значением. Это печально, но верно, и ваши разработчики будут ненавидеть вас за это. Второй тип нулевых данных должен быть помещен в связанную таблицу (IE: учетная запись, учетные данные и т. Д.) И иметь отношения «один-к-одному». Это позволяет пользователю существовать без учетных данных, если только они не нужны. Это устраняет дополнительный риск безопасности, ценное пространство базы данных и обеспечивает гораздо более чистую базу данных.

Ниже представлена ​​очень упрощенная структура таблицы, показывающая как нулевую колонку, так и отношения «один-к-одному».

Неизвестные отношения Nullable and One-to-One

Я знаю, что я немного опаздываю на вечеринку, так как этот вопрос задавался много лет назад, но, надеюсь, это поможет пролить свет на эту проблему и как лучше всего справиться с ней.

ответил Nicholas Aguirre 10 WedEurope/Moscow2014-12-10T00:10:52+03:00Europe/Moscow12bEurope/MoscowWed, 10 Dec 2014 00:10:52 +0300 2014, 00:10:52
10

Интересные вопросы.

  

Все, что я могу представить, это то, что в качестве разработчика приложения вам не нужно было бы тестировать NULL и возможное несуществующее значение данных (например, пустую строку для строк).

Это сложнее, чем это. Null имеет ряд различных значений, и одна действительно важная причина не допускать, чтобы нули во многих столбцах заключались в том, что когда столбец имеет значение null, это означает одно и только одно (а именно, что оно не отображалось во внешнем соединении). Кроме того, это позволяет вам установить минимальные стандарты ввода данных, которые действительно полезны.

  

Но что вы делаете в случае дат, времени и времени (SQL Server 2008)? Вам придется использовать историческую или нижнюю дату.

Это иллюстрирует проблему с нулями сразу, а именно, что значение, хранящееся в таблице, может означать либо «это значение не применяется», либо «мы не знаем». С строками пустая строка может служить как «это не применяется», но с датами и временем, такого соглашения нет, потому что нет допустимого значения, которое обычно означает это. Как правило, вы будете застревать с помощью NULL.

Есть способы обойти это (добавив больше отношений и присоединения), но они представляют собой те же самые проблемы с семантической ясностью, которые имеют NULL в базе данных. Для этих баз данных я бы не стал беспокоиться об этом. На самом деле вы ничего не можете с этим поделать.

EDIT: одна область, где NULL обязательна, находится во внешних ключах. Здесь они обычно имеют только одно значение, идентичное нулевому значению в значении внешнего соединения. Это, конечно, исключение из проблемы.

ответил Chris Travers 23 FebruaryEurope/MoscowbSat, 23 Feb 2013 18:08:15 +0400000000pmSat, 23 Feb 2013 18:08:15 +040013 2013, 18:08:15
9

статья Википедии о SQL Null содержит некоторые интересные замечания о значении NULL, и как ответ агностики базы данных, если вы знаете о потенциальном влиянии наличия значений NULL для вашей конкретной РСУБД, они приемлемы в вашем дизайне. Если бы они не были, вы не смогли бы указать столбцы как обнуляемые.

Просто знайте, как ваша RDBMS обрабатывает их в операциях SELECT, таких как математика, а также в индексах.

ответил Derek Downey 31 AM00000010000004431 2011, 01:34:44
8

Помимо всех проблем с запуском NULL, у NULL есть еще один очень серьезный недостаток: Производительность

Столбцы NULL'able - это катастрофа с точки зрения производительности. Рассмотрим пример арифметики целых чисел. В разумном мире без NULL «легко» векторизовать целочисленную арифметику в коде двигателя базы данных с помощью инструкций SIMD для выполнения практически любых вычислений со скоростью быстрее, чем 1 строка за цикл ЦП. Однако в тот момент, когда вы вводите NULL, вам нужно обрабатывать все особые случаи, которые создает NULL. Современные наборы команд процессора (чтение: x86 /x64 /ARM и GPU-логика тоже) просто не оснащены, чтобы сделать это эффективно.

Рассмотрим деление как пример. На очень высоком уровне это логика, которая вам нужна с непустым целым числом:

if (b == 0)
  делать что-то при делении по ошибке
еще
  return a /b

С NULL это становится немного сложнее. Вместе с b вам понадобится индикатор, если b имеет значение null и аналогично для a. Теперь проверка:

if (b_null_bit == NULL)
   return NULL
else if (b == 0)
   делать что-то при делении по ошибке
else if (a_null_bit == NULL)
   return NULL
еще
   return a /b

Арифметика NULL значительно медленнее запускается на современном процессоре, чем не нулевая арифметика (в 2-3 раза).

Усиливается, когда вы вводите SIMD. С помощью SIMD современный процессор Intel может выполнять 4 х 32-разрядных целочисленных деления в одной команде, например:

x_vector = a_vector /b_vector
if (fetestexception (FE_DIVBYZERO))
   делать что-то при делении на ноль
return x_vector;

Теперь есть способы обрабатывать NULL на территории SIMD, но для этого требуется использование большего количества векторов и регистров процессора, а также умная маскировка бит. Даже при хороших трюках оценка производительности NULL целочисленной арифметики ползает в 5-10x более медленном диапазоне для даже относительно простых выражений.

То же, что и выше, выполняется для агрегатов и в некоторой степени для объединений.

Другими словами: существование NULL в SQL является несоответствием импеданса между теорией базы данных и фактическим дизайном современных компьютеров. Существует довольно веская причина, по которой NULL смущает разработчиков - потому что целое число не может быть NULL на самых разумных языках программирования - это просто не то, как работают компьютеры.

ответил Thomas Kejser 4 PMpMon, 04 Apr 2016 17:31:40 +030031Monday 2016, 17:31:40
-10

Ничего себе, правильный ответ «Не разрешать NULL, когда вам не нужно, потому что они ухудшают производительность» - это как-то последний рейтинг. Я буду продвигать его и разработать. Когда RDBMS разрешает NULL для нерезкого столбца, этот столбец добавляется в растровое изображение, которое отслеживает, является ли значение NULL для каждой отдельной строки. Таким образом, добавляя NULL-способность к столбцу в таблице, где все столбцы не допускают NULL, вы увеличиваете пространство для хранения, необходимое для сохранения таблицы. Кроме того, вам требуется, чтобы RDBMS читала и записывала в растровое изображение, ухудшая производительность при всех операциях.

Кроме того, в ряде случаев разрешающие NULL будут прерывать 3NF. Хотя я не сторонник 3NF, как многие мои коллеги, рассмотрим следующий сценарий:

В таблице Person есть столбец, называемый DateOfDeath, который является нулевым. Если человек умер, он будет заполнен их DateOfDeath, иначе он будет оставлен NULL. Также есть столбец с битами, не содержащий NULL, называемый IsAlive. Этот столбец установлен в 1, если человек жив, и 0, если человек мертв. Подавляющее большинство хранимых процедур используют столбец IsAlive, они заботятся только о том, жив ли человек, а не в DateOfDeath.

Однако столбец IsAlive нарушает нормализацию базы данных, поскольку он полностью выводится из DateOfDeath. Но поскольку IsAlive является жестко подключенным к большинству SP, прямое решение заключается в том, чтобы сделать DateOfDeath непустым и присвоить значение по умолчанию столбцу в случае, если человек все еще жив. Несколько SP, которые используют DateOfDeath, могут быть переписаны, чтобы проверить столбец IsAlive, и только честь DateOfDeath, если человек не жив. Опять же, поскольку большинство SPs заботятся только об IsAlive (бит), а не DateOfDeath (дата), используя этот шаблон, значительно ускоряет доступ.

Полезный сценарий T-SQL для поиска столбцов с нулевым значением без NULL во всех схемах:

выберите 'IF NOT EXISTS (SELECT 1 FROM' + QUOTENAME (s.name) + '.' + QUOTENAME (t.name) + 'WHERE' + QUOTENAME (c.name) + 'IS NULL)
    И (SELECT COUNT (*) FROM '+ QUOTENAME (s.name) +'. '+ QUOTENAME (t.name) +')> 1 PRINT '' '+ s.name +'. ' + t.name + '.' + REPLACE (c.name, '' '', '' '' '') + '' ''
    из sys.columns c
    внутреннее соединение sys.tables t ON c.object_id = t.object_id
    внутреннее соединение sys.schemas s ON s.schema_id = t.schema_id
    где c.is_nullable = 1 AND c.is_computed = 0
    порядок по s.name, t.name, c.name;

Если вы запустите это на копии своей производственной базы данных, вы можете найти разработчиков столбцов, помеченных как позволяющие NULL, которые на практике не имеют NULL. Подавляющее большинство из них могут быть отмечены как NOT NULL, что повышает производительность и снижает пространство для хранения.

Возможно, не удастся устранить все NULL во всех таблицах и по-прежнему иметь чистый дизайн, но есть значительное преимущество в устранении как можно большего количества NULL. Оптимизатор работает намного быстрее с этой информацией, и если вы можете устранить все NULL в таблице, вы можете восстановить значительный объем пространства для хранения.

Я знаю, что производительность - это не то, что администраторы баз данных думают обо всем этом, но вы можете бросить ограниченное количество памяти и мощности процессора на решение, в какой-то момент вам придется начать думать о логическом и физический дизайн.

Также обратите внимание, что это только для истинных RDBMS, и я основываю техническую часть своих ответов на SQL Server. Перечисленный T-SQL для поиска нулевых столбцов без нулей также относится к SQL Server.

ответил Matthew Sontum 24 FebruaryEurope/MoscowbFri, 24 Feb 2017 14:40:09 +0300000000pmFri, 24 Feb 2017 14:40:09 +030017 2017, 14:40:09

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132