Как преподаватель, могу сказать, что студентам непросто бывает привести базу данных к какому‑то осмысленному виду (не говоря уже про третью нормальную форму). Во‑первых, нередко «всё связано со всем», во‑вторых, в мало‑мальски сложной (в смысле, комплексной) задаче бывает трудно правильно спроектировать таблицы (то есть определить, какие таблицы должны быть в базе, как они должны быть связаны друг с другом, где и какая информация должна в них храниться). Помогает ли им в этом теория? И да, и нет. Дело в том, что нормализация данных говорит о желаемом виде каждой таблицы, и, преобразуя отдельно взятую таблицу к нормальной форме, мы также что‑то делаем со всей базой данных (добавляем новые таблицы, перемещаем между ними поля, и так далее) — это как сборка кубика Рубика. Второй проблемой здесь является то, что даже база данных, состоящая из единственной таблицы, не приведенной к первой нормальной форме, внезапно, тоже будет работать — криво‑косо, но будет! Теория — штука хорошая, но кое‑чего ей не хватает, а именно — задания точки отсчёта. Ведь для того, чтобы пройти к библиотеке третьей нормальной форме, для начала нужно понимать, где мы находимся.

С чего начинается база данных? - С проектирования её структуры!
Как проектируют базу данных студенты? Берут в охапку весь набор предоставленных в задаче или обнаруженных самостоятельно сущностей и пытаются сгруппировать их параметры в таблицы. Как говорится, правильно, но не верно. При таком подходе база данных получится, скорее всего, стихийно упорядоченной, а добавление в неё новой информации с высокой вероятностью потребует рефакторинга (а не простого расширения).
В литературе описывается шесть или даже больше нормальных форм, однако в большинстве случаев достаточно доведения базы данных до третьей нормальной формы. Более того, в ряде случаев, если это даёт прирост производительности, допускается отступление и от этих требований — выполняется так называемая денормализация таблиц. Нормализация — не истина в последней инстанции, а некоторый набор практик, следование которым в большинстве случаев даёт определённые преимущества, но, строго говоря, не является обязательным. Возможно, в силу всего этого в учебниках нередко встречаются примеры, в которых архитектура таблиц баз данных, даже доведенная до 3nf, вызывает больше вопросов, чем даёт ответов. Как говорится, «работает — не трожь», но как быть, если нужно разработать базу данных сегодня, да с прицелом на далёкое «завтра», легко обслуживаемую и расширяемую в соответствии с новыми (пока неизвестными) пожеланиями бизнеса?
События и справочники
База данных — это практически всегда система таблиц, в которой чаще всего можно увидеть одну большую таблицу (содержащую множество полей, в большинстве из которых содержатся ссылки на значения, расположенные в других таблицах) и множество относительно маленьких таблиц, число записей в каждой из которых так или иначе ограничено, хотя это ограничение не всегда очевидно. Приведу два примера:
Пример с очевидными ограничениями: школьное расписание занятий. В большой таблице будут регистрироваться все уроки, в каком бы классе, с каким бы учителем и по какому предмету они бы ни проводились, а во множестве более мелких таблиц, подчинённых этой большой таблице, будут содержаться ФИО учителей, номера кабинетов (а заодно — и дополнительная информация о каждом из них), названия предметов и многое другое.
Пример с неочевидными ограничениями: в базе данных республиканской больницы может быть таблица, в которую вносятся записи о каждом приёме пациента, а также таблица, куда будут занесены все пациенты, хотя бы раз обратившиеся в больницу, при этом отдельно взятый пациент может обращаться в больницу неограниченное количество раз, а вот число самих пациентов в принципе ограничено численностью населения региона, который больница обслуживает. Это ограничение сложно увидеть, потому что обычно (хотя и не всегда!) среднестатистический пациент обращается примерно один раз, и обе таблицы растут с почти что одинаковой скоростью (медицинские статистики меня, конечно, поправят, скажут, что на практике пациенты приезжают по много раз даже из других городов, но здесь моя цель была в том, чтобы показать ситуацию, когда в базе данных число записей в одной таблице будет иметь ограничения, а в другой — нет).
Большая таблица, связывающая информацию из множества других таблиц, рассказывает нам историю, ради которой собственно и «затевалась» база данных (история движения имущества предприятия в бухучёте, история обращений пациентов, история проведения занятий в учебном заведении, история обращений клиентов автосервиса, и так далее), и эта история состоит из событий (поэтому могу только предложить называть такую таблицу «событиями»). Каждая строка этой таблицы содержит ссылки на другие таблицы, которые раскрывают суть события, поясняют какие‑то его аспекты. То есть мы можем отметить, что таблица с событиями всегда находится на верхнем уровне иерархии таблиц: она ссылается на другие таблицы, другие таблицы на неё не ссылаются.
Таблицы, не хранящие информацию о событиях, содержат информацию, помогающую дополнить и расширить информацию о том или ином событии. Предлагаю называть такие таблицы справочниками. Как правило, это информация дублирующаяся (номера кабинетов, фамилии врачей / преподавателей / сотрудников). Более того, информация из справочника может быть дополнена и расширена информацией из другого справочника. Например, из описания события мы узнаём, что первый урок класса id_klass=5523 завтра пройдёт в кабинете id_cabinet=424, это будет id_subject=225, вести урок будет id_teacher=72. В справочниках, на которые (с помощью индексов) указывает событие, мы можем увидеть расшифровку, благодаря которой узнаем, что завтра первый урок у класса 9в пройдёт в кабинете 24, это будет математика, вести урок будет Иванова Мария Семёновна. В каждом из использованных в данном случае справочников могут быть свои отсылки на другие справочники, например — таблица, содержащая информацию о кабинетах, может иметь собственные ссылки на таблицу с информацией об учебных корпусах, в которой, в свою очередь, будут, например, номера телефонов вахты и других сотрудников, отвечающих за работу на месте.
Было бы неплохо, если бы студенты, приступая к проектированию структуры базы данных, начинали с определения того, что же является в ней событием, вокруг какой единственной, постоянно растущей, объёмной таблицы будет выстраиваться вся база данных. Событие — это нечто достаточно уникальное и неповторимое, но при этом — происходящее много‑много‑много раз (в принципе, неограниченное количество).
В небольшой базе данных, разработанной корректно, будет только одно событие, не больше и не меньше. Однако на практике могут встречаться и ситуации, когда в одной базе данных существует более одной таблицы с событиями, и это — разные события. Например, вы пишете базу данных для больницы — а там есть выписка лекарств, и по хорошему это должна быть одна база (аптеки), есть врачи, пациенты, приёмы и назначения лекарств — это другая база (приёмы), есть процедурные кабинеты, процедуры и тому подобное — это ещё одна база, а то и несколько.
Могу предложить лайфхак для того, чтобы определить, какие таблицы считать справочниками, а какие — событиями. База данных нужна и важна не сама по себе, а как инструмент, и этот инструмент рассказывает некоторую историю. Например, история, которую рассказывает расписание занятий, заключается в том, что такие‑то преподаватели в такое‑то заданное время в заданных кабинетах провели у определённых групп занятия по таким‑то предметам или дисциплинам. История? Несомненно! Так вот, таблица, глядя на которую мы можем восстановить эту историю, подглядывая в другие для уточнения деталей, и будет таблицей, описывающей события. Отдельно взятое событие — это занятие по отдельно взятой дисциплине, проведенное конкретным преподавателем в конкретном кабинете у конкретной группы. Всё остальное — справочники. Но ещё раз повторюсь: некоторые базы данных рассказывают сразу несколько историй, нужно быть внимательными!
Преимущества деления всех таблиц на события и справочники заключается в том, что все переменные, которыми оперирует база данных, выстраиваются в чёткую (и корректную) иерархическую структуру, которая не требует переработки и может долгое время просто дополняться путём наполнения справочников и добавления в них новых полей (или добавления новых справочников).
Любой справочник может быть дополнен и расширен, причём это не затронет главную таблицу — в ней по‑прежнему останется только ссылка на справочник. События хороши ещё и тем, что с их помощью начинает легко прослеживаться логика ответа на вопросы, адресуемые к базе данных.
В качестве траектории, по которой может двигаться разработчик базы данных, может выступать разработка единственной таблицы (минимального рабочего продукта), рассказывающей самую важную часть истории (т. е. пригодную для регистрации событий), затем в ходе нормализации какая‑то информация будет вынесена в отдельные справочники, и в этот момент может возникнуть хороший вопрос: а насколько сильно нужно дробить таблицы в ходе выделения? С одной стороны, пройдя весь этот путь до конца, мы придём к третьей нормальной форме, и это хорошо! С другой стороны, при этом мы скорее всего получим справочники с названиями дней недели и месяцев, что увеличит число таблиц в базе данных (и может потребовать дополнительных ресурсов сервера) и усложнит её поддержку в дальнейшем. И вот здесь имеет смысл выполнить денормализацию таблиц, приведя их к компромиссу между «абсолютно правильно» и «удобно в работе». Как правило, денормализация охватывает справочники, имеющие небольшой размер, не подверженные изменениям и не требующие дальнейших уточнений (дни недели, месяцы и т. п.).
Комментарии (11)
pnmv
01.06.2025 05:17открыл очередную статью, ожидая увидеть упорядоченное повествование с внятными определениями этих ваших форм.
штош. будем дальше подождать.
pingo
01.06.2025 05:171НФ — устраняет повторяющиеся группы
2НФ — убирает зависимости от части ключа
3НФ — устраняет косвенные зависимости между данными
смотрите сразу BCNF, 4НФ и 5НФ там действительно интересно, но имхо в первых двух человечество хранит 99% всей своей информации, и ничего.. пока шевелятся байтики
pnmv
01.06.2025 05:17спасибо. разумеется, я в курсе всего этого.
заодно, глянул, что там на википедии, на эту тему - с тех пор, как смотрел это дело, последний раз, в статьях многое поменялось. местами, в лучшую сторону. но, не смотря на то, что я категорически против физисеских, да и каких-либо наказаний вообще, за большинство объяснений, к моему глубочайшему сожалению, всё ещё, хочется сильно бить.
если следующий шаг нормализации данных (приведение к следующей нормальной форме, например) не до конца очевиден, на интуитивном уровне, то зачем он вообще нужен? требуется, хотя-бы, что-нибудь, из чьей-нибудь практики, как минимум, в виде - "очередной амазон применил вот это, и посмотрите, как хорошо всё стало, поэтому и применяет по сей день".
nin-jin
01.06.2025 05:17Поздравляю, вы почти изобрели таблицу фактов из схемы "звезда". Продолжайте ваши исследования и откроете для себя новые типы схем, в том числе не являющиеся деревьями.
AlexAiZzz
01.06.2025 05:17К сожалению большинство преподавателей чисто теоретики, поэтому не только не преподают актуальную теорию, но зачастую из-за этого не владеют профессиональной терминологией в достаточной мере.
punhin Автор
01.06.2025 05:17К сожалению большинство преподавателей чисто теоретики, поэтому не только не преподают актуальную теорию, но зачастую из-за этого не владеют профессиональной терминологией в достаточной мере.
По поводу актуальной теории, я бы больше жалел, что в преподавание не идут практики, хотя... это тоже не панацея - 99,9% классных специалистов всё сделают правильно, учтут кучу нюансов, но всё их объяснение закончится на втором, максимум на третьем предложении, потому как не привыкли рассказывать, и лишь один из тысячи практиков сможет внятно рассказать всё, что нужно знать студенту и что сам хотел бы узнать, будучи студентом, но... вы сами прекрасно понимаете, почему он не пойдёт преподавать.
Если под владением профессиональной терминологией понимать умение жонглировать умными, но зачастую совершенно непонятными ученику словами, то зачем такое умение? В 90-е годы ходила шутка, что существует порядка пяти тысяч определений слова "маркетинг". Подозреваю, что сегодня существует примерно такое же количество определений 1-2-3 нормальной формы, а что толку-то? Вопрос не в том, чтобы придумать ещё одно, а в том, чтобы попробовать найти что-то важное, такое, что поможет разобраться со всем остальным, какое-то правило, что ли... в одном из комментариев ниже есть упоминание про то, чтобы отталкиваться от бизнес-процессов (я в программирование пришёл из бизнес-планирования, то есть как раз из планирования и анализ этих самых бизнес-процессов), и я действительно учу студентов видеть за цифрами реальные процессы, обслуживаемые ими. Я не прав?
AnnMaslova
01.06.2025 05:17А как вы обычно подходите к проектированию БД: сначала рисуете ER-диаграмму или сразу думаете в терминах таблиц? И ещё: как часто вам приходилось сознательно денормализовать структуру ради производительности?
gsaw
01.06.2025 05:17Имхо такой подход только запутает учащихся. Вы предлагаете выискивать истории и справочники. А в жизни есть сущности их свойства и связи. А "истории" это одна из связей.
Вы сами пишите в начале, что "Берут в охапку весь набор предоставленных в задаче или обнаруженных самостоятельно сущностей и пытаются сгруппировать их параметры в таблицы. "
Такой подход естественен. То, что вы предлагаете отдает искусственностью, потому вряд ли будет принято и понятно.
По сути то все просто. Все эти нормализации служат практической цели, уменьшить повторяющиеся данные в базе данных и облегчить поиск по этим данным. Все, что повторяется выносится в отдельный справочник, таблицу. Мне кажется такого объяснения вполне достаточно. Кмк чем абстрактнее идея, тем труднее ее принять и понять.
Nich123
01.06.2025 05:17Правильный подход - от бизнес-процессов. Для начинающих - очень даже полезно. Автор, продолжай!
makartarentiev
Спасибо за статью, созданием баз занимался в школе и колледже(сами понимаете как это преподносят). Подскажите что можно почитать, от базы до более широкого понимания?
punhin Автор
В мире нет какой-то одной книжки, чтоб вот только её прочитал - и всё сразу понял. Читай всё, до чего дотянешься, но - читай вдумчиво и разборчиво, уделяя больше внимания тем авторам и книгам, от которых почерпнул новые знания. Ты по сути в начале пути, "копай" и вглубь, и в ширь - потом найдёшь свою специализацию и будешь "копать" уже преимущественно в ту сторону.
И самое главное - обязательно применяй (и проверяй) полученные знания на практике. Не столь важно количество прочитанных книг, сколько количество понятых. Не столь важно количество понятых книг, сколько количество применённых на практике.