通过


你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Synapse SQL 中的临时表

本文包含有关使用临时表的基本指南,并重点介绍了 Synapse SQL 中的会话级别临时表的原则。

专用 SQL 池和无服务器 SQL 池资源都可以利用临时表。 无服务器 SQL 池具有本文末尾讨论的限制。

临时表

临时表在处理数据时非常有用,尤其是在中间结果暂时性转换期间。 使用 Synapse SQL 时,临时表存在于会话级别。 它们仅显示给创建它们的会话。 因此,当会话结束时,它们会自动删除。

专用 SQL 池中的临时表

在专用 SQL 池资源中,临时表提供性能优势,因为它们的结果将写入本地存储而不是远程存储。

创建临时表

临时表通过在表名称前添加前缀 # 来创建。 例如:

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
)

此外可以使用 CTAS 通过完全相同的方法来创建临时表:

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

注释

CTAS 是一个功能强大的命令,并且在事务日志空间的使用效率方面具有额外的优势。

删除临时表

创建新会话时,不应存在临时表。 但是,如果要调用相同的存储过程来创建同名的临时表,若要确保CREATE TABLE语句成功,请使用简单的存在性检查:DROP

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

为了编码一致性,最好对表和临时表使用此模式。 最好在处理完临时表后使用 DROP TABLE 来删除它们。

在存储过程开发中,通常会在过程末尾看到捆绑在一起的 drop 命令,以确保清理这些对象。

DROP TABLE #stats_ddl

模块化代码

临时表可在用户会话中的任何位置使用。 然后,可以利用此功能来帮助你模块化应用程序代码。 为了演示,以下存储过程生成 DDL 以按统计信息名称更新数据库中的所有统计信息:

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

在此阶段,唯一发生的动作是创建生成 #stats_ddl 临时表的存储过程。 如果 #stats_ddl 已存在,存储过程将其删除。 此删除可确保存储过程在会话内多次运行时不会失败。

由于存储过程末尾没有 DROP TABLE,当存储过程完成时,创建的表会保留,并可在存储过程之外读取。

与其他 SQL Server 数据库相比,Synapse SQL 允许在创建临时表的过程之外使用临时表。 通过专用 SQL 池创建的临时表可以在会话内的 任意位置 使用。 因此,你将有更多的模块化且易于管理的代码,如以下示例所示:

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;

临时表限制

专用 SQL 池对临时表有一些实现限制:

  • 仅支持会话范围的临时表。 不支持全局临时表。
  • 无法在临时表上创建视图。
  • 只能通过哈希或轮循机制分布来创建临时表。 不支持重复的临时表分布。

无服务器 SQL 池中的临时表

支持无服务器 SQL 池中的临时表,但其用法有限。 它们不能用于目标文件的查询。

例如,不能将临时表与存储中的文件中的数据联接。 临时表数限制为 100,其总大小限制为 100 MB。

后续步骤

若要详细了解如何开发表,请参阅 Synapse SQL 资源文章中的“设计表 ”。