Должен ли я использовать тип данных datetime или timestamp в MySQL?

StackOverflow https://stackoverflow.com/questions/409286

Вопрос

Вы бы порекомендовали использовать дата и время или временная метка поле и почему (используя MySQL)?

Я работаю с PHP на стороне сервера.

Это было полезно?

Решение

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

Если вы имели в виду, что хотите выбрать между использованием метки времени UNIX или собственным полем даты и времени MySQL, используйте собственный формат.Таким образом вы можете выполнять вычисления в MySQL.("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)") и легко изменить формат значения на временную метку UNIX. ("SELECT UNIX_TIMESTAMP(my_datetime)") когда вы запрашиваете запись, хотите ли вы работать с ней с помощью PHP.

Другие советы

В MySQL 5 и выше ВРЕМЯ значения преобразуются из текущего часового пояса в формат UTC для хранения и обратно из формата UTC в текущий часовой пояс для извлечения.(Это происходит только для типа данных TIMESTAMP и нет для других типов, таких как DATETIME.)

По умолчанию текущий часовой пояс для каждого соединения — это время сервера.Часовой пояс можно установить для каждого соединения, как описано в разделе Поддержка часового пояса сервера MySQL.

Я всегда использую поля DATETIME для чего-либо, кроме метаданных строки (дата создания или изменения).

Как упомянул в документации MySQL:

Тип DATETIME используется, когда вам нужны значения, содержащие информацию о дате и времени.MySQL извлекает и отображает значения DATETIME в формате «ГГГГ-ММ-ДД ЧЧ:ММ:СС».Поддерживаемый диапазон: от «1000-01-01 00:00:00» до «9999-12-31 23:59:59».

...

Тип данных TIMESTAMP имеет диапазон от «1970-01-01 00:00:01» UTC до «2038-01-09 03:14:07» UTC.Он имеет разные свойства в зависимости от версии MySQL и режима SQL, в котором работает сервер.

Вы, скорее всего, достигнете нижнего предела общего использования TIMESTAMP, например.сохранение даты рождения.

Приведенные ниже примеры показывают, как TIMESTAMP тип даты изменил значения после изменения time-zone to 'america/new_york' где DATETIMEнеизменен.

mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name    | Value               |
+------------------+---------------------+
| system_time_zone | India Standard Time |
| time_zone        | Asia/Calcutta       |
+------------------+---------------------+

mysql> create table datedemo(
    -> mydatetime datetime,
    -> mytimestamp timestamp
    -> );

mysql> insert into datedemo values ((now()),(now()));

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 14:11:09 |
+---------------------+---------------------+

mysql> set time_zone="america/new_york";

mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime          | mytimestamp         |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+

Я преобразовал свой ответ в статью, чтобы больше людей могли найти это полезным, MySQL:Типы данных Datetime и Timestamp.

Основное отличие состоит в том, что DATETIME является константой, а TIMESTAMP зависит от time_zone параметр.

Поэтому это имеет значение только тогда, когда у вас есть (или могут быть в будущем) синхронизированные кластеры в разных часовых поясах.

Проще говоря: Если у меня есть база данных в Австралии и я делаю дамп этой базы данных для синхронизации/заполнения базы данных в Америке, тогда TIMESTAMP обновится, чтобы отразить реальное время события в новом часовом поясе, а DATETIME по-прежнему будет отражать время. мероприятия в часовом поясе au.

Отличным примером использования DATETIME там, где следовало бы использовать TIMESTAMP, является Facebook, где их серверы никогда не знают точно, какое время произошло в разных часовых поясах.Однажды у меня был разговор, в котором время сказало, что я отвечаю на сообщения до того, как сообщение было фактически отправлено.(Это, конечно, также могло быть вызвано неправильным переводом часовых поясов в программе обмена сообщениями, если бы время отображалось, а не синхронизировалось.)

Я принимаю это решение на смысловой основе.

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

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

TIMESTAMP имеет размер 4 байта по сравнению с 8 байтами для DATETIME.

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

Но, как сказал Скронид, у него есть нижний предел — 1970 год.Это здорово для всего, что может случиться в будущем;)

