Проектирование Базы Данных. Лучшие практики

    В преддверии старта очередного потока по курсу «Базы данных» подготовили небольшой авторский материал с важными советами по конструированию БД. Надеемся данный материал будет полезен для вас.




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

    1. Определите, для чего таблица и какова ее структура




    Сегодня такие методы разработки, как Scrum или RAD (быстрая разработка приложения), помогают ИТ-командам быстро разрабатывать базы данных. Однако, в погоне за временем очень велик соблазн погрузиться сразу в построение базы, смутно представляя, в чем же сама цель, какие должны быть конечные результаты.
     
    Как будто команда нацелена на эффективную, скоростную работу, но это мираж. Чем дальше и быстрее погружаться вглубь проекта, тем больше потребуется времени, чтобы выявить и изменить ошибки в проекте базы.

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

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

    2. Какие данные выбрать для хранения?




    Планируйте наперед. Мысли о том, что в будущем будет делать сайт или система, для которых проектируется база данных. Важно выходить за рамки простых требований технического задания. Только пожалуйста, не начинайте размышлять сразу обо всех возможных типах данных, которые когда-либо будет хранить пользователь. Лучше подумайте о том, смогут ли пользователи писать посты, загружать документы или фотографии  или обмениваться сообщениями. Если это так, то в базе нужно выделить место под них.

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

    Неизбежно потребности пользователей в рамках даже одного департамента будут конфликтовать. Если вы столкнетесь с этим, не бойтесь опереться на собственный опыт и найти компромисс, который устроит все стороны и будет удовлетворять конечной цели БД. Будьте уверенны: в будущем вам прилетит +100500 в карму и гора печенек.

    3. Моделируйте данные с осторожностью




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

    Во время моделирования строятся концептуальные (CDM), физические (PDM) и логические (LDM) модели данных. 

    Концептуальные модели описывают сущности и типы данных, которые они включают, а также отношения между ними. Делите ваши данные на логические куски — так намного проще жить.
    Главное — мера, не переусердствуйте.

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

    Если же сущность ведет собственную жизнь, имеет атрибуты, которые описывают ее поведение и ее вид, а также отношения с другими объектами, то смело можно использовать не только подтип, но и супертип ( родительская сущность). 

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

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

    Затем Логическая модель данных сопоставляется с выбранной заранее платформой СУБД (системы управления базами данных) и получается Физическая модель. Она описывает способ физического хранения данных.

    4. Используйте подходящие типы данных




    Применение неправильного типа данных может привести к менее точным данным, трудностям в объединении таблиц, синхронизации атрибутов и к раздуванию размеров файлов.
    Чтобы гарантировать целостность информации, атрибут должен содержать только приемлемые для него типы данных. Если в базу данных вносится возраст, то убедитесь, что в колонке хранятся целые числа из максимум 3 цифр.

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

    Большинство софта для моделирования (ER/Studio, MySQL Workbench, SQL DBM, gliffy.com) данных позволяет создавать прототипы областей данных. Так гарантируется  не только правильный тип данных, логика приложения и хорошая производительность, но также и обязательное задание значения.

    5. Предпочитайте естественное




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

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

    Если только бизнес-ключ не уникален (имя, фамилия, должность) и повторяется в разных строках таблицы или он должен изменяться, то первичным ключом стоит назначить сгенерированный искусственный, суррогатный ключ (artificial key).

    6. Нормализуйте в меру




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

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

    7. Тестируйте пораньше, тестируйте почаще




    Тестовый план и надлежащее тестирование должны быть частью проектирования базы данных.

    Лучше всего тестировать базу данных путем Continuous Integration (непрерывной интеграции). Моделируйте сценарий “Один день из жизни базы данных” и проверяйте, все ли граничные случаи обрабатываются, какие взаимодействия пользователей вероятны. Чем раньше вы найдете баги, тем больше сэкономите и времени, и денег.

    Это всего лишь семь советов, с помощью которых вы можете спроектировать отличную базу данных  по производительности и  эффективности. Если будете следовать им, вы избежите большинства головных болей в будущем. Эти советы — всего лишь верхушка айсберга в моделировании базы данных. Существует огромное число лайфхаков. Какими пользуетесь вы?
    OTUS. Онлайн-образование
    638,99
    Цифровые навыки от ведущих экспертов
    Поделиться публикацией

    Комментарии 21

      –3
      все правильно, очень хорошие советы.

      касательно «Ведь мы же не можем заранее заполнить столбцы “Дата смерти” или “Дата увольнения”, мы же не предсказатели тыкать пальцем в небо :-).» — такая рекомендация пройдет только если мы делаем базу данных для морга где ожидается что все люди мертвы (с единичными исключениями когда дата неизвестна).
      в остальных случаях, если база не мертвых и не уволенных людей, то лучше это моделировать в представлении (view) как вычисляемое поле.
        0
        Эм… а из чего его вычислять, если под это нет полей? )
          0
          полей нет, зато есть таблицы ))
          например для увольнения есть таблица приказов/заявлений
          для смерти — другая таблица.

          я имел в виду, что добавляя столбец например дата смерти мы гарантируем что почти у всех значения будут NULL (мы же не базу мертвецов строим, ведь?) и только у единиц будут значения, а SQL движки плохо работают с разреженными столбцами где много NULL и мало значений.
          правильнее будет нормализовать дальше и сделать таблицы (Сотрудники, Приказы)
            0
            т.е. вьюха «сотрудник» будет постоянно лазать в приказы? причём выбирая по дате, типу документа и неизвестно чему ещё, особенно если приказы ведутся в другой системе?

            В этом плане иногда лучше денормализовать, чем делать сотню джоинов.

            Так можно дойти и до того что таблица «сотрудник» не нужна. Можно собрать из документов, остатки — из проводок итп-итп.

            Что значит «плохо работают»? Вы собрались индексировать этот столбец? Зачем? )
              0
              мы же не базу мертвецов строим, ведь?
              Если у вас вообще как-то фигурирует слово «смерть» в ТЗ, то да, мы строим базу мертвецов. Например, БД ЗАГСа будет такой базой. Вы же не думаете, что в момент смерти данные по человеку тупо удаляются из БД?

              полей нет, зато есть таблицы ))
              например для увольнения есть таблица приказов/заявлений
              для смерти — другая таблица.
              Целую таблицу под смерти? Слишком дофига. Для разовых событий (типа рождения и смерти) вполне достаточно просто одного поля с соответсвующим событием. А вот под документальное сопровождение этих процессов уже можно нагородить таблиц (например, человек может быть признан мертвым, потом найтись живым, а то и несколько раз так, но в итоге рано или поздно он умрет окончательно, и на каждый такой случай будет решение уполномоченного органа — полиции, больницы, суда и т. д., а на каждое решение — запись в базе).
                0

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

                  0
                  >>>Для разовых событий (типа рождения и смерти) вполне достаточно просто одного поля с соответсвующим событием. А вот под документальное сопровождение этих процессов уже можно нагородить таблиц

                  вы только что подтвердили, что я прав. под документальное сопровождение данные нормализуются, а вот ваш «один столбец в таблице» это лишь один вычисляемый столбец в материализованном представлении
                  0
                  А почему нельзя в основной таблице (Сотрудники) сделать boolean поле dead/fired? А всю информацию о смертях/увольнениях (дата, № свидетельства о смерти/приказа об увольнении и т.д.) хранить в отдельной таблице. Т.к. информация по мертвым/уволенным скорее всего нечасто нужна будет.
                    0
                    Потому что:
                    1. Поддержка историчности. Если надо состояние сотрудника на дату — то хорошо бы знать не просто факт его смерти на текущий момент, а дату смерти/увольнения.
                    2. Что бы не лазать за датой далеко-далеко, а её обычно хотят знать.
                    3. Если есть записи типа «уволен — принят» потом опять «уволен — принят», к примеру, при смене подразделений или должностей.
                      0
                      Я исхожу из того, что бОльшая часть запросов будет относиться к действующим сотрудникам.
                      Выбирать действующих сотрудников по условию уволен=false мне кажется более безопасным, чем по условию дата_увольнения=NULL.
                      И да, для одного сотрудника действительно может быть несколько записей «уволен-принят». Т.е. между сотрудником и датами приема/увольнения связь один-ко-многим, соответственно — даты приема/увольнения нужно в отдельной таблице хранить.
                        0
                        в учете кадров все намного сложнее, потому что сотрудник может быть уволен но начиная с даты в будущем (например с 1 ноября).
                        Любые флаги и состояния имеют дату, когда они вступают в эффект.
                        поэтому одним булевским полем не обойтись, тут нужна максимальная нормализация
                          0
                          Ну да, большая часть запросов будет к действующим сотрудникам. К действующим сотрудникам на дату. На прошлый понедельник, на прошлый отчётный квартал или на завтра.

                          В случае если сотрудник уволен-принят чаще всего его заводят как нового сотрудника, к сожалению.
                0
                Есть 6 нормальных форм и шестая как раз с той самой избыточностью
                  0
                  зря Вы так категорично!
                  +10

                  Статья — редкостный бред. Неправильно почти каждое предложение. Такое ощущение, что автор базы данных видел только в детском саду в книжке-раскраске.
                  Первые два пункта — просто вода, можно сразу заменить на "делайте хорошо и не делайте плохо".


                  А дальше вода кончается, и начинаются перлы.

                  Как мы уже ранее говорили, от назначения базы данных зависит, какие методы использовать при моделировании.
                  Методы моделирования совершенно не зависят от назначения БД.
                  Если мы проектируем базу данных для оперативной обработки записей (OLTP), иными словами для их создания, редактирования и удаления, то используем моделирование транзакций. Если же база данных должна быть реляционной, то лучше всего применять многомерное моделирование.
                  Как сие понимать? База может быть либо OLTP, либо реляционной??? Конечно же нет, база очень легко может быть и OLTP, и реляционной одновременно. OLTP обычно противопоставляется OLAP'у, но тут и выбирать особо нечего: если знать, что каждая из аббревиатур означает, перепутать их друг с другом практически невозможно.

                  используем моделирование транзакций
                  Моделирование транзакций — это что за зверь? Что там моделировать??? За 12 лет в IT ни разу не слышал ничего подобного.

                  Во время моделирования строятся концептуальные (CDM), физические (PDM) и логические (LDM) модели данных.
                  Эти модели строятся разве что диванными теоретиками. На практике обычной ER-диаграммы более чем достаточно.

                  Если же сущность ведет собственную жизнь, имеет атрибуты, которые описывают ее поведение и ее вид, а также отношения с другими объектами, то смело можно использовать не только подтип, но и супертип ( родительская сущность).
                  Совершенно непонятно, о каких БД вы говорите в статье. Вроде бы в одних местах говорите не только о реляционных, но зачем-то в других местах употребляете термины, относящиеся только к реляционной модели, не уточняя, что имеете в виду именно ее, а где-то говорите о вещах, к реляционной модели не относящихся вообще. Лучшего способа запутать читателя не придумаешь. Этот кусок, например, — он о чем вообще?

                  Лучше всего использовать естественный, или бизнес, ключ (natural key). Он имеет смысловое значение, так вы избежите дублирования в базе данных.
                  Лучше, конечно, не использовать. Натуральные ключи иногда состоят из нескольких полей, и написание джойнов превращается в ад.

                  Если только бизнес-ключ не уникален
                  Если ключ не уникален, то он не ключ. Ваш Кэп.

                  Существует пять нормальных форм, которым нужно следовать.
                  Во-первых, не пять (но тут как считать, и вообще, это неважно), во-вторых, не «нужно», а «можно», и в большинстве случаев работает правило «бери третью — не ошибешься».

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

                  В общем, статья — отличная антиреклама для курсов. Ни за что никому не порекомендую курсы, которые таким образом рекламируются.
                    +1

                    Согласен по каждому пункту.

                      0
                      Так это ещё и курсы, а не школьник упражняется?? )
                      +2
                      Гм, разверните пожалуйста мысль, почему использование NULL — однозначно плохо, а пустой строки — нормальное приемлемое решение?
                        +1
                        Для строк, позволяющих NULL, сравнения сложнее, и, бывает, мешают использованию индексов.
                        Допустим, вам нужно найти все строки, не начинающиеся со слова «тест».
                        Если строка не позволяет NULL, то поиск будет через условие value not like 'тест%', если позволяет, то такое условие не выдаст вам null-овые строки, поэтому нужно писать либо isnull(value, '') not like 'тест%', либо value not like 'тест%' or value is null.
                        Вариант без NULL будет использовать поиск по индексу.
                        Первый вариант с NULL — полный скан индекса, применение к каждой строке функции, и только потом фильтрацию.
                        Второй вариант с NULL возможно развернется оптимизатором в два поиска по индексу, а возможно и нет… И даже если развернется — два поиска это дольше, чем один.
                        +2

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


                        Это о чём?

                          +3

                          Интересно — а для кого статья?
                          И что полезного для реального мира проектирования Баз Данных, читатель после должен вынести?
                          Хотя, это от риторические вопросы, конечно.

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое