Zarządzanie obciążeniami przy użyciu klas zasobów w usłudze Azure Synapse Analytics
Wskazówki dotyczące używania klas zasobów do zarządzania pamięcią i współbieżnością zapytań puli SQL usługi Synapse w Azure Synapse.
Co to są klasy zasobów
Wydajność zapytania jest określana przez klasę zasobów użytkownika. Klasy zasobów są wstępnie określone limity zasobów w puli SQL usługi Synapse, które zarządzają zasobami obliczeniowymi i współbieżnością na potrzeby wykonywania zapytań. Klasy zasobów mogą pomóc w konfigurowaniu zasobów dla zapytań, ustawiając limity liczby zapytań uruchamianych współbieżnie i zasobów obliczeniowych przypisanych do każdego zapytania. Istnieje kompromis między pamięcią a współbieżnością.
- Mniejsze klasy zasobów zmniejszają maksymalną ilość pamięci na zapytanie, ale zwiększają współbieżność.
- Większe klasy zasobów zwiększają maksymalną ilość pamięci na zapytanie, ale zmniejszają współbieżność.
Istnieją dwa typy klas zasobów:
- Klasy zasobów statycznych, które są dobrze dopasowane do zwiększonej współbieżności w stałym rozmiarze zestawu danych.
- Dynamiczne klasy zasobów, które są dobrze odpowiednie dla zestawów danych, które rosną i wymagają zwiększonej wydajności, ponieważ poziom usługi jest skalowany w górę.
Klasy zasobów używają miejsc współbieżności do mierzenia zużycia zasobów. Miejsca współbieżności zostały wyjaśnione w dalszej części tego artykułu.
- Aby wyświetlić użycie zasobów dla klas zasobów, zobacz Limity pamięci i współbieżności.
- Aby dostosować klasę zasobów, możesz uruchomić zapytanie w ramach innego użytkownika lub zmienić członkostwo w klasie zasobów bieżącego użytkownika .
Statyczne klasy zasobów
Statyczne klasy zasobów przydzielają taką samą ilość pamięci, niezależnie od bieżącego poziomu wydajności, który jest mierzony w jednostkach magazynu danych. Ponieważ zapytania uzyskują tę samą alokację pamięci niezależnie od poziomu wydajności, skalowanie magazynu danych w poziomie umożliwia uruchamianie większej liczby zapytań w ramach klasy zasobów. Statyczne klasy zasobów są idealne, jeśli wolumin danych jest znany i stały.
Statyczne klasy zasobów są implementowane przy użyciu wstępnie zdefiniowanych ról bazy danych:
- staticrc10
- staticrc20
- staticrc30
- staticrc40
- staticrc50
- staticrc60
- staticrc70
- staticrc80
Dynamiczne klasy zasobów
Dynamiczne klasy zasobów przydzielają zmienną ilość pamięci w zależności od bieżącego poziomu usługi. Chociaż statyczne klasy zasobów są korzystne dla wyższych woluminów współbieżności i danych statycznych, dynamiczne klasy zasobów są lepiej dostosowane do rosnącej lub zmiennej ilości danych. Podczas skalowania w górę do większego poziomu usługi zapytania automatycznie uzyskują więcej pamięci.
Dynamiczne klasy zasobów są implementowane przy użyciu wstępnie zdefiniowanych ról bazy danych:
- smallrc
- mediumrc
- większe
- xlargerc
Alokacja pamięci dla każdej klasy zasobów jest następująca.
Poziom usługi | smallrc | mediumrc | większe | xlargerc |
---|---|---|---|---|
DW100c | 25% | 25% | 25% | 70% |
DW200c | 12.5% | 12.5% | 22% | 70% |
DW300c | 8% | 10% | 22% | 70% |
DW400c | 6,25% | 10% | 22% | 70% |
DW500c. | 5% | 10% | 22% | 70% |
DW1000c do DW30000c |
3% | 10% | 22% | 70% |
Domyślna klasa zasobów
Domyślnie każdy użytkownik jest członkiem dynamicznej klasy zasobów smallrc.
Klasa zasobów administratora usługi jest stała w małej klasie i nie można jej zmienić. Administrator usługi jest użytkownikiem utworzonym podczas procesu aprowizacji. Administrator usługi w tym kontekście jest identyfikatorem logowania określonego dla nazwy logowania administratora serwera podczas tworzenia nowej puli SQL usługi Synapse z nowym serwerem.
Uwaga
Użytkownicy lub grupy zdefiniowane jako administratorzy usługi Active Directory są również administratorami usług.
Operacje klasy zasobów
Klasy zasobów zostały zaprojektowane tak, aby zwiększyć wydajność działań związanych z zarządzaniem danymi i manipulowaniem nimi. Złożone zapytania mogą również korzystać z uruchamiania w ramach dużej klasy zasobów. Na przykład wydajność zapytań dla dużych sprzężeń i sortowania może poprawić, gdy klasa zasobów jest wystarczająco duża, aby umożliwić wykonywanie zapytania w pamięci.
Operacje zarządzane przez klasy zasobów
Te operacje podlegają klasom zasobów:
- INSERT-SELECT, UPDATE, DELETE
- SELECT (podczas wykonywania zapytań dotyczących tabel użytkowników)
- ALTER INDEX — PONOWNE KOMPILOWANIE lub REORGANIZACJA
- ALTER TABLE REBUILD
- CREATE INDEX
- TWORZENIE KLASTROWANEGO INDEKSU MAGAZYNU KOLUMN
- TWORZENIE TABELI JAKO SELECT (CTAS)
- Ładowanie danych
- Operacje przenoszenia danych prowadzone przez usługę przenoszenia danych (DMS)
Uwaga
Instrukcje SELECT dotyczące dynamicznych widoków zarządzania (DMV) lub innych widoków systemowych nie podlegają żadnym limitom współbieżności. System można monitorować niezależnie od liczby zapytań wykonywanych na nim.
Operacje nie podlegają klasom zasobów
Niektóre zapytania są zawsze uruchamiane w klasie zasobów smallrc, mimo że użytkownik jest członkiem większej klasy zasobów. Te wykluczone zapytania nie są liczone do limitu współbieżności. Jeśli na przykład limit współbieżności wynosi 16, wielu użytkowników może wybierać z widoków systemowych bez wpływu na dostępne gniazda współbieżności.
Następujące instrukcje są wykluczone z klas zasobów i zawsze są uruchamiane w smallrc:
- TWORZENIE LUB UPUSZCZANIE TABELI
- ALTER TABLE ... PRZEŁĄCZANIE, DZIELENIE LUB SCALANIE PARTYCJI
- ALTER INDEX DISABLE
- DROP INDEX
- TWORZENIE, AKTUALIZOWANIE LUB USUWANIE STATYSTYK
- TRUNCATE TABLE
- ALTER AUTHORIZATION
- CREATE LOGIN
- TWORZENIE, ZMIENIANIE LUB UPUSZCZANIE UŻYTKOWNIKA
- TWORZENIE, ZMIENIANIE LUB USUWANIE PROCEDURY
- TWORZENIE LUB UPUSZCZANIE WIDOKU
- WSTAWIANIE WARTOŚCI
- WYBIERANIE z widoków systemowych i widoków DMV
- EXPLAIN
- DBCC
Gniazda współbieżności
Miejsca współbieżności to wygodny sposób śledzenia zasobów dostępnych na potrzeby wykonywania zapytań. Są one jak bilety, które kupujesz, aby zarezerwować miejsca na koncercie, ponieważ siedzenia są ograniczone. Łączna liczba miejsc współbieżności na magazyn danych jest określana przez poziom usługi. Aby zapytanie mogło rozpocząć wykonywanie, musi być w stanie zarezerwować wystarczająco dużo miejsc współbieżności. Po zakończeniu zapytania zwalnia on gniazda współbieżności.
- Zapytanie uruchomione z 10 miejscami współbieżności może uzyskać dostęp do 5 razy więcej zasobów obliczeniowych niż zapytanie uruchomione z 2 miejscami współbieżności.
- Jeśli każde zapytanie wymaga 10 miejsc współbieżności i istnieje 40 miejsc współbieżności, tylko 4 zapytania mogą działać współbieżnie.
Tylko zapytania zarządzane przez zasoby używają miejsc współbieżności. Zapytania systemowe i niektóre proste zapytania nie używają żadnych miejsc. Dokładna liczba wykorzystanych miejsc współbieżności jest określana przez klasę zasobów zapytania.
Wyświetlanie klas zasobów
Klasy zasobów są implementowane jako wstępnie zdefiniowane role bazy danych. Istnieją dwa typy klas zasobów: dynamiczne i statyczne. Aby wyświetlić listę klas zasobów, użyj następującego zapytania:
SELECT name
FROM sys.database_principals
WHERE name LIKE '%rc%' AND type_desc = 'DATABASE_ROLE';
Zmienianie klasy zasobów użytkownika
Klasy zasobów są implementowane przez przypisywanie użytkowników do ról bazy danych. Gdy użytkownik uruchamia zapytanie, zapytanie jest uruchamiane z klasą zasobów użytkownika. Jeśli na przykład użytkownik jest członkiem roli bazy danych staticrc10, zapytania są uruchamiane z małą ilością pamięci. Jeśli użytkownik bazy danych jest członkiem ról bazy danych xlargerc lub staticrc80, ich zapytania są uruchamiane z dużą ilością pamięci.
Aby zwiększyć klasę zasobów użytkownika, użyj sp_addrolemember , aby dodać użytkownika do roli bazy danych dużej klasy zasobów. Poniższy kod dodaje użytkownika do większej roli bazy danych. Każde żądanie pobiera 22% pamięci systemowej.
EXEC sp_addrolemember 'largerc', 'loaduser';
Aby zmniejszyć klasę zasobów, użyj sp_droprolemember. Jeśli "loaduser" nie jest członkiem ani żadną inną klasą zasobów, przechodzą do domyślnej klasy zasobów smallrc z 3% przydziałem pamięci.
EXEC sp_droprolemember 'largerc', 'loaduser';
Pierwszeństwo klasy zasobów
Użytkownicy mogą być członkami wielu klas zasobów. Gdy użytkownik należy do więcej niż jednej klasy zasobów:
- Dynamiczne klasy zasobów mają pierwszeństwo przed statyczną klasą zasobów. Jeśli na przykład użytkownik jest członkiem zarówno mediumrc(dynamic) i staticrc80 (static), zapytania są uruchamiane przy użyciu mediumrc.
- Większe klasy zasobów mają pierwszeństwo przed mniejszymi klasami zasobów. Jeśli na przykład użytkownik jest członkiem mediumrc i większego, zapytania są uruchamiane z większym rozmiarem. Podobnie, jeśli użytkownik jest członkiem zarówno staticrc20, jak i statirc80, zapytania są uruchamiane przy użyciu alokacji zasobów staticrc80.
Zalecenia
Uwaga
Rozważ wykorzystanie możliwości zarządzania obciążeniami (izolacja obciążeń, klasyfikacja i znaczenie), aby uzyskać większą kontrolę nad obciążeniem i przewidywalną wydajnością.
Zalecamy utworzenie użytkownika dedykowanego do uruchamiania określonego typu zapytania lub operacji ładowania. Należy przyznać użytkownikowi stałą klasę zasobów zamiast często zmieniać klasę zasobów. Statyczne klasy zasobów zapewniają większą ogólną kontrolę nad obciążeniem, dlatego zalecamy użycie statycznych klas zasobów przed rozważeniem dynamicznych klas zasobów.
Klasy zasobów dla użytkowników ładu
CREATE TABLE
domyślnie używa klastrowanych indeksów magazynu kolumn. Kompresowanie danych do indeksu magazynu kolumn jest operacją intensywnie obciążającą pamięć, a ciśnienie pamięci może zmniejszyć jakość indeksu. Wykorzystanie pamięci może prowadzić do konieczności wyższej klasy zasobów podczas ładowania danych. Aby zapewnić wystarczającą ilość pamięci, możesz utworzyć użytkownika wyznaczonego do uruchamiania obciążeń i przypisać tego użytkownika do wyższej klasy zasobów.
Pamięć wymagana do wydajnego przetwarzania obciążeń zależy od charakteru załadowanej tabeli i rozmiaru danych. Aby uzyskać więcej informacji na temat wymagań dotyczących pamięci, zobacz Maksymalizowanie jakości grupy wierszy.
Po określeniu wymagania dotyczącego pamięci wybierz, czy użytkownik ładowania ma zostać przypisany do statycznej lub dynamicznej klasy zasobów.
- Użyj statycznej klasy zasobów, gdy wymagania dotyczące pamięci tabeli mieszczą się w określonym zakresie. Ładuje przebieg z odpowiednią pamięcią. Podczas skalowania magazynu danych obciążenia nie wymagają większej ilości pamięci. Przy użyciu statycznej klasy zasobów alokacje pamięci pozostają stałe. Ta spójność oszczędza pamięć i umożliwia jednoczesne uruchamianie większej liczby zapytań. Zalecamy, aby nowe rozwiązania używały najpierw statycznych klas zasobów, ponieważ zapewniają większą kontrolę.
- Użyj dynamicznej klasy zasobów, gdy wymagania dotyczące pamięci tabeli różnią się znacznie. Obciążenia mogą wymagać większej ilości pamięci niż bieżący poziom jednostek DWU lub cDWU. Skalowanie magazynu danych zwiększa ilość pamięci do operacji ładowania, co pozwala na szybsze wykonywanie obciążeń.
Klasy zasobów dla zapytań
Niektóre zapytania intensywnie korzystają z obliczeń, a niektóre z nich nie są.
- Wybierz dynamiczną klasę zasobów, gdy zapytania są złożone, ale nie wymagają dużej współbieżności. Na przykład generowanie codziennych lub tygodniowych raportów jest okazjonalną potrzebą zasobów. Jeśli raporty przetwarzają duże ilości danych, skalowanie magazynu danych zapewnia większą ilość pamięci do istniejącej klasy zasobów użytkownika.
- Wybierz statyczną klasę zasobów, gdy oczekiwania dotyczące zasobów różnią się w ciągu dnia. Na przykład statyczna klasa zasobów działa dobrze, gdy magazyn danych jest zapytany przez wiele osób. Podczas skalowania magazynu danych ilość pamięci przydzielonej użytkownikowi nie zmienia się. W związku z tym więcej zapytań można wykonywać równolegle w systemie.
Odpowiednie przydziały pamięci zależą od wielu czynników, takich jak ilość zapytań dotyczących danych, charakter schematów tabeli i różne sprzężenia, wybieranie i predykaty grup. Ogólnie rzecz biorąc, przydzielanie większej ilości pamięci umożliwia szybsze wykonywanie zapytań, ale zmniejsza ogólną współbieżność. Jeśli współbieżność nie jest problemem, nadmierne przydzielanie pamięci nie szkodzi przepływności.
Aby dostosować wydajność, użyj różnych klas zasobów. W następnej sekcji przedstawiono procedurę składowaną, która ułatwia ustalenie najlepszej klasy zasobów.
Przykładowy kod do znajdowania najlepszej klasy zasobów
Można użyć następującej procedury składowanej, aby ustalić współbieżność i udzielanie pamięci dla danej klasy zasobów w danej klasie slo i najlepszą klasę zasobów dla operacji CCI intensywnie korzystających z pamięci w tabeli CCI bez partycjonowania w danej klasie zasobów:
Oto cel tej procedury składowanej:
- Aby wyświetlić współbieżność i przydział pamięci na klasę zasobów w danym celu SLO. Użytkownik musi podać wartość NULL dla schematu i nazwy tabeli, jak pokazano w tym przykładzie.
- Aby wyświetlić najlepszą klasę zasobów dla operacji CCI intensywnie korzystających z pamięci (ładowanie, kopiowanie tabeli, ponowne kompilowanie indeksu itp.) w tabeli CCI bez partycji w danej klasie zasobów. Przechowywany proc używa schematu tabeli, aby dowiedzieć się, czy wymagana ilość pamięci jest przyznawana.
Ograniczenia zależności &
- Ta procedura składowana nie jest przeznaczona do obliczania wymagań dotyczących pamięci dla partycjonowanej tabeli cci.
- Ta procedura składowana nie uwzględnia wymagań dotyczących pamięci dla części SELECT CTAS/INSERT-SELECT i zakłada, że jest to select.
- Ta procedura składowana używa tabeli tymczasowej, która jest dostępna w sesji, w której utworzono tę procedurę składowaną.
- Ta procedura składowana zależy od bieżących ofert (na przykład konfiguracji sprzętu, konfiguracji usługi DMS), a jeśli którakolwiek z tych zmian ulegnie zmianie, ta przechowywana wartość proc nie będzie działać poprawnie.
- Ta procedura składowana zależy od istniejących ofert limitów współbieżności, a jeśli te zmiany zostaną zmienione, ta procedura składowana nie będzie działać poprawnie.
- Ta procedura składowana zależy od istniejących ofert klas zasobów, a jeśli te zmiany zostaną zmienione, ta procedura składowana nie będzie działać poprawnie.
Uwaga
Jeśli nie otrzymujesz danych wyjściowych po wykonaniu procedury składowanej z podanymi parametrami, mogą wystąpić dwa przypadki.
- Jeden z parametrów DW zawiera nieprawidłową wartość SLO
- Lub nie ma pasującej klasy zasobów dla operacji CCI w tabeli.
Na przykład w dw100c najwyższy dostępny przydział pamięci wynosi 1 GB, a jeśli schemat tabeli jest wystarczająco szeroki, aby przekroczyć wymaganie 1 GB.
Przykład użycia
Składnia:
EXEC dbo.prc_workload_management_by_DWU @DWU VARCHAR(7), @SCHEMA_NAME VARCHAR(128), @TABLE_NAME VARCHAR(128)
- @DWU: Podaj parametr NULL w celu wyodrębnienia bieżącej jednostki DWU z bazy danych DW lub podania dowolnej obsługiwanej jednostki DWU w postaci "DW100c"
- @SCHEMA_NAME: Podaj nazwę schematu tabeli
- @TABLE_NAME: Podaj nazwę tabeli interesującej
Przykłady wykonywania tego przechowywanego proc:
EXEC dbo.prc_workload_management_by_DWU 'DW2000c', 'dbo', 'Table1';
EXEC dbo.prc_workload_management_by_DWU NULL, 'dbo', 'Table1';
EXEC dbo.prc_workload_management_by_DWU 'DW6000c', NULL, NULL;
EXEC dbo.prc_workload_management_by_DWU NULL, NULL, NULL;
Poniższa instrukcja tworzy tabelę Table1, która jest używana w poprzednich przykładach.
CREATE TABLE Table1 (a int, b varchar(50), c decimal (18,10), d char(10), e varbinary(15), f float, g datetime, h date);
Definicja procedury składowanej
-------------------------------------------------------------------------------
-- Dropping prc_workload_management_by_DWU procedure if it exists.
-------------------------------------------------------------------------------
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'prc_workload_management_by_DWU')
DROP PROCEDURE dbo.prc_workload_management_by_DWU
GO
-------------------------------------------------------------------------------
-- Creating prc_workload_management_by_DWU.
-------------------------------------------------------------------------------
CREATE PROCEDURE dbo.prc_workload_management_by_DWU
(@DWU VARCHAR(8),
@SCHEMA_NAME VARCHAR(128),
@TABLE_NAME VARCHAR(128)
)
AS
IF @DWU IS NULL
BEGIN
-- Selecting proper DWU for the current DB if not specified.
SELECT @DWU = 'DW'+ CAST(CASE WHEN Mem> 4 THEN Nodes*500
ELSE Mem*100
END AS VARCHAR(10)) +'c'
FROM (
SELECT Nodes=count(distinct n.pdw_node_id), Mem=max(i.committed_target_kb/1000/1000/60)
FROM sys.dm_pdw_nodes n
CROSS APPLY sys.dm_pdw_nodes_os_sys_info i
WHERE type = 'COMPUTE')A
END
-- Dropping temp table if exists.
IF OBJECT_ID('tempdb..#ref') IS NOT NULL
BEGIN
DROP TABLE #ref;
END;
-- Creating ref. temp table (CTAS) to hold mapping info.
CREATE TABLE #ref
WITH (DISTRIBUTION = ROUND_ROBIN)
AS
WITH
-- Creating concurrency slots mapping for various DWUs.
alloc
AS
(
SELECT 'DW100c' AS DWU,4 AS max_queries,4 AS max_slots,1 AS slots_used_smallrc,1 AS slots_used_mediumrc,2 AS slots_used_largerc,4 AS slots_used_xlargerc,1 AS slots_used_staticrc10,2 AS slots_used_staticrc20,4 AS slots_used_staticrc30,4 AS slots_used_staticrc40,4 AS slots_used_staticrc50,4 AS slots_used_staticrc60,4 AS slots_used_staticrc70,4 AS slots_used_staticrc80
UNION ALL
SELECT 'DW200c',8,8,1,2,4,8,1,2,4,8,8,8,8,8
UNION ALL
SELECT 'DW300c',12,12,1,2,4,8,1,2,4,8,8,8,8,8
UNION ALL
SELECT 'DW400c',16,16,1,4,8,16,1,2,4,8,16,16,16,16
UNION ALL
SELECT 'DW500c',20,20,1,4,8,16,1,2,4,8,16,16,16,16
UNION ALL
SELECT 'DW1000c',32,40,1,4,8,28,1,2,4,8,16,32,32,32
UNION ALL
SELECT 'DW1500c',32,60,1,6,13,42,1,2,4,8,16,32,32,32
UNION ALL
SELECT 'DW2000c',48,80,2,8,17,56,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW2500c',48,100,3,10,22,70,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW3000c',64,120,3,12,26,84,1,2,4,8,16,32,64,64
UNION ALL
SELECT 'DW5000c',64,200,6,20,44,140,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW6000c',128,240,7,24,52,168,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW7500c',128,300,9,30,66,210,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW10000c',128,400,12,40,88,280,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW15000c',128,600,18,60,132,420,1,2,4,8,16,32,64,128
UNION ALL
SELECT 'DW30000c',128,1200,36,120,264,840,1,2,4,8,16,32,64,128
)
-- Creating workload mapping to their corresponding slot consumption and default memory grant.
,map
AS
(
SELECT CONVERT(varchar(20), 'SloDWGroupSmall') AS wg_name, slots_used_smallrc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupMedium') AS wg_name, slots_used_mediumrc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupLarge') AS wg_name, slots_used_largerc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT CONVERT(varchar(20), 'SloDWGroupXLarge') AS wg_name, slots_used_xlargerc AS slots_used FROM alloc WHERE DWU = @DWU
UNION ALL
SELECT 'SloDWGroupC00',1
UNION ALL
SELECT 'SloDWGroupC01',2
UNION ALL
SELECT 'SloDWGroupC02',4
UNION ALL
SELECT 'SloDWGroupC03',8
UNION ALL
SELECT 'SloDWGroupC04',16
UNION ALL
SELECT 'SloDWGroupC05',32
UNION ALL
SELECT 'SloDWGroupC06',64
UNION ALL
SELECT 'SloDWGroupC07',128
)
-- Creating ref based on current / asked DWU.
, ref
AS
(
SELECT a1.*
, m1.wg_name AS wg_name_smallrc
, m1.slots_used * 250 AS tgt_mem_grant_MB_smallrc
, m2.wg_name AS wg_name_mediumrc
, m2.slots_used * 250 AS tgt_mem_grant_MB_mediumrc
, m3.wg_name AS wg_name_largerc
, m3.slots_used * 250 AS tgt_mem_grant_MB_largerc
, m4.wg_name AS wg_name_xlargerc
, m4.slots_used * 250 AS tgt_mem_grant_MB_xlargerc
, m5.wg_name AS wg_name_staticrc10
, m5.slots_used * 250 AS tgt_mem_grant_MB_staticrc10
, m6.wg_name AS wg_name_staticrc20
, m6.slots_used * 250 AS tgt_mem_grant_MB_staticrc20
, m7.wg_name AS wg_name_staticrc30
, m7.slots_used * 250 AS tgt_mem_grant_MB_staticrc30
, m8.wg_name AS wg_name_staticrc40
, m8.slots_used * 250 AS tgt_mem_grant_MB_staticrc40
, m9.wg_name AS wg_name_staticrc50
, m9.slots_used * 250 AS tgt_mem_grant_MB_staticrc50
, m10.wg_name AS wg_name_staticrc60
, m10.slots_used * 250 AS tgt_mem_grant_MB_staticrc60
, m11.wg_name AS wg_name_staticrc70
, m11.slots_used * 250 AS tgt_mem_grant_MB_staticrc70
, m12.wg_name AS wg_name_staticrc80
, m12.slots_used * 250 AS tgt_mem_grant_MB_staticrc80
FROM alloc a1
JOIN map m1 ON a1.slots_used_smallrc = m1.slots_used and m1.wg_name = 'SloDWGroupSmall'
JOIN map m2 ON a1.slots_used_mediumrc = m2.slots_used and m2.wg_name = 'SloDWGroupMedium'
JOIN map m3 ON a1.slots_used_largerc = m3.slots_used and m3.wg_name = 'SloDWGroupLarge'
JOIN map m4 ON a1.slots_used_xlargerc = m4.slots_used and m4.wg_name = 'SloDWGroupXLarge'
JOIN map m5 ON a1.slots_used_staticrc10 = m5.slots_used and m5.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m6 ON a1.slots_used_staticrc20 = m6.slots_used and m6.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m7 ON a1.slots_used_staticrc30 = m7.slots_used and m7.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m8 ON a1.slots_used_staticrc40 = m8.slots_used and m8.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m9 ON a1.slots_used_staticrc50 = m9.slots_used and m9.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m10 ON a1.slots_used_staticrc60 = m10.slots_used and m10.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m11 ON a1.slots_used_staticrc70 = m11.slots_used and m11.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
JOIN map m12 ON a1.slots_used_staticrc80 = m12.slots_used and m12.wg_name NOT IN ('SloDWGroupSmall','SloDWGroupMedium','SloDWGroupLarge','SloDWGroupXLarge')
WHERE a1.DWU = @DWU
)
SELECT DWU
, max_queries
, max_slots
, slots_used
, wg_name
, tgt_mem_grant_MB
, up1 as rc
, (ROW_NUMBER() OVER(PARTITION BY DWU ORDER BY DWU)) as rc_id
FROM
(
SELECT DWU
, max_queries
, max_slots
, slots_used
, wg_name
, tgt_mem_grant_MB
, REVERSE(SUBSTRING(REVERSE(wg_names),1,CHARINDEX('_',REVERSE(wg_names),1)-1)) as up1
, REVERSE(SUBSTRING(REVERSE(tgt_mem_grant_MBs),1,CHARINDEX('_',REVERSE(tgt_mem_grant_MBs),1)-1)) as up2
, REVERSE(SUBSTRING(REVERSE(slots_used_all),1,CHARINDEX('_',REVERSE(slots_used_all),1)-1)) as up3
FROM ref AS r1
UNPIVOT
(
wg_name FOR wg_names IN (wg_name_smallrc,wg_name_mediumrc,wg_name_largerc,wg_name_xlargerc,
wg_name_staticrc10, wg_name_staticrc20, wg_name_staticrc30, wg_name_staticrc40, wg_name_staticrc50,
wg_name_staticrc60, wg_name_staticrc70, wg_name_staticrc80)
) AS r2
UNPIVOT
(
tgt_mem_grant_MB FOR tgt_mem_grant_MBs IN (tgt_mem_grant_MB_smallrc,tgt_mem_grant_MB_mediumrc,
tgt_mem_grant_MB_largerc,tgt_mem_grant_MB_xlargerc, tgt_mem_grant_MB_staticrc10, tgt_mem_grant_MB_staticrc20,
tgt_mem_grant_MB_staticrc30, tgt_mem_grant_MB_staticrc40, tgt_mem_grant_MB_staticrc50,
tgt_mem_grant_MB_staticrc60, tgt_mem_grant_MB_staticrc70, tgt_mem_grant_MB_staticrc80)
) AS r3
UNPIVOT
(
slots_used FOR slots_used_all IN (slots_used_smallrc,slots_used_mediumrc,slots_used_largerc,
slots_used_xlargerc, slots_used_staticrc10, slots_used_staticrc20, slots_used_staticrc30,
slots_used_staticrc40, slots_used_staticrc50, slots_used_staticrc60, slots_used_staticrc70,
slots_used_staticrc80)
) AS r4
) a
WHERE up1 = up2
AND up1 = up3
;
-- Getting current info about workload groups.
WITH
dmv
AS
(
SELECT
rp.name AS rp_name
, rp.max_memory_kb*1.0/1048576 AS rp_max_mem_GB
, (rp.max_memory_kb*1.0/1024)
*(request_max_memory_grant_percent/100) AS max_memory_grant_MB
, (rp.max_memory_kb*1.0/1048576)
*(request_max_memory_grant_percent/100) AS max_memory_grant_GB
, wg.name AS wg_name
, wg.importance AS importance
, wg.request_max_memory_grant_percent AS request_max_memory_grant_percent
FROM sys.dm_pdw_nodes_resource_governor_workload_groups wg
JOIN sys.dm_pdw_nodes_resource_governor_resource_pools rp ON wg.pdw_node_id = rp.pdw_node_id
AND wg.pool_id = rp.pool_id
WHERE rp.name = 'SloDWPool'
GROUP BY
rp.name
, rp.max_memory_kb
, wg.name
, wg.importance
, wg.request_max_memory_grant_percent
)
-- Creating resource class name mapping.
,names
AS
(
SELECT 'smallrc' as resource_class, 1 as rc_id
UNION ALL
SELECT 'mediumrc', 2
UNION ALL
SELECT 'largerc', 3
UNION ALL
SELECT 'xlargerc', 4
UNION ALL
SELECT 'staticrc10', 5
UNION ALL
SELECT 'staticrc20', 6
UNION ALL
SELECT 'staticrc30', 7
UNION ALL
SELECT 'staticrc40', 8
UNION ALL
SELECT 'staticrc50', 9
UNION ALL
SELECT 'staticrc60', 10
UNION ALL
SELECT 'staticrc70', 11
UNION ALL
SELECT 'staticrc80', 12
)
,base AS
( SELECT schema_name
, table_name
, SUM(column_count) AS column_count
, ISNULL(SUM(short_string_column_count),0) AS short_string_column_count
, ISNULL(SUM(long_string_column_count),0) AS long_string_column_count
FROM ( SELECT sm.name AS schema_name
, tb.name AS table_name
, COUNT(co.column_id) AS column_count
, CASE WHEN co.system_type_id IN (36,43,106,108,165,167,173,175,231,239)
AND co.max_length <= 32
THEN COUNT(co.column_id)
END AS short_string_column_count
, CASE WHEN co.system_type_id IN (165,167,173,175,231,239)
AND co.max_length > 32 and co.max_length <=8000
THEN COUNT(co.column_id)
END AS long_string_column_count
FROM sys.schemas AS sm
JOIN sys.tables AS tb on sm.[schema_id] = tb.[schema_id]
JOIN sys.columns AS co ON tb.[object_id] = co.[object_id]
WHERE tb.name = @TABLE_NAME AND sm.name = @SCHEMA_NAME
GROUP BY sm.name
, tb.name
, co.system_type_id
, co.max_length ) a
GROUP BY schema_name
, table_name
)
, size AS
(
SELECT schema_name
, table_name
, 75497472 AS table_overhead
, column_count*1048576*8 AS column_size
, short_string_column_count*1048576*32 AS short_string_size, (long_string_column_count*16777216) AS long_string_size
FROM base
UNION
SELECT CASE WHEN COUNT(*) = 0 THEN 'EMPTY' END as schema_name
,CASE WHEN COUNT(*) = 0 THEN 'EMPTY' END as table_name
,CASE WHEN COUNT(*) = 0 THEN 0 END as table_overhead
,CASE WHEN COUNT(*) = 0 THEN 0 END as column_size
,CASE WHEN COUNT(*) = 0 THEN 0 END as short_string_size
,CASE WHEN COUNT(*) = 0 THEN 0 END as long_string_size
FROM base
)
, load_multiplier as
(
SELECT CASE
WHEN FLOOR(8 * (CAST (CAST(REPLACE(REPLACE(@DWU,'DW',''),'c','') AS INT) AS FLOAT)/6000)) > 0
AND CHARINDEX(@DWU,'c')=0
THEN FLOOR(8 * (CAST (CAST(REPLACE(REPLACE(@DWU,'DW',''),'c','') AS INT) AS FLOAT)/6000))
ELSE 1
END AS multiplication_factor
)
SELECT r1.DWU
, schema_name
, table_name
, rc.resource_class as closest_rc_in_increasing_order
, max_queries_at_this_rc = CASE
WHEN (r1.max_slots / r1.slots_used > r1.max_queries)
THEN r1.max_queries
ELSE r1.max_slots / r1.slots_used
END
, r1.max_slots as max_concurrency_slots
, r1.slots_used as required_slots_for_the_rc
, r1.tgt_mem_grant_MB as rc_mem_grant_MB
, CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) AS est_mem_grant_required_for_cci_operation_MB
FROM size
, load_multiplier
, #ref r1, names rc
WHERE r1.rc_id=rc.rc_id
AND CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) < r1.tgt_mem_grant_MB
ORDER BY ABS(CAST((table_overhead*1.0+column_size+short_string_size+long_string_size)*multiplication_factor/1048576 AS DECIMAL(18,2)) - r1.tgt_mem_grant_MB)
GO
Następne kroki
Aby uzyskać więcej informacji na temat zarządzania użytkownikami i zabezpieczeniami bazy danych, zobacz Zabezpieczanie bazy danych w usłudze Synapse SQL. Aby uzyskać więcej informacji o tym, jak większe klasy zasobów mogą poprawić jakość indeksu magazynu kolumn klastra, zobacz Optymalizacje pamięci na potrzeby kompresji magazynu kolumn.