Blog JSystems - uwalniamy wiedzę!

Szukaj
Analizator wydajności Power BI na stronie Przegląd raportu Nordvelli: czasy wizualizacji w milisekundach i rozbicie karty oraz tabeli
Pomiar strony Przegląd w Analizatorze wydajności: po lewej strona raportu Nordvelli, po prawej czas każdej wizualizacji w milisekundach. Najdłużej trwają karta (350 ms) i tabela ze sklepami (338 ms). Rozwinięte wiersze pokazują, że zapytanie DAX zajmuje w nich 6 i 9 ms, a większość czasu to pozycja Inne. Każda liczba w tym rozdziale pochodzi z takiego pomiaru, nie z oszacowania.

W skrócieOptymalizacja wydajności modelu Power BI zaczyna się od pomiaru: Analizator wydajności pokazuje czas wizualizacji, a VertiPaq Analyzer rozmiar kolumn. Na modelu Nordvelli znajdujemy, gdzie uciekają czas i pamięć, i odchudzamy model tak, że tabela faktów zajmuje prawie o połowę mniej, a raport pokazuje te same liczby.

Lekcja 18 z 28 bezpłatnego kursu Power BI, od pierwszego raportu do Fabric i Copilota, na jednym zestawie danych sieci Nordvella.

<-- Spis wszystkich lekcji
<-- Lekcja 17: Grupy obliczeniowe i Tabular EditorLekcja 19: Odświeżanie przyrostowe (incremental refresh) -->

Raport Nordvelli ma już wszystko: model gwiazdy, kilkadziesiąt miar DAX, wykresy trendu, mapę sklepów, inteligencję czasową i grupę obliczeniową. Z każdą lekcją model rósł, a nie wszystko, co do niego trafiło, jest jeszcze potrzebne. W tym rozdziale pokażemy Ci, jak zmierzyć wydajność liczbowo, gdzie faktycznie uciekają czas i pamięć, i jak odchudzić model Nordvelli bez utraty żadnej liczby w raporcie. Na końcu lekcji tabela faktów zajmuje w pamięci prawie o połowę mniej niż na jej początku, a strony raportu pokazują te same wyniki.

Analizator wydajności Power BI z rozbiciem czasu na zapytanie DAX, wyświetlanie i pozostałe dla raportu Nordvella
Analizator wydajności rozbija czas każdego wizualu na trzy części: zapytanie DAX (ile trwa policzenie danych), wyświetlanie (ile trwa narysowanie) i pozostałe. Czytasz to od najwyższej liczby milisekund w kolumnie zapytania DAX, bo to ona pokazuje, którą miarę lub relację warto poprawić.

Z tej lekcji dowiesz się:

Pliki do tej lekcji

Gotowy efekt: plik startowy po krokach tej lekcji: bez kolumny obliczeniowej Wartosc Brutto Sprawdzenie, z pięcioma miarami z pułapek DAX (Łączna sprzedaż (wolno), Sprzedaż karta, Sprzedaż karta (wolno), Sprzedaż brutto, Marża % (VAR)), nową stroną Wydajność miar i układem Układ 1 w widoku Model.

Pobierz nordvella_18_optymalizacja.pbix

Plik startowy: stan z końca poprzedniej lekcji. Otwórz go, jeśli chcesz wykonywać kroki tej lekcji od razu, bez odtwarzania wcześniejszych.

Pobierz nordvella_17_grupy_obliczeniowe.pbix

Dane źródłowe:
Nordvella_dane.xlsx - dziewięć tabel Nordvelli w arkuszu Excel.
Nordvella.bak.gz - te same dane jako baza MS SQL Server (odtwarzasz poleceniem RESTORE DATABASE), do ćwiczeń z połączeniem z bazą SQL.

Pobierz Nordvella_dane.xlsxPobierz Nordvella.bak.gz

Analizator wydajności: mierz, zanim zaczniesz zgadywać

Co chcemy osiągnąć. Raport Nordvelli zwalnia, gdy przybywa danych i wizualizacji. Chcemy zmierzyć, który wizual zabiera najwięcej czasu i na co, zanim zaczniemy cokolwiek przyspieszać.

Pierwsza zasada optymalizacji brzmi: nie zgaduj. Zanim zaczniesz coś przyspieszać, zmierz, co jest wolne. Power BI Desktop ma do tego wbudowane narzędzie o nazwie Analizator wydajności (ang. Performance Analyzer). Włączasz je na karcie Optymalizowanie przyciskiem Analizator wydajności (ten sam przycisk jest na karcie Widok, w grupie Pokaż okienka). Po prawej stronie ekranu pojawi się panel z przyciskiem Rozpocznij nagrywanie.

Karta Optymalizowanie w Power BI Desktop: Wstrzymaj wizualizacje, Odśwież wizualizacje, Ustawienia wstępne optymalizacji, Analizator wydajności
Karta Optymalizowanie: Wstrzymaj wizualizacje, Odśwież wizualizacje, Ustawienia wstępne optymalizacji, Analizator wydajności oraz Przycisk Zastosuj wszystkie fragmentatory, który wstawia na stronę przycisk ograniczający liczbę przeliczeń.
Panel Analizator wydajności przed pomiarem na stronie Przegląd raportu Nordvelli
Analizator wydajności przed pomiarem. Nagrywanie startuje przyciskiem Rozpocznij nagrywanie, a wyniki pojawiają się dopiero po odświeżeniu wizualizacji.

