Projekt bazy danych: Nowa tabela a nowe kolumny

38

(Sugerowano, aby zostać tutaj ponownie z StackOverflow)

Obecnie masz tabelę… i musisz zacząć dodawać do niej nowe kolumny danych. Nie każdy rekord (nawet przejście do nowych danych po dodaniu nowych kolumn danych) będzie zawierał dane. Zastanawiam się więc, czy jest to bardziej odpowiednie dla nowej tabeli, ponieważ tak naprawdę jest rozszerzeniem niektórych wierszy danych i nie ma zastosowania do każdego wiersza.

Innymi słowy, skoro będzie wiele nieużywanych kolumn dla tych nowych elementów danych, wydaje się, że byłoby to bardziej odpowiednie dla nowej tabeli?

Pierwsza tabela jest zapisem odsłon (obecnie 2 miliony rekordów)

- ID
- Adres IP
- razy oglądane
- znacznik czasu utworzonej_czasu
- data

dla każdego adresu IP zapisywany jest dzienny dzien - a kolejne wyświetlenia stron są dodawane do liczby wyświetleń dziennie

dodatkowe pola byłyby przeznaczone do śledzenia punktu początkowego (tj. źródło / medium / kampania Google Analytics)

Nie każda wizyta zawiera te informacje. Zakładam, że około 10% wierszy będzie zawierało dane (ponieważ zwykle przypisuje się je tylko przy pierwszej wizycie)

Głównym zastosowaniem danych byłoby przypisanie, skąd pochodzą ludzie. Może to skończyć się częstszym używaniem (co wydaje się wtedy pasować do pojedynczego stołu)

Doceń opinię - w razie potrzeby możesz dodać więcej

cgmckeever
źródło

Odpowiedzi:

29

To, z czym walczysz, to pionowe partycjonowanie. Jest to technika projektowania fizycznej bazy danych w celu poprawy wydajności. Podobnie jak w przypadku każdej techniki projektowania fizycznej bazy danych, jej zastosowanie zależy od konkretnych zapytań, które próbujesz zoptymalizować i czy ta technika je zoptymalizuje. Z logicznego punktu widzenia, jeśli te nowe pola zależą od klucza kandydującego dla twojego bytu, to są to fakty na jego temat. Najpierw upewnij się, że w pełni rozumiesz funkcjonalną zależność tych nowych pól od kluczy kandydatów, aby sprawdzić, czy naprawdę są to fakty dotyczące codziennych odsłon. Jeśli tak, decyzja o podzieleniu ich na inną tabelę jest optymalizacją wydajności, którą należy wykonać tylko wtedy, gdy osiągnie założone cele.

Ogólnie rzecz biorąc, partycjonowanie pionowe jest przydatne, jeśli rzadko i wyraźnie odszukujesz te nowe kolumny w stosunku do innych kolumn w oryginalnej tabeli. Umieszczając te kolumny w innej tabeli, która ma tę samą PK co twoja istniejąca tabela, możesz zapytać ją bezpośrednio, gdy chcesz te nowe kolumny i uzyskać znacznie większą przepustowość, ponieważ będziesz mieć o wiele więcej wierszy na stronie na dysku dla tej nowej tabeli ponieważ wszystkie kolumny z oryginalnej tabeli nie będą siedziały w tych rzędach. Jeśli jednak zawsze będziesz sprawdzać te kolumny wraz z kolumnami w oryginalnej tabeli, partycja pionowa nie miałaby większego sensu, ponieważ zawsze będziesz musiał je połączyć zewnętrznie, aby je uzyskać. Strony z tabel na dysku trafiają do puli buforów DBMS niezależnie, nigdy wcześniej nie łączone, i tak, że dołączenie będzie musiało nastąpić przy każdym wykonaniu zapytania, nawet jeśli dane zostaną przypięte do puli buforów. W tym scenariuszu uczynienie ich kolumnami NULLABLE w oryginalnej tabeli umożliwiłoby silnikowi pamięci DBMS efektywne przechowywanie ich, gdy NULL, i wyeliminowałoby potrzebę dołączania przy pobieraniu.

Wydaje mi się, że twój przypadek użycia jest tym drugim, a dodanie ich jako NULLABLE do oryginalnego stołu jest dobrym rozwiązaniem. Ale tak jak w przypadku wszystkich innych elementów związanych z projektowaniem baz danych, zależy to od tego, a aby podjąć właściwą decyzję, musisz znać spodziewane obciążenie pracą i od tego, jaki będzie dobry wybór. Dobrym przykładem właściwego zastosowania partycjonowania pionowego może być panel wyszukiwania osób, w którym aplikacja zawiera bardzo rzadko wypełniane informacje o osobie, którą ktoś może chcieć wyszukać, ale rzadko. Jeśli umieścisz te informacje w innej tabeli, masz kilka dobrych opcji wydajności. Możesz napisać wyszukiwanie, dzięki czemu będziesz mieć 2 zapytania - jedno, które wykorzystuje główne, zawsze wypełnione informacje tylko do wyszukiwania (takie jak nazwisko lub ssn), i zewnętrzny, który dołącza do bardzo rzadko wypełnianych informacji tylko wtedy, gdy są one wymagane do wyszukiwania. Lub możesz skorzystać z optymalizatora DBMS, jeśli jest wystarczająco inteligentny, aby rozpoznać dla danego zestawu zmiennych hosta, że ​​zewnętrzne połączenie nie jest potrzebne i nie wykona go, a zatem musisz utworzyć tylko 1 zapytanie.

