Когда нули "безопасны" в столбце? - PullRequest
3 голосов
/ 26 января 2011

Существует ли общее практическое правило для проектирования баз данных, чтобы разрешить столбцы как нули против 3nf нормализации? У меня есть таблица со столбцом, который в основном будет состоять из нулей (85%), но размер таблицы не превышает 10 КБ записей (не очень большой). Это в основном для ведения журнала и ведения записей, поэтому большинство транзакций будут вставлены и выбраны, без обновлений. Я пытаюсь рассмотреть как производительность, так и упрощенный дизайн. Будет ли большая польза от денормализованного или нормализованного в этом случае? Разные РСУБД ведут себя по-разному?

Ответы [ 11 ]

7 голосов
/ 27 января 2011

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

  1. Вы хотите правильно смоделировать свои данные.

  2. Вы хотите предоставить базу данных, которая позволит легко создавать правильные приложения.

  3. Вы хотите сэкономить место на диске.

  4. Вы беспокоитесь о производительности.

Хорошо, есть четыре отдельных причины!

Из четырех я очень обеспокоен # 1, довольно обеспокоен # 2 (тем более, что я тоже всегда программист), и меня действительно не волнует # 3, потому что дисковое пространство дешево а также потому, что # 1 и # 2 избавились от большинства NULL в любой базе данных для меня. Что касается # 4, я никогда не хочу жертвовать правильностью ради производительности - не имеет значения, как быстро я получу ответ, если не уверен, что он правильный. Если я не могу достичь своих целей производительности в хорошо смоделированной базе данных SQL, тогда база данных SQL может оказаться неподходящим инструментом для работы.

Таким образом, самый важный вопрос для меня будет таков: «Правильно ли использование единой таблицы моделирует данные, которые вы хотите сохранить?» Также важно, «сделает ли использование единой таблицы слишком легким для написания неверного кода для базы данных?» Я хочу заставить себя (или любого программиста, который придет за мной) иметь , чтобы поместить данные в правильные места. Посмотрите на свои данные и ответьте на эти вопросы, и это должно помочь вам определиться с правильной структурой.

2 голосов
/ 27 января 2011

Нули не безопасны, поэтому нет смысла пытаться сделать их безопасными или оправдать их или переопределить их как «безопасные».

Self-Противоречие

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

  • Либо вам нужны стандарты (нормализация, нет пустых значений, много небольших быстрых таблиц, простота использования и простота расширения), либо вам нужен простой код (толстые таблицы, пустые значения, нет производительности, невозможно расширить)

  • Либо вам нужны общие стандарты или кратчайшие кодовые блоки.

1024 * Оправдание *

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

Один стандартный технический ответ

Но вы задали технический вопрос об известной теме, на которую гиганты отрасли ответили более 30 лет назад. Органы по стандартизации приняли эти принципы в качестве стандартов. Есть только один технический ответ. Другие ответы - это обоснование нетехнических и нестандартных методов.

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

    • Нормализовать, потому что это избавляет от дублирования данных.

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

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

    • Нормализация, поскольку результирующая база данных будет намного меньше (больше, таблицы меньше, но в целом меньше)

    • И, наконец, нормализованные данные не будут иметь нулевых значений.

  • Нули означают одну из двух вещей.

    • Либо «необязательные» поля (ну, они не могут быть столбцами, потому что это не база данных), что означает, что данные не нормализованы.

    • Или «отсутствует / неизвестно», что означает, что у вас нет целостности данных (опять же, обычный файл, а не база данных); данные не могут быть использованы для анализа.

Конечно, SQL громоздок с объединениями, но SQL - это все, что у нас есть, так что разберитесь с ним. Это значит, научиться кодировать объединения, использовать вырезать и вставить.

"Стоимость присоединения"

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

Теперь не путайте, не неправильно истолковывайте то, что я говорю:

  • стоимость указана в размере объединенных наборов данных; могут ли индексы использоваться; характер объединения; если есть несоответствие DataType; аргументы поиска; и т. д. Но сам код требуется для соединений (при условии, что мы присоединяемся к ключам). «стоимость соединения» - ничто. Просто проверьте статистику и планы запросов.

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

SQL и не-SQL

Вы отметили свой вопрос «SQL» и «MySQL». SQL - это стандарт, опубликованный IEC / ISO / ANSI. MySQL не является SQL. Обработка Нуль изложена в Стандарте. То, что делает MySQL, нестандартно в обоих движках. На самом деле то, что он сделал в прошлом году и что он будет делать в этом году, отличается и нестандартно.

Чтобы назвать не-SQL, «SQL», когда SQL является стандартом, является простым обманом. Точно так же, как называть кучу простых файлов «базой данных».

