Sdílet prostřednictvím


Dočasné tabulky v Synapse SQL

Tento článek obsahuje základní pokyny k používání dočasných tabulek a zdůrazňuje principy dočasných tabulek na úrovni relace v rámci Synapse SQL.

Prostředky vyhrazeného fondu SQL i bezserverového fondu SQL můžou využívat dočasné tabulky. Fond SQL bez serveru má omezení, která jsou popsána na konci tohoto článku.

Dočasné tabulky

Dočasné tabulky jsou užitečné při zpracování dat, zejména při transformaci, kde jsou přechodné výsledky. V Synapse SQL existují dočasné tabulky na úrovni relace. Jsou viditelné pouze pro relaci, ve které byly vytvořeny. Tím pádem se po skončení relace automaticky zahodí.

Dočasné tabulky ve vyhrazeném SQL fondu

Dočasné tabulky ve vyhrazeném prostředku fondu SQL nabízejí výkonnostní výhodu, protože jejich výsledky se zapisují do místního úložiště, nikoli do vzdáleného úložiště.

Vytvoření dočasné tabulky

Dočasné tabulky se vytvářejí tak, že se k názvu tabulky připojí předpona #. Například:

CREATE TABLE #stats_ddl
(
    [schema_name]        NVARCHAR(128) NOT NULL
,    [table_name]            NVARCHAR(128) NOT NULL
,    [stats_name]            NVARCHAR(128) NOT NULL
,    [stats_is_filtered]     BIT           NOT NULL
,    [seq_nmbr]              BIGINT        NOT NULL
,    [two_part_name]         NVARCHAR(260) NOT NULL
,    [three_part_name]       NVARCHAR(400) NOT NULL
)
WITH
(
    DISTRIBUTION = HASH([seq_nmbr])
,    HEAP
)

Dočasné tabulky je možné vytvořit také pomocí CTAS pomocí stejného přístupu:

CREATE TABLE #stats_ddl
WITH
(
    DISTRIBUTION = HASH([seq_nmbr])
,    HEAP
)
AS
(
SELECT
        sm.[name]                                                                AS [schema_name]
,        tb.[name]                                                                AS [table_name]
,        st.[name]                                                                AS [stats_name]
,        st.[has_filter]                                                            AS [stats_is_filtered]
,       ROW_NUMBER()
        OVER(ORDER BY (SELECT NULL))                                            AS [seq_nmbr]
,                                 QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name])  AS [two_part_name]
,        QUOTENAME(DB_NAME())+'.'+QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name])  AS [three_part_name]
FROM    sys.objects            AS ob
JOIN    sys.stats            AS st    ON    ob.[object_id]        = st.[object_id]
JOIN    sys.stats_columns    AS sc    ON    st.[stats_id]        = sc.[stats_id]
                                    AND st.[object_id]        = sc.[object_id]
JOIN    sys.columns            AS co    ON    sc.[column_id]        = co.[column_id]
                                    AND    sc.[object_id]        = co.[object_id]
JOIN    sys.tables            AS tb    ON    co.[object_id]        = tb.[object_id]
JOIN    sys.schemas            AS sm    ON    tb.[schema_id]        = sm.[schema_id]
WHERE    1=1
AND        st.[user_created]   = 1
GROUP BY
        sm.[name]
,        tb.[name]
,        st.[name]
,        st.[filter_definition]
,        st.[has_filter]
)
;

Poznámka:

CTAS je výkonný příkaz a má přidanou výhodu efektivního využívání prostoru transakčních protokolů.

Vyřazení dočasných tabulek

Při vytvoření nového sezení by neměly existovat žádné dočasné tabulky. Pokud ale voláte stejnou uloženou proceduru, která vytvoří dočasnou proceduru se stejným názvem, abyste měli jistotu, že jsou příkazy CREATE TABLE úspěšné, použijte jednoduchou kontrolu existence s DROP:

IF OBJECT_ID('tempdb..#stats_ddl') IS NOT NULL
BEGIN
    DROP TABLE #stats_ddl
END

Pro konzistenci kódování je vhodné tento vzor použít pro tabulky i dočasné tabulky. Je také vhodné použít DROP TABLE k odebrání dočasných tabulek, až s nimi budete hotovi.

Ve vývoji uložených procedur je běžné, že se příkazy drop seskupí dohromady na konci procedury, aby se zajistilo, že se tyto objekty vyčistí.

DROP TABLE #stats_ddl

Modularizace kódu

Dočasné tabulky lze použít kdekoli v uživatelském sezení. Tuto funkci pak můžete využít, aby vám pomohla modularizovat kód aplikace. K demonstraci následující uložená procedura generuje DDL pro aktualizaci všech statistik v databázi podle názvu statistiky.

CREATE PROCEDURE    [dbo].[prc_sqldw_update_stats]
(   @update_type    tinyint -- 1 default 2 fullscan 3 sample 4 resample
    ,@sample_pct     tinyint
)
AS

