2013-04-15 15 views
7

Co jest bardziej wydajnym (pod względem wydajności wykonywania zapytań) projektem tabeli bazy danych - długim lub szerokim?MySQL: Długi stół vs szeroki stół

Ie, to

id size price 
1 S 12.4 
1 M 23.1 
1 L 33.3 
2 S 3.3 
2 M 5.3 
2 L 11.0 

kontra tym

id S  M  L 
1 12.4 23.1 33.3 
2 3.3 5.3 11.0 

Ogólnie (I liczyć) sprowadza się do porównania wydajności między GROUP BY i wybierając kolumny bezpośrednio:

SELECT AVG(price) FROM table GROUP BY size 

lub

SELECT AVG(S), AVG(M), AVG(L) FROM table 

Po drugie jest nieco dłużej pisać (w kategoriach wielu kolumn), ale co z wydajnością tych dwóch? Jeśli to możliwe, jakie są ogólne zalety/wady każdego z tych formatów tabel?

Odpowiedz

5

Przede wszystkim są to dwa różne modele danych odpowiednie do różnych celów.

Mając na uwadze powyższe, będę oczekiwać drugi model będzie szybciej do agregacji, po prostu dlatego, że dane są pakowane bardziej zwarty, dlatego potrzebuje mniej I/O:

  • w grupie przez pierwszy model może być spełniony przez skanowanie pełne na indeksie {size, price}. Alternatywa dla indeksu jest zbyt wolna, gdy dane są zbyt duże, aby zmieścić się w pamięci RAM.
  • Zapytanie w drugim modelu może zostać spełnione przez pełne skanowanie tabeli. Nie jest wymagany indeks .

Ponieważ pierwsze podejście wymaga tabeli + indeksu, a drugie tylko samej tabeli, wykorzystanie pamięci podręcznej jest lepsze w drugim przypadku.Nawet jeśli pominiemy buforowanie i porównać indeks (bez stołu) w pierwszym modelu z tabelą w drugim modelu, podejrzewam indeks będzie większa niż w tabeli, po prostu dlatego, że fizycznie rejestruje size i ma nieużywane „dziury” typowy dla drzew typu B (chociaż to samo dotyczy tabeli, jeśli jest to clustered).

I wreszcie, drugi model nie posiada narzut konserwacji indeksu, które mogłyby wpłynąć na INSERT/UPDATE/DELETE wydajność.

Poza tym, można rozważyć buforowanie SUM i COUNT w osobnej tabeli zawierającej tylko jeden wiersz. Zaktualizuj oba wyzwalacze SUM i COUNT za każdym razem, gdy wiersz jest wstawiany, aktualizowany lub usuwany w głównej tabeli. Następnie można łatwo pobrać bieżący system AVG, dzieląc SUMA i COUNT.


Ale trzeba naprawdę miarą na reprezentatywnych ilości danych, aby mieć pewność.

Ponieważ w zapytaniu nie ma klauzuli WHERE, wszystkie wiersze zostaną przeskanowane. Indeksy są przydatne tylko przy pobieraniu stosunkowo niewielkiego podzbioru wierszy tabeli (a czasami dla index-only scans). Jako szorstki zasada, jeśli więcej niż 10% wierszy w tabeli są potrzebne, indeksy nie pomoże, a DBMS często zdecydować się na pełne skanowanie tabeli, nawet gdy indeksy są dostępne.

+0

dziękuję za wielką wyjaśnienia! Twoje dodatkowe komentarze na końcu są bardzo przydatne, moje pytanie to tylko zwięzłe podsumowanie większego problemu, z jakim się borykam i na pewno będę je uważnie rozważać. – sashkello

1

Długi jest bardziej elastyczny w użyciu. To pozwala na filtrowanie size np

SELECT MAX(price) where size='L' 

także pozwala na indeksowanie na size i na id. Przyspiesza to GROUP BY i wszelkie zapytania, w których inne tabele są połączone na id i/lub size takich tabelach produktów.

2

Pierwsza opcja powoduje zwiększenie liczby wierszy i generalnie będzie wolniejsza niż druga opcja.

Jednak, jak wskazał również Deltalima, pierwsza opcja jest bardziej elastyczna. Nie tylko w przypadku różnych opcji zapytań, ale także wtedy, gdy pewnego dnia trzeba rozszerzyć tabelę o inne rozmiary, kolory itp.

Jeśli nie masz bardzo dużego zestawu danych lub potrzebujesz bardzo szybkiego czasu wyszukiwania, możesz Najprawdopodobniej będzie lepiej z pierwszą opcją.

Jeśli masz lub potrzebujesz bardzo duży zbiór danych, lepiej jest utworzyć tabelę ze wstępnie obliczonymi wartościami podsumowania.