1.1 Введение

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

Есть чек-лист на что важно тебе обратить внимание при проектировании БД:

  1. Обеспечить корректное хранение всей информации
  2. Запросы должны отрабатывать корректно
  3. Старайся сократить дублирование данных и тех, которые банально не нужны
  4. Целостность базы данных
  5. Оптимизация скорости доступа к данным

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

  1. Логика твоей структуры должна быть понятной другому разработчику
  2. Правильная структура базы данных - ключ к успеху
  3. Никогда не торопись что-то оптимизировать

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

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

Premature Optimisation Is the Root of All Evil. Не торопись оптимизировать все что можно. В базе данных есть кэши и другие способы оптимизации работы с запросами и данными.

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

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

1.2 Проектирование библиотеки

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

Начнем с главного, какая задача у библиотеки? Конечно, это наши CRUD операции, но с добавление бизнес логики - получить книгу, добавить книгу, забронировать ее и так далее. Исходя из этого мы выделим три группы в нашем проекте: читатель, библиотекарь и администратор. Возможности каждого из них показана на диаграмме вариантов использования.

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

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

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

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

Когда пользователь захочет открыть список литературы, мы добавим ему возможность разных сортировок, фильтров по автору, году и так далее.

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

Теперь переходим к формированию основных сущностей нашей библиотеки:

  • пользователь (библиотекари и администраторы);
  • читатель;
  • читальный зал;
  • книга;
  • карточка выдачи книги;
  • карточка бронирования книги.

Готовая диаграмма базы данных будет выглядеть вот так:

Теперь давай попробуем собрать запросы, которые нужно будет нам написать:

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

1.3 Формирование схемы данных

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

Как это можно сделать? Мы поместим в книгу реквизит “номер зала”, но это плохой подход, потому что придется дублировать книги, если она находится в разных залах.

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

Полученную диаграмму мы легко спроецируем на таблицы, связи и атрибуты и перенесем это все в БД. В результате мы получим таблицы изображены прямоугольниками, разделенными на 3 секции:

  • имя таблицы;
  • внутренние ключи (помечаются маркером);
  • остальные поля, при этом обязательные помечаются маркером.

Тут можно заметить, что мы не объединили таблицу администраторов и библиотекарей и не сделали из этого users. Но почему?

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

Плюс, мы добавили таблицу о которой говорили выше librarians_rooms - тут мы объединили библиотекарей и залы. Несколько библиотекарей могут быть в одном зале, и один библиотекарь может отвечать за несколько залов.

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