IF @update_type NOT IN (1,2,3,4)
BEGIN;
    THROW 151000,'Invalid value for @update_type parameter. Valid range 1 (default), 2 (fullscan), 3 (sample) or 4 (resample).',1;
END;

IF @sample_pct IS NULL
BEGIN;
    SET @sample_pct = 20;
END;

IF OBJECT_ID('tempdb..#stats_ddl') IS NOT NULL
BEGIN
    DROP TABLE #stats_ddl
END

CREATE TABLE #stats_ddl
WITH
(
    DISTRIBUTION = HASH([seq_nmbr])
)
AS
(
SELECT
        sm.[name]                                                                AS [schema_name]
,        tb.[name]                                                                AS [table_name]
,        st.[name]                                                                AS [stats_name]
,        st.[has_filter]                                                            AS [stats_is_filtered]
,       ROW_NUMBER()
        OVER(ORDER BY (SELECT NULL))                                            AS [seq_nmbr]
,                                 QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name])  AS [two_part_name]
,        QUOTENAME(DB_NAME())+'.'+QUOTENAME(sm.[name])+'.'+QUOTENAME(tb.[name])  AS [three_part_name]
FROM    sys.objects            AS ob
JOIN    sys.stats            AS st    ON    ob.[object_id]        = st.[object_id]
JOIN    sys.stats_columns    AS sc    ON    st.[stats_id]        = sc.[stats_id]
                                    AND st.[object_id]        = sc.[object_id]
JOIN    sys.columns            AS co    ON    sc.[column_id]        = co.[column_id]
                                    AND    sc.[object_id]        = co.[object_id]
JOIN    sys.tables            AS tb    ON    co.[object_id]        = tb.[object_id]
JOIN    sys.schemas            AS sm    ON    tb.[schema_id]        = sm.[schema_id]
WHERE    1=1
AND        st.[user_created]   = 1
GROUP BY
        sm.[name]
,        tb.[name]
,        st.[name]
,        st.[filter_definition]
,        st.[has_filter]
)
SELECT
    CASE @update_type
    WHEN 1
    THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+');'
    WHEN 2
    THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH FULLSCAN;'
    WHEN 3
    THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH SAMPLE '+CAST(@sample_pct AS VARCHAR(20))+' PERCENT;'
    WHEN 4
    THEN 'UPDATE STATISTICS '+[two_part_name]+'('+[stats_name]+') WITH RESAMPLE;'
    END AS [update_stats_ddl]
,   [seq_nmbr]
FROM    #stats_ddl
;
GO

V této fázi je jedinou akcí, ke které došlo, vytvoření uložené procedury, která generuje dočasnou tabulku #stats_ddl. Uložená procedura zahodí #stats_ddl, pokud už existuje. Tento krok zajišťuje, že nedojde k selhání, když se spustí vícekrát během jedné relace.

Vzhledem k tomu, že na konci uložené procedury není DROP TABLE, po dokončení uložené procedury zůstane vytvořená tabulka a může být přečtená mimo uloženou proceduru.

Na rozdíl od jiných databází SQL Serveru umožňuje Synapse SQL použít dočasnou tabulku mimo proceduru, která ji vytvořila. Dočasné tabulky vytvořené prostřednictvím vyhrazeného fondu SQL je možné použít kdekoli uvnitř relace. V důsledku toho budete mít modulární a spravovatelný kód, jak je znázorněno v následující ukázce:

EXEC [dbo].[prc_sqldw_update_stats] @update_type = 1, @sample_pct = NULL;

DECLARE @i INT              = 1
,       @t INT              = (SELECT COUNT(*) FROM #stats_ddl)
,       @s NVARCHAR(4000)   = N''

WHILE @i <= @t
BEGIN
    SET @s=(SELECT update_stats_ddl FROM #stats_ddl WHERE seq_nmbr = @i);

    PRINT @s
    EXEC sp_executesql @s
    SET @i+=1;
END

DROP TABLE #stats_ddl;

Dočasná omezení tabulek

Vyhrazený SQL fond má několik omezení implementace pro dočasné tabulky:

  • Podporují se pouze dočasné tabulky s vymezeným oborem relace. Globální dočasné tabulky nejsou podporované.
  • Zobrazení nelze vytvořit v dočasných tabulkách.
  • Dočasné tabulky lze vytvořit pouze s využitím hash nebo round robin distribuce. Distribuce replikovaných dočasných tabulek není podporována.

Dočasné tabulky v bezserverovém fondu SQL

Dočasné tabulky v bezserverovém fondu SQL se podporují, ale jejich využití je omezené. Není možné je používat v dotazech, které cílí na soubory.

Dočasnou tabulku například nemůžete spojit s daty ze souborů v úložišti. Počet dočasných tabulek je omezený na 100 a jejich celková velikost je omezená na 100 MB.

Další kroky

Další informace o vývoji tabulek najdete v článku Navrhování tabulek pomocí prostředků Synapse SQL článku.