Я рекомендую использовать ни один поле DATETIME или TIMESTAMP.Если вы хотите представить конкретный день в целом (например, день рождения), используйте тип ДАТА, но если вы более конкретны, вы, вероятно, заинтересованы в записи фактического момента, а не единицы времени. время (день, неделя, месяц, год).Вместо использования DATETIME или TIMESTAMP используйте BIGINT и просто сохраните количество миллисекунд с начала эпохи (System.currentTimeMillis(), если вы используете Java).Это имеет несколько преимуществ:

  1. Вы избегаете привязки к поставщику.Практически каждая база данных поддерживает целые числа относительно схожим образом.Предположим, вы хотите перейти в другую базу данных.Хотите ли вы беспокоиться о различиях между значениями DATETIME в MySQL и тем, как их определяет Oracle?Даже среди разных версий MySQL TIMESTAMPS имеют разный уровень точности.Лишь недавно MySQL стал поддерживать миллисекунды в метках времени.
  2. Никаких проблем с часовым поясом.Здесь было несколько содержательных комментариев о том, что происходит с часовыми поясами с разными типами данных.Но является ли это общеизвестным знанием и потратят ли все ваши коллеги время на его изучение?С другой стороны, довольно сложно испортить замену BigINT на java.util.Date.Использование BIGINT приводит к тому, что многие проблемы с часовыми поясами отходят на второй план.
  3. Не беспокойтесь о дальности или точности.Вам не нужно беспокоиться о том, что будет сокращено в будущих диапазонах дат (TIMESTAMP относится только к 2038 году).
  4. Интеграция сторонних инструментов.Использование целого числа упрощает работу сторонних инструментов (например,EclipseLink) для взаимодействия с базой данных.Не каждый сторонний инструмент будет иметь такое же понимание «даты и времени», как MySQL.Хотите попробовать выяснить в Hibernate, следует ли вам использовать объект java.sql.TimeStamp или java.util.Date, если вы используете эти пользовательские типы данных?Использование базовых типов данных упрощает использование сторонних инструментов.

Этот вопрос тесно связан с тем, как следует хранить денежную стоимость (т. е.$1,99) в базе данных.Следует ли вам использовать десятичный тип, тип «Деньги» базы данных или, что еще хуже, двойной?Все три варианта ужасны по многим причинам, перечисленным выше.Решение состоит в том, чтобы сохранить стоимость денег в центах с помощью BIGINT, а затем конвертировать центы в доллары, когда вы отображаете это значение пользователю.Задача базы данных — хранить данные, а НЕ интерпретировать эти данные.Все эти причудливые типы данных, которые вы видите в базах данных (особенно Oracle), мало что добавляют и начинают путь к привязке к поставщику.

  1. TIMESTAMP составляет четыре байта против восьми байтов для DATETIME.

  2. Временные метки также легче помещаются в базу данных и индексируются быстрее.

  3. Тип DATETIME используется, когда вам нужны значения, содержащие информацию о дате и времени.MySQL извлекает и отображает значения DATETIME в формате «ГГГГ-ММ-ДД ЧЧ:ММ:СС».Поддерживаемый диапазон: от «1000-01-01 00:00:00» до «9999-12-31 23:59:59».

Тип данных TIMESTAMP имеет диапазон от «1970-01-01 00:00:01» UTC до «2038-01-09 03:14:07» UTC.Он имеет разные свойства в зависимости от версии MySQL и режима SQL, в котором работает сервер.

  1. DATETIME является константой, а TIMESTAMP зависит от настройки часового пояса.

Зависит от приложения, правда.

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

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

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

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

2016 +:Я советую установить часовой пояс Mysql в UTC и использовать DATETIME:

Любой современный интерфейсный фреймворк (Angular 1/2, React, Vue,...) может легко и автоматически конвертировать дату и время в формате UTC в местное время.

Кроме того:

(Если только вы не измените часовой пояс своих серверов)


Пример с AngularJs

// back-end: format for angular within the sql query
SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")...

// font-end Output the localised time
{{item.my_datetime | date :'medium' }}

Все локализованные форматы времени доступны здесь:https://docs.angularjs.org/api/ng/filter/date

А timestamp поле является частным случаем datetime поле.Вы можете создать timestamp столбцы, имеющие специальные свойства;его можно настроить на автоматическое обновление при создании и/или обновлении.

В терминах «большой» базы данных, timestamp имеет пару триггеров для особых случаев.

Какой из них правильный, полностью зависит от того, что вы хотите сделать.

TIMESTAMP всегда указывается в формате UTC (то есть секунды, прошедшие с 01.01.1970 г. в формате UTC), и ваш сервер MySQL автоматически преобразует его в дату/время для часового пояса соединения.В долгосрочной перспективе лучше использовать TIMESTAMP, поскольку вы знаете, что ваши временные данные всегда будут в формате UTC.Например, вы не испортите даты, если перейдете на другой сервер или измените настройки часового пояса на своем сервере.

Примечание:Часовой пояс соединения по умолчанию — это часовой пояс сервера, но его можно (должно) изменить для каждого сеанса (см. SET time_zone = ...).

Сравнение между DATETIME, TIMESTAMP и DATE

enter image description here

