はじめに
Snowflakeには TIMESTAMP 型が 3種類 あります。
-
TIMESTAMP_NTZ— タイムゾーンなし -
TIMESTAMP_LTZ— セッションのタイムゾーンに連動 -
TIMESTAMP_TZ— タイムゾーンオフセットを保持
「とりあえず TIMESTAMP って書いておけばいいんでしょ?」と思いがちですが、タイムゾーンの扱いを誤るとデータの不整合やバグの温床になります。この記事では、3つの型の内部動作の違いをSQLの実行例を交えて解説します。
対象読者: Snowflake初学者〜中級者、SnowPro Core受験者
前提知識: SQLの基本操作、UTC(協定世界時)の概念
この記事はSnowflake公式ドキュメント(2026年3月時点)をもとに執筆しています。最新情報は公式ドキュメントをご確認ください。
参考リンク
TIMESTAMPエイリアスの仕組み
Snowflakeで単に TIMESTAMP と書くと、それは3つの型のいずれかへの エイリアス(別名) として扱われます。どの型にマッピングされるかは、セッションパラメータ TIMESTAMP_TYPE_MAPPING で決まります。
-- 現在のマッピングを確認
SHOW PARAMETERS LIKE 'TIMESTAMP_TYPE_MAPPING' IN SESSION;
デフォルトは TIMESTAMP_NTZ です。つまり、以下の2つは同じ意味になります。
CREATE TABLE sample (ts TIMESTAMP);
-- ↓ 実質的に同じ
CREATE TABLE sample (ts TIMESTAMP_NTZ);
TIMESTAMP のマッピング先はアカウントやセッションごとに変更可能です。チーム開発では「TIMESTAMP ではなく TIMESTAMP_NTZ / LTZ / TZ を明示的に指定する」のがベストプラクティスです。
3種類のTIMESTAMP型
以降の実行例では、次のテーブルを使います。
CREATE OR REPLACE TABLE ts_test (
id INT,
ts_ntz TIMESTAMP_NTZ,
ts_ltz TIMESTAMP_LTZ,
ts_tz TIMESTAMP_TZ
);
TIMESTAMP_NTZ — タイムゾーンなし
NTZは "No Time Zone" の略です。内部的にはいわゆる wallclock time(壁時計の時刻) をそのまま保存します。タイムゾーンの変換は一切行われません。
-- セッションをニューヨーク時間に設定して INSERT
ALTER SESSION SET TIMEZONE = 'America/New_York';
INSERT INTO ts_test (id, ts_ntz) VALUES (1, '2025-07-01 12:00:00');
-- セッションを東京時間に切り替えて INSERT
ALTER SESSION SET TIMEZONE = 'Asia/Tokyo';
INSERT INTO ts_test (id, ts_ntz) VALUES (2, '2025-07-01 12:00:00');
-- どのタイムゾーンで SELECT しても結果は同じ
ALTER SESSION SET TIMEZONE = 'UTC';
SELECT id, ts_ntz FROM ts_test;
| id | ts_ntz |
|---|---|
| 1 | 2025-07-01 12:00:00.000 |
| 2 | 2025-07-01 12:00:00.000 |
ポイント: セッションの TIMEZONE を変更しても、INSERT時もSELECT時も値は一切変わりません。文字列で渡した時刻がそのまま保存され、そのまま返ってきます。
TIMESTAMP_LTZ — セッションタイムゾーン連動
LTZは "Local Time Zone" の略です。内部的には UTC で保存しますが、SELECT時にセッションの TIMEZONE パラメータに従って自動変換して表示します。
-- ニューヨーク時間で INSERT
ALTER SESSION SET TIMEZONE = 'America/New_York';
INSERT INTO ts_test (id, ts_ltz) VALUES (3, '2025-07-01 12:00:00');
-- ニューヨーク時間で SELECT → 12:00 と表示
SELECT id, ts_ltz FROM ts_test WHERE id = 3;
| id | ts_ltz |
|---|---|
| 3 | 2025-07-01 12:00:00.000 -0400 |
-- 東京時間に切り替えて SELECT → 翌日 01:00 と表示
ALTER SESSION SET TIMEZONE = 'Asia/Tokyo';
SELECT id, ts_ltz FROM ts_test WHERE id = 3;
| id | ts_ltz |
|---|---|
| 3 | 2025-07-02 01:00:00.000 +0900 |
ポイント: 同じデータなのに、セッションの TIMEZONE によって表示される時刻が変わります。内部的にはUTCで統一されているため、グローバルなチームで「各自のローカル時間で見える」という利点があります。
INSERT時にタイムゾーン情報が付与されていない文字列を渡すと、セッションの TIMEZONE がローカル時間として解釈されます。異なるタイムゾーンのセッションから同じ文字列を INSERT すると、内部的に異なるUTC値が保存される点に注意してください。
TIMESTAMP_TZ — タイムゾーンオフセット保持
TZは "Time Zone" の略です。内部的には UTC + タイムゾーンオフセット をセットで保存します。
-- ニューヨーク時間で INSERT
ALTER SESSION SET TIMEZONE = 'America/New_York';
INSERT INTO ts_test (id, ts_tz) VALUES (4, '2025-07-01 12:00:00');
-- 東京時間に切り替えて SELECT
ALTER SESSION SET TIMEZONE = 'Asia/Tokyo';
SELECT id, ts_tz FROM ts_test WHERE id = 4;
| id | ts_tz |
|---|---|
| 4 | 2025-07-01 12:00:00.000 -0400 |
ポイント: セッションのタイムゾーンを変えても、INSERT時のオフセット(-0400)がそのまま表示されます。LTZとの最大の違いはここです。「データが作られた時点のタイムゾーン情報」を保持したい場合に適しています。
TIMESTAMP_TZ が保存するのは タイムゾーン名ではなくオフセット値(例: -0400)です。そのため、サマータイム(夏時間)の切り替わりを正しく追跡することはできません。例えば America/New_York は夏が -0400、冬が -0500 ですが、保存されるのはINSERT時点のオフセットのみです。
3型の比較まとめ
| 項目 | TIMESTAMP_NTZ | TIMESTAMP_LTZ | TIMESTAMP_TZ |
|---|---|---|---|
| 内部保存 | wallclock time | UTC | UTC + オフセット |
| INSERT時の変換 | なし | セッションTZ → UTC | セッションTZ → UTC + オフセット記録 |
| SELECT時の変換 | なし | UTC → セッションTZ | なし(オフセット付きで返す) |
| セッションTZ変更の影響 | なし | あり(表示が変わる) | なし |
| 値の比較基準 | wallclock値そのまま | UTC値 | UTC値 |
どれを選ぶ? ユースケース別ガイド
- TIMESTAMP_NTZ: ソースシステムのローカル時刻をそのまま保存したいとき。ETLでタイムゾーン変換を自分で管理する場合に向いています。Snowflakeのデフォルトでもあり、最もシンプルです。
- TIMESTAMP_LTZ: グローバルチームでデータを共有し、各メンバーが自分のタイムゾーンで時刻を確認したいとき。監査ログやイベントログなど「いつ起きたか」が重要なデータに適しています。
- TIMESTAMP_TZ: データの発生元のタイムゾーン情報を残したいとき。複数リージョンからデータを収集し、元の時刻とオフセットの両方を保持したい場合に有効です。
まとめ
- Snowflakeの
TIMESTAMPはエイリアスであり、デフォルトでTIMESTAMP_NTZにマッピングされる - NTZ はタイムゾーンを一切考慮せず、文字列をそのまま保存する最もシンプルな型
- LTZ は内部的にUTCで保存し、SELECT時にセッションのタイムゾーンで自動変換する
- TZ はUTC + INSERT時のオフセットを保持するが、タイムゾーン名やサマータイム情報は持たない
- チーム開発では
TIMESTAMPではなく 3型のいずれかを明示的に指定 するのがベストプラクティス