Odziedziczyłem aplikację, która łączy wiele różnych rodzajów działań z witryną. Istnieje około 100 różnych rodzajów aktywności, a każdy z nich ma inny zestaw 3-10 pól. Jednak wszystkie działania mają co najmniej jedno pole daty (może to być dowolna kombinacja daty, daty rozpoczęcia, daty zakończenia, zaplanowanej daty rozpoczęcia itp.) Oraz jedno pole osoby odpowiedzialnej. Wszystkie pozostałe pola różnią się znacznie, a pole daty początkowej niekoniecznie będzie nosiło nazwę „Data początkowa”.
Utworzenie jednej tabeli podtypów dla każdego rodzaju działania skutkowałoby schematem zawierającym 100 różnych tabel podtypów, co byłoby zbyt dziwne, aby sobie z tym poradzić. Obecnym rozwiązaniem tego problemu jest przechowywanie wartości aktywności jako par klucz-wartość. Jest to znacznie uproszczony schemat obecnego systemu, aby uzyskać punkt.
Każde działanie ma wiele pól ActivityField; każda witryna ma wiele działań, a tabela SiteActivityData przechowuje KVP dla każdej SiteActivity.
To sprawia, że aplikacja (internetowa) jest bardzo łatwa do kodowania, ponieważ wszystko, co naprawdę musisz zrobić, to zapętlić rekordy w SiteActivityData dla danego działania i dodać etykietę i kontrolę wejściową dla każdego wiersza do formularza. Ale jest wiele problemów:
- Uczciwość jest zła; możliwe jest umieszczenie pola w SiteActivityData, które nie należy do typu działania, a DataValue jest polem varchar, więc liczby i daty muszą być stale rzutowane.
- Raporty i zapytania ad hoc tych danych są trudne, podatne na błędy i powolne. Na przykład uzyskanie listy wszystkich działań określonego typu, które mają datę końcową w określonym zakresie, wymaga osi przestawnych i rzutowania varcharów na daty. Autorzy raportu NIENAWIDZĄ tego schematu i nie winię ich.
Tak więc szukam sposobu na przechowywanie dużej liczby działań, które prawie nie mają wspólnych pól w sposób, który ułatwia raportowanie. Do tej pory wymyśliłem XML do przechowywania danych aktywności w formacie pseudo-noSQL:
Tabela aktywności zawierałaby XSD dla każdego działania, eliminując potrzebę korzystania z tabeli ActivityField. SiteActivity będzie zawierał klucz-wartość XML, więc każde działanie dla witryny będzie teraz w jednym wierszu.
Aktywność wyglądałaby mniej więcej tak (ale nie w pełni ją rozwinąłem):
<SomeActivityType>
<SomeDateField type="StartDate">2000-01-01</SomeDateField>
<AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
<EmployeeId type="ResponsiblePerson">1234</EmployeeId>
<SomeTextField>blah blah</SomeTextField>
...
Zalety:
- XSD sprawdziłby poprawność XML, wychwytując błędy takie jak wstawianie ciągu znaków w polu liczbowym na poziomie bazy danych, co było niemożliwe w starym schemacie, który przechowywał wszystko w varchar.
- Zestaw rekordów KVP używanych do budowy formularzy internetowych można łatwo odtworzyć przy użyciu
select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
- Podkwerenda xpath w pliku XML może zostać użyta do wygenerowania zestawu wyników zawierającego kolumny dla daty początkowej, końcowej itp. Bez użycia osi przestawnej, coś w rodzaju
select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, ActivityXML.value('.[@type=EndDate]', 'datetime') as EndDate from SiteActivity where...
Czy to wydaje się dobrym pomysłem? Nie mogę wymyślić innych sposobów przechowywania tak dużej liczby różnych zestawów właściwości. Inną myślą, którą miałem, było zachowanie istniejącego schematu i przetłumaczenie go na coś łatwiejszego do zapytania w hurtowni danych, ale nigdy wcześniej nie projektowałem schematu gwiazdy i nie mam pojęcia, od czego zacząć.
Dodatkowe pytanie: jeśli zdefiniuję znacznik jako typ danych daty w XSD za pomocą xs:date
, czy SQL Server będzie indeksował go jako wartość daty? Obawiam się, że jeśli zapytam według daty, będzie musiał rzucić ciąg daty na wartość daty i zniszczyć każdą szansę na użycie indeksu.
źródło
Odpowiedzi:
Za mało przedstawicieli, aby skomentować, więc proszę bardzo!
Jeśli głównym celem jest raportowanie i masz DW (nawet jeśli nie jest to schemat gwiazdy), zaleciłbym próbę przekształcenia tego w schemat gwiazdy. Korzyści to szybkie, proste zapytania. Minusem jest ETL, ale już rozważasz przeniesienie danych do nowego projektu, a ETL do schematu gwiaździstego jest prawdopodobnie łatwiejszy w budowie i utrzymaniu niż rozwiązanie opakowania XML (a SSIS jest objęty licencją SQL Server). Ponadto rozpoczyna proces uznanego projektu raportowania / analizy.
Jak to zrobić ... Wygląda na to, że masz tak zwany fakt bez faktów . Jest to skrzyżowanie atrybutów, które definiują zdarzenie bez powiązanej miary (takiej jak cena sprzedaży). Masz dostępne daty niektórych lub wszystkich swoich działań? Prawdopodobnie powinieneś naprawdę przeciąć działanie, witrynę i datę (daty).
DimActivity
- Zgaduję, że istnieje wzorzec, coś, co może pozwolić ci podzielić je na przynajmniej względnie wspólne kolumny. Jeśli tak, możesz mieć trzy? pięć? wymiary dla klas zajęć. W najgorszym przypadku masz kilka spójnych kolumn, takich jak nazwa działania, możesz je filtrować i pozostawiasz ogólne nagłówki, takie jak „Atrybut1” itp. Dla pozostałych losowych szczegółów.Nie potrzebujesz wszystkiego w wymiarze - tam (prawdopodobnie) nie powinny znajdować się żadne daty w wymiarze Aktywność - wszystkie powinny być w rzeczywistości, ponieważ Klucz zastępczy odnosi się do wymiaru Data. Na przykład data, która pozostanie w wymiarze osoby, byłaby datą urodzenia, ponieważ jest to atrybut osoby. Termin wizyty w szpitalu byłby związany z faktem, ponieważ jest to wydarzenie w czasie związane między innymi z osobą, ale nie jest atrybutem osoby odwiedzającej szpital. Więcej faktów na temat dyskusji.
DimSite
- wydaje się prosty, więc opiszemy tutaj klucze zastępcze. Zasadniczo jest to tylko rosnący, unikalny identyfikator. Kolumna Tożsamość całkowita jest wspólna. Umożliwia to separację systemów DW i źródłowych oraz zapewnia optymalne połączenia w hurtowni danych. Twój klucz naturalny lub klucz biznesowy jest zwykle przechowywany, ale do celów konserwacji / projektowania nie należy analizować i dołączać. Przykładowy schemat:DimDate
- atrybuty daty. Zrób „inteligentny klucz” zamiast Tożsamości. Oznacza to, że możesz wpisać znaczącą liczbę całkowitą odnoszącą się do daty dla zapytań, takich jak WHERE DateSK = 20150708. Istnieje wiele bezpłatnych skryptów do załadowania DimDate, a większość zawiera ten inteligentny klucz. ( jedna opcja )DimEmployee
- Twój XML to uwzględnił, jeśli jest to bardziej ogólna zmiana w DimPerson i wypełnij odpowiednie atrybuty osoby, ponieważ są one dostępne i odnoszą się do raportowania.A twoim faktem jest:
Możesz zmienić ich nazwy w faktach i możesz mieć wiele kluczy daty na wydarzenie. Fakty są zwykle bardzo duże, więc unikanie aktualizacji jest zwykle dobre ... jeśli masz wiele aktualizacji daty dla jednego zdarzenia, możesz spróbować projektu Usuń / Wstaw, dodając SK do faktu, który umożliwia wybór wierszy „aktualizacja” do zostać usunięte, a następnie wstawiając najnowsze dane.
Rozwiń dat fakcie co trzeba:
StartDateSK, EndDateSK, ScheduledStartDateSK
.Wszystkie wymiary powinny mieć nieznany wiersz, zwykle z zakodowanym na stałe -1 SK. Gdy załadujesz fakt, a działanie nie ma żadnej z zawartych dat, powinno po prostu załadować -1.
Faktem jest zbiór odniesień liczb całkowitych do twoich atrybutów przechowywanych w wymiarach, połącz je ze sobą, a otrzymasz wszystkie szczegóły, w bardzo czysty wzór łączenia, a fakt, ze względu na typy danych, jest wyjątkowo mały i szybki. Ponieważ jesteś w programie SQL Server, dodaj indeks magazynu kolumn, aby jeszcze bardziej zwiększyć wydajność. Możesz po prostu upuścić i odbudować podczas ETL. Po przejściu do SQL 2014+ możesz pisać do indeksów magazynu kolumn.
Jeśli pójdziesz tą drogą, poszukaj Modelowania wymiarowego. Polecam metodologię Kimball . Istnieje również wiele bezpłatnych przewodników, ale jeśli będzie to coś innego niż jednorazowe rozwiązanie, inwestycja jest prawdopodobnie tego warta.
źródło