Что это за [.fraction]?

  • Значение DateTime или TimeStamp может включать в себя следующую часть дробной секунды в точке микросекунд (6 цифр).В частности, хранится любая дробная часть в значении, вставленном в столбец DateTime или TimeStamp, а не выброшен.Это, конечно, необязательно.

Источники:

Стоит отметить, что в MySQL вы можете использовать что-то вроде приведенного ниже при создании столбцов таблицы:

on update CURRENT_TIMESTAMP

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

Я всегда использовал временную метку Unix при работе с MySQL и PHP.Основной причиной этого является то, что по умолчанию дата Метод в PHP использует метку времени в качестве параметра, поэтому синтаксический анализ не требуется.

Чтобы получить текущую временную метку Unix в PHP, просто выполните time();
и в MySQL сделайте SELECT UNIX_TIMESTAMP();.

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

Например, рассмотрим user стол с ДАТА РЕГИСТРАЦИИ поле.В этом user таблице, если вы хотите узнать время последнего входа в систему конкретного пользователя, используйте поле временная метка введите, чтобы поле обновилось.

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

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Тип данных timestamp хранит дату и время, но в формате UTC, а не в формате текущего часового пояса, как datetime.И когда вы извлекаете данные, временная метка снова преобразует их в текущее время часового пояса.

Предположим, вы находитесь в США и получаете данные с сервера, находящегося в часовом поясе США.Затем вы получите дату и время в соответствии с часовым поясом США.Столбец типа данных отметки времени всегда обновляется автоматически при обновлении его строки.Поэтому может быть полезно отслеживать, когда конкретная строка обновлялась в последний раз.

Более подробную информацию вы можете прочитать в блоге Временная метка против даты и времени .

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

Еще одна вещь, на которую стоит обратить внимание:

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

Остерегайтесь изменения временной метки при выполнении оператора UPDATE в таблице.Если у вас есть таблица со столбцами «Имя» (varchar), «Возраст» (int) и «Date_Added» (метка времени), и вы запускаете следующий оператор DML.

UPDATE table
SET age = 30

тогда каждое значение в столбце «Date_Added» будет изменено на текущую временную метку.

Ссылка взята из этой статьи:

Основные отличия:

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

TIMESTAMP также зависит от различных настроек, связанных с ЧАСОВЫМ ПОЯСОМ.DATETIME является постоянным.

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

Поддерживаемый диапазон TIMESTAMP:'1970-01-01 00:00:01 ′ UTC до' 2038-01-19 03:14:07 ′ UTC DateTime Поддерживается диапазон:от «1000-01-01 00:00:00» до «9999-12-31 23:59:59»

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

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

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

Итак, подводя итог, я ценю преимущества метки времени:

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

По всем этим причинам я выбираю поля UTC и метки времени, где это возможно.И я избегаю головной боли ;)

Основное различие заключается в

  • ИНДЕКС на временной метке - работает
  • ИНДЕКС по Datetime - Не работает

посмотри на это опубликуйте, чтобы увидеть проблемы с индексацией Datetime

Еще одно различие между Timestamp и Datetime заключается в том, что в Timestamp вы не можете установить значение по умолчанию NULL.

Я обнаружил непревзойденную полезность в способности TIMESTAMP автоматически обновляться на основе текущего времени без использования ненужных триггеров.Это только я, хотя TIMESTAMP, как и было сказано, — это UTC.

Он может отслеживать различные часовые пояса, поэтому, если вам нужно, например, отображать относительное время, вам нужно время UTC.

Я предпочитаю использовать временную метку, чтобы хранить все в одном общем необработанном формате и форматировать данные в коде PHP или в вашем SQL-запросе.Бывают случаи, когда в вашем коде бывает полезно хранить все в считанные секунды.

+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       TIMESTAMP                                       |                                 DATETIME                                 |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes.                                                           | DATETIME requires 8 bytes.                                               |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format.                |
| TIMESTAMP supported range: ‘1970-01-01 00:00:01′ UTC to ‘2038-01-19 03:14:07′ UTC.    | DATETIME supported range: ‘1000-01-01 00:00:00′ to ‘9999-12-31 23:59:59′ |
| TIMESTAMP during retrieval converted back to the current time zone.                   | DATETIME can not do this.                                                |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose.    | DATETIME is used mostly for user-data.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+

Мне нравится временная метка Unix, потому что ее можно преобразовать в числа и беспокоиться только о числе.Плюс вы добавляете/вычитаете и получаете продолжительность и т. д.Затем преобразуйте результат в дату в любом формате.Этот код определяет, сколько времени в минутах прошло между отметкой времени из документа и текущим временем.

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);

А TIMESTAMP требуется 4 байта, тогда как DATETIME требуется 8 байт.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top