2012-10-30 1 views
50

Utworzyłem aplikację w Railsach na Heroku przy użyciu bazy danych PostgreSQL.Czy klucz UUID jako klucz podstawowy w PostgreSQL daje niepoprawną wydajność indeksu?

Ma kilka stołów zaprojektowanych, aby móc synchronizować z urządzeń mobilnych, w których dane mogą być tworzone w różnych miejscach. Dlatego mam pole uuid, które jest ciągiem przechowującym identyfikator GUID oprócz klucza kluczowego auto increment. Uuid to ten, który jest komunikowany między serwerem a klientami.

Po uruchomieniu mechanizmu synchronizacji po stronie serwera zdałem sobie sprawę, że prowadzi to do problemów z wydajnością, gdy trzeba odwzorować między uuid < -> id cały czas (podczas pisania obiektów, muszę zapytać o identyfikator użytkownika, aby uzyskać identyfikator przed zapisaniem, a odwrotnie przy wysyłaniu danych).

mam teraz myśleć o przejściu na tylko za pomocą UUID jako klucz podstawowy dzięki czemu pisanie i czytanie o wiele prostsze i szybsze.

Czytałem, że UUID jako klucz podstawowy czasami może dać złe wyniki indeksu (indeks) fragmentacji przy użyciu indeksu klastrowego klucza podstawowego. Czy PostgreSQL cierpi na ten problem, czy może używać UUID jako klucza podstawowego?

już mam kolumnę UUID dzisiaj więc przechowywanie mądry będzie lepiej, bo upuść kolumnę id regularny.

+2

Czy pole "id" jest używane jako klucz obcy przez jakąkolwiek inną relację w bazie danych? Czy zachowujesz tylko to pole "id", ponieważ uważasz, że KEY PRIMARY powinien być typem seryjnym z powodów, które opisałeś? –

+0

Tworzenie klastrów za pomocą syntetycznego klucza podstawowego to korzyść tylko wtedy, gdy masz często dostęp do ścieżki, która chce zapytać o zakres tych wartości pkeya - jest to dość rzadkie w prawdziwym świecie. UUID jest idealnie cienkim typem dla klucza podstawowego, jest wystarczająco kompaktowy (16 bitów) i szybszy w porównaniu z tekstem. – dbenhur

+0

@Joshua Pola id są używane jako klucze obce, pola UUID są używane tylko jako zwykłe pola używane do odwoływania się do relacji podczas komunikacji (to potrzeba tłumaczenia między nimi przez cały czas) – thejaz

Odpowiedz

55

(pracuję na Heroku PostgreSQL)

Używamy UUID jako podstawowych klawiszy na kilku systemach i działa świetnie.

polecam używać rozszerzenia uuid-ossp, a nawet postgres generowania UUID dla Ciebie:

heroku pg:psql 
psql (9.1.4, server 9.1.6) 
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256) 
Type "help" for help. 

dcvgo3fvfmbl44=> CREATE EXTENSION "uuid-ossp"; 
CREATE EXTENSION 
dcvgo3fvfmbl44=> CREATE TABLE test (id uuid primary key default uuid_generate_v4(), name text); 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "test_pkey" for table "test" 
CREATE TABLE 
dcvgo3fvfmbl44=> \d test 
       Table "public.test" 
Column | Type |    Modifiers    
--------+------+------------------------------------- 
id  | uuid | not null default uuid_generate_v4() name | text | 
Indexes: 
    "test_pkey" PRIMARY KEY, btree (id) 

dcvgo3fvfmbl44=> insert into test (name) values ('hgmnz'); 
INSERT 0 1 
dcvgo3fvfmbl44=> select * from test; 
        id     | name 
--------------------------------------+------- 
e535d271-91be-4291-832f-f7883a2d374f | hgmnz 
(1 row) 

skuteczności EDIT implikacje

Będzie zawsze zależy od obciążenia.

Liczba całkowita klucza podstawowego ma tę zaletę, że lokalizacja danych podobnych jest bliżej siebie. Może to być pomocne w przypadku np. Zapytań typu zakresu, takich jak WHERE id between 1 and 10000, chociaż rywalizacja o blokady jest gorsza.

Jeśli obciążenie jest całkowicie losowy odczyt w które zawsze sprawiają wyszukiwań klucza podstawowego, nie powinno być żadnego mierzalnego degradacja wydajność: płacisz tylko za większego typu danych.

Piszecie dużo do tego stołu i czy ten stół jest bardzo duży? Możliwe, choć nie zmierzyłem tego, że istnieją implikacje w utrzymywaniu tego indeksu. W przypadku wielu zestawów danych identyfikatory UUID są w porządku, a używanie identyfikatorów UUID jako identyfikatorów ma kilka fajnych właściwości.

Wreszcie, nie może być najbardziej wykwalifikowaną osobę w celu omówienia lub porady na temat tego, jak nigdy nie uruchamiać stolik wystarczająco duży z PK UUID gdzie stało się problemem. YMMV. (Powiedziawszy to, chciałbym usłyszeć o ludziach, którzy mają problemy z podejściem!)

+0

Dzięki za odpowiedź. Tworzę UUID w modelach Rails dzisiaj, czy to jest tak dobre, jak korzystanie z powyższej funkcji bazy danych? – thejaz

+0

Tak, nie widzę z tym problemu, o ile tylko modele szyn są jedynymi elementami wstawiającymi dane do bazy danych. – hgmnz

+0

@hgmnz: Jak zdefiniować kolumnę identyfikatora, aby była uuid przez migrację Rails? –

1

Zgodnie z przyjętą odpowiedzią zapytania dotyczące zakresu mogą być w tym przypadku powolne, ale nie tylko w przypadku id.

Autoinkrementacja jest naturalnie sortowana według daty, więc gdy używana jest autorekrecja, dane są przechowywane chronologicznie na dysku (patrz B-Tree), co przyspiesza odczyty (bez poszukiwania dysków twardych).Na przykład, jeśli wymienisz wszystkich użytkowników, naturalna kolejność zostanie utworzona według daty, która jest taka sama, jak autoinkrementacji, więc zapytania o zakresy będą wykonywane szybciej na dyskach twardych na dysku SSD, to chyba nie będzie różnicy, ponieważ dyski SSD są z założenia zawsze losowe dostęp (bez szukania głowy, bez części mechanicznych, tylko czysta energia elektryczna)