MySQL
 Computer >> コンピューター >  >> プログラミング >> MySQL

MySQLのDATETIME型とTIMESTAMP型の違いとは?特徴と使い分けを徹底解説

DATETIME型とTIMESTAMP型は、どちらも「YYYY-MM-DD HH:MM:SS」という形式で日付と時刻の両方を格納できるデータ型です。よく似ていますが、実際にはいくつかの重要な違いがあります。ここでは、それぞれの特徴を詳しく見ていきましょう。

DATETIME型とTIMESTAMP型の主な違い

1. 格納できる範囲

DATETIME型:「1000-01-01 00:00:00」から「9999-12-31 23:59:59」までの広い範囲の日付・時刻を扱えます。
TIMESTAMP型:「1970-01-01 00:00:01」から「2038-01-19 08:44:07」(UTC基準)までと、範囲が限定されます。これはUNIXタイムスタンプを32ビット整数で表現しているためで、いわゆる「2038年問題」の原因にもなっています。

2. 必要なストレージサイズ

DATETIME型は5バイト、TIMESTAMP型は4バイトを必要とします。小数秒を格納する場合は、それぞれ最大3バイトが追加されます。なお、MySQL 5.6.4より前のバージョンでは、DATETIME型は8バイトを使用していました。

3. タイムゾーン変換

MySQL 5以降では、TIMESTAMP型の値は保存時にセッションのタイムゾーンからUTCへ変換され、取得時に再びセッションのタイムゾーンへ戻されます。一方、DATETIME型はタイムゾーンによる変換を行わず、入力された値がそのまま保存されます。

4. インデックス

どちらの型の列にもインデックスを作成できます。ただし、TIMESTAMP型は内部的にUTCで値を保持するため、タイムゾーン設定が異なる環境間で範囲検索を行う場合は、結果の解釈に注意が必要です。

5. クエリキャッシュへの影響

NOW()やCURRENT_TIMESTAMP()のように実行ごとに結果が変わる非決定的な関数を含むクエリは、クエリキャッシュの対象になりません。なお、クエリキャッシュ機能自体はMySQL 5.7.20で非推奨となり、MySQL 8.0で削除されています。

それでは、両者の違いを実際に確認できる具体例を見てみましょう。

実行例

mysql> Create table test_datetime(time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.44 sec)

mysql> INSERT INTO test_datetime (time) values (CURRENT_TIMESTAMP);
Query OK, 1 row affected (0.04 sec)

mysql> Select * from test_datetime;
+---------------------+
| time                |
+---------------------+
| 2017-11-14 17:29:03 |
+---------------------+
1 row in set (0.00 sec)

mysql> Create table test_timestamp(time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.64 sec)

mysql> INSERT INTO test_timestamp (time) values (CURRENT_TIMESTAMP);
Query OK, 1 row affected (0.06 sec)

mysql> Select * from test_timestamp;
+---------------------+
| time                |
+---------------------+
| 2017-11-14 17:29:50 |
+---------------------+
1 row in set (0.00 sec)

次に、セッションのタイムゾーンをUTC-05:00に変更してから、同じテーブルを参照してみます。

mysql> SET @@session.time_zone = '-5:00';
Query OK, 0 rows affected (0.00 sec)

mysql> Select * from test_timestamp;
+---------------------+
| time                |
+---------------------+
| 2017-11-14 06:59:50 |
+---------------------+
1 row in set (0.00 sec)

実行結果

TIMESTAMP型のテーブルでは、タイムゾーンの変更に応じて表示時刻が「17:29:50」から「06:59:50」へと自動的に変換されました。これは、TIMESTAMP型が値をUTCで保持しているためです。

mysql> Select * from test_datetime;
+---------------------+
| time                |
+---------------------+
| 2017-11-14 17:29:03 |
+---------------------+
1 row in set (0.00 sec)

一方、DATETIME型のテーブルでは、タイムゾーンを変更しても値は「2017-11-14 17:29:03」のまま変わりません。この結果から、複数のタイムゾーンを扱うグローバルなサービスにはTIMESTAMP型が、タイムゾーンに依存しない固定の日時を保存したい場合にはDATETIME型が適していることがわかります。用途に応じて正しく使い分けることが、堅牢なデータベース設計のポイントです。

  1. MySQLにおける「!=NULL」と「IS NOT NULL」の違いとは?

    MySQLでは、値を!=NULLと比較すると、結果は必ずNULLになります。つまり、!=NULLという比較は意味を持ちません。NULLは「不明な値」を表すため、通常の比較演算子では判定できないのです。NULL値を判定するには、専用の演算子であるIS NOT NULLを使用します。ここでは、!=NULLとIS NOT NULLの違いを実際に確認するために、まずテーブルを作成します。テーブルの作成まず、次のコマンドでテーブルを作成します。mysql> create table DemoTable1970     (    

  2. Pythonのdatetime.now()とdatetime.today()の違いとは?使い分けを解説

    datetime.now() と datetime.today() の主な違い Pythonのdatetimeモジュールには、現在の日時を取得するためのメソッドとして datetime.now() と datetime.today() の2つがあります。どちらも現在のローカル日時を返す点で似ていますが、両者には重要な違いが存在します。 1. キーワード引数(tz引数)の有無 最大の違いは、datetime.now() はオプションのキーワード引数 tz(tzinfoオブジェクト)を受け取ることができるのに対し、datetime.today() は一切のキーワード引数を受け取らないという点です