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

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

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

30 ответов


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

Если вы имели в виду, что хотите выбрать между использованием метки времени UNIX или собственного поля datetime 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 для чего-либо, кроме метаданных строк (дата создания или изменения).

As указано в документации MySQL:

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

...

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

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


ниже примеры показывают, как 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 настройка.

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

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

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


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

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

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


метка времени-4 байта против 8 байтов для DATETIME.

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

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


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

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

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

метка времени тип данных имеет диапазон от '1970-01-01 00:00:01' UTC до '2038-01-09 03:14:07' мирового. Он имеет различные свойства, в зависимости от версии MySQL и SQL Server работает в режиме.

  1. DATETIME является константой, в то время как отметка времени осуществляется настройкой time_zone.

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

  1. вы избегаете блокировки поставщика. Практически каждая база данных поддерживает целые числа относительно аналогичным образом. Предположим, вы хотите перейти в другую базу данных. Вы хотите беспокоиться о различиях между значениями DATETIME MySQL и тем, как Oracle определяет их? Даже среди различных версий MySQL метки времени имеют различный уровень точности. Только недавно MySQL поддерживал миллисекунды во временных метках.
  2. нет проблем с часовым поясом. Здесь были некоторые проницательные комментарии о том, что происходит с часовыми поясами с различными типами данных. Но является ли это общеизвестным, и все ваши коллеги потратят время, чтобы изучить его? С другой стороны, довольно сложно испортить изменение BigINT в java.утиль.Дата. Использование BIGINT вызывает много проблем с часовыми поясами, чтобы упасть на обочине.
  3. Не беспокойтесь о диапазоне и точности. Вам не нужно беспокоиться о том, что оборвала будущем диапазоны (метка переходит только к 2038).
  4. интеграция сторонних инструментов. Используя целое число, для сторонних инструментов (например, EclipseLink) тривиально взаимодействовать с базой данных. Не каждый сторонний инструмент будет иметь такое же понимание "datetime", как MySQL. Хотите попробовать и выяснить в спящем режиме, следует ли использовать java.язык SQL.Метка времени или java.утиль.Объект Date если вы используете эти пользовательские типы данных? Использование базовых типов данных использование make с сторонними инструментами тривиально.

эта проблема тесно связана с тем, как вы должны хранить денежное значение (т. е. $1.99) в базе данных. Следует ли использовать десятичный или денежный тип базы данных или, что хуже всего, двойной? Все 3 из этих вариантов ужасны, по многим из тех же причин, перечисленных выше. Решение состоит в том, чтобы хранить стоимость денег в центах с помощью BIGINT, а затем конвертировать центы в доллары при отображении значения пользователю. Задача базы данных-хранить данных, а не intrepret данных. Все эти причудливые типы данных, которые вы видите в базах данных (особенно Oracle), мало добавляют и начинают вас по дороге к блокировке поставщика.


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

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

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

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

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


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

любой недавний front-end framework (угловой 1/2, react, Vue,...) может легко и автоматически конвертировать ваш UTC datetime в местное время.

дополнительно:


A timestamp поле является частным случаем


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


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

enter image description here

что это [.фракция]?

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

источники:


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

on update CURRENT_TIMESTAMP

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


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

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


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

например,user таблицы ДАТА РЕГИСТРАЦИИ


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

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

для более подробной информации вы можете прочитать в блоге Метка Времени Vs Datetime .


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

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

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


основная разница

  • индекс на отметке времени-работает
  • индекс в Datetime -не работает

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


остерегайтесь изменения метки времени при выполнении инструкции UPDATE в таблице. Если у вас есть таблица со столбцами "Name" (varchar), " Age "(int) и "Date_Added" (timestamp), и вы запускаете следующий оператор DML

UPDATE table
SET age = 30

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


другое различие между меткой времени и Datetime в метке времени вы не можете по умолчанию значение NULL.


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

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


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

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

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

отметка времени также зависит от различных настроек, связанных с часовым поясом. DATETIME является постоянным.

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

диапазон поддерживаемых меток времени: '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'


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


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

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

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

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

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

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


Мне нравится временная метка 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);

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


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


Я просто использую unsigned BIGINT при хранении UTC ...

который тогда еще можно настроить на местное время в PHP.

на DATETIME выбирается с помощью FROM_UNIXTIME( integer_timestamp_column ).

очевидно, нужно установить индекс на этот столбец, иначе не было бы никакого продвижения.