Эта известная ошибка структуры данных превращает жизнь разработчиков в ад.

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

Дата и время

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

Дата и время: проблема

Давайте взглянем на следующую таблицу базы данных users. Вы видите какие-либо проблемы со следующими данными?

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

У нас есть столбец id, определенный как первичный ключ с автоматическим приращением. Пока все хорошо. Имя пользователя, определенное как varchar(250), хотя размер этого varchar, вероятно, слишком велик для имени пользователя, varchar по-прежнему является разумным выбором. Затем мы обнаруживаем столбец registration_date, хранящийся как text.

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

Но это еще не все. Представьте, что вы разработчик и хотите отображать дату на веб-странице. Хорошо, мы можем просто отобразить необработанные данные из базы данных, верно?

Выглядит не очень красиво, правда? Команда дизайнеров вместо этого предоставляет нам следующий макет дизайна в качестве требования.

По сути, они хотят, чтобы мы отображали не дату, а количество времени, прошедшее с момента сообщения. Это означает, что нам нужно точно понимать, что означает значение даты в нашем внешнем коде. Давайте продолжим с JavaScript для некоторых примеров.

Теперь нам нужно преобразовать дату text в дату объекта Date, которую понимает JavaScript. С этой даты мы можем рассчитать разницу с настоящего момента до указанного времени. Давайте воспользуемся известной библиотекой дат, чтобы облегчить нашу жизнь, под названием MomentJS.

Библиотека моментов полезна для преобразования дат текста в даты реальных объектов javascript. Однако, как вы могли заметить, 01.06.2021 должно было быть 6 January, а не 1 June. Это потому, что момент подумал, что мы задаем ему month/day/year формат даты вместо формата day/month/year.

Без проблем! Мы можем это решить. Давайте воспользуемся магией момента, чтобы проанализировать строку в правильном формате.

Мы получили это! Это действительно было 2 месяца назад, так как это старое сообщение. Однако теперь часовой пояс кажется неправильным. Похоже, что у Moment нет формата для получения этого часового пояса. У Moment есть метод .utcOffset(), который заботится об этом, но его использование требует еще большей ручной работы, чего мы хотим избежать в первую очередь!

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

Дата и время: решение

Давайте найдем решение этой проблемы! Это может быть так же просто, как определение хорошей структуры данных. Почему бы не использовать метки времени Unix вместо строковых дат? Это время в секундах с 1 января 1970 года в полночь по всемирному координированному времени.

С помощью простой команды мы можем получить текущую временную метку. А как насчет того, чтобы снова превратить его в свидание?

Вот наш объект даты JavaScript! Нам даже не потребовались сторонние библиотеки, и это действительно так просто.

Дата и время: Datetime vs. timestamp

А как насчет типа данных datetime, предлагаемого некоторыми механизмами баз данных? Они тоже нормально работают. Однако временные метки работают универсально и, как правило, в базах данных их меньше. Целые числа - действительно эффективный тип данных в мире баз данных.

Одно важное различие между меткой времени и DateTime заключается в том, что datetime также будет хранить часовой пояс даты. С другой стороны, временная метка будет хранить только количество секунд с начала эпохи в формате UTC. Вы больше не сможете узнать, какова была временная метка сохраненной даты. В зависимости от вашего приложения вы можете выбрать DateTime или timestamp. Это оба очень надежных варианта. Альтернативой может быть сохранение часового пояса отдельно, если это лучше соответствует вашим требованиям.

Дата и время: сводка

Хотя текстовый формат может быть сложным для использования разработчиками, есть и другие причины не выбирать текстовые даты:

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

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

Что делать, если уже слишком поздно?

Что делать, если ваше приложение уже использует неправильные типы данных? Распространенной стратегией миграции было бы дублирование столбца данных. Если у вас раньше был столбец date, просто добавьте новый столбец, например timestamp. Создайте сценарий, который перенесет предыдущие данные в этот новый столбец в новом формате. Создание конвертера для предыдущего формата может быть обременительным, но, по крайней мере, вы можете избавиться от старого формата данных в будущем.

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

Ключевые выводы

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

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

Обновите свои методы нормализации базы данных, чтобы избежать подобных ситуаций! Вместо того, чтобы хранить несколько данных в одном поле, всегда извлекайте поле, чтобы разделить столбцы, насколько это возможно, пока они не станут независимыми. Ваши коллеги-разработчики будут вам благодарны. Это именно то, что предписывает первая нормальная форма или 1NF методов нормализации базы данных. Убедитесь, что данные атомарны.

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

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

Держите данные в чистоте и радуйте своих коллег-разработчиков!

Дополнительные ресурсы

1NF, 2NF и 3NF: методы нормализации базы данных.

Datetime vs. timestamp: когда лучше использовать?

Документация по отметкам времени MariaDB