Projektowanie tabel przy użyciu puli SQL usługi Synapse
W tym artykule wyjaśniono kluczowe pojęcia dotyczące projektowania tabel z dedykowaną pulą SQL i bezserwerową pulą SQL w usłudze Azure Synapse Analytics.
- Bezserwerowa pula SQL to usługa zapytań, która działa na danych w usłudze Data Lake. Nie ma on magazynu lokalnego na potrzeby pozyskiwania danych.
- Dedykowana pula SQL reprezentuje kolekcję zasobów analitycznych aprowizowania podczas korzystania z usługi Synapse SQL. Rozmiar dedykowanej puli SQL jest określany przez Magazyn danych Units (DWU).
Następujące tematy dotyczą dedykowanej puli SQL w porównaniu z bezserwerową pulą SQL:
Temat | Dedykowana pula SQL | Bezserwerowa pula SQL |
---|---|---|
Kategoria tabeli | Tak | Nie. |
Nazwy schematów | Tak | Tak |
Nazwy tabel | Tak | Nie. |
Trwałość tabeli | Tak | Nie. |
Zwykła tabela | Tak | Nie. |
Tabela tymczasowa | Tak | Tak |
Tabela zewnętrzna | Tak | Tak |
Typy danych | Tak | Tak |
Rozproszone tabele | Tak | Nie. |
Tabele działania okrężnego | Tak | Nie. |
Tabele rozproszone przy użyciu skrótów | Tak | Nie. |
Replicated tables (Zreplikowane tabele) | Tak | Nie. |
Typowe metody dystrybucji tabel | Tak | Nie. |
Partycje | Tak | Tak |
Indeksy magazynu kolumn | Tak | Nie. |
Statystyki | Tak | Tak |
Klucz podstawowy i unikatowy klucz | Tak | Nie. |
Polecenia służące do tworzenia tabel | Tak | Nie. |
Dopasowywanie danych źródłowych do magazynu danych | Tak | Nie. |
Nieobsługiwane funkcje tabeli | Tak | Nie. |
Zapytania dotyczące rozmiaru tabeli | Tak | Nie. |
Kategoria tabeli
Schemat gwiazdy organizuje dane w tabele faktów i wymiarów. Niektóre tabele są używane do integracji lub przemieszczania danych przed przejściem do tabeli faktów lub wymiarów. Podczas projektowania tabeli zdecyduj, czy dane tabeli należą do tabeli faktów, wymiarów lub tabeli integracji. Ta decyzja informuje o odpowiedniej strukturze tabeli i dystrybucji.
Tabele faktów zawierają dane ilościowe, które są często generowane w systemie transakcyjnym, a następnie ładowane do magazynu danych. Na przykład firma detaliczna generuje transakcje sprzedaży każdego dnia, a następnie ładuje dane do tabeli faktów magazynu danych na potrzeby analizy.
Tabele wymiarów zawierają dane atrybutów , które mogą ulec zmianie, ale zwykle zmieniają się rzadko. Na przykład nazwa i adres klienta są przechowywane w tabeli wymiarów i aktualizowane tylko wtedy, gdy profil klienta ulegnie zmianie. Aby zminimalizować rozmiar dużej tabeli faktów, nazwa i adres klienta nie muszą znajdować się w każdym wierszu tabeli faktów. Zamiast tego tabela faktów i tabela wymiarów mogą udostępniać identyfikator klienta. Zapytanie może łączyć dwie tabele w celu skojarzenia profilu i transakcji klienta.
Tabele integracji zapewniają miejsce na integrowanie lub przemieszczanie danych. Tabelę integracji można utworzyć jako zwykłą tabelę, tabelę zewnętrzną lub tabelę tymczasową. Można na przykład załadować dane do tabeli przejściowej, wykonać przekształcenia danych w środowisku przejściowym, a następnie wstawić dane do tabeli produkcyjnej.
Nazwy schematu
Schematy to dobry sposób grupowania obiektów używanych w podobny sposób. Poniższy kod tworzy schemat zdefiniowany przez użytkownika o nazwie wwi.
CREATE SCHEMA wwi;
Nazwy tabel
Jeśli migrujesz wiele baz danych z rozwiązania lokalnego do dedykowanej puli SQL, najlepszym rozwiązaniem jest migrowanie wszystkich tabel faktów, wymiarów i integracji do jednego schematu puli SQL. Można na przykład przechowywać wszystkie tabele w przykładowym magazynie danych WideWorldImportersDW w jednym schemacie o nazwie wwi.
Aby wyświetlić organizację tabel w dedykowanej puli SQL, można użyć fact
parametrów , dim
i int
jako prefiksów nazw tabel. W poniższej tabeli przedstawiono niektóre nazwy schematów i tabel dla wideWorldImportersDW.
Tabela WideWorldImportersDW | Typ tabeli | Dedykowana pula SQL |
---|---|---|
City | Wymiar | Wwi. DimCity |
Zamówienie | Fakt | Wwi. FactOrder |
Trwałość tabeli
Tabele przechowują dane na stałe w usłudze Azure Storage, tymczasowo w usłudze Azure Storage lub w magazynie danych spoza magazynu danych.
Zwykła tabela
Zwykła tabela przechowuje dane w usłudze Azure Storage w ramach magazynu danych. Tabela i dane utrzymują się, czy sesja jest otwarta. Poniższy przykład tworzy zwykłą tabelę z dwiema kolumnami.
CREATE TABLE MyTable (col1 int, col2 int );
Tabela tymczasowa
Tabela tymczasowa istnieje tylko przez czas trwania sesji. Możesz użyć tabeli tymczasowej, aby uniemożliwić innym użytkownikom wyświetlanie wyników tymczasowych. Korzystanie z tabel tymczasowych zmniejsza również potrzebę czyszczenia. Tabele tymczasowe korzystają z magazynu lokalnego i, w dedykowanych pulach SQL, mogą oferować szybszą wydajność.
Bezserwerowa pula SQL obsługuje tabele tymczasowe, ale ich użycie jest ograniczone, ponieważ można wybrać z tabeli tymczasowej, ale nie można jej połączyć z plikami w magazynie.
Aby uzyskać więcej informacji, zobacz Tabele tymczasowe.
Tabela zewnętrzna
Tabele zewnętrzne wskazują dane znajdujące się w obiekcie blob usługi Azure Storage lub usłudze Azure Data Lake Storage.
Dane z tabel zewnętrznych można zaimportować do dedykowanych pul SQL przy użyciu instrukcji CREATE TABLE AS SELECT (CTAS). Aby zapoznać się z samouczkiem dotyczącym ładowania, zobacz Load the New York Taxicab dataset (Ładowanie zestawu danych Taxicab w Nowym Jorku).
W przypadku bezserwerowej puli SQL można użyć polecenia CREATE EXTERNAL TABLE AS SELECT (CETAS), aby zapisać wynik zapytania w tabeli zewnętrznej w usłudze Azure Storage.
Typy danych
Dedykowana pula SQL obsługuje najczęściej używane typy danych. Aby uzyskać listę obsługiwanych typów danych, zobacz typ danych w dokumentacji CREATE TABLE. Aby uzyskać więcej informacji na temat używania typów danych, zobacz Typy danych tabel w usłudze Synapse SQL.
Rozproszone tabele
Podstawową cechą dedykowanej puli SQL jest sposób, w jaki może przechowywać tabele i obsługiwać je w różnych dystrybucjach. Dedykowana pula SQL obsługuje trzy metody dystrybucji danych:
- Tabele działania okrężnego (ustawienie domyślne)
- Tabele dystrybuowane przy użyciu skrótu
- Tabele replikowane
Tabele działania okrężnego
Tabela okrężna dystrybuuje wiersze tabeli równomiernie we wszystkich dystrybucjach. Wiersze są dystrybuowane losowo. Ładowanie danych do tabeli okrężnej jest szybkie, ale zapytania mogą wymagać większego przenoszenia danych niż inne metody dystrybucji.
Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące projektowania tabel rozproszonych.
Tabele dystrybuowane przy użyciu skrótu
Tabela rozproszona skrótu dystrybuuje wiersze na podstawie wartości w kolumnie dystrybucji. Tabela rozproszona skrótu została zaprojektowana w celu uzyskania wysokiej wydajności zapytań w dużych tabelach. Podczas wybierania kolumny dystrybucji należy wziąć pod uwagę kilka czynników.
Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące projektowania tabel rozproszonych.
Tabele replikowane
Replikowana tabela zawiera pełną kopię tabeli dostępnej w każdym węźle obliczeniowym. Zapytania są szybko uruchamiane w replikowanych tabelach, ponieważ sprzężenia w replikowanych tabelach nie wymagają przenoszenia danych. Jednak replikacja wymaga dodatkowego magazynu i nie jest praktyczne w przypadku dużych tabel.
Aby uzyskać więcej informacji, zobacz Wskazówki dotyczące projektowania replikowanych tabel.
Typowe metody dystrybucji tabel
Kategoria tabeli często określa optymalną opcję rozkładu tabel.
Kategoria tabeli | Zalecana opcja dystrybucji |
---|---|
Fakt | Użyj dystrybucji skrótów z klastrowanym indeksem magazynu kolumn. Wydajność poprawia się, gdy dwie tabele skrótów są łączone w tej samej kolumnie dystrybucji. |
Wymiar | Użyj replikowanej dla mniejszych tabel. Jeśli tabele są zbyt duże do przechowywania w każdym węźle obliczeniowym, użyj rozproszonego skrótu. |
Przygotowanie | Użyj działania okrężnego dla tabeli przejściowej. Ładowanie przy użyciu usługi CTAS jest szybkie. Gdy dane są w tabeli przejściowej, użyj polecenia INSERT...SELECT , aby przenieść dane do tabel produkcyjnych. |
Partycje
W dedykowanych pulach SQL partycjonowana tabela przechowuje i wykonuje operacje na wierszach tabeli zgodnie z zakresami danych. Na przykład tabela może być partycjonowana według dnia, miesiąca lub roku. Wydajność zapytań można poprawić dzięki eliminacji partycji, co ogranicza skanowanie zapytań do danych w ramach partycji.
Możesz również zachować dane za pomocą przełączania partycji. Ponieważ dane w dedykowanej puli SQL są już rozproszone, zbyt wiele partycji może spowolnić wydajność zapytań. Aby uzyskać więcej informacji, zobacz Partitioning guidance (Wskazówki dotyczące partycjonowania).
Napiwek
Podczas przełączania partycji na partycje tabeli, które nie są puste, rozważ użycie TRUNCATE_TARGET
opcji w instrukcji ALTER TABLE , jeśli istniejące dane mają zostać obcięte.
Poniższy kod przełącza przekształcone dane dzienne na partycję SalesFact i zastępuje wszystkie istniejące dane.
ALTER TABLE SalesFact_DailyFinalLoad SWITCH PARTITION 256 TO SalesFact PARTITION 256 WITH (TRUNCATE_TARGET = ON);
W bezserwerowej puli SQL można ograniczyć pliki lub foldery (partycje), które są odczytywane przez zapytanie. Partycjonowanie według ścieżki jest obsługiwane przy użyciu filepath
funkcji i fileinfo
opisanych w artykule Wykonywanie zapytań dotyczących plików magazynu. Poniższy przykład odczytuje folder z danymi dla roku 2017:
SELECT
nyc.filepath(1) AS [year],
payment_type,
SUM(fare_amount) AS fare_total
FROM
OPENROWSET(
BULK 'https://sqlondemandstorage.blob.core.windows.net/parquet/taxi/year=*/month=*/*.parquet',
FORMAT='PARQUET'
) AS nyc
WHERE
nyc.filepath(1) = 2017
GROUP BY
nyc.filepath(1),
payment_type
ORDER BY
nyc.filepath(1),
payment_type
Indeksy magazynu kolumn
Domyślnie dedykowana pula SQL przechowuje tabelę jako indeks klastrowanego magazynu kolumn. Ta forma magazynu danych zapewnia wysoką kompresję danych i wydajność zapytań w dużych tabelach. Indeks klastrowanego magazynu kolumn jest zwykle najlepszym wyborem, ale w niektórych przypadkach indeks klastrowany lub sterta jest odpowiednią strukturą magazynu.
Napiwek
Tabela sterty może być szczególnie przydatna do ładowania danych przejściowych, takich jak tabela przejściowa, która jest przekształcana w końcową tabelę.
Aby uzyskać listę funkcji magazynu kolumn, zobacz Co nowego w indeksach magazynu kolumn. Aby zwiększyć wydajność indeksu magazynu kolumn, zobacz Maksymalizowanie jakości grupy wierszy dla indeksów magazynu kolumn.
Statystyki
Optymalizator zapytań używa statystyk na poziomie kolumny podczas tworzenia planu wykonywania zapytania. Aby zwiększyć wydajność zapytań, ważne jest, aby statystyki dotyczące poszczególnych kolumn, zwłaszcza kolumn używanych w sprzężeniach zapytań. Usługa Synapse SQL obsługuje automatyczne tworzenie statystyk.
Aktualizacja statystyczna nie jest automatycznie aktualizowana. Statystyki można aktualizować po dodaniu lub zmianie dużej liczby wierszy. Na przykład zaktualizuj statystyki po załadowaniu. Aby uzyskać więcej informacji, zobacz Statystyki w usłudze Synapse SQL.
Klucz podstawowy i unikatowy klucz
W przypadku dedykowanej puli SQL jest obsługiwana tylko wtedy, PRIMARY KEY
gdy NONCLUSTERED
są używane i NOT ENFORCED
używane.
UNIQUE
ograniczenie jest obsługiwane tylko wtedy, gdy NOT ENFORCED
jest używane. Aby uzyskać więcej informacji, zobacz klucz podstawowy, klucz obcy i unikatowy klucz przy użyciu dedykowanej puli SQL.
Polecenia służące do tworzenia tabel
W przypadku dedykowanej puli SQL można utworzyć tabelę jako nową pustą tabelę. Możesz również utworzyć i wypełnić tabelę wynikami instrukcji select. Poniżej przedstawiono polecenia języka T-SQL służące do tworzenia tabeli.
Instrukcja języka T-SQL | opis |
---|---|
CREATE TABLE | Tworzy pustą tabelę, definiując wszystkie kolumny i opcje tabeli. |
TWORZENIE TABELI ZEWNĘTRZNEJ | Tworzy tabelę zewnętrzną. Definicja tabeli jest przechowywana w dedykowanej puli SQL. Dane tabeli są przechowywane w usłudze Azure Blob Storage lub Azure Data Lake Storage. |
CREATE TABLE AS SELECT | Wypełnia nową tabelę wynikami instrukcji select. Kolumny tabeli i typy danych są oparte na wynikach instrukcji select. Aby zaimportować dane, ta instrukcja może wybrać elementy z tabeli zewnętrznej. |
UTWÓRZ TABELĘ ZEWNĘTRZNĄ PODCZAS WYBIERANIA | Tworzy nową tabelę zewnętrzną przez wyeksportowanie wyników instrukcji select do lokalizacji zewnętrznej. Lokalizacja to Azure Blob Storage lub Azure Data Lake Storage. |
Dopasowywanie danych źródłowych do magazynu danych
Dedykowane tabele puli SQL są wypełniane przez ładowanie danych z innego źródła danych. Aby osiągnąć pomyślne ładowanie, liczba i typy danych kolumn w danych źródłowych muszą być zgodne z definicją tabeli w magazynie danych.
Uwaga
Pobieranie danych do wyrównania może być najtrudniejszą częścią projektowania tabel.
Jeśli dane pochodzą z wielu magazynów danych, możesz przenosić dane do magazynu danych i przechowywać je w tabeli integracji. Gdy dane będą znajdować się w tabeli integracji, możesz użyć możliwości dedykowanej puli SQL do zaimplementowania operacji przekształcania. Po przygotowaniu danych można wstawić je do tabel produkcyjnych.
Nieobsługiwane funkcje tabeli
Dedykowana pula SQL obsługuje wiele funkcji tabeli oferowanych przez inne bazy danych, ale nie wszystkie. Na poniższej liście przedstawiono niektóre funkcje tabeli, które nie są obsługiwane w dedykowanej puli SQL.
- Klucz obcy, sprawdzanie ograniczeń tabeli
- Obliczone kolumny
- Widoki indeksowane
- Sekwencja
- Kolumny rozrzedłe
- Klucze zastępcze, implementowanie przy użyciu tożsamości
- Synonimy
- Wyzwalacze
- Indeksy unikatowe
- Typy zdefiniowane przez użytkownika
Zapytania dotyczące rozmiaru tabeli
W dedykowanej puli SQL jednym prostym sposobem identyfikowania miejsca i wierszy używanych przez tabelę w każdej z 60 dystrybucji jest użycie PDW_SHOWSPACEUSED DBCC.
DBCC PDW_SHOWSPACEUSED('dbo.FactInternetSales');
Należy pamiętać, że używanie poleceń DBCC może być dość ograniczające. Dynamiczne widoki zarządzania (DMV) pokazują więcej szczegółów niż polecenia DBCC. Zacznij od utworzenia następującego widoku.
CREATE VIEW dbo.vTableSizes
AS
WITH base
AS
(
SELECT
GETDATE() AS [execution_time]
, DB_NAME() AS [database_name]
, s.name AS [schema_name]
, t.name AS [table_name]
, QUOTENAME(s.name)+'.'+QUOTENAME(t.name) AS [two_part_name]
, nt.[name] AS [node_table_name]
, ROW_NUMBER() OVER(PARTITION BY nt.[name] ORDER BY (SELECT NULL)) AS [node_table_name_seq]
, tp.[distribution_policy_desc] AS [distribution_policy_name]
, c.[name] AS [distribution_column]
, nt.[distribution_id] AS [distribution_id]
, i.[type] AS [index_type]
, i.[type_desc] AS [index_type_desc]
, nt.[pdw_node_id] AS [pdw_node_id]
, pn.[type] AS [pdw_node_type]
, pn.[name] AS [pdw_node_name]
, di.name AS [dist_name]
, di.position AS [dist_position]
, nps.[partition_number] AS [partition_nmbr]
, nps.[reserved_page_count] AS [reserved_space_page_count]
, nps.[reserved_page_count] - nps.[used_page_count] AS [unused_space_page_count]
, nps.[in_row_data_page_count]
+ nps.[row_overflow_used_page_count]
+ nps.[lob_used_page_count] AS [data_space_page_count]
, nps.[reserved_page_count]
- (nps.[reserved_page_count] - nps.[used_page_count])
- ([in_row_data_page_count]
+ [row_overflow_used_page_count]+[lob_used_page_count]) AS [index_space_page_count]
, nps.[row_count] AS [row_count]
from
sys.schemas s
INNER JOIN sys.tables t
ON s.[schema_id] = t.[schema_id]
INNER JOIN sys.indexes i
ON t.[object_id] = i.[object_id]
AND i.[index_id] <= 1
INNER JOIN sys.pdw_table_distribution_properties tp
ON t.[object_id] = tp.[object_id]
INNER JOIN sys.pdw_table_mappings tm
ON t.[object_id] = tm.[object_id]
INNER JOIN sys.pdw_nodes_tables nt
ON tm.[physical_name] = nt.[name]
INNER JOIN sys.dm_pdw_nodes pn
ON nt.[pdw_node_id] = pn.[pdw_node_id]
INNER JOIN sys.pdw_distributions di
ON nt.[distribution_id] = di.[distribution_id]
INNER JOIN sys.dm_pdw_nodes_db_partition_stats nps
ON nt.[object_id] = nps.[object_id]
AND nt.[pdw_node_id] = nps.[pdw_node_id]
AND nt.[distribution_id] = nps.[distribution_id]
LEFT OUTER JOIN (select * from sys.pdw_column_distribution_properties where distribution_ordinal = 1) cdp
ON t.[object_id] = cdp.[object_id]
LEFT OUTER JOIN sys.columns c
ON cdp.[object_id] = c.[object_id]
AND cdp.[column_id] = c.[column_id]
WHERE pn.[type] = 'COMPUTE'
)
, size
AS
(
SELECT
[execution_time]
, [database_name]
, [schema_name]
, [table_name]
, [two_part_name]
, [node_table_name]
, [node_table_name_seq]
, [distribution_policy_name]
, [distribution_column]
, [distribution_id]
, [index_type]
, [index_type_desc]
, [pdw_node_id]
, [pdw_node_type]
, [pdw_node_name]
, [dist_name]
, [dist_position]
, [partition_nmbr]
, [reserved_space_page_count]
, [unused_space_page_count]
, [data_space_page_count]
, [index_space_page_count]
, [row_count]
, ([reserved_space_page_count] * 8.0) AS [reserved_space_KB]
, ([reserved_space_page_count] * 8.0)/1000 AS [reserved_space_MB]
, ([reserved_space_page_count] * 8.0)/1000000 AS [reserved_space_GB]
, ([reserved_space_page_count] * 8.0)/1000000000 AS [reserved_space_TB]
, ([unused_space_page_count] * 8.0) AS [unused_space_KB]
, ([unused_space_page_count] * 8.0)/1000 AS [unused_space_MB]
, ([unused_space_page_count] * 8.0)/1000000 AS [unused_space_GB]
, ([unused_space_page_count] * 8.0)/1000000000 AS [unused_space_TB]
, ([data_space_page_count] * 8.0) AS [data_space_KB]
, ([data_space_page_count] * 8.0)/1000 AS [data_space_MB]
, ([data_space_page_count] * 8.0)/1000000 AS [data_space_GB]
, ([data_space_page_count] * 8.0)/1000000000 AS [data_space_TB]
, ([index_space_page_count] * 8.0) AS [index_space_KB]
, ([index_space_page_count] * 8.0)/1000 AS [index_space_MB]
, ([index_space_page_count] * 8.0)/1000000 AS [index_space_GB]
, ([index_space_page_count] * 8.0)/1000000000 AS [index_space_TB]
FROM base
)
SELECT *
FROM size
;
Podsumowanie obszaru tabeli
To zapytanie zwraca wiersze i spację według tabeli. Podsumowanie obszaru tabeli umożliwia sprawdzenie, które tabele są największymi tabelami. Można również sprawdzić, czy są one działaniem okrężnym, zreplikowanym lub rozproszonym skrótem. W przypadku tabel rozproszonych skrótów zapytanie wyświetla kolumnę dystrybucji.
SELECT
database_name
, schema_name
, table_name
, distribution_policy_name
, distribution_column
, index_type_desc
, COUNT(distinct partition_nmbr) as nbr_partitions
, SUM(row_count) as table_row_count
, SUM(reserved_space_GB) as table_reserved_space_GB
, SUM(data_space_GB) as table_data_space_GB
, SUM(index_space_GB) as table_index_space_GB
, SUM(unused_space_GB) as table_unused_space_GB
FROM
dbo.vTableSizes
GROUP BY
database_name
, schema_name
, table_name
, distribution_policy_name
, distribution_column
, index_type_desc
ORDER BY
table_reserved_space_GB desc
;
Odstęp w tabeli według typu dystrybucji
SELECT
distribution_policy_name
, SUM(row_count) as table_type_row_count
, SUM(reserved_space_GB) as table_type_reserved_space_GB
, SUM(data_space_GB) as table_type_data_space_GB
, SUM(index_space_GB) as table_type_index_space_GB
, SUM(unused_space_GB) as table_type_unused_space_GB
FROM dbo.vTableSizes
GROUP BY distribution_policy_name
;
Odstęp w tabeli według typu indeksu
SELECT
index_type_desc
, SUM(row_count) as table_type_row_count
, SUM(reserved_space_GB) as table_type_reserved_space_GB
, SUM(data_space_GB) as table_type_data_space_GB
, SUM(index_space_GB) as table_type_index_space_GB
, SUM(unused_space_GB) as table_type_unused_space_GB
FROM dbo.vTableSizes
GROUP BY index_type_desc
;
Podsumowanie obszaru dystrybucji
SELECT
distribution_id
, SUM(row_count) as total_node_distribution_row_count
, SUM(reserved_space_MB) as total_node_distribution_reserved_space_MB
, SUM(data_space_MB) as total_node_distribution_data_space_MB
, SUM(index_space_MB) as total_node_distribution_index_space_MB
, SUM(unused_space_MB) as total_node_distribution_unused_space_MB
FROM dbo.vTableSizes
GROUP BY distribution_id
ORDER BY distribution_id
;
Powiązana zawartość
Po utworzeniu tabeli dla magazynu danych następnym krokiem jest załadowanie danych do tabeli.