Факт, который должна помнить система
Начните не с CREATE TABLE, а с предложений предметной области: пользователь создаёт проект; проект содержит задачи; задача имеет одного ответственного и меняет статус. Существительные подсказывают сущности, но не каждое слово становится таблицей. Статус с коротким закрытым набором может быть колонкой, а история статусов — отдельным рядом событий.
Таблица представляет множество фактов одного вида. Строка должна иметь устойчивую идентичность, а колонка — одно понятное значение, пригодное для ограничения и поиска.
Ключи и связи
Первичный ключ не равен публичному адресу
Внутренний bigint удобен для соединений и компактных индексов. Публичный идентификатор может быть случайным UUID или другим непредсказуемым значением, если последовательность раскрывает нежелательную информацию. Не делайте email первичным ключом: он способен измениться и несёт прикладной смысл.
Внешний ключ защищает ссылочную целостность. Выберите действие при удалении осознанно: CASCADE полезен для зависимого мусора, RESTRICT — когда удаление должно быть отдельным бизнес-сценарием.
Нормализация с причиной
Повторяющаяся группа и список значений в одной строке затрудняют проверку и поиск. Выносите сущность, когда ей нужны собственная идентичность, ограничения или независимая жизнь. Не разделяйте данные только ради формальной третьей нормальной формы: иногда снимок адреса заказа должен сохраниться отдельно от редактируемого профиля.
JSON-колонка подходит для редко запрашиваемых расширяемых свойств, но не должна становиться обходом моделирования основных связей. Если поле участвует в фильтрах, уникальности и внешних ключах, обычная колонка обычно честнее.
Ограничения ближе к данным
NOT NULL, UNIQUE, CHECK и FOREIGN KEY делают неверное состояние невозможным независимо от того, какой контроллер выполняет запись. Проверка приложения даёт дружелюбное сообщение, а ограничение базы закрывает гонку и ошибку другого клиента.
Время храните с определённой семантикой. Для момента события удобна единая временная шкала UTC; пользовательский часовой пояс хранится отдельно и применяется при отображении. Не смешивайте дату календарного события и абсолютный timestamp.
Миграция — версия контракта
Каждое изменение схемы оформите однонаправленным файлом с уникальным номером и записью о применении. Миграция не должна зависеть от ручного состояния phpMyAdmin. Для больших таблиц заранее оцените блокировки, объём backfill и совместимость старой версии приложения с промежуточной схемой.
Rollback релиза не всегда означает обратную миграцию данных. Удалённую колонку нельзя безопасно вернуть вместе с содержимым. Предпочитайте расширяющий переход: добавить, заполнить, переключить код, затем удалить в следующем релизе.
Практика главы
Создайте модель пользователей, проектов, задач и истории изменения статуса. Для каждой связи сформулируйте правило удаления и минимум одно ограничение, которое должна обеспечивать база.
Закрепите материал
Отметка, заметка, чек-лист и ответы остаются в localStorage этого браузера и не отправляются в аналитику.
Перелинковка со справочником
Проверка актуальности
- dev.mysql.comhttps://dev.mysql.com/doc/refman/8.4/en/Первичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.
Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .