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

2685

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

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

karlipoppins
источник
1
здесь есть некоторая соответствующая информация codeproject.com/Tips/1215635/MySQL-DATETIME-vs-TIMESTAMP
Waqleh
Если вы хотите, чтобы ваше приложение было разбито в феврале 2038 года, используйте отметку времени. Проверьте диапазон дат.
Уилсон Хаук

Ответы:

1829

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

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

невозможный трезубец
источник
981
Важным отличием является то, что оно DATETIMEпредставляет дату (как указано в календаре) и время (как можно наблюдать на настенных часах), а также TIMESTAMPпредставляет четко определенный момент времени. Это может быть очень важно, если ваше приложение обрабатывает часовые пояса. Как давно было '2010-09-01 16:31:00'? Это зависит от того, в каком часовом поясе вы находитесь. Для меня это было всего несколько секунд назад, для вас это может представлять время в будущем. Если я произнесу 1283351460 секунд после «1970-01-01 00:00:00 UTC», вы точно знаете, в какой момент времени я говорю. (См. Отличный ответ Нира ниже). Недостаток: допустимый диапазон.
MattBianco
121
Еще одно отличие: запросы с «родной» датой и временем не будут кэшироваться, а запросы с отметкой времени - будут.
OZ_
39
«Метки времени в MySQL обычно используются для отслеживания изменений в записях». Не думайте, что это хороший ответ. Метка времени намного более мощная и сложная, чем сказали MattBianco и Nir. Хотя вторая часть ответа очень хорошая. Это правда, что сказал Blivet, и это хороший совет.
santiagobasulto
10
Также 1 важное замечание, DATETIME и TIMESTAMP могут использовать CURRENT_TIMESTAMP, NOW () с уважением, поскольку это значение по умолчанию, но DATE, например, не может, потому что он использует «0000-00-00» по умолчанию, поэтому для решения этого вопроса U должен написать Ваш собственный триггер к этой таблице, чтобы вставить текущую дату (без времени) в поле / столбец с типом DATE mysql.
Артур Кушман
14
@DavidHarkness: в документации сказано: «Чтобы указать автоматические свойства, используйте предложения DEFAULT CURRENT_TIMESTAMP и ON UPDATE CURRENT_TIMESTAMP» dev.mysql.com/doc/refman/5.0/en/timestamp-initialization.html
разместите
916

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

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

Nir
источник
11
эта презентация OReilly очень хороша для этой темы (извините в PDF) cdn.oreillystatic.com/en/assets/1/event/36/…
gcb
13
Также о характере мероприятия: - Видеоконференция (TIMESTAMP). Все участники должны видеть ссылку на абсолютный момент времени, скорректированный с учетом его часового пояса. - Время местного задания (DATETIME), я должен выполнить это задание в 9 марта 2014 г., 31:00, независимо от того, работаю ли я в этот день в Нью-Йорке или Париже. Я начну работать в 8:00 утра по местному времени, где я буду в тот день.
yucer
1
Так что, если я ИЗМЕНИЮ часовой пояс сервера, то значение TIMESTAMP останется прежним или оно тоже изменится ??
Андрей
3
@ Андрей, поскольку сейчас UTC, он останется UTC. Однако обратное преобразование изменится на «новый» часовой пояс сервера.
Нэмблтон
@yucer - я не рекомендую так думать. Наиболее последовательное использование в глобальной экономике - это преобразование всех временных дат в UTC для хранения. По соглашению обработайте Datetime как поле UTC. Это накладывает бремя на все задачи, которые вводят datetime для преобразования в UTC, но это более чистый проект в долгосрочной перспективе. Конечно, представить информацию пользователю на основе его текущих настроек. Если пользователь желает ввести «09:00 в Париже», то пусть он установит парижское время, затем введите 09:00. Тогда тот , кто находится в Нью - Йорке можно легко найти то , что им нужно времени , чтобы бодрствовать в свое время, чтобы телеконференции в.
ToolmakerSteve
524

Я всегда использую поля 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 в общем использовании - например, для хранения даты рождения.

scronide
источник
195
Вы также можете легко достичь верхнего предела, если вы занимаетесь банковским делом или недвижимостью ... 30-летняя ипотека выходит за рамки 2038 года
Кип
16
Конечно, используйте 64-битные метки времени Unix. Например, в Java new Date().getTime()уже выдается 64-битное значение.
OSA
5
+1 для DATETIME: В нашем потоке данных с SQL Server физического хранилища для покупки и счета-фактуры, переданного на MySQL Server для виртуального хранилища на веб-странице, DATETIME лучше подходит для даты и времени модификации, поскольку этот тип данных также существует в Transact. -SQL. Но TIMESTAMP означает другое в Transact-SQL, он является двоичным, как ROWVERSION, хотя MySQL TIMESTAMP похож на DateTime. Поэтому мы избегаем использования TIMESTAMP для совместимости двух БД.
Джако
10
Без понятия. Это гораздо большая проблема, чем просто MySQL, и нет простого решения: en.wikipedia.org/wiki/Year_2038_problem Я не верю, что MySQL может просто объявить, что временные метки теперь 64-битные и что все будет хорошо. Они не контролируют оборудование.
скронид
5
Дата рождения может быть DATETIME, если вы знаете время рождения, как я знаю для себя.
Крис Крэйг,
322

В приведенных ниже примерах показано, как 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 .

mr_eclair
источник
55
Ну, фактически DATETIMEэффективное время изменилось с изменением часового пояса, TIMESTAMPне изменилось, но человеческое представление изменилось.
Флиндеберг
3
Похоже, эта команда не работает в MySQL 5.6 set time_zone="america/new_york";
Манджунат Редди
Вот ответ на поставленную проблему time_zone. stackoverflow.com/questions/3451847/mysql-timezone-change
Манджунат Редди
2
Согласитесь с @flindeberg. Отметка времени представляет собой правильное время, а не дату, после смены часового пояса
Nitin Bansal
193

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

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

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

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

ekerner
источник
83
Я не думаю, что это хороший способ мышления. Я бы просто сохранил и обработал все даты в UTC и убедился, что интерфейс отображает их в соответствии с заданным часовым поясом. Этот подход прост и предсказуем.
Кос
8
@ Kos: не хранит и не обрабатывает ли все даты в UTC именно то, что TIMESTAMP делает внутренне? (Затем преобразовать его для отображения вашего местного часового пояса?)
carbocation
10
мой местный часовой пояс? Как ваша БД узнает мой часовой пояс? ;-) Обычно между базой данных и пользовательским интерфейсом довольно много обработки. Я делаю локализацию только после всей обработки.
Кос
3
@Koz: моя база данных не знает часовой пояс вашей базы данных:! Но он знает метку времени. Ваша база данных знает свои собственные настройки часового пояса и применяет их при интерпретации / представлении метки времени. 1:01 утра 11 декабря 2013 года в Пекине Китай не совпадает с моментом 1:01 утра 11 декабря 2013 года в Сиднее, Австралия. Google: «часовые пояса» и «первичный меридиан».
ekerner
2
MySQL преобразует значения TIMESTAMP из текущего часового пояса в UTC для хранения и обратно из UTC в текущий часовой пояс для извлечения. (Это не происходит для других типов , таких как DATETIME.) Dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo
125

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

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

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

MaxVT
источник
временная метка - фиксированная точка времени, всемирное координированное время, дата-время - относительно точки зрения, к эталону времени (например, местное время часового пояса), может быть. Координированное местное время?
yucer
110

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

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

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

user64141
источник
12
Мне нравится это решение. TIMESTAMP истекает в 2038 году является серьезной проблемой. Это не так далеко!
Чарли Далсасс
4
@CharlieDalsass Вы думаете, что текущее программное обеспечение будет там в это время :-P
Habeeb Perwad
13
Это затрудняет запрос данных по дате, если они хранятся в виде количества миллисекунд
Али Саид
4
Это действительно лучшее решение, если вы заботитесь о переносимости и работе с пользователями в нескольких часовых поясах или в базе данных в другом часовом поясе, чем пользователи. TIMESTAMP может быть подходящим вариантом, если у него нет недостатков дизайна. Очень жаль, что взломанные решения получили больше голосов, потому что они были опубликованы рано (годы!).
немецкий
4
Отличное решение! И вы совершенно правы, будучи «запертым». Когда вы привыкли позволять другим «делать работу за вас», вы начинаете терять кусочки, которые делают ВАС программистом.
Fmc
98

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

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

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

Alex
источник
186
Будущее заканчивается в 2038-01-19 03:14:07 UTC.
MattBianco
5
Это глупо. Я думал, что тип TIMESTAMP будет "готов к будущему", потому что он относительно новый. Нельзя конвертировать дату и время в UTC и обратно каждый раз, когда вы работаете с разными часовыми поясами. Они должны были сделать TIMESTAMP больше ... по крайней мере на 1 байт больше. это добавит еще 68 * 255 = 17340 лет ... хотя это не будет 32-битным выравниванием.
NickSoft
10
Знаете ли вы, почему TIMESTAMP заканчивается в 2038 году? Потому что это целое число, а целые числа имеют ограничение 2147483647. Я думаю, что это причина. Может быть, если они изменят его тип на varchar и изменят способ манипулирования им, он будет «готов к будущему».
Винса
6
@ Vinsa, я не думаю, что к тому времени это будет готово. Все еще помните ошибку Y2K? 2038 грядет.
Pacerier
2
К 2038 году MySQL (если он все еще существует) просто обновит поле TIMESTAMP, чтобы использовать более 4 байтов, и разрешит более широкий диапазон
the_nuts
95
  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 определяется настройкой time_zone.
Вивек С
источник
6
Вы должны уточнить # 4: временная метка как сохраненная является постоянной и не относительной (полностью независимой) от часового пояса, в то время как отображаемый вывод при получении зависит от часового пояса запрашивающего сеанса. DATETIME всегда зависит от часового пояса, в котором он был записан, и всегда должен рассматриваться в этом контексте, ответственность, которая теперь ложится на приложение.
Кристофер МакГоуэн
1
Отличный ответ. Чтобы добавить к этому ответу, если мы пытаемся сохранить значения за пределами этого «2038-01-09 03:14:07», мы либо получим ошибку, либо она будет сохранена как «0000-00-00 00:00:00». Я получал эту ошибку для своей базы данных, так как она имеет значения со сдвигом во времени (для целей шифрования).
KarthikS
Кроме того, существует проблема с DATETIME со значением DEFAULT в версиях mysql ниже 5.5. dba.stackexchange.com/questions/132951/…
Velaro
47

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

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

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

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

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

ianaré
источник
Ваше приложение не должно полагаться на часовой пояс сервера. Приложение должно ВСЕГДА выбирать часовой пояс в сеансе соединения с базой данных, которое оно использует, перед выполнением любого запроса. Если соединение используется несколькими пользователями (например, webapp), используйте UTC и выполните преобразование часового пояса на стороне рендеринга.
дольмен
42

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

Любая недавняя интерфейсная структура (Angular 1/2, реагировать, 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

Себастьян Хорин
источник
8
Ваши данные не должны быть привязаны к настройкам часового пояса ваших серверов. Может быть, это работает для вас, если у вас есть одна коробка MySql под столом
Jin
@Jin UTC означает отсутствие часового пояса, как TIMESTAMP. Если все ваши серверы находятся в UTC, проблем нет. Может быть, это не работает для вас, если у вас есть конфигурации 2000-х годов.
Себастьян Хорин
TIMESTAMP может быть обновлен до 64-битного значения в будущем. Тогда больше нет проблем.
дважды
Загрузка целых сторонних библиотек для отлова чего-то подобного тоже не может быть слишком хорошей для производительности, не так ли? Учитывая, что это на стороне клиента и не влияет на вашу базу данных ... Тем не менее, все, что вы делаете на стороне клиента, потребует проверки на стороне сервера. Итак, если подумать о полной картине, это действительно помогает с проблемой скорости? - Кстати, эти критерии немного странные. Использование строки в запросе для сравнения полей меток времени также выглядит довольно странно. Это также должно повредить производительности, верно?
NoobishPro
1
Не полагайтесь в своем приложении на часовой пояс сервера. Вместо этого определите часовой пояс для использования в каждом соединении с базой данных: SET time_zone = '+0:00';для UTC.
дольмен
37

timestampПоле является частным случаем datetimeполя. Вы можете создавать timestampстолбцы, чтобы иметь специальные свойства; это может быть установлено, чтобы обновить себя или создать и / или обновить.

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

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

Джефф Варника
источник
6
Нет, разница не просто в «особом случае». Поскольку часовые пояса сеанса, который устанавливает / запрашивает значения, задействованы по-разному.
дольмен
Я рад, что вы написали: «Какой правильный выбор полностью зависит от того, что вы хотите сделать». На SE слишком много ответов, в которых без достаточного обоснования говорится: «Вы никогда не должны делать X» или «Вы должны всегда делать Y».
Agi Hammerthief
37

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

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

Sobes
источник
29

Сравнение DATETIME, TIMESTAMP и DATE

введите описание изображения здесь

Что это [.fraction]?

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

Источники:

Дехан де Кроос
источник
24

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

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

Марк Дэвидсон
источник
6
-1 Я на самом деле думаю, что ответ ниже лучше - использование datetime позволяет использовать больше логики для обработки даты в самом MySQL, что может быть очень полезно.
Тоби Хеде
Разве не было тестов, показывающих, что сортировка в MySQL медленнее, чем в php?
sdkfasldf
ну, это зависит, иногда это полезно использовать, когда мы не хотим использовать strtotime. (php5.3 dep)
Адам Рамадан
вы можете вставить логику в mysql, просто используя FROM_UNIXTIME, если необходимо
inarilo
Я использовал все метки времени Unix в своих приложениях PHP и в MySQL, однако я обнаружил, что гораздо удобнее хранить даты и время в MySQL в качестве собственных типов даты / времени. Это особенно полезно для составления отчетов и просто просмотра наборов данных. Со временем, когда я разочаровался в необходимости копировать / пропускать метки времени Unix, я начал переключаться. Я вполне уверен, что есть производительность и другие плюсы и минусы, но в зависимости от вашего варианта использования удобство может быть важнее, чем довольно микрооптимизация.
DavidScherer
24

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

on update CURRENT_TIMESTAMP

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

leejmurphy
источник
17

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

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

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

ALTER TABLE your_table
      MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Каннан Прасад
источник
15

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

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

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

Эрвинд
источник
Вы можете (должны) всегда определять часовой пояс на уровне сеанса с помощью SET time_zone = '+0:00';(здесь UTC), чтобы быть уверенным в том, что вы получаете / устанавливаете из TIMESTAMPзначений, и избегаете зависимости от значения по умолчанию для часового пояса сервера, которое может измениться.
дольмен
14

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

Стоит рассмотреть еще одну вещь:

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

Оливер Холмберг
источник
14

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

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

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

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

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

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

Роджер Кампанера
источник
Данные о временной отметке будут интересны для лица, поддерживающего вашу заявку, когда прибудет 20 января 2038 года. тик тук тик ток
Уилсон Хаук
Тип отметки времени может быть увеличен немного и удвоить возможные значения.
Роджер
Проверьте свою теорию, чтобы она «немного выросла», и посмотрите, сможете ли вы успешно сохранить 1 февраля 2038 года и получить ее с MySQL. Давайте посмотрим определение вашей таблицы, когда закончите, пожалуйста. Вероятно, у вас будет много несчастных прошлых знакомых в феврале 2038 года.
Уилсон Хаук
1
@WilsonHauck В любом случае вам придется обновить версию MySQL до 2038 года. И этот расширенный TIMESTAMP будет обрабатываться миграцией. Кроме того, немногие приложения, помимо обработки закладных, действительно должны заботиться о 2038 году прямо сейчас.
дольмен
@dolmen Многие профессиональные инструменты и материалы имеют гарантию 20+ лет. Таким образом, что-то вроде warranties.expires_atне может быть меткой времени MySQL сегодня.
alexw
13

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

UPDATE table
SET age = 30

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

Ллойд Бэнкс
источник
3
основываясь на том, как вы настраиваете свою таблицу, вы можете контролировать это поведение. посмотрите на dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Чарльз Фаига,
5
@CharlesFaiga Поведение по умолчанию заключается в том, что отметка времени обновляется при обновлении любого другого столбца. Вы должны явно отключить это, если вы хотите, чтобы временная метка сохранила свое первоначальное значение
Lloyd Banks
Что это ?! Вы должны установить столбец Timstamp наON UPDATE CURRENT_TIMESTAMP
Бухгалтер م
Это функция, которую вы должны явно включить при создании таблицы.
дольмен
13

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

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

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

На TIMESTAMP также влияют различные настройки, связанные с TIME ZONE. 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 ′

Anvesh
источник
11
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       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.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
Premraj
источник
10

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

ecleel
источник
8
Это явно неправильно. Вот пример: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); первый столбец может принимать значение NULL.
Ormoz
10

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

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

Марк ДиМилло
источник
9

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

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

Чарльз Файга
источник
6
Оба имеют одинаковую проблему, если вы выбираете с функцией, основанной на значении столбца, и оба могут быть проиндексированы.
Маркус Адамс
4
Индекс работает по метке времени и не работает по дате и времени? Вы сделали неправильные выводы из этих постов.
Салман А
9

Я перестал использовать datetimeв своих приложениях после того, как столкнулся со многими проблемами и ошибками, связанными с часовыми поясами. ИМХО использовать timestampлучше, чем datetimeв большинстве случаев .

Когда вы спрашиваете, который час? и ответ приходит как что-то вроде «2019-02-05 21:18:30», это не завершенный, не определенный ответ, потому что ему не хватает другой части, в каком часовом поясе? Вашингтон? Г. Москва ? Пекин?

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

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

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

    SET time_zone = '+2:00';
  2. Вы изменили страну, в которой находитесь, и продолжили работу по сохранению данных, просматривая их в другом часовом поясе (без изменения фактических данных).

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

Короче говоря

datetime = приложение поддерживает 1 часовой пояс (как для вставки, так и для выбора)

timestamp = приложение поддерживает любой часовой пояс (как для вставки, так и для выбора)


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

Бухгалтер م
источник
Что делать, если есть поля, которые используют date, а другие поля используются timestampв одной таблице. Я думаю, что это вызовет новую проблему, потому что данные, которые фильтруются, whereне соответствуют изменениям часового пояса.
Erlang P
@ErlangP В этом случае ваше приложение должно исправить проблему с часовым поясом в dateстолбце перед отправкой запроса.
Бухгалтер م
7

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

Hans
источник
7

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

Мванги Тига
источник
6

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

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);
user723220
источник
4
Или используйте удобную для чтения и родную дату и время MySQL и используйте собственные функции MySQL для добавления / вычитания даты и времени.
Жюльен Палар