web-dev-qa-db-ja.com

CURRENT_TIMESTAMPを主キーとして使用できますか?

CURRENT_TIMESTAMPPRIMARY KEYとして使用できますか?

2つ以上の異なるINSERTが同じCURRENT_TIMESTAMPを取得する可能性はありますか?

10
John Puskin

documentation のとおり、CURRENT_TIMESTAMPの精度はマイクロ秒です。したがって、衝突の確率は低くなりますが、可能です。

発生するバグを想像してみてくださいveryめったになく、データベースエラーを引き起こします。それをデバッグするのはどれほど難しいですか?これは、少なくとも決定論的なバグよりもはるかに悪いバグです。

より広範なコンテキスト:シーケンスでのこれらの小さなニュアンスはおそらく避けたいでしょう。これは、MySQLに慣れている場合は特に厄介です。

さらに、トランザクション(ほとんどのWebフレームワーク、特にJava ones、do!))を使用している場合、タイムスタンプはトランザクション内で同じになります!デモ:

postgres=# begin;
BEGIN
postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

postgres=# select current_timestamp;
       current_timestamp       
-------------------------------
 2018-08-06 02:41:42.472163+02
(1 Zeile)

またね? 2つの選択、まったく同じ結果。私はそれほど速くタイプしません。 ;-)

-

シーケンスの使用を避けて簡単にIDが必要な場合は、レコードの実際の識別子からハッシュ値を生成します。たとえば、データベースに人間が含まれていて、その生年月日、母親の旧姓、本名がそれらを一意に識別していることがわかっている場合は、

md5(mother_name || '-' || given_name || '-' birthday);

iDとして。それ以外に、テーブルにインデックスを付けた後にCreationDate列を使用できますが、これはキーではありません(idです)。

追伸一般に、DBを可能な限り確定的にすることは非常に良い習慣です。つまり同じ操作でDBにまったく同じ変更が作成される。タイムスタンプベースのIDは、この重要な機能に失敗します。何かをデバッグまたはシミュレーションしたい場合はどうなりますか?操作を再生すると、同じオブジェクトが別のIDで作成されます ...追跡するのはそれほど難しくなく、多くの作業時間を節約できます。

P.s.2上記の理由により、将来コードをチェックする人は誰でも、タイムスタンプで生成されたIDを確認することはできません。

CURRENT_TIMESTAMPが2つの後続のINSERT(または複数の行を持つ単一のINSERT)に2つの同一の値を提供する可能性があるからではありません。

代わりに、時間ベースのUUIDを使用してください: id_generate_v1mc()

10
Linas

厳密に言うと:いいえCURRENT_TIMESTAMP関数であるためおよび PRIMARY KEY 制約を形成できるのは、1つ以上のテーブルcolumnsのみです。

列にPRIMARY KEY制約をデフォルト値CURRENT_TIMESTAMPで作成する場合、答えははい、できます。息子の頭からりんごを撃つことを妨げるようなものは何もないように、それを行うことを妨げるものはありません。質問の目的を定義しない限り、質問はまだ意味がありません。列とテーブルはどのようなデータを保持することになっていますか?どのルールを実装しようとしていますか?

CURRENT_TIMESTAMPSTABLE関数であり、同じトランザクション(トランザクションの開始時刻)に対して同じ値を返すため、通常、アイデアは重複キーエラーに遭遇します。同じトランザクション内の複数のINSERTは、すでに説明されている他の回答と同様に、衝突するようにバインドされています。 マニュアル:

これらの関数は現在のトランザクションの開始時間を返すため、それらの値はトランザクション中に変更されません。これは機能と見なされます。1つのトランザクションが「現在の」時間の一貫した概念を持つことができるようにして、同じトランザクション内の複数の変更が同じタイムスタンプを持つようにすることを目的としています。

Postgresのタイムスタンプは、最大6の小数桁(マイクロ秒の分解能)を表す8バイトの整数として実装されます。

Ifマイクロ秒あたり1行以下を保持することになっているテーブルを作成していて、その条件が変更されない(sensor_reading_per_microsecond)、そしてそれは意味をなすかもしれません。重複する行は仮定で、重複キー違反エラーが発生します。ただし、これはエキゾチックな例外です。そして、データ型timestamptztimestampではない)がおそらく望ましいでしょう。見る:

代わりに、代わりに代理シリアル主キーを使用します。そして、タイムスタンプ列にUNIQUE制約を追加します。 RDBMSの実装の詳細に依存せずに、起こりうる複雑さを減らします。

7