Compartilhar via


Tabelas temporárias no SQL do Synapse

Este artigo contém diretrizes essenciais para o uso de tabelas temporárias e realça os princípios das tabelas temporárias no nível da sessão no SQL do Synapse.

O pool de SQL dedicado e os recursos do pool de SQL sem servidor podem utilizar tabelas temporárias. O pool de SQL sem servidor tem limitações discutidas no final deste artigo.

Tabelas temporárias

Tabelas temporárias são úteis ao processar dados, especialmente durante a transformação em que os resultados intermediários são transitórios. Com o SQL do Synapse, existem tabelas temporárias no nível da sessão. Eles só são visíveis para a sessão na qual foram criados. Dessa forma, eles são descartados automaticamente quando a sessão termina.

Tabelas temporárias no pool de SQL dedicado

No recurso de pool de SQL dedicado, as tabelas temporárias oferecem um benefício de desempenho porque seus resultados são gravados no armazenamento local em vez de remoto.

Criar uma tabela temporária

As tabelas temporárias são criadas prefixando o nome da tabela com um #. Por exemplo:

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
)

Tabelas temporárias podem também ser criadas usando CTAS exatamente da mesma maneira:

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]
)
;

Observação

CTAS é um comando poderoso e tem a vantagem adicional de ser eficiente no uso do espaço de log de transações.

Excluir tabelas temporárias

Quando uma nova sessão é criada, nenhuma tabela temporária deve existir. Contudo, se você estiver chamando o mesmo procedimento armazenado que cria um temporário com o mesmo nome, para garantir que suas instruções CREATE TABLE sejam bem-sucedidas, use uma simples verificação de existência com DROP:

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

Para consistência de codificação, é uma boa prática usar esse padrão para tabelas e tabelas temporárias. Também é uma boa ideia usar DROP TABLE para remover tabelas temporárias quando terminar de usá-las.

No desenvolvimento de procedimentos armazenados, é comum ver os comandos DROP agrupados no final de um procedimento para garantir que esses objetos sejam removidos.

DROP TABLE #stats_ddl

Modularizar código

Tabelas temporárias podem ser usadas em qualquer lugar em uma sessão de usuário. Esse recurso pode ser explorado para ajudá-lo a modularizar o código do aplicativo. Para demonstrar, o seguinte procedimento armazenado gera DDL para atualizar todas as estatísticas no banco de dados pelo nome da estatística:

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

Neste estágio, a única ação que ocorreu é a criação de um procedimento armazenado que gera a tabela temporária #stats_ddl. O procedimento armazenado descartará #stats_ddl se ele já existir. Essa remoção garante que ele não falhará caso seja executado mais de uma vez em uma sessão.

Como não há um DROP TABLE no final do procedimento armazenado, quando o procedimento armazenado é concluído, a tabela criada permanece e pode ser lida fora do procedimento armazenado.

Ao contrário de outros bancos de dados do SQL Server, o SQL do Synapse permite que você use a tabela temporária fora do procedimento que a criou. As tabelas temporárias criadas por meio do pool de SQL dedicado podem ser usadas em qualquer lugar dentro da sessão. Como resultado, você terá um código mais modular e gerenciável, conforme demonstrado no exemplo abaixo:

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;

Limitações temporárias da tabela

O pool de SQL dedicado tem algumas limitações de implementação para tabelas temporárias:

  • Há suporte apenas para tabelas temporárias com escopo de sessão. Não há suporte para tabelas temporárias globais.
  • As exibições não podem ser criadas em tabelas temporárias.
  • As tabelas temporárias só podem ser criadas com a distribuição de hash ou round robin. Não há suporte para a distribuição de tabela temporária replicada.

Tabelas temporárias no pool de SQL sem servidor

Há suporte para tabelas temporárias no pool de SQL sem servidor, mas seu uso é limitado. Eles não podem ser usados em consultas que direcionam arquivos.

Por exemplo, você não pode juntar uma tabela temporária com dados de arquivos armazenados. O número de tabelas temporárias é limitado a 100 e seu tamanho total é limitado a 100 MB.

Próximas etapas

Para saber mais sobre como desenvolver tabelas, consulte o artigo Designing tables using the Synapse SQL resources.