Wygląda na to, że już wybrałeś rozwiązanie - wrzucę jeszcze notkę dla potomnych.
Dlaczego ENUM to zły pomysł?
W tej chwili masz 4 możliwe statusy, więc robisz ENUM z czterema opcjami. Załóżmy, że Twój klient pracuje tak przez 2 lata i potem dochodzi do wniosku, że potrzebuje nowy status. Przez te 2 lata zebrało się 2 mln zamówień (bo klient dobrze prosperuje ;)). Żeby dodać nowy status musisz wykonać ALTER na tabeli, który będzie trwał bardzo długo. Nie można tego nazwać elastyczną strukturą. Dodatkowo jeśli chciałbyś wyświetlić wszystkie możliwe statusy w polu typu select na stronie to jedyna sensowna droga to wypisanie ich w kodzie "na sztywno".
Tworząc tabelę słownikową nic nie tracisz na wydajności - gdybyś jej nie miał to wówczas miałbyś jedno z proponowanych rozwiązań, czyli samą kolumnę int - jeśli nie chcesz nikt Ci nie każe robić JOINa do tabeli słownikowej, ale za to gdy ktoś "odziedziczy" Twój kod to od razu będzie wiedział co dany numerek statusu oznacza (a i Ty się sam w tym nie pogubisz). Tak jak wspomniałem - na wydajności nie tracisz nic, nawet jeśli do każdego zapytania dopiszesz JOIN do słownika to będzie to bardzo szybkie złączenie - niezauważalne nawet przy wyciąganiu dużej ilości danych z dużej tabeli.
Pozdrawiam
Ja ekspertem od baz ne jestem, ale:
Gdy testuję, to każdy JOIN o ileś spowalnia.
Używanie tablicy słownikowej i operowanie na intach (bez join) nie jest zbyt wygodne.
Listę typów z enum można selectem pozyskać, nic nie trzeba na szytywno w kodzie wpisywać.
Dodanie nowego pola do enum też jest proste.
http://stackoverflow.com/questions/1616123/sql-query-to-get-all-values-a-enum-can-have/1616161
https://www.postgresql.org/docs/9.1/static/sql-altertype.html
[ALTER TYPE ... ADD VALUE (the form that adds a new value to an enum type) cannot be executed inside a transaction block.]
Poświęciłem się, zrobiłem eksperyment. W tym przykładzie mam znacznie większy słownik, bo tabelę z krajami. Ilość krajów
wynosi 300, więc użycie tabeli słownikowej jest znacznie bardziej wskazane, ale czy na pewno?
Przykład zapytania
Kopiuj
select * from users as u join countries as c on c.id = u.id_country order by c.name,u.name offset 10000 limit 10 ;
id | id_country | name | id | name
---------+------------+------+-----+-------
1486520 | 227 | HGFC | 227 | AAEFB
749251 | 227 | HGFC | 227 | AAEFB
1113106 | 227 | HGFD | 227 | AAEFB
2630231 | 227 | HGFD | 227 | AAEFB
2421530 | 227 | HGFD | 227 | AAEFB
2200889 | 227 | HGFD | 227 | AAEFB
1843388 | 227 | HGFE | 227 | AAEFB
1334618 | 227 | HGFE | 227 | AAEFB
2908654 | 227 | HGFE | 227 | AAEFB
1400578 | 227 | HGFH | 227 | AAEFB
Time: 64214,685 ms
Czas jak widać, 64 sekundy.
Teraz mała sztuczka, dodaję kolumnę do użytkowników z nazwą kraju i dodaję indeks:
Kopiuj
alter table users add column country varchar(255);
update users as u set country = (select name from countries as c where c.id = u.id_country);
create index users_cn on users(country,name);
Kopiuj
select * from users as u order by u.country,u.name offset 10000 limit 10 ;
id | id_country | name | country
---------+------------+------+---------
749251 | 227 | HGFC | AAEFB
1486520 | 227 | HGFC | AAEFB
1113106 | 227 | HGFD | AAEFB
2200889 | 227 | HGFD | AAEFB
2421530 | 227 | HGFD | AAEFB
2630231 | 227 | HGFD | AAEFB
1334618 | 227 | HGFE | AAEFB
1843388 | 227 | HGFE | AAEFB
2908654 | 227 | HGFE | AAEFB
724483 | 227 | HGFH | AAEFB
(10 rows)
Time: 38,939 ms
Czas 38ms, przyspieszenie 1650 razy - ale join nie spowalnia zapytań ;-)
Może łatwych zapytań nie spowalnia.
Przez dodanie pola varchar(255) rozmiar tabel znacznie się zwiększył, no ale cóż, nie ma optymalizacji za darmo.
Pozdrawiam