Zrób tak. Otwórz stronę Przegląd (dwie karty, fragmentatory Miasto i Kategoria, przyciski, tabela sklepów i wykres miast). Kliknij Rozpocznij nagrywanie, a potem Odśwież wizualizacje (przycisk pojawia się w tym samym panelu). Analizator przeliczy każdy wizual od nowa i wypisze go na liście z czasem w milisekundach. Lista idzie w kolejności wizualizacji na stronie, a nie po czasie, więc najwolniejszy wizual szukasz po liczbach w kolumnie Czas trwania.

Wynik pomiaru strony Przegląd w Analizatorze wydajności: jedenaście wizualizacji z czasem w milisekundach
Wynik pomiaru strony Przegląd. Najdłużej trwają dwie karty (350 i 336 ms) i tabela ze sklepami (338 ms), fragmentatory i przyciski po około 165-170 ms, wykres miast 257 ms.

Kliknij plus przy nazwie wizualu, żeby rozwinąć rozbicie na trzy pozycje. Rozwiń pierwszą kartę i tabelę.

Rozwinięte wiersze Karta i Tabela w Analizatorze wydajności: Zapytanie DAX, Wyświetlanie elementu wizualnego, Inne
Rozbicie karty i tabeli: zapytanie DAX 6 i 9 ms, wyświetlanie elementu wizualnego 82 i 94 ms, Inne 262 i 235 ms. Na tej stronie żadna miara nie jest wolna, czas zabiera kolejka jedenastu wizualizacji, które czekają na siebie nawzajem.

Jak czytać trzy liczby przy każdym wizualu

Każdy wizual ma trzy składowe czasu, a rozróżnienie między nimi decyduje o tym, gdzie w ogóle szukać poprawy:

SkładowaCo mierzyCo robisz, gdy jest wysoka
Zapytanie DAXIle silnik liczy dane dla wizualuPoprawiasz miarę, relacje, kardynalność
Wyświetlanie elementu wizualnegoIle trwa narysowanie wizualu na ekranieZmniejszasz liczbę punktów danych, upraszczasz wizual
InneOczekiwanie na inne wizualizacje na stronie, przygotowanie zapytaniaZmniejszasz liczbę wizualizacji na stronie albo przenosisz część na stronę szczegółów

Praktyczny próg: pojedynczy wizual, którego zapytanie DAX przekracza 120 ms, wart jest przyjrzenia się, a powyżej 500 ms zwykle psuje odczucie płynności, bo strona z kilkoma takimi wizualami zaczyna liczyć się grubo ponad sekundę. Na stronie Przegląd żaden wizual nie zbliża się do tych progów: najdłuższe zapytanie DAX trwa 9 ms, a o czasie decyduje pozycja Inne. Najwyższe czasy zapytania DAX dostają zwykle macierze, które krzyżują kilka wymiarów naraz (sklep, kategoria, miesiąc) i wywołują po kilka miar.

Wskazówka: obok każdego wizualu w Analizatorze jest link Kopiuj zapytanie. Skopiuj je i wklej do zewnętrznego narzędzia DAX Studio (bezpłatne), żeby zobaczyć, ile czasu zajmuje silnik magazynu (odczyt skompresowanych kolumn) w porównaniu z silnikiem formuł (logika miary). Jeśli dominuje silnik formuł, problemem jest sama miara, jeśli silnik magazynu, problemem jest zwykle za duża albo źle poukładana tabela.

Zanim ruszysz dalej, zapisz sobie wartości bazowe. Odśwież wizualizacje jeszcze raz, spisz czasy trzech najwolniejszych wizuali, a potem wróć do tego samego pomiaru po każdej zmianie z kolejnych sekcji. Bez punktu odniesienia nie stwierdzisz, czy naprawa cokolwiek dała.

Redukcja rozmiaru: typy danych, kolumny i kardynalność

Co chcemy osiągnąć. Model Nordvelli rośnie z każdym miesiącem sprzedaży, a od jego rozmiaru zależą szybkość raportu i czas odświeżania. Chcemy zmniejszyć model, usuwając zbędne kolumny i ograniczając liczbę różnych wartości, bez utraty żadnej liczby w raporcie.

Power BI trzyma dane w silniku kolumnowym VertiPaq, który kompresuje każdą kolumnę osobno. Klucz do rozmiaru i szybkości to kardynalność, czyli liczba różnych wartości w kolumnie. Kolumna o niskiej kardynalności (na przykład KanalSprzedazy z kilkoma wartościami, albo Kategoria z czterema) kompresuje się świetnie. Kolumna o wysokiej kardynalności (na przykład WartoscNetto z tysiącami niepowtarzalnych kwot do drugiego miejsca po przecinku) zabiera dużo miejsca i spowalnia odczyt.

Ile waży każda tabela i kolumna, pokazuje VertiPaq Analyzer wbudowany w bezpłatne narzędzie DAX Studio. W naszym Power BI ikona DAX Studio jest na karcie Narzędzia zewnętrzne, obok Tabular Editor z lekcji 17. Kliknij ją, a DAX Studio połączy się od razu z otwartym plikiem. Przejdź na kartę Advanced, kliknij View Metrics i okno Metric Options zatwierdź przyciskiem Ok. Na dole okna pojawi się karta VertiPaq Analyzer z widokiem Tables.

VertiPaq Analyzer w DAX Studio, widok Tables: FaktSprzedaz zajmuje 87,58 procent modelu Nordvelli
VertiPaq Analyzer w DAX Studio, widok Tables posortowany po Total Size. FaktSprzedaz ze 108 675 wierszami zajmuje 8 412 166 bajtów, czyli 87,58 procent całego modelu. Druga w kolejności FaktZwroty ma 3,29 procent.

