日時フィールドまたはタイムスタンプフィールドの使用をお勧めしますか? また、その理由 (MySQL を使用) はありますか?
サーバー側でPHPを使用しています。
MySQL のタイムスタンプは通常、レコードの変更を追跡するために使用され、レコードが変更されるたびに更新されることがよくあります。特定の値を保存する場合は、日時フィールドを使用する必要があります。
UNIX タイムスタンプとネイティブの MySQL 日時フィールドのどちらを使用するかを決定したい場合は、ネイティブ形式を使用してください。そのように MySQL 内で計算を行うことができ
、PHP で操作する場合は、レコードをクエリするときに("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")
値の形式を UNIX タイムスタンプに簡単に変更できます。("SELECT UNIX_TIMESTAMP(my_datetime)")
MySQL 5 以降では、TIMESTAMP値は保存のために現在のタイム ゾーンから UTC に変換され、検索のために UTC から現在のタイム ゾーンに変換されます。(これは TIMESTAMP データ型でのみ発生し、DATETIME などの他の型では発生しません。)
デフォルトでは、各接続の現在のタイム ゾーンはサーバーの時間です。タイム ゾーンは、 MySQL Server Time Zone Supportで説明されているように、接続ごとに設定できます。
行のメタデータ(作成または変更された日付)以外には、常にDATETIMEフィールドを使用します。
MySQLのドキュメントに記載されているように:
DATETIMEタイプは、日付と時刻の両方の情報を含む値が必要な場合に使用されます。MySQLは、DATETIME値を「YYYY-MM-DDHH:MM:SS」形式で取得して表示します。サポートされる範囲は、「1000-01-0100:00:00」から「9999-12-3123:59:59」です。
..。
TIMESTAMPデータ型の範囲は、「1970-01-0100:00:01」UTCから「2038-01-0903:14:07」UTCです。MySQLのバージョンとサーバーが実行されているSQLモードに応じて、さまざまなプロパティがあります。
一般的に使用されているタイムスタンプの下限に達する可能性が非常に高くなります。たとえば、誕生日の保存などです。
以下の例は、変更されていない場所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:日時とタイムスタンプのデータ型を見つけられるように、回答を記事に変換しました。
主な違いは、TIMESTAMP が設定の影響を受けるのに対し、DATETIME は一定であることtime_zone
です。
したがって、タイム ゾーン間でクラスターを同期した場合 (または将来的に同期する可能性がある場合) にのみ問題になります。
簡単に言えば、オーストラリアにデータベースがあり、そのデータベースのダンプを取得してアメリカのデータベースを同期/入力すると、TIMESTAMP は更新され、新しいタイム ゾーンでのイベントのリアルタイムが反映されますが、DATETIME はイベントの時刻は引き続き au タイム ゾーンで反映されます。
TIMESTAMP が使用されるべき場所で DATETIME が使用されている好例は Facebook です。Facebook のサーバーでは、タイム ゾーン間で何が起こったのかがまったくわかりません。メッセージが実際に送信される前に、メッセージに返信していると言われている会話をしていたことがあります。(もちろん、これは、時刻が同期されずに投稿されている場合、メッセージング ソフトウェアの不適切なタイム ゾーン変換が原因である可能性もあります。)
私はセマンティックベースでこの決定を下します。
(多かれ少なかれ) 一定の時点を記録する必要がある場合は、タイムスタンプを使用します。たとえば、レコードがデータベースに挿入されたときや、何らかのユーザー アクションが発生したときなどです。
日付/時刻を任意に設定および変更できる場合は、日時フィールドを使用します。たとえば、ユーザーが後で変更予定を保存できる場合などです。
DATETIME フィールドも TIMESTAMP フィールドも使用しないことをお勧めします。特定の日全体 (誕生日など) を表したい場合は DATE 型を使用しますが、それよりも具体的な場合は、単位ではなく実際の瞬間を記録することにおそらく関心があります。時間 (日、週、月、年)。DATETIME または TIMESTAMP を使用する代わりに、BIGINT を使用して、エポック (Java を使用している場合は System.currentTimeMillis()) からのミリ秒数を単純に格納します。これにはいくつかの利点があります。
この問題は、金額 (つまり $1.99) をデータベースに格納する方法と密接に関連しています。Decimal を使用するか、データベースの Money 型を使用するか、最悪の場合 Double を使用する必要がありますか? これらの 3 つのオプションはすべて、上記と同じ理由でひどいものです。解決策は、BIGINT を使用してお金の価値をセントで保存し、ユーザーに値を表示するときにセントをドルに変換することです。データベースの仕事はデータを保存することであり、そのデータを解釈することではありません。データベース (特に Oracle) で見られるこれらの派手なデータ型はすべて、ほとんど追加せず、ベンダー ロックインへの道を歩み始めます。
TIMESTAMP は 4 バイトで、DATETIME は 8 バイトです。
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
しかし、scronideが言ったように、1970年の下限があります.将来起こる可能性のあるものには素晴らしいです;)
本当に、アプリケーションに依存します。
Sanghaiでの予約のために、ユーザーがニューヨークのサーバーにタイムスタンプを設定することを検討してください。これで、ユーザーがSanghaiに接続すると、東京のミラーサーバーから同じ予定のタイムスタンプにアクセスします。彼は、元のニューヨーク時間からオフセットされた東京時間での予定を見るでしょう。
したがって、予定やスケジュールなどのユーザー時間を表す値の場合は、日時の方が適しています。これにより、サーバーの設定に関係なく、ユーザーは希望する正確な日時を制御できます。設定時間は設定時間であり、サーバーのタイムゾーン、ユーザーのタイムゾーン、または夏時間の計算方法の変更(はい、変更されます)の影響を受けません。
一方、支払いトランザクション、テーブルの変更、ロギングなどのシステム時間を表す値には、常にタイムスタンプを使用します。サーバーを別のタイムゾーンに移動したり、異なるタイムゾーンのサーバー間で比較したりしても、システムは影響を受けません。
タイムスタンプもデータベース上で軽量であり、インデックス作成が高速です。
ない。DATETIME
and型は、TIMESTAMP
一般的なユース ケースでは根本的に壊れています。MySQL は将来それらを変更します。BIGINT
他の何かを使用する特別な理由がない限り、UNIX タイムスタンプを使用する必要があります。
選択がより簡単で、この回答の分析と一般的な推奨事項が必要ない特定の状況を次に示します。
日付のみ— 日付のみ (次の旧正月の日付、2022 年 2 月 1 日など) を気にし、その日付が適用されるタイムゾーンを明確に理解している場合 (または、次の場合のように気にしない場合)旧正月の)DATE
列タイプを使用します。
挿入時間を記録する— データベース内の行の挿入日時をログに記録していて、アプリケーションが今後 17 年以内に壊れてもかまわない場合TIMESTAMP
は、デフォルト値の を使用してCURRENT_TIMESTAMP()
ください。
TIMESTAMP
壊れているのですか?TIMESTAMP
タイプは UTC タイムゾーンでディスクに保存されます。これは、サーバーを物理的に移動しても壊れないことを意味します。いいですよね✅。ただし、現在定義されているタイムスタンプは、2038 年には完全に機能しなくなります❌。
INSERT INTO
あなたまたは列SELECT FROM
のたびTIMESTAMP
に、クライアント/アプリケーション サーバーの物理的な場所 (つまり、タイムゾーンの構成) が考慮されます。アプリケーション サーバーを移動すると、日付が壊れます ❌。
VARCHAR
壊れているのですか?このVARCHAR
型を使用すると、非ローカルの日付/時刻/両方を ISO 8601 形式で明確に保存でき、2037 年以降の日付に対しても機能します。Zulu 時刻を使用するのが一般的ですが、ISO 8601 では任意のオフセットをエンコードできます。MySQL の日付と時刻の関数は、日付/時刻/両方が予期される場所の入力として文字列をサポートしますが、入力がタイムゾーン オフセットを使用する場合、結果は正しくないため、これはあまり役に立ちません。
またVARCHAR
、余分なバイト数のストレージも使用します。
DATETIME
壊れているのですか?aDATETIME
は aDATE
と aTIME
を同じ列に格納します。タイムゾーンが理解されない限り、これらのことはどちらも意味がなく、タイムゾーンはどこにも保存されません❌。タイムゾーンはデータと密接に関連しているため、目的のタイムゾーンをコメントとして列に入力する必要があります。列コメントを使用する人はほとんどいないため、これは発生するのを待っている間違いです。私はアリゾナからサーバーを継承したので、常にすべてのタイムスタンプをアリゾナ時間から別の時間に変換する必要があります。
(更新 2021-12-08 何年にもわたる稼働時間の後にサーバーを再起動し、データベース クライアント (アップグレードあり) が UTC にリセットされました。つまり、アプリケーションはリセットの前後の日付を異なる方法で処理する必要があります。ハードコード!)
DATETIME
aが正しい唯一の状況は、次の文を完成させることです。
あなたの 2020 年の太陽の新年はちょうど に始まります
DATETIME("2020-01-01 00:00:00")
。
sには他に良い使い方はありませんDATETIME
。おそらく、デラウェア州の市政府の Web サーバーを想像するでしょう。確かに、このサーバーとこのサーバーにアクセスするすべての人々のタイムゾーンは、東部タイムゾーンのデラウェアにあると暗示される可能性がありますよね? 違う!このミレニアムでは、サーバーは「クラウド」に存在すると考えられています。したがって、サーバーはいつか移動するため、特定のタイムゾーンでサーバーを考えるのは常に間違っています.
注: MySQLはリテラルでタイム ゾーン オフセットをサポートするようになりました ( @Marko に感謝します)。これにより、 s の挿入がより便利になるかもしれませんが、データの不完全で無用な意味には対応していません。この致命的な問題は、上記の ("❌") を識別します。DATETIME
DATETIME
BIGINT
?定義:
CREATE TEMPORARY TABLE good_times (
a_time BIGINT
)
特定の値を挿入します。
INSERT INTO good_times VALUES (
UNIX_TIMESTAMP(CONVERT_TZ("2014-12-03 12:24:54", '+00:00', @@global.time_zone))
);
またはもちろん、これは次のようにアプリケーションからはるかに優れています。
$statement = $myDB->prepare('INSERT INTO good_times VALUES (?)');
$statement->execute([$someTime->getTimestamp()]);
選択する:
SELECT a_time FROM good_times;
ここでの範囲を超えて、相対的な時間 (過去 30 日以内の投稿を選択し、登録から 10 分以内に購入したユーザーを見つける) をフィルタリングする手法があります。
TIMESTAMP は常に UTC (つまり、1970 年 1 月 1 日から UTC で経過した秒数) であり、MySQL サーバーはそれを接続タイムゾーンの日付/時刻に自動変換します。長期的には、時間データが常に UTC であることがわかっているため、TIMESTAMP が適しています。たとえば、別のサーバーに移行したり、サーバーのタイムゾーン設定を変更したりしても、日付が台無しになることはありません。
注: デフォルトの接続タイムゾーンはサーバーのタイムゾーンですが、これはセッションごとに変更できます (変更する必要があります) (「 」を参照SET time_zone = ...
)。
フィールドはフィールドのtimestamp
特殊なケースですdatetime
。timestamp
特別なプロパティを持つ列を作成できます。作成時および/または更新時に自身を更新するように設定できます。
「より大きな」データベース用語でtimestamp
は、いくつかの特殊なケースのトリガーがあります。
何が正しいかは、あなたが何をしたいかによって完全に異なります。
DATETIME、TIMESTAMP、DATE の比較
[.fraction] とは何ですか?
ソース:
MySQL では、テーブルの列を作成するときに、以下の行に沿って何かを使用できることに注意してください。
on update CURRENT_TIMESTAMP
これにより、行を変更するたびに時刻が更新され、最終編集情報を保存するのに非常に役立つ場合があります。ただし、これはタイムスタンプでのみ機能し、日時では機能しません。
MySQL と PHP を使用するときは、常に Unix タイムスタンプを使用します。これの主な理由は、PHP のデフォルトの日付メソッドがタイムスタンプをパラメーターとして使用するため、解析は必要ありません。
PHP で現在の Unix タイムスタンプを取得するには、単に実行time();
し、MySQL で実行しますSELECT UNIX_TIMESTAMP();
。
私の経験から、挿入が1回だけ行われる日付フィールドが必要で、その特定のフィールドに対して更新やその他のアクションを実行したくない場合は、日時を使用してください。
たとえば、 REGISTRATIONDATEフィールドuser
を持つテーブルについて考えてみます。そのテーブルで、特定のユーザーの最後のログイン時刻を知りたい場合は、タイムスタンプタイプのフィールドを使用して、フィールドが更新されるようにします。user
phpMyAdminからテーブルを作成している場合、デフォルト設定では、行の更新が発生したときにタイムスタンプフィールドが更新されます。提出されたタイムスタンプが行の更新で更新されていない場合は、次のクエリを使用して、タイムスタンプフィールドを自動更新することができます。
ALTER TABLE your_table
MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
タイムスタンプ データ型は日付と時刻を格納しますが、datetime のように現在のタイムゾーン形式ではなく UTC 形式で格納します。データをフェッチすると、timestamp はそれを現在のタイムゾーン時間に再度変換します。
米国にいて、米国のタイムゾーンを持つサーバーからデータを取得しているとします。次に、米国のタイムゾーンに従って日付と時刻を取得します。タイムスタンプ データ型の列は、行が更新されると常に自動的に更新されます。そのため、特定の行が最後にいつ更新されたかを追跡すると便利です。
詳細については、ブログ投稿Timestamp Vs Datetimeを参照してください。
私は常にUnixタイムスタンプを使用します。これは、多くの日時情報を処理するとき、特にタイムゾーンの調整、日付の加算/減算などを実行するときに、正気を維持するためです。タイムスタンプを比較する場合、これによりタイムゾーンの複雑な要素が除外され、サーバー側の処理(アプリケーションコードまたはデータベースクエリ)でリソースを節約できるため、より重い日時の加算/減算ではなく、軽量の演算を使用できます。関数。
検討する価値のあるもう1つのこと:
アプリケーションを構築している場合、データを今後どのように使用する必要があるかはわかりません。たとえば、データセット内の一連のレコードをサードパーティのAPIからの一連のアイテムと比較し、それらを時系列に並べる必要がある場合は、次のようになります。行のUnixタイムセット。MySQLタイムスタンプを使用することにした場合でも、保険としてUnixタイムスタンプを保存してください。
不必要なトリガーを使用せずに、現在の時刻に基づいて自分自身を自動更新する TIMESTAMP の機能には、卓越した有用性があることがわかりました。TIMESTAMP は言われたように UTC ですが、それは私だけです。
異なるタイムゾーン間で追跡できるため、たとえば相対時間を表示する必要がある場合は、UTC 時間が必要です。
datetime
タイムゾーンに関連する多くの問題やバグに直面した後、アプリケーションでの使用をやめました。私見の使用は、ほとんどの場合timestamp
よりも優れてdatetime
います。
何時ですか?そして、答えは「2019-02-05 21:18:30」のようなものになります。これは、別の部分がないため、完了していない、定義されていない答えです。どのタイムゾーンですか? ワシントン?モスクワ?北京?
タイムゾーンなしで日時を使用すると、アプリケーションが 1 つのタイムゾーンのみを処理することになりますが、タイムスタンプを使用するとdatetime
、異なるタイムゾーンで正確に同じ時点を表示できるという利点と柔軟性が得られます。
datetime
使用を後悔し、タイムスタンプでデータを保存したいと思ういくつかのケースを次に示します。
クライアントが快適に過ごせるように、計算を行わせずに、好みのタイムゾーンに基づいて時間を表示し、時間を意味のあるタイムゾーンに変換したいと考えています。タイムゾーンを変更するだけで、すべてのアプリケーション コードは同じになります。(実際には、アプリケーションの開始時にタイムゾーンを定義するか、PHP アプリケーションの場合は処理を要求する必要があります)
SET time_zone = '+2:00';
滞在する国を変更し、別のタイムゾーンでデータを表示しながら (実際のデータを変更せずに) データを維持する作業を続けます。
datetime
= アプリケーションは 1 つのタイムゾーンをサポートします (挿入と選択の両方で)
timestamp
= アプリケーションは任意のタイムゾーンをサポートします (挿入と選択の両方で)
この回答は、タイムゾーンに関するタイムスタンプの柔軟性と使いやすさを強調するためだけのものであり、列のサイズ、範囲、分数などの他の違いはカバーしていません。
Timestamp と Datetime のもう 1 つの違いは、Timestamp ではデフォルト値を NULL にできないことです。
私はタイムスタンプを使用することを好みます。これにより、すべてを 1 つの一般的な生の形式に保ち、データを PHP コードまたは SQL クエリでフォーマットすることができます。コード内ですべてを数秒で保持できると便利な場合があります。
私は 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);
これまで言及されていなかったのは、DEFAULT CURRENT_TIMESTAMP は Timestamp でのみ機能し、DateTime タイプのフィールドでは機能しないということです。
これは、DateTime のみを使用でき、Timestamp を使用できない MS Access テーブルに関連します。
ここでの多くの回答は、明確に定義された時点を表す必要がある場合に備えて、タイムスタンプとして保存することを提案しています。ただし、慣例によりすべてを UTC で保存する場合は、datetime で特定の時点を持つこともできます。
BIGINT
UTCの保存中に署名なしを使用するだけです...
その後、PHP で現地時間に調整することができます。
でDATETIME
選択しFROM_UNIXTIME( integer_timestamp_column )
ます。
明らかに、その列にインデックスを設定する必要があります。そうしないと、進歩はありません。