it-swarm.com.ru

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

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

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

2434
karlipoppins

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

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

1654
blivet

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

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

851
Nir

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

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

467
scronide

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

299
mr_eclair

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

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

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

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

182
ekerner

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

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

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

115
unbeknown

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

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

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

92
Alex
  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.
89
Vivek S

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

88
user64141

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

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

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

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

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

41
ianaré

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

37
Sebastien Horin

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

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

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

32
Jeff Warnica

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

28
Sobes

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

 enter image description here

Что это [.fraction]?

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

Источники:

24
jdc91

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

on update CURRENT_TIMESTAMP

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

21
leejmurphy

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

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

20
Mark Davidson

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

Например, рассмотрим таблицу user с полем REGISTRATION DATE. В этой таблице user, если вы хотите узнать время последнего входа определенного пользователя, используйте поле типа timestamp, чтобы поле обновлялось.

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

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

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

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

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

13
Arvind

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

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

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

На TIMESTAMP также влияют различные настройки, связанные с TIME ZONE . DATETIME постоянна.

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

Диапазон поддерживаемых TIMESTAMP: '1970-01-01 00:00:01' UTC до '2038-01-19 03:14:07' UTC Диапазон поддерживаемых данных: '1000-01-01 От 00:00:00 до 9999-12-31 23:59:59

12
Anvesh

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

UPDATE table
SET age = 30

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

12
Lloyd Banks

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

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

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

12
Oliver Holmberg

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

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

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

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

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

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

11
rogerpro

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

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

10
Marc DiMillo

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

10
ecleel

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

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

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

10
Charles Faiga

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

8
Hans
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       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.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
8
Premraj

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

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

6
Mwangi Thiga

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

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

DATETIME, который будет выбран с FROM_UNIXTIME( integer_timestamp_column ).

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

4
Martin Zeitler

До сих пор не упоминалось, что DEFAULT CURRENT_TIMESTAMP работает только с метками времени, но не с полями типа DateTime. 

Это становится актуальным для таблиц MS Access, которые могут использовать только DateTime, но не Timestamp.

4
Elliptical view

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

4
Mahdi Jazini

Многие ответы здесь предлагают сохранить в качестве метки времени в том случае, если вы должны представлять четко определенные моменты времени. Но вы также можете иметь моменты времени с datetime, если вы храните их все в формате UTC по договоренности.

3
Matthew

Если вы хотите ГАРАНТИРОВАТЬ, ваше приложение НЕ будет работать в феврале 2038 года, используйте TIMESTAMP. Обратитесь к вашему REFMAN за ДИАПАЗОНОМ поддерживаемых дат.

1
Wilson Hauck

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

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

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

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

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

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

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

Короче

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

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


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

1
Accountant م

Разница между DATETIME и TIMESTAMP

  1. Поддерживаемый диапазон для 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.

  2. До MySQL 5.6.4 TIMESTAMP требовало 4 байта (+3 байта за доли секунды) для хранения данных, в то время как DATETIME требовало 8 байтов (+3 байта за доли секунды).

  3. Начиная с MySQL 5.6.4, для DATETIME требуется 5 байтов + 3 дополнительных байта для хранения данных за доли секунды.

    4. В MySQL5 + значение TIMESTAMP конвертируется из текущего времени в UTC и наоборот, тогда как DATETIME не выполняет никакого преобразования.

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

  5. Запросы с DATETIME не будут кэшироваться, но запросы с TIMESTAMP будут кэшироваться.

0
Arman Hakim Sagar

timestamp - текущее время события, записанного компьютером через Сетевой протокол времени (NTP) .

datetime - текущий часовой пояс, заданный в вашейPHPконфигурации.

0
curiosity