Дело в том, что вы получите один ответ, если ваш вопрос был помечен как «SQL», и другой ответ, если он был помечен как «MyNonSQL».

Нормализовано для удобства кодера

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

2 голосов
/ 26 января 2011

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

этот столбец сам по себе является частью таблицы и зависит от ее семантики.Обнуляемый столбец не обязательно (хотя он может ) указывать на проблему проектирования - возможно, это должна быть его собственная сущность в модели с кардинальностью 0: 1 или 0: M для родительской сущности.Возможно, это не должно быть.Все зависит от семантики сущности и атрибута.Но вы не можете просто сделать общее утверждение, что обнуляемый столбец == денормализованные данные: это ведет к безумию.

2 голосов
/ 27 января 2011

Итог: если вы хотите, чтобы ваша структура данных действительно была нормализована до 3-й нормальной формы, у вас не должно быть нулевых столбцов.

Если вы живете и работаете в реальном мире, как и все мы, вы найдете пустые столбцы, вполне приемлемые и «безопасные». Технически ваша база данных не будет нормализована, но какая система данных на самом деле?

Очень мало.

2 голосов
/ 26 января 2011

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

Тем не менее, я не вижу, что NULL здесь связано с нормализацией?

2 голосов
/ 26 января 2011

Вы говорите о таблицах, позволяющих пользователям хранить NULL, а не пустую строку или число?

Если это так, я бы сказал, что вы должны разрешать значения NULL в столбце, только если NULL имеетспециальное значение (не просто эквивалент пустой строки '' или 0).

1 голос
/ 26 января 2011

Некоторые вещи, которые я изучил в отношении значений NULL - пытаясь избежать дублирования ответа: -)

Кроме того, соответствующая информация также представлена ​​в статье Википедии NULL: Противоречие (и окружающий контекст).

Не все системы RDBMS ведут себя одинаково.

В SQL Server NULL считается уникальным значениемв UNIQUE столбце / индексе.В SQLite значение NULL может появляться много раз и не считается дублирующим значением .Очевидно, что спецификация SQL92 неоднозначна в этом отношении.

NULL is NULL -> true (стандартная и правильная), но NULL = NULL -> ??? Она должна быть ложной, но это зависит от СУБД и настроек!В SQL Server это может управляться параметром ANSI_NULLS .Это может привести к неправильному поведению при соединении в другом контексте!В зависимости от RDMBS подобное поведение может также применяться к другим операциям. Пожалуйста, всегда используйте / поддерживайте правильное равенство SQL!

Различные системы RDBM могут также использовать другую физическую структуру таблиц, и когда столбец равен NULLABLE, это может означать, чтов записи не зарезервировано в записи (это верно для CHAR(100) или XML (бит-заглушка) в SQL Server, например).Если эту запись необходимо обновить после первоначального создания (например, изначально NULL), это может привести к избыточной фрагментации , при определенных обстоятельствах .Тем не менее, это должно быть только что-то, на что следует обратить внимание, и я не решусь принять общие решения, основанные на такой детали реализации, так как в игре есть другие факторы!

определить, что означает NULL

К сожалению, нет значений NOTSET или INVALID для дополнения NULL.Каждый столбец должен иметь определенное значение NULL.Означает ли это «недопустимое значение» или «значение не указано» или «значение не известно» и т. Д.?Для достижения правильной бизнес-логики может потребоваться смешать NULL с non-NULL значениями дозорного (или вообще не использовать NULL или использовать дополнительные столбцы / отношения состояний).

Happy SQL'ing.

1 голос
/ 26 января 2011

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

vehicle
----------------------------
vehicleId int
makeId int not null references make(makeId)
modelId int not null references model(modelId)
numberOfWheels tinyint null
hullMaterialId int null refrences hullMaterial(hullMaterialId)

Затем вы можете нормализовать некоторые из этих пустых столбцов в таблицы «от 1 до нуля или 1», чтобы лучше понять данные:

roadvehicle
----------------------------
vehicleId int references vehicle(vehicleId)
numberOfWheels tinyint not null

waterVehicle
----------------------------
vehicleId int references vehicle(vehicleId)
hullMaterialId int not null refrences hullMaterial(hullMaterialId)

(Прошу прощения за очень упрощенный пример)

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

1 голос
/ 26 января 2011

SQL Server 2008 имеет разреженных столбцов и отфильтрованных индексов , чтобы помочь разрешить эту ситуацию.

1 голос
/ 26 января 2011

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

Возможно, вы не получили счет.Ширина не должна быть 0, она должна быть нулевой.Это особенно актуально, если 0 является допустимой шириной или значением того, что вы отслеживаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...