Przełącz widok na Columns. Lista kolumn ze wszystkich tabel, posortowana po rozmiarze, od razu wskazuje, która kolumna waży najwięcej.

VertiPaq Analyzer, widok Columns: kolumna obliczeniowa Wartosc Brutto Sprawdzenie na pierwszym miejscu z 42,19 procent modelu
Widok Columns. Na samej górze kolumna obliczeniowa Wartosc Brutto Sprawdzenie z lekcji 07: 96 887 różnych wartości, 4 052 372 bajtów, 48,19 procent tabeli i 42,19 procent modelu. Źródłowa WartoscBrutto o podobnej kardynalności zajmuje 8,55 procent, bo silnik koduje ją wartościowo (Encoding VALUE), a kolumnę obliczeniową słownikiem (HASH).
Edytor Power Query, zapytanie FaktSprzedaz z Jakością kolumn i Rozkładem kolumn: WartoscBrutto 1000 odrębnych, KanalSprzedazy 3, CzyZwrot 2
Kardynalność widać, zanim cokolwiek wczytasz do modelu. W edytorze Power Query (Narzędzia główne, Przekształć dane, zapytanie FaktSprzedaz) na karcie Widok zaznacz Jakość kolumn i Rozkład kolumn, a pod każdym nagłówkiem pojawi się histogram i linijka Odrębne / unikatowe. WartoscBrutto ma 1000 wartości odrębnych na 1000 zbadanych wierszy, MarzaNetto 996, a KanalSprzedazy 3, FormaPlatnosci 5 i CzyZwrot 2. Pierwsze kolumny są drogie dla VertiPaq, ostatnie prawie darmowe. Uwaga praktyczna: profilowanie liczy z pierwszego tysiąca wierszy i tak podpisuje się na pasku stanu, dlatego Sezon pokazuje jedną wartość (pierwszy tysiąc transakcji to styczeń). Przełącznik na cały zestaw danych jest w tym samym miejscu, ale na 108 675 wierszach liczy się długo, więc włączaj go świadomie. Zapytanie FaktSprzedaz uruchamia skrypt Python z lekcji 13, więc podgląd wczytuje się około minuty.
Redukcja rozmiaru modelu Power BI: usuwanie kolumn, mniejsza precyzja, klucze zamiast tekstu, bez automatycznej daty
Cztery dźwignie z diagramu: usuń zbędne kolumny, pilnuj kardynalności (znacznik czasu do daty, liczby do sensownej liczby miejsc), dobieraj właściwe typy i trzymaj model w kształcie gwiazdy.

Krok 1: usuń kolumny, których nie używasz

To najprostsza i często najskuteczniejsza zmiana. Kolumnę źródłową, której nie potrzebujesz w ogóle, usuwasz w Power Query (prawy przycisk na nagłówku, Usuń), żeby silnik nawet nie próbował jej kompresować. W Nordvelli nie usuwamy jednak żadnej kolumny źródłowej: z WartoscBrutto liczy strona Python i R z lekcji 13, a z MarzaNetto miara Łączna marża z lekcji 07 i wszystko, co z niej korzysta. Menu z zrzutu niżej tylko oglądamy i zamykamy klawiszem Esc.

Menu kontekstowe nagłówka kolumny WartoscBrutto w edytorze Power Query z pozycjami Usuń i Usuń inne kolumny
Prawy przycisk na nagłówku kolumny w Power Query. Usuń wyrzuca zaznaczone kolumny, Usuń inne kolumny zostawia tylko zaznaczone. Przy szerokiej tabeli, z której potrzebujesz pięciu kolumn z dwudziestu, szybciej jest zaznaczyć te pięć (Ctrl i klik na nagłówkach) i wybrać Usuń inne kolumny. Gdy w źródle przybędzie kolumna, zapytanie jej nie wciągnie, bo lista potrzebnych jest zapisana wprost.
// Power Query (język M): wzór kroku usuwającego kolumny źródłowe.
// Dopisujesz go na końcu zapytania. PoprzedniKrok to nazwa ostatniego kroku,
// KolumnaA i KolumnaB to kolumny, których nie używa żadna miara ani wizualizacja.
BezZbednych = Table.RemoveColumns(PoprzedniKrok, {"KolumnaA", "KolumnaB"})

W Nordvelli zbędna jest kolumna, której w Power Query w ogóle nie ma: kolumna obliczeniowa Wartosc Brutto Sprawdzenie, dopisana w lekcji 07, żeby pokazać kontekst wiersza. Żaden wizual jej nie używa, a według VertiPaq Analyzer zajmuje 42 procent modelu. Kolumna obliczeniowa powstaje dopiero w modelu, więc usuwasz ją w Power BI, nie w Power Query.

Krok po kroku. Kliknij drugą ikonę na lewym pasku (Widok tabeli). W polu wyszukiwania panelu Dane wpisz Sprawdzenie i kliknij znalezioną kolumnę. Power BI pokaże tabelę FaktSprzedaz z zaznaczoną kolumną, jej formułę w pasku formuły i liczbę odrębnych wartości na pasku stanu.

Widok tabeli Power BI: zaznaczona kolumna obliczeniowa Wartosc Brutto Sprawdzenie w FaktSprzedaz i jej formuła
Kolumna Wartosc Brutto Sprawdzenie zaznaczona w widoku tabeli. Pasek formuły pokazuje jej definicję z lekcji 07, a pasek stanu na dole: 108 675 wierszy i 96 887 odrębnych wartości.