Z jakiej platformy DBMS korzystasz? Sposób, w jaki platforma obsługuje przechowywanie NULL w kolumnie, optymalizuje zapytanie, a także dostępność rzadkiej obsługi kolumn (SQL Server ma to) ma wpływ na decyzję. Ostatecznie zaleciłbym wypróbowanie obu projektów w środowisku testowym z danymi o wielkości produkcyjnej i obciążeniem oraz sprawdzenie, które z nich lepiej osiągają cele wydajnościowe.

Todd Everett
źródło
Nie jest dla mnie jasne, co rozumiesz przez „Jednak jeśli zawsze będziesz pytał o te kolumny wraz z kolumnami w oryginalnej tabeli, wówczas pionowa partycja nie miałaby większego sensu, ponieważ zawsze musisz je połączyć zewnętrznie, aby je uzyskać”. , musisz wykonać łączenie zewnętrzne tylko wtedy, gdy chcesz, aby kolumny główne były dostępne niezależnie od tego, czy kolumny dodatkowe będą dostępne, w przeciwnym razie użyjesz WEJŚCIA WEWNĘTRZNEGO, co w większości przypadków jest korzystne (zmniejszenie liczby spojrzonych wierszy ).
jmoreno
Dzięki za wszelką pomoc tutaj. Właściwie nie dodałem pól, ale po przemyśleniu tego, zobaczyłem, że powinienem mieć kilka innych tabel, aby lepiej wszystko zidentyfikować. W końcu doszło do odwiedzin visitor_visits (który ma identyfikator_użytkownika i zawiera źródło) page_views (który ma vistor_id i visitor_visit_id), ponieważ chcę dokładnie wiedzieć, które page_view jest przypisane do wizyty, dodałem ten link. Zmagałem się z tym przez chwilę, ale myślę, że to była właściwa decyzja
cgmckeever
10

Osobiście skłaniam się do dodawania kolumn do istniejącej tabeli. Nowy stół tak naprawdę nic Ci nie kupuje:

  • tak naprawdę nie oszczędzasz dużo miejsca, ponieważ wartości NULL w oryginalnej tabeli nie zajmują żadnego miejsca, a nowa tabela potrzebuje pewnego rodzaju identyfikatora, który i tak kompensuje wszelkie oszczędności
  • Twoje zapytania stają się bardziej złożone ... where newcolumn is not nullstaje sięleft outer join

W pojedynczej tabeli oznacza to tylko, że rozmiar wiersza może się różnić w zależności od strony, ale nie powinno to wpływać na wiele istniejących stron, szczególnie jeśli indeks klastrowany znajduje się w monotonicznie rosnącej kolumnie (tożsamość lub data / godzina).

Aaron Bertrand
źródło
Ponieważ tabela nie jest obecnie szeroka (na podstawie twojego opisu) i te dane nie uczynią jej zbyt szeroką, zgodziłbym się.
HLGEM
4

Biorąc pod uwagę informacje, które dostarczyłeś, a celem jest po prostu ogólna normalizacja, prawdopodobnie po prostu dodałbym kolumny z zerowymi wartościami, ale nie podałeś wystarczających informacji o tym, w jaki sposób dane zostaną wykorzystane, aby wiedzieć, jaki jest najlepszy sposób modelowania danych jest.

W zależności od tego, jak naprawdę używasz tych danych, możesz rozważyć inny model danych. Jeśli przekazujesz te dane do raportowania, możesz przyjrzeć się modelowi wymiarowemu, który może być bardziej wydajny w przypadku niektórych rodzajów raportów - na przykład analiza dnia działa dobrze z podziałem wymiaru daty i godziny.

W przypadku odpowiedzi na pytania analityczne, takie jak „jaka jest najbardziej popularna pora dnia dla wizyt z kampanii takich jak X” lub „w którym dniu kampanii widzimy najwięcej wizyt na godzinę”, pojedyncza kolumna danych czasowych nie zadziała bardzo dobrze (ale można to nawet podzielić na model relacyjny), i istnieje wiele przypadków, w których możesz traktować adres IP jako wymiar (być może z jakimś rodzajem danych geograficznych w płatku śniegu).

Cade Roux
źródło