Projektowanie schematów i ORM

Jan 05 2023
Każda baza danych ma zasadniczo 2 rodzaje tabel — wymiary i fakty: Podczas projektowania schematu bazy danych niektóre z poniższych wskazówek pomogą zrobić to dobrze. Najpierw normalny Niezależnie od tego, czy baza danych będzie SQL czy NoSQL, warto raz pomyśleć o jednostkach / obiektach, a tym samym o tabelach, z perspektywy znormalizowanego schematu.

Każda baza danych ma zasadniczo 2 rodzaje tabel — wymiary i fakty:

  1. Wymiary to tabele konfiguracyjne. Te tabele nie są często zmieniane i zazwyczaj zawierają pojedynczą bieżącą wartość migawki (być może z pewnymi zmianami w historii — szczegóły poniżej). Najczęstszymi operacjami są edycje tabeli. Można o nich również myśleć jako o konfiguracji lub mistrzach.
  2. Fakty to tabele, które rosną prawie liniowo w czasie. Zazwyczaj jednostki te są regularnie generowane w miarę upływu czasu, aktualizacje generowanych faktów nie są powszechne i zazwyczaj odnoszą się do wymiarów w celu uzyskania szerszego kontekstu.

Podczas projektowania schematu bazy danych niektóre z poniższych wskazówek pomogą zrobić to dobrze.

Najpierw normalne

Niezależnie od tego, czy baza danych będzie SQL, czy NoSQL, warto raz pomyśleć o jednostkach/obiektach, a tym samym o tabelach, z perspektywy znormalizowanego schematu. Znormalizowany schemat zapewnia przejrzystość jednostek, relacji i pól. Denormalizacja lub konwersja do NoSQL z tego może być prosta i może być świadomym projektem.

Odzwierciedlaj obiekty ze świata rzeczywistego

Nawet jeśli przypadki użycia/raporty są niejasne, elementy schematu powinny odzwierciedlać rzeczywisty przypadek użycia. Taki schemat jest zwykle solidny.

Dowolne z poniższych przypadków są na ogół przypadkami identyfikowania i tworzenia różnych jednostek, a tym samym tabel:

  1. Logicznie oddzielne jednostki, które mogą istnieć niezależnie i potencjalnie bez żadnych powiązań ze sobą — np. zbiór danych i stacja
  2. Mieć między sobą relacje wiele-do-wielu lub jeden-do-wielu — np. dla firmy e-commerce, zamówień i klientów.

Jeśli w zapytaniach, wyszukiwaniu lub sortowaniu jest używane pole, domyślnie dodaj dla niego indeksy. Proste indeksy powinny być domyślnie włączone dla tych pól, ponieważ przynoszą maksymalne korzyści. Niedodanie indeksu powinno być świadomym wyborem, a nie stanem domyślnym.

Użyj właściwych typów pól

  1. Typy wyliczeniowe vs łańcuchowe dla pól ze stałym zestawem wartości opcji: Wyliczenia są implementowane jako bajtowe, a więc zajmują mniej miejsca (np. wyszukiwania. W przypadku dużych stołów sumują się wymagania dotyczące miejsca i wydajności. Domyślnie używaj wyliczeń.
  2. Typ klucza podstawowego (ID): Wydajność i przechowywanie — zawsze zaleca się używanie klucza o stałym rozmiarze — tj. liczb całkowitych lub identyfikatorów UUID.
  3. Wspólne pola tabeli: Niektóre pola są sugerowane we wszystkich encjach ORM, które mogą się zmieniać — np. created_at, updated_at, created_by, updated_by. Ponadto w przypadku jednostek, które często mogą mieć powiązania z kluczem obcym i są rzadko usuwane, proponuje się stosowanie usuwania nietrwałego.

Zapytanie Drishti może być złożone i obejmować wiele połączeń. Bazy danych są zoptymalizowane pod kątem połączeń i obliczeń w pamięci. Tam, gdzie to możliwe, uruchamiaj te połączenia lub obliczenia w bazie danych — albo poprzez dodatki do warstwy ORM, odpowiednie zapytanie, albo przeprojektowanie schematu. Zasadniczo należy patrzeć na duże łączenia wyników w kodzie aplikacji tylko wtedy, gdy baza danych nie może tego zrobić w pamięci — np. w przypadku łączenia między bazami danych.

Kiedy dodawać tabele historii?

Każdy system oparty na transakcjach wymaga podstawowego rejestrowania wszystkich zmian dla kluczowych podmiotów. Dotyczy to w szczególności tabel wymiarów, ponieważ są one konfigurowane/modyfikowane za pomocą interfejsów API.

Można je konserwować na 2 sposoby:

  1. Zachowaj ogólną abstrakcję zmiany atrybutu, w której każdy wiersz w tej historii zmian wskazuje na typ jednostki, atrybut, identyfikator jednostki, starą wartość i nową wartość. Zaleta: nie wymaga nowej tabeli na jednostkę.
  2. Utrzymuj tabelę historii z podziałem na jednostki dla każdej zmiany wartości. Zaleta: Przechwytywanie wielu zmian w polach jako niepodzielnych transakcji, pokazując je jako takie klientowi. W ten sposób zostaje zachowana koncepcja transakcji dokonanej przez użytkownika na interfejsie użytkownika lub w inny sposób.