Kliknij prawym przyciskiem nagłówek kolumny i wybierz Usuń.

Menu nagłówka kolumny w widoku tabeli Power BI z pozycjami Usuń i Ukryj w widoku raportu
Menu nagłówka kolumny w widoku tabeli. Usuń kasuje kolumnę z modelu. Ukryj w widoku raportu tylko ją chowa i nie zmniejsza modelu ani o bajt.

Power BI zapyta o potwierdzenie. Kliknij Tak.

Okno Usuwanie kolumny w Power BI z pytaniem o usunięcie elementu Wartosc Brutto Sprawdzenie
Okno Usuwanie kolumny. Gdyby z kolumny korzystała miara albo wizualizacja, przestałaby działać, dlatego przed usunięciem sprawdź na stronach raportu i w miarach, że nikt jej nie używa.

Wróć do DAX Studio i jeszcze raz kliknij View Metrics.

VertiPaq Analyzer po usunięciu kolumny: FaktSprzedaz zajmuje 4 359 794 bajtów i 78,52 procent modelu
VertiPaq Analyzer po usunięciu kolumny. FaktSprzedaz spada z 8 412 166 do 4 359 794 bajtów i z 87,58 do 78,52 procent modelu. Plik .pbix po zapisie waży 7,1 MB zamiast 8,4 MB. Żadna liczba w raporcie się nie zmieniła.

Gdyby w Twoim modelu nie było kolumny WartoscBrutto, wartość brutto odtworzysz miarą, która liczy się dopiero na potrzeby wizualu, a nie zajmuje miejsca w każdym z 108 675 wierszy. W Nordvelli zakładamy ją obok kolumny, żeby porównać wyniki. Miara trafia do tabeli FaktSprzedaz:

Sprzedaż brutto =
SUMX(
    FaktSprzedaz,
    FaktSprzedaz[WartoscNetto] * ( 1 + RELATED( DimProdukty[StawkaVAT] ) )
)

Miara działa, bo StawkaVAT w DimProdukty jest liczbą (0,23 albo 0,08; wartości 0.23 w kolumnie StawkaVAT widać w podglądzie okna relacji w dalszej części lekcji). W arkuszu Excela kolumna ma tekst „23%”, ale zapytanie DimProdukty w Power Query zamienia go na typ procentowy. Gdyby została tekstem, miara musiałaby w każdym z 108 675 wierszy wycinać znak procentu i zamieniać tekst na liczbę (VALUE, SUBSTITUTE), a to jest dokładnie ten rodzaj kosztu, który Analizator wydajności pokazuje jako wolne zapytanie DAX. Typ zmieniasz raz, przy wczytywaniu. Wynik zobaczysz na stronie Wydajność miar z końca sekcji o miarach: 566 064 986 zł, niecałe 2 zł więcej niż suma kolumny WartoscBrutto (566 064 984,87 zł). Różnica wynika z zaokrągleń groszy w źródle.

Krok 2: obetnij precyzję znaczników czasu i liczb

Jeśli którakolwiek kolumna niesie znacznik czasu z godziną, minutą i sekundą, jej kardynalność wybucha, bo prawie każdy wiersz ma inną wartość. W Nordvelli takiej kolumny nie ma: daty w tabelach faktów to klucze liczbowe w postaci RRRRMMDD (DataID, DataZwrotu, DataZakupu), połączone z DimKalendarz. Gdy w swoim modelu trafisz na kolumnę typu data i godzina, a raportujesz w skali dnia, obetnij czas do samej daty. To jedna z najsilniejszych pojedynczych redukcji, bo liczba różnych wartości spada do liczby dni.

// Power Query (język M): wzór kroku obcinającego datę i godzinę do samej daty.
// PoprzedniKrok i DataGodzina zastąp nazwami ze swojego zapytania.
Table.TransformColumns(
    PoprzedniKrok,
    {{"DataGodzina", each DateTime.Date(_), type date}}
)

To samo dotyczy liczb. Kwota zapisana do sześciu miejsc po przecinku, gdy raportujesz do grosza, ma więcej wartości unikalnych, niż potrzeba. Zaokrąglenie do dwóch miejsc (karta Przekształć, Zaokrąglanie) obniża kardynalność i poprawia kompresję. Kwoty Nordvelli mają już po dwa miejsca po przecinku, a KosztWlasny jest liczbą całkowitą, więc tu nie ma czego obcinać.

Krok 3: wyłącz automatyczną datę i godzinę

Power BI domyślnie tworzy ukrytą tabelę dat dla każdej kolumny typu data w modelu. Przy kilku kolumnach dat i osobnej, poprawnej tabeli DimKalendarz te ukryte tabele to zbędny ciężar. Wejdź w Plik, Opcje i ustawienia, Opcje, sekcja Bieżący plik, Ładowanie danych i w grupie Analiza czasowa odznacz Automatyczna data/godzina. Datę obsługuje wtedy Twoja DimKalendarz, którą i tak masz oznaczoną jako tabelę dat.

Okno Opcje Power BI, Bieżący plik, Ładowanie danych: odznaczona opcja Automatyczna data/godzina w grupie Analiza czasowa
Tu się to wyłącza. Zwróć uwagę na lewą kolumnę: opcje dzielą się na GLOBALNE i BIEŻĄCY PLIK, a Ładowanie danych występuje w obu sekcjach i w każdej znaczy co innego. Potrzebujesz tego z dołu - ustawienie zapisuje się w pliku raportu, więc w nowym projekcie trzeba je zdjąć od nowa. W modelu Nordvelli pole Automatyczna data/godzina jest już odznaczone. Gdyby zostało włączone, Power BI dorobiłby ukrytą tabelę dat do każdej kolumny typu data w modelu.

