2011-10-24 15 views
16

Obecnie mam ten schemat:MySQL wydajność kwerendy dylemat: enum vs tabelach

CREATE TABLE `users` (
    `users_id` int(11) NOT NULL AUTO_INCREMENT, 
    `users_name` varchar(50), 
    `users_lastname` varchar(50), 
    `users_dob` date, 
    `users_type` int(11) NOT NULL default 0, 
    `users_access` int(11) NOT NULL default 0, 
    `users_level` int(11) NOT NULL default 0, 
    /* etc...*/ 
    PRIMARY KEY (`users_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

CREATE TABLE `users_types` (
    `types_id` int(11) NOT NULL AUTO_INCREMENT, 
    `types_name` varchar(50), 
    PRIMARY KEY (`types_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

/* etc..*/ 

Zapytanie:

SELECT 
    types_name AS user_type, 
    /* all other fields*/ 
    users.* 
    FROM users 
    INNER JOIN users_types ON (users.users_type=types_id); 
    /* INNER JOIN for all other tables*/ 
/* Rest of query */ 

Moje nowe rozwiązanie:

CREATE TABLE `users` (
    `users_id` int(11) NOT NULL AUTO_INCREMENT, 
    `users_name` varchar(50), 
    `users_lastname` varchar(50), 
    `users_dob` date, 
    `users_type` ENUM('type1', 'type2', 'type3'), 
    `users_access` ENUM('access1', 'access2', 'access3'), 
    `users_level` ENUM('level1', 'level2', 'level3'), 
    /* etc...*/ 
    PRIMARY KEY (`users_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

Zapytanie:

SELECT 
    * 
    FROM users 

Z tego, co widzę, wynika, że ​​ENUM jest bardzo prosty i może być bardzo szybki do wykonania.

  1. Mam rację? Czy silnik MySQL byłby szybszy do przetwarzania pola typu ENUM niż LEWEGO DOŁĄCZENIA?
  2. Czy korzystanie z ENUM jest dobrą praktyką?

Dzięki

+1

Tabele są dobre, jeśli lista wyliczeń zostanie zmieniona. To proste zapytanie o wstawienie/aktualizację. Enumy wymagałyby tabeli zmian. –

+0

liczby całkowite ze znakiem (4 bajty) dla typów odnośników wydają się nieco przesadzone - a co z niepodpisanymi znakami? –

+0

Należy użyć unsigned int? Mam ponad 200 000 użytkowników. – Tech4Wilco

Odpowiedz

19

Osobiście uważam, że należy użyć typu danych int, a emulacja tych danych powinna być wykonana w innej warstwie.

Definicja stołu jest kiepskim miejscem do przechowywania wartości enum. Trudno jest uzyskać łatwy dostęp, a podanie aplikacji umożliwiającej modyfikowanie definicji tabel jest problemem bezpieczeństwa (prawdopodobnie).

Zamiast tego, polecam użycie typu INT, a następnie w oprogramowaniu, tworząc model, który współdziała z bazą danych poniżej, aby uzyskać wygląd ENUM.

Po wybraniu tego projektu zmiana oprogramowania bazy danych jest banalna, nie trzeba przyznawać przywilejów "ALTER TABLE" do aplikacji produkcyjnej, a rozszerzanie wyliczenia jest łatwe. Dodatkowo redukujesz liczbę koniecznych programów do tłumaczenia z ENUM -> integer - można to zrobić w czasie kompilacji zamiast z każdym zapytaniem SQL bazy danych.

+0

, więc będziesz mieć plik dla tych opcji w osobnym pliku i użyjesz ich jako define lub coś np.: Define ('USER_ACCESS_ADMIN', 1) ;? – Tech4Wilco

+0

Tak, właśnie to zrobiłbym –

+0

dzięki za informacje – Tech4Wilco

1

1) Tak, byłoby szybciej, jak typ danych ENUM jest indeksowana w samej tabeli (czyli nie trzeba czytać inną tabelę dla każdego rekordu)

2) Tak, tak długo, jak nie chcesz używać tych pól w żadnej innej tabeli. Gdy tylko chcesz użyć danego pola w więcej niż jednej tabeli, powinieneś utworzyć osobną tablicę przeglądową dla tego pola. Ponadto, jeśli chcesz, aby pole zawierało wartości definiowane przez użytkownika (i nie wymagało od nich bezpośredniej modyfikacji bazy danych w celu ich zmiany), należy użyć oddzielnej tabeli.

+0

Dodawanie wpisów do wyliczenia w rzeczywistości nie wymusza przebudowy stołu, więc jest bardziej elastyczny niż myślisz. – Johan

+0

Wiem, to trochę trudniej utrzymać go, gdy trzeba zmodyfikować wpis w pliku information_schema.columns, aby zachować aktualność swojej listy ENUM. – Crontab

+0

Jest to prosta instrukcja 'alter table change column', nie wymagająca ingerencji w potrzebne informacje. – Johan