DECIMAL длина для microtime (true)?

Я хочу хранить PHP microtime в качестве моей метки времени в MySQL.

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

Кто-нибудь знает, что возвращает максимальный размер microtime(true), поэтому я могу поместить это как длину моего типа данных?

Должен ли я выбирать переменную DECIMAL length?

Ответ 1

TL;DR. Используйте microtime (false) и сохраняйте результаты в MySQL bigint как миллионные доли секунд. В противном случае вам нужно узнать все о арифметике с плавающей запятой, которая является большим жирным волосом.

Функция microtime PHP захватывает временную метку Unix (в настоящее время примерно шестнадцатеричную 50eb7c00 или десятичную цифру 1,357,609,984) от одного системного вызова и микросекундное время от другого системного вызова. Затем он превращает их в строку символов. Затем, если вы вызываете его с помощью (true), он преобразует это число в 64-битное число с плавающей запятой IEEE 745, что PHP вызывает float.

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

Вы не достигнете полной точности микросекунды. Большинство систем сохраняют свои подчиненные системные часы с разрешением что-то в диапазоне 1-33 миллисекунды. Он зависит от системы.

MySQL версии 5.6.4 и более поздних версий позволяют указать столбцы DATETIME(6), которые будут содержать даты и время до разрешения микросекунды. Если вы используете такую ​​версию MySQL, которая абсолютно подходит для вас.

Перед версией 5.6.4 вам необходимо использовать MySQL DOUBLE (64-разрядная плавающая точка IEEE 754) для хранения этих чисел. MySQL float (32-разрядная плавающая точка IEEE 754) не имеет достаточного количества бит в своей мантиссе, чтобы полностью сохранить текущее время UNIX за считанные секунды.

Почему вы храните эти временные метки? Вы надеетесь сделать

  WHERE table.timestamp = 1357609984.100000

или аналогичные запросы для поиска определенных элементов? Это чревато опасностью, если вы используете float или double numbers в любой точке вашей цепочки обработки (то есть, даже если вы используете microtime(true) даже один раз). Они печально известны тем, что не достигли равных даже тогда, когда вы думали, что должны. Вместо этого вам нужно использовать что-то вроде этого. 0.001, называемый "эпсилон" в торговле цифровой обработкой.

  WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
                            AND 1357609984.100000 + 0.001

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

64-разрядная плавающая точка IEEE имеет 53 бит мантиссы - точности. Нынешняя временная метка UNIX Epoch (секунды с 1 января по 1970 год 00: 00Z) раз один миллион использует 51 бит. Таким образом, в DOUBLE не так много дополнительной точности, если мы заботимся о младшем разряде. С другой стороны, точность не исчерпывается уже несколько столетий.

У вас нет прецедента с int64 (BIGINT). Если бы я действительно хранил микросекундные временные метки только для их заказа в MySQL, я бы пошел с DATETIME(6), потому что я получил бы много арифметики даты бесплатно. Если бы я делал приложение с большим объемом памяти, я бы использовал int64.

Ответ 2

Это зависит от требуемой точности. Если вам достаточно миллисекунд, и вы не ожидаете, что какое-либо время работы превышает 999999 секунд, вы можете использовать DECIMAL(10,4). Таким образом, вы можете подгонять его к вашим потребностям.

О теоретическом максимуме он ограничен размером a float на вашей системе (32 бит, 64 бит). Подробнее см. PHP Float. Но, как я уже сказал, это теоретически. Никакой таймер не даст вам времени в этой точности.

Ответ 3

В MySQL 5.6.4 и выше родные DATETIME и TIMESTAMP типы могут поддерживать дробные секунды. Таким образом, вы можете сохранить временную метку с разрешением микросекунды в столбце DATETIME(6) или TIMESTAMP(6).

Чтобы преобразовать PHP microtime(), возвращайте значения в формат MySQL datetime, вы можете использовать MySQL FROM_UNIXTIME() или, если вы используете класс PHP DateTime, DateTime::format(). Обратите внимание, что функция PHP date() в настоящее время не поддерживает микросекундные метки времени. (Он имеет формат для микросекунд, u, но он всегда сопоставляет его с 000000.)

Для более старых версий MySQL, которые не могут хранить микросекунды в своих родных типах даты и времени, вы должны использовать либо DOUBLE, BIGINT (со значениями, выраженными в микросекундах, т.е. умноженными на 1 000 000), или DECIMAL(16,6) (что должно быть достаточно на несколько сотен лет).

Ответ 4

Почему бы вам просто не сохранить его как float? То, что возвращает microtime(true), поэтому он лучший кандидат.