Efekt: co daje redukcja na Nordvelli

Tak wygląda bilans redukcji na Nordvelli. Kardynalności pochodzą z widoku Columns w VertiPaq Analyzer.

Element modeluKardynalnośćDziałanie
FaktSprzedaz[Wartosc Brutto Sprawdzenie], kolumna obliczeniowa z lekcji 0796 887Usunięta: nikt jej nie używał, a zajmowała 42,19 procent modelu
FaktSprzedaz[WartoscBrutto]96 652Zostaje, korzysta z niej strona Python i R. W nowym modelu licz ją miarą Sprzedaż brutto
FaktSprzedaz[DataID]1 612Zostaje, klucz do DimKalendarz
FaktSprzedaz[KanalSprzedazy]3Zostaje, kompresuje się idealnie
Ukryte tabele automatycznej datybrakWyłączone w opcjach pliku

Wskazówka: jedna kolumna klucza zastępczego (integer) o rosnących wartościach kompresuje się lepiej niż długi tekst. Zamiast trzymać pełną nazwę produktu w tabeli faktów, trzymaj tam tylko ProduktID, a nazwę zostaw w wymiarze DimProdukty. W Nordvelli tak właśnie jest zbudowany model, więc masz to za darmo, o ile nie skopiujesz opisów do faktów.

Star schema kontra jedna tabela płaska

Co chcemy osiągnąć. Model Nordvelli ma być mały i szybki, bo od tego zależy czas otwierania każdej strony raportu. Chcemy zrozumieć, dlaczego schemat gwiazdy spełnia ten warunek lepiej niż jedna szeroka tabela.

Kusi, żeby przed wczytaniem połączyć wszystko w Power Query w jedną szeroką tabelę: dokleić do faktu nazwę produktu, kategorię, markę, miasto sklepu, imię pracownika. Taka tabela płaska (ang. flat table) wygląda wygodnie, bo wszystko jest w jednym miejscu. Dla silnika VertiPaq to zła decyzja. Star schema (schemat gwiazdy z tabelą faktów pośrodku i tabelami wymiarów wokół) jest lżejsza i szybsza, i to z konkretnego powodu.

Gdy dokleisz nazwę produktu do każdego z 108 675 wierszy sprzedaży, powielasz ten sam tekst dziesiątki tysięcy razy. Owszem, VertiPaq to kompresuje, ale kolumna tekstowa o dużej długości i tak zajmuje więcej niż jeden krótki klucz liczbowy plus mały wymiar z 30 wierszami, w którym nazwa występuje raz. Do tego każde grupowanie po kategorii przelicza się teraz na wielkiej tabeli, a nie na 4 wierszach kategorii połączonych relacją. Efekt: większy model i wolniejsze miary.

Widok Model Power BI, Układ 1: FaktSprzedaz pośrodku i cztery wymiary DimProdukty, DimSklepy, DimPracownicy, DimKalendarz
Gwiazda Nordvelli w nowym układzie widoku Model: FaktSprzedaz pośrodku, wokół cztery wymiary (DimProdukty, DimSklepy, DimPracownicy, DimKalendarz). Każda relacja ma po stronie wymiaru 1, a po stronie faktu gwiazdkę: jeden sklep ma wiele transakcji, jeden produkt ma wiele transakcji. Strzałka na linii pokazuje kierunek filtrowania, od wymiaru do faktu. Układ powstaje w trzech ruchach: plus obok karty Wszystkie tabele na dole tworzy pusty Układ 1, przeciągasz na niego FaktSprzedaz z panelu Dane, a potem prawym przyciskiem na nagłówku tabeli wybierasz Dodaj powiązane tabele. DimKategorie się nie pojawia, bo łączy się z DimProdukty, a nie z faktem.
// ANTYWZORZEC: doklejanie opisów wymiaru do tabeli faktów w Power Query.
// Nazwa i Kategoria zostają powielone w każdym z 108 675 wierszy sprzedaży.
let
    Zlaczenie = Table.NestedJoin(FaktSprzedaz, {"ProduktID"}, DimProdukty, {"ProduktID"}, "prod", JoinKind.LeftOuter),
    Rozwiniete = Table.ExpandTableColumn(Zlaczenie, "prod", {"Nazwa", "Kategoria", "Marka"})
in
    Rozwiniete
// Nie rób tego dla wydajności. Zostaw ProduktID w fakcie i relacje do DimProdukty.

Poniższa tabela zestawia dwie drogi na tych samych danych Nordvelli. Kolumny opisowe (Nazwa, Kategoria, Marka, Miasto) w schemacie gwiazdy żyją raz na wymiar, a w tabeli płaskiej są powielone tyle razy, ile jest wierszy sprzedaży.

AspektStar schema (gwiazda)Jedna tabela płaska
Nazwa produktu w modelu30 razy (DimProdukty)108 675 razy (w każdym fakcie)
Miasto sklepu w modelu15 razy (DimSklepy)108 675 razy
Grupowanie po kategorii4 wiersze wymiaru DimKategorie + relacjaskan całej tabeli faktów
Rozmiar modelumniejszywyraźnie większy
Miary DAXczytelne, szybkiewolniejsze, trudniejsze

