В базе данных, почему мы не можем просто использовать «длинные» целые числа для дат (миллис с эпохи) - PullRequest
7 голосов
/ 18 июля 2010

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

Обратите внимание, я чувствую, что часовой пояс является просто презентационным.Это никогда не должно храниться в первую очередь.У большинства компаний есть политика использования только UTC, но, опять же, это просто дополнительная информация.Давайте просто сохраним количество миллисекунд с начала эпохи, и при отображении покажем пользователю миллисекунды, отформатированные в ИХ конкретный часовой пояс.

РЕДАКТИРОВАТЬ: Кажется, что миллионы долларов ошибок и потерянной производительности / путаницы связаны с часовыми поясами и форматированием даты, а также сумасшедшим преобразователем / преобразованием даты из драйвера jdbc.Давайте покончим с этим раз и навсегда.

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

Ответы [ 7 ]

2 голосов
/ 07 февраля 2011

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

Тривиально для почти всех основных языков программирования / веб-страниц конвертировать для отображения.Фактически, целочисленная дата эпохи Unix может быть передана непосредственно на веб-страницу и позволяет JavaScript переводить в местное время, избегая промежуточного преобразования.

Единственное место, где это не работает, - арифметика Календаря: Добавить 1 месяц до 31 января.

2 голосов
/ 18 июля 2010

Вы можете использовать целые числа или какой-либо другой подходящий тип для представления значений даты / времени в вашей базе данных.Однако это создает пару проблем:

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

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

  • Использованиецелые числа для представления дат затруднят выполнение специальных SQL-запросов к таблице, включающей столбцы даты.

РЕДАКТИРОВАТЬ

Экономия пространства путем представления дат в виде целых чисел зависит от базы данных.IIRC, Oracle хранит значения даты / времени в виде простых целых чисел.И я ожидаю, что любая приличная СУБД будет делать то же самое ... и для хранения, и для эффективности запросов.

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

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

Тогдаэто вопрос гранулярности.(Для ясности используется синтаксис даты ISO) означает ли "1999" то же самое, что и "1999-01-01" или "1999-01-01T00: 00: 00"?А как насчет точности до секунды?

Дело в том, что ни одно простое SQL-представление даты / времени (или целое число) не может справиться со всем этим.Основная причина ошибок / проблем / трудностей, с которыми мы сталкиваемся, заключается в том, что программисты используют ярлыки в своей реализации и (что еще более важно) неаккуратны в своем мышлении.

EDIT 2

По-прежнему существует проблема, заключающаяся в том, что многие проблемы все еще возникают из-за различий в способах обработки различными базами данных и их соответствующими драйверами JDBC литералов даты и предположений о часовых поясах.Я не эксперт по JDBC и стандарту (ам) SQL, но проблемы с корнем выглядят следующим образом:

  • Поставщики баз данных не полностью реализовали типы datetime, как указано в (например) SQL-92.
  • Стандарты SQL не определяют единый синтаксис для литералов даты и времени, но разрешают синтаксисы, специфичные для поставщика базы данных.
  • Стандарты SQL позволяют устанавливать часовой пояс по умолчанию без какого-либо стандартного способауказать (или даже выяснить), что он по умолчанию.Больше решений для конкретного поставщика.
  • Спецификация JDBC не предоставляет приложению способа получить или установить часовой пояс по умолчанию или выбрать литеральные синтаксисы даты и времени.

Всеиз этого складывается беспорядок переносимости и проблем конфигурации для разработчика Java.Однако я не думаю, что это значительно хуже, чем проблемы с переносимостью и конфигурацией, которые возникают у нас с другими аспектами приложений Java / RDBMS.И если полностью исключить типы datetime, вы бы столкнулись с множеством других проблем;см. выше.

1 голос
/ 11 сентября 2012

Просто сохраните длинный UTC (большое целое число) и сделайте так, чтобы имя столбца БД указывало, что оно содержит millis_since_epoch (также можно использовать комментарий, но я не уверен, что все комментарии поддержки БД).Таким образом, вы можете беспрепятственно перемещать данные в любую БД, данные можно безопасно интерпретировать за пределами приложения, которое их создало (именно поэтому имя столбца БД так важно), и вы можете обрабатывать представление / зону так, как вам нужно, через пользовательский интерфейс..

1 голос
/ 18 июля 2010

Теперь проблема вообще.

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

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

1 голос
/ 18 июля 2010

По той причине, о которой я могу подумать, это сохранить дату и время до 1 января 1970 года 00:00:00 по Гринвичу.

Хотя я чувствую твою боль. Оракул дата / дата и время болезненен в JDBC. Это даже несовместимо среди разных версий драйверов!

Я должен сказать, что я не обнаружил особых проблем с другими драйверами JDBC (другими поставщиками БД), хотя ...

0 голосов
/ 18 июля 2010

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

0 голосов
/ 18 июля 2010

В чем вопрос?Вы спрашиваете, возможно ли это?Это будет зависеть от того, какую базу данных вы используете, но я предполагаю, что это возможно с большинством.Я определенно сделал это с помощью SQL lite в приложениях Android (которые программируются на Java, если вы не знакомы с ним).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...