PHP のマイクロタイムをタイムスタンプとして MySQL に保存したいと考えています。
に収納するのがベストと言われDECIMAL
ていますが、理想的なサイズが見つかりません。
最大サイズが何を返すかを誰かが知っているmicrotime(true)
ので、それをデータ型の長さとすることができますか?
可変長を選択する必要がありますDECIMAL
か?
tl;dr。microtime(false) を使用し、結果を 100 万分の 1 秒として MySQL bigint に格納します。それ以外の場合は、浮動小数点演算についてすべて学習する必要があります。これは、大きな太った毛玉です。
PHP マイクロタイム関数は、あるシステム コールから Unix タイムスタンプ (現在は約 16 進数の 50eb7c00 または 10 進数の 1,357,609,984) を取得し、別のシステム コールからマイクロ秒の時間を取得します。次に、それらを文字列にします。次に、(true) を付けて呼び出すと、その数値が 64 ビットの IEEE 745 浮動小数点数に変換されます。これは、PHP がfloat
.
現在、整数の UNIX タイムスタンプを格納するには、小数点の左側に 10 桁が必要です。これは、あなたの子孫が 11 桁を必要とするようになる CE 2280 年頃まで当てはまります。マイクロ秒を格納するには、小数点以下 6 桁が必要です。
合計マイクロ秒の精度は得られません。ほとんどのシステムは、1 ミリ秒から 33 ミリ秒の範囲の分解能で、1 秒未満のシステム クロックを維持します。それはシステムに依存します。
MySQL バージョン 5.6.4 以降DATETIME(6)
では、日付と時刻をマイクロ秒単位で保持する列を指定できます。そのようなMySQLバージョンを使用している場合は、絶対に行くべきです.
バージョン 5.6.4 より前では、MySQL DOUBLE
(IEEE 754 64 ビット浮動小数点) を使用してこれらの数値を格納する必要があります。MySQL FLOAT
(IEEE 754 32 ビット浮動小数点) には、現在の UNIX 時間を秒単位で完全に正確に格納するのに十分なビットが仮数にありません。
なぜこれらのタイムスタンプを保存するのですか? やりたいと思っていますか
WHERE table.timestamp = 1357609984.100000
または特定のアイテムを検索するための同様のクエリ? 処理チェーンのどこかで浮動小数点数または倍精度数を使用すると (つまり、microtime(true)
1 回でも使用したとしても)、危険が伴います。彼らは、あなたがそうすべきだと思っていたとしても、平等にならないことで有名です. 代わりに、このようなものを使用する必要があります。数値処理業界では「0.001
イプシロン」と呼ばれています。
WHERE table.timestamp BETWEEN 1357609984.100000 - 0.001
AND 1357609984.100000 + 0.001
または似たようなもの。bigint
これらのタイムスタンプを 10 進数または 100 万分の 1 秒で列に格納すると、この問題は発生しません。
IEEE 64 ビット浮動小数点には、53 ビットの仮数部 (精度) があります。現在の UNIX エポック タイムスタンプ (1970 年 1 月 1 日 00:00Z からの秒数) に 100 万を掛けると、51 ビットが使用されます。したがって、下位ビットを気にする場合、DOUBLE の精度はそれほど高くありません。一方、精度は数世紀にわたって尽きることはありません。
int64(BIGINT) で精度が不足することはほとんどありません。MySQL での順序付けのためだけにマイクロ秒のタイムスタンプを実際に保存している場合は、DATETIME(6)
多くの日付計算を無料で取得できるため、それを使用します。インメモリの大容量アプリを実行している場合は、int64 を使用します。
MySQL 5.6.4以降では、ネイティブDATETIME
とTIMESTAMP
タイプは小数秒をサポートできます。DATETIME(6)
したがって、マイクロ秒の解像度のタイムスタンプをまたはTIMESTAMP(6)
列に格納できます。
PHPmicrotime()
の戻り値をMySQLの日時形式に変換するには、MySQLFROM_UNIXTIME()
関数を使用するか、PHPのDateTimeクラスを使用している場合はDateTime::format()
。PHPdate()
関数は現在、マイクロ秒のタイムスタンプをサポートしていないことに注意してください。(マイクロ秒のフォーマットコードはありますu
が、常にマップされ000000
ます。)
ネイティブの日時タイプでマイクロ秒を格納できない古いMySQLバージョンの場合はDOUBLE
、BIGINT
(マイクロ秒で表された値、つまり1,000,000を掛けた値)またはDECIMAL(16,6)
(まだ数百年は十分なはずです)のいずれかを使用する必要があります。
それは、必要な精度によって異なります。ミリ秒で十分で、ランタイムが 999999 秒を超えるとは思わない場合は、DECIMAL(10,4)
. このようにニーズに合わせることができます。
float
理論上の最大値については、システム上の のサイズ (32 ビット、64 ビット)によって制限されます。詳細については、 PHP フロートを参照してください。しかし、私が言ったように、それは理論的なものです。その精度で時間を提供するタイマーはありません。
として保存してみませんfloat
か?それがmicrotime(true)
返ってくるので、最有力候補です。