Zasada praktyczna: fakty trzymają liczby (ilości, kwoty) i klucze do wymiarów, a wszystkie opisy (nazwy, kategorie, miasta, imiona) mieszkają w wymiarach. W raporcie Nordvelli model jest już gwiazdą, więc Twoje zadanie sprowadza się do pilnowania, by nie psuć go doklejaniem opisów do faktów. O budowie samych relacji piszemy szerzej w rozdziale o modelu danych, tutaj patrzymy na nie wyłącznie przez pryzmat wydajności.

Wskazówka: jeśli musisz odfiltrować fakt po atrybucie z wymiaru (na przykład tylko kategoria Telefony), rób to relacją i fragmentatorem, a nie kopiowaniem kolumny do faktu. Relacja jeden do wielu na kluczu liczbowym o średniej kardynalności jest dla silnika najtańsza.

Kosztowne miary DAX i jak je poznać

Co chcemy osiągnąć. Raport Nordvelli ma wiele miar i nie każdą opłaca się mierzyć po kolei. Chcemy umieć wskazać miary, które spowalniają raport, już po samym ich zapisie.

Kiedy Analizator wydajności pokaże wysoki czas zapytania DAX, a nie wyświetlania, wina leży po stronie miary albo relacji. Są wzorce, które prawie zawsze kosztują za dużo, i można je poznać po samym zapisie, jeszcze przed pomiarem. Poniżej trzy najczęstsze pułapki na danych Nordvelli i sposób, w jaki je przepisujemy.

Pułapka 1: iterator tam, gdzie wystarczy agregacja

Miara SUMX chodzi wiersz po wierszu po tabeli faktów. Gdy w środku jest tylko jedna kolumna, silnik rozpoznaje ten wzorzec i liczy go tak samo jak zwykłe SUM, więc obie wersje niżej dają ten sam wynik w podobnym czasie. Iterator robi się drogi dopiero wtedy, gdy w środku pojawi się wyrażenie, którego silnik magazynu nie policzy sam: IF, zamiana tekstu na liczbę, wywołanie innej złożonej miary. Wtedy każdy wiersz trafia do silnika formuł. Dlatego do zwykłej sumy kolumny używaj SUM, a SUMX zostaw na mnożenie kolumn i na logikę, która naprawdę musi iść wiersz po wierszu. Miarę Łączna sprzedaż masz od lekcji 07. Załóż w FaktSprzedaz tylko wersję z dopiskiem (wolno), żeby porównać je w tabeli na końcu sekcji:

// Iterator tam, gdzie wystarczy suma (zakładasz tę miarę)
Łączna sprzedaż (wolno) = SUMX(FaktSprzedaz, FaktSprzedaz[WartoscNetto])

// Prosta agregacja (miara z lekcji 07, już jest w modelu)
Łączna sprzedaż = SUM(FaktSprzedaz[WartoscNetto])

Pułapka 2: FILTER na całej tabeli w CALCULATE

Kolejny częsty koszt to owijanie warunku w FILTER po całej tabeli faktów wewnątrz CALCULATE. To zmusza silnik do przejścia wszystkich 108 675 wierszy. Gdy warunek dotyczy jednej kolumny, przekaż go jako prosty warunek, a silnik zamieni go na tani filtr:

// Za drogo: FILTER na całej tabeli faktów
Sprzedaż karta (wolno) =
CALCULATE(
    SUM(FaktSprzedaz[WartoscNetto]),
    FILTER(FaktSprzedaz, FaktSprzedaz[FormaPlatnosci] = "Karta")
)

// Dobrze: prosty warunek na kolumnie, silnik zamienia go na tani filtr
Sprzedaż karta =
CALCULATE(
    SUM(FaktSprzedaz[WartoscNetto]),
    FaktSprzedaz[FormaPlatnosci] = "Karta"
)

Załóż obie miary w FaktSprzedaz. Jedno zastrzeżenie, bo te dwie miary nie różnią się wyłącznie kosztem. Dają ten sam wynik dopóki kolumna FormaPlatnosci nie jest już filtrowana w wizualizacji. Połóż ją na wierszach tabeli, a wersja z FILTER pokaże wartość tylko w wierszu Karta, w pozostałych zostawi pustkę - bo FILTER zawęża to, co w kontekście już jest, a prosty warunek ten filtr podmienia. W praktyce najczęściej filtrujesz po czymś innym (kategoria, region, miesiąc) i wtedy obie wersje zwracają to samo, więc zostaje sam argument o wydajności. Warto jednak wiedzieć, że przy filtrze na tej samej kolumnie wynik też się rozjedzie.

Pułapka 3: powtarzanie tego samego liczenia w jednej mierze

Gdy miara liczy udział marży, kusi, żeby tę samą sumę policzyć kilka razy: raz w warunku, raz w mianowniku. Wtedy silnik liczy to samo kilka razy. Wyciągnij powtarzalny wynik do zmiennej VAR, policz raz i użyj wielokrotnie. Pierwszej wersji nie zakładaj, to tylko przykład, drugą załóż w FaktSprzedaz pod nazwą Marża % (VAR) z formatem procentowym:

// Za drogo: ta sama suma sprzedaży liczona dwa razy, plus osobne sprawdzenie zera
Marża % (powtórzenia) =
IF(
    SUM(FaktSprzedaz[WartoscNetto]) = 0,
    BLANK(),
    SUM(FaktSprzedaz[MarzaNetto]) / SUM(FaktSprzedaz[WartoscNetto])
)

// Dobrze: każda suma liczona raz, DIVIDE pilnuje dzielenia przez zero
Marża % (VAR) =
VAR SumaMarzy = SUM(FaktSprzedaz[MarzaNetto])
VAR SumaSprzedazy = SUM(FaktSprzedaz[WartoscNetto])
RETURN
    DIVIDE(SumaMarzy, SumaSprzedazy)

Zwróć uwagę na DIVIDE zamiast operatora ukośnika. DIVIDE bezpiecznie zwraca pustą wartość przy dzieleniu przez zero, więc nie musisz dodawać osobnego sprawdzenia, które też kosztuje. Miara Marża % z lekcji 07, DIVIDE([Łączna marża], [Łączna sprzedaż], 0), jest zbudowana w tym samym duchu: każda suma liczona raz, przez odwołanie do miary. Dlatego jej nie zmieniamy, a Marża % (VAR) zakładamy obok, żeby porównać wyniki.

Wskazówka: po każdej przeróbce miary wróć do Analizatora wydajności, skopiuj zapytanie problematycznego wizualu do DAX Studio i porównaj czas silnika formuł przed i po. Na dużych tabelach różnica między wersjami bywa wyraźna. Na Nordvelli zobaczysz ją dopiero w DAX Studio, w widoku Server Timings, bo cała tabela miar liczy się w kilkadziesiąt milisekund.

Porównanie na stronie Wydajność miar

Zbierz miary z trzech pułapek w jednej tabeli. Dodaj stronę i nazwij ją Wydajność miar. Wstaw wizualizację Tabela i przez pole wyszukiwania w panelu Dane zaznacz kolejno: FormaPlatnosci, Sprzedaż karta, Sprzedaż karta (wolno), Łączna sprzedaż, Łączna sprzedaż (wolno), Sprzedaż brutto, Marża % i Marża % (VAR). W Formatuj element wizualny ustaw rozmiar 1240 na 260, pozycję 20 i 20 oraz czcionkę siatki 14, a dolną krawędź tabeli pociągnij myszą w dół, aż zmieszczą się wszystkie wiersze.

Tabela na stronie Wydajność miar: formy płatności Nordvelli i miary Sprzedaż karta, Sprzedaż karta (wolno), Łączna sprzedaż, Sprzedaż brutto, Marża %
Tabela na stronie Wydajność miar. Sprzedaż karta z prostym warunkiem pokazuje 187 035 098 zł w każdym wierszu, bo podmienia filtr formy płatności. Wersja z FILTER pokazuje kwotę tylko przy Karcie. Pary Łączna sprzedaż i Marża % liczą to samo różnymi zapisami i dają identyczne wyniki. Sprzedaż brutto razem: 566 064 986 zł.

Teraz zmierz stronę. W Analizatorze wydajności kliknij Wyczyść, potem Odśwież wizualizacje i rozwiń wiersz Tabela.

Analizator wydajności na stronie Wydajność miar: tabela 159 ms, zapytanie DAX 34 ms, wyświetlanie 73 ms, Inne 51 ms
Tabela z siedmioma miarami na pięciu formach płatności liczy się 159 ms, z czego zapytanie DAX trwa 34 ms, wyświetlanie elementu wizualnego 73 ms, a Inne 51 ms. Przy wysokim zapytaniu DAX poprawiasz miarę, przy wysokim wyświetlaniu liczbę punktów na wizualu.

Na 108 675 wierszach Nordvelli całe zapytanie DAX trwa 34 ms, więc różnice między wersjami miar giną w pomiarze. Pułapki z tej sekcji zaczynają kosztować na tabelach liczonych w milionach wierszy i w wizualizacjach, które wywołują miarę tysiące razy, na przykład w macierzy sklep, produkt i dzień. Tańszy zapis opłaca się więc, zanim model urośnie.

Dobre praktyki modelu pod silnik VertiPaq

Na koniec zbierzmy praktyki, które stosujesz w każdym modelu Power BI, nie tylko w Nordvelli. To lista, do której wracasz przed publikacją raportu. Każdy punkt działa w tę samą stronę: mniej danych do skanowania, prostsze relacje, tańsze miary.

Infografika JSystems z dziesięciopunktową checklistą optymalizacji modelu Power BI pod silnik VertiPaq
Dziesięć rzeczy, które zmniejszają model, w skrócie. Ramka niżej zbiera zasady w wersji do skopiowania, w kolejności kroków tej lekcji.
CHECKLISTA WYDAJNOŚCI MODELU (VertiPaq)
[1] Usuń kolumny, których nikt nie używa (u nas Wartosc Brutto Sprawdzenie)
[2] Obetnij znaczniki czasu do daty i liczby do sensownej precyzji
[3] Wyłącz Automatyczną datę i godzinę w opcjach pliku
[4] Trzymaj opisy w wymiarach, klucze liczbowe w fakcie (star schema)
[5] Relacje jeden do wielu, kierunek pojedynczy, na kluczu liczbowym
[6] SUM zamiast SUMX, gdy nie mnożysz kolumn
[7] Prosty warunek w CALCULATE zamiast FILTER na całej tabeli
[8] VAR na powtarzalne składniki, DIVIDE zamiast ukośnika
[9] Ukryj kolumny techniczne i klucze przed użytkownikiem
[10] Zmierz przed i po w Analizatorze wydajności

Relacje: kardynalność i kierunek filtra

Relacja w modelu Nordvelli między FaktSprzedaz a DimProdukty jest typu wiele do jednego (wiele wierszy sprzedaży do jednego produktu) z kierunkiem filtra pojedynczym. To jest ustawienie, którego pilnujesz. Kierunek dwukierunkowy (ang. both) bywa potrzebny w wąskich przypadkach, ale kosztuje wydajność i potrafi wprowadzić niejednoznaczność w modelu, więc włączaj go tylko, gdy naprawdę musisz, i tylko na konkretnej relacji.

Okno Edytowanie relacji w Power BI: FaktSprzedaz do DimProdukty po ProduktID, Wiele do jednego, kierunek Pojedyncza
Dwuklik na linii relacji w widoku Model otwiera to okno. Na dole dwa pola, których pilnujesz: Kardynalność ustawiona na Wiele do jednego (*:1) i Kierunek filtrowania krzyżowego na Pojedyncza. Podgląd obu tabel u góry (Z tabeli FaktSprzedaz, Do tabeli DimProdukty) służy do jednej rzeczy: sprawdzenia, czy klucz po obu stronach to naprawdę ta sama kolumna i ten sam typ, w tej relacji ProduktID. Pole Przyjmowanie integralności referencyjnej zostaje wyszarzone, bo dotyczy tylko modeli w trybie DirectQuery.

Ukrywaj to, czego użytkownik nie liczy

Klucze techniczne (DataID, ProduktID, SklepID, PracownikID) i kolumny pomocnicze ukryj w widoku Model prawym przyciskiem, Ukryj w widoku raportu. To nie zmienia rozmiaru, ale porządkuje listę pól, zmniejsza ryzyko, że ktoś przeciągnie klucz na wykres i wywoła kosztowne grupowanie po kolumnie o średniej kardynalności zamiast po atrybucie opisowym.

Widok Model Power BI: menu kolumny DataID w FaktSprzedaz z zaznaczoną pozycją Ukryj w widoku raportu i Jest ukryty Tak
Kolumna DataID w FaktSprzedaz już jest ukryta - widać to na dwa sposoby: ptaszek przy pozycji Ukryj w widoku raportu w menu i przełącznik Jest ukryty: Tak w panelu Właściwości po prawej. Przekreślone oko przy nazwie kolumny w kafelku to ten sam sygnał. Ukryte pole nadal działa w relacjach i w mierze, znika tylko z listy, którą widzi osoba budująca raport.
PraktykaNa co wpływaPriorytet
Redukcja kardynalności kolumnrozmiar i szybkość odczytubardzo wysoki
Schemat gwiazdy zamiast płaskiej tabelirozmiar i szybkość miarwysoki
Przepisanie kosztownych miarczas zapytania DAXwysoki
Kierunek filtra pojedynczyszybkość i jednoznacznośćśredni
Ukrywanie kluczy technicznychporządek i profilaktykaniski

Po tej lekcji model Nordvelli zajmuje w pamięci 5,30 MiB (DAX Studio, VertiPaq Analyzer, widok Summary), plik .pbix waży 7,1 MB zamiast 8,4 MB, a wszystkie strony raportu pokazują te same liczby co przed zmianą. To ważne nie tylko dla komfortu, bo mniejszy model odświeża się szybciej i lżej obciąża pojemność w usłudze Power BI, o czym piszemy w rozdziałach o publikacji i odświeżaniu.

Plik do pobrania: plik startowy nordvella_17_grupy_obliczeniowe.pbix i gotowy efekt nordvella_18_optymalizacja.pbix. Zmierz stronę Przegląd Analizatorem wydajności, usuń kolumnę Wartosc Brutto Sprawdzenie i porównaj VertiPaq Analyzer przed i po. Najlepiej uczysz się wydajności na własnym pomiarze.

✕

Najczęściej zadawane pytania

Jak zmierzyć, który wizual w raporcie Power BI działa najwolniej?
Włącz Analizator wydajności na karcie Widok, kliknij Rozpocznij nagrywanie, następnie Odśwież wizualizacje i wejdź w interakcję z raportem. Analizator pokaże dla każdego wizualu czas w milisekundach z podziałem na zapytanie DAX, wyświetlanie elementu wizualnego i Inne. Najwyższa wartość zapytania DAX wskazuje wizual do optymalizacji.
Co najbardziej zmniejsza rozmiar modelu Power BI?
Największy wpływ ma redukcja kardynalności kolumn, czyli liczby wartości unikalnych. Usuń niepotrzebne kolumny, obetnij precyzję znaczników czasu do daty, zamień długie teksty na klucze liczbowe i wyłącz automatyczną hierarchię dat. Silnik VertiPaq kompresuje kolumny o niskiej liczbie różnych wartości znacznie lepiej.
Star schema czy jedna tabela płaska dla wydajności w Power BI?
Star schema, czyli schemat gwiazdy z tabelą faktów pośrodku i tabelami wymiarów wokół, jest szybsza i lżejsza. Jedna szeroka tabela płaska powiela wartości opisowe w każdym wierszu faktów, przez co rośnie kardynalność, rośnie rozmiar i wolniej działają miary.
Po czym poznać miarę DAX, która spowalnia raport Power BI?
Analizator wydajności pokazuje wtedy wysoki czas zapytania DAX, a nie wyświetlania. Typowe kosztowne wzorce to iterator z wyrażeniem, którego silnik magazynu nie policzy sam, na przykład IF albo zamiana tekstu na liczbę, oraz FILTER po całej tabeli faktów wewnątrz CALCULATE zamiast prostego warunku na kolumnie.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...