Może CURRENT_TIMESTAMP
być używany jako PRIMARY KEY
?
Czy istnieje możliwość, że dwa lub więcej różnych WSTAWEK dostanie to samo CURRENT_TIMESTAMP
?
Może CURRENT_TIMESTAMP
być używany jako PRIMARY KEY
?
Czy istnieje możliwość, że dwa lub więcej różnych WSTAWEK dostanie to samo CURRENT_TIMESTAMP
?
Odpowiedzi:
Zgodnie z dokumentacją dokładność CURRENT_TIMESTAMP
wynosi mikrosekund. Zatem prawdopodobieństwo kolizji jest niskie, ale możliwe.
Teraz wyobraź sobie błąd, który zdarza się bardzo rzadko i powoduje błędy bazy danych. Jak trudno jest to debugować? Jest to znacznie gorszy błąd niż ten, który jest co najmniej deterministyczny.
Szerszy kontekst: prawdopodobnie chcesz uniknąć tych małych niuansów w sekwencjach, co jest szczególnie denerwujące, jeśli jesteś przyzwyczajony do MySQL.
Ponadto, jeśli używasz transakcji (większość frameworków internetowych, szczególnie Java, zrób!), Znaczniki czasu będą takie same w transakcji! Demonstracja:
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)
Do zobaczenia? Dwa selekcje, dokładnie taki sam wynik. Nie piszę tak szybko. ;-)
-
Jeśli chcesz łatwo identyfikować, unikając użycia sekwencji, wygeneruj pewną wartość skrótu na podstawie rzeczywistych identyfikatorów rekordów. Na przykład, jeśli w Twojej bazie danych znajdują się ludzie i wiesz, że ich data urodzenia, nazwisko panieńskie matki i prawdziwe nazwisko jednoznacznie ich identyfikują, użyj
md5(mother_name || '-' || given_name || '-' birthday);
jako identyfikator Poza tym możesz użyć CreationDate
kolumny po tym, co indeksujesz tabelę, ale nie jest to klucz (który jest id).
Ps Ogólnie rzecz biorąc, bardzo dobrą praktyką jest, aby twoja DB była tak deterministyczna, jak to możliwe. To znaczy ta sama operacja powinna stworzyć dokładnie taką samą zmianę w DB . Identyfikator oparty na znacznikach czasu nie spełnia tej ważnej funkcji. Co jeśli chcesz coś debugować lub symulować? Ponownie odtworzysz operację, a ten sam obiekt zostanie utworzony z innym identyfikatorem ... naprawdę nie jest trudny do naśladowania i oszczędza wiele godzin pracy.
Ps2 Każdy, kto sprawdzi kod w przyszłości, nie będzie miał najlepszej opinii na podstawie identyfikatorów wygenerowanych znacznikami czasu z powyższych powodów.
INSERT
wiele wierszy, wszystkie otrzymają to samo current_timestamp
. A potem masz wyzwalacze ...
Nie do końca, ponieważ CURRENT_TIMESTAMP może podać dwie identyczne wartości dla dwóch kolejnych WSTAWEK (lub jednego WSTAWU z wieloma wierszami).
Zamiast tego użyj UUID opartego na czasie: uuid_generate_v1mc () .
Ściśle mówiąc: Nie. Ponieważ CURRENT_TIMESTAMP
jest funkcją i tylko jedna lub więcej kolumn tabeli może tworzyć PRIMARY KEY
ograniczenie.
Jeśli masz na myśli, aby stworzyć PRIMARY KEY
presję na kolumnie z wartości domyślnej CURRENT_TIMESTAMP
, to odpowiedź brzmi: Tak, to możliwe . Nic nie powstrzymuje cię przed zrobieniem tego, tak jak nic nie powstrzymuje cię przed wystrzeleniem jabłek z głowy syna. Pytanie wciąż nie miałoby sensu, dopóki nie zdefiniujesz jego celu. Jakie dane mają przechowywać kolumna i tabela? Jakie zasady próbujesz wdrożyć?
Zazwyczaj pomysł jest związany napotkasz duplikatów kluczowych błędów, ponieważ CURRENT_TIMESTAMP
jest to STABLE
funkcja powrocie taką samą wartość dla tej samej transakcji (czas rozpoczęcia transakcji). Wiele WSTAWEK w tej samej transakcji musi się zderzyć - podobnie jak inne zilustrowane już odpowiedzi. Instrukcja:
Ponieważ funkcje te zwracają czas rozpoczęcia bieżącej transakcji, ich wartości nie zmieniają się podczas transakcji. Jest to uważane za cechę: celem jest umożliwienie jednej transakcji spójnego pojęcia „bieżącego” czasu, tak aby wielokrotne modyfikacje w ramach tej samej transakcji były opatrzone tym samym znacznikiem czasu.
Znaczniki czasu Postgres są implementowane jako 8-bajtowe liczby całkowite reprezentujące do 6 cyfr ułamkowych (rozdzielczość mikrosekundowa).
Jeśli budujesz tabelę, która ma pomieścić nie więcej niż jeden wiersz na mikrosekundy, a warunek ten nie ulegnie zmianie (coś o nazwie sensor_reading_per_microsecond
), wówczas może to mieć sens. Zduplikowane wiersze powinny wywoływać błąd naruszenia klucza duplikatu. To jednak egzotyczny wyjątek. I typ danych timestamptz
(nie timestamp
) byłby prawdopodobnie preferowany. Widzieć:
Wolałbym zamiast tego użyć zastępczego klucza podstawowego szeregowego. I dodaj UNIQUE
ograniczenie do kolumny znacznika czasu. Mniej możliwych komplikacji, nie polegających na szczegółach implementacji RDBMS.
sensor_reading_per_microsecond
Może nawet kolidować, jeśli nie można absolutnie zagwarantować, że czas każdego odczytu jest idealnie zsynchronizowany w stosunku do poprzedniego; odchylenie poniżej mikrosekundy (co często nie jest niemożliwe) psuje schemat. Generalnie nadal całkowicie tego unikam. (Pamiętaj, jak wskazałeś w takim przypadku, pożądana kolizja może być pożądana!)