مشاركة عبر


جداول مؤقتة في تجمع SQL مخصص في Azure Synapse Analytics

تحتوي هذه المقالة على إرشادات أساسية لاستخدام الجداول المؤقتة وتبرز كيانات الجداول المؤقتة على مستوى الجلسة.

تساعدك استخدام المعلومات الواردة في هذه المقالة في تعديل التعليمة البرمجية، وتحسين إمكانية إعادة الاستخدام وسهولة الصيانة.

ما الجداول المؤقتة؟

تعد الجداول المؤقتة مفيدة عند معالجة البيانات، خاصة أثناء التحويل حيث تكون النتائج الوسيطة عابرة. في تجمع SQL المخصص، توجد جداول مؤقتة على مستوى الجلسة.

تكون الجداول المؤقتة مرئية فقط للجلسة التي تم إنشاؤها فيها ويتم إسقاطها تلقائياً عند إغلاق تلك الجلسة.

تقدم الجداول المؤقتة ميزة في الأداء لأن نتائجها مكتوبة على التخزين المحلي بدلاً من التخزين البعيد.

الجداول المؤقتة في تجمع SQL المخصص

في مورد تجمع SQL المخصص، توفر الجداول المؤقتة ميزة أداء لأن نتائجها مكتوبة إلى التخزين المحلي بدلاً من التخزين عن بعد.

إنشاء جدول مؤقت «Temporary table»

يتم إنشاء الجداول المؤقتة عن طريق إضافة البادئة # إلى اسم الجدول. على سبيل المثال:

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 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، مع عبارات DDL.

يؤدي هذا الإجراء المخزن إلى حذف #stats_ddl موجود للتأكد من عدم إخفاقه إذا تم تشغيله أكثر من مرة خلال الجلسة.

ومع ذلك، نظراً لعدم وجود DROP TABLE في نهاية الإجراء المخزن، عند اكتمال الإجراء المخزن، فإنه يترك الجدول الذي تم إنشاؤه بحيث يمكن قراءته خارج الإجراء المخزن.

في تجمع SQL المخصص، بخلاف قواعد بيانات SQL Server الأخرى، من الممكن استخدام الجدول المؤقت خارج الإجراء الذي أنشأه. يمكن استخدام الجداول المؤقتة لتجمع 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 المخصصة.