it-swarm.asia

لماذا يستغرق أمر ALTER TABLE البسيط وقتًا طويلاً على الطاولة مع فهرس النص الكامل؟

لدي جدول قيمة اسم كبير (~ 67 مليون صف) يحتوي على فهرسة نص كامل على العمود DataValue.

إذا حاولت تشغيل الأمر التالي:

ALTER TABLE VisitorData ADD NumericValue bit DEFAULT 0 NOT NULL;

يتم تشغيله لمدة ساعة واحدة و 10 دقائق ولا يزال غير مكتمل على جدول VisitorData الذي يحتوي على ~ 67 مليون صف.

  1. لماذا يستغرق هذا وقتًا طويلاً ولا يكتمل؟
  2. ما الذي يمكنني القيام به حيال ذلك؟

فيما يلي المزيد من التفاصيل حول الجدول:

CREATE TABLE [dbo].[VisitorData](
            [VisitorID] [int] NOT NULL,
            [DataName] [varchar](80) NOT NULL,
            [DataValue] [nvarchar](3800) NOT NULL,
            [EncryptedDataValue] [varbinary](max) NULL,
            [VisitorDataID] [int] IDENTITY(1,1) NOT NULL, 
CONSTRAINT [PK_VisitorData_VisitorDataID] PRIMARY KEY CLUSTERED (
            [VisitorDataID] ASC
) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY], 
CONSTRAINT [UNQ_VisitorData_VisitorId_DataName] UNIQUE NONCLUSTERED (
            [VisitorID] ASC,
            [DataName] ASC
) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
        ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[VisitorData]
ADD  CONSTRAINT [UNQ_VisitorData_VisitorDataID] UNIQUE NONCLUSTERED (

[VisitorDataID] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF,
      IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, 
      ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

ALTER TABLE [dbo].[VisitorData]
    WITH CHECK ADD
        CONSTRAINT [FK_VisitorData_Visitors] FOREIGN KEY([VisitorID])
        REFERENCES [dbo].[Visitors] ([VisitorID])
GO

ALTER TABLE [dbo].[VisitorData]
    CHECK CONSTRAINT [FK_VisitorData_Visitors] GO

CREATE FULLTEXT CATALOG DBName_VisitorData_Catalog WITH ACCENT_SENSITIVITY = ON
CREATE FULLTEXT INDEX ON VisitorData ( DataValue Language 1033 )
    KEY INDEX UNQ_VisitorData_VisitorDataID
    ON DBName_VisitorData_Catalog
    WITH CHANGE_TRACKING AUTO
GO

أنواع الانتظار التي تحدث أثناء ALTER TABLE الأمر هم LCK_M_SCH_M (تعديل المخطط) ، حسب نتائج الاستعلام أدناه:

select * from  sys.dm_os_waiting_tasks

waiting_task_address    session_id exec_context_id wait_duration_ms     wait_type            resource_address       blocking_task_address   blocking_session_id blocking_exec_context_id resource_description
--------------------             ----------     --------------- --------------------              -------------------- ------------------             ---------------------            -------------------        ------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x0000000000B885C8   54               0                   112695                            LCK_M_SCH_M   0x00000000802DF600 0x000000000054E478     25                            0                                         objectlock lockPartition=0 objid=834102012 subresource=FULL dbid=5 id=lock438a02e80 mode=IS associatedObjectId=834102012
0x0000000000B885C8   54               0                   112695                            LCK_M_SCH_M   0x00000000802DF600 0x00000000088AB048    23                            0                                         objectlock lockPartition=0 objid=834102012 subresource=FULL dbid=5 id=lock438a02e80 mode=IS associatedObjectId=834102012

أنا أعمل مع خوادم الإنتاج التي تعمل على SQL Server 2005 SP 2 (سيتم ترقيته قريبًا إلى 2008 SP2).

14
BobbyR-1of4

يغير المخطط وقتًا طويلاً لأنك تقوم بتعيين قيمة افتراضية للعمود أثناء التغيير وفرض ذلك مع عمود غير قابل للإلغاء ، ويجب عليه تعبئة العمود لأكثر من 60 مليون صف ، وهي عملية مكلفة للغاية. لست متأكدًا من متطلبات التطبيق الخاصة بك ولكن النهج الذي من شأنه أن يجعل تغيير المخطط أسرع هو إضافته كعمود فارغ مع عدم وجود قيمة افتراضية ثم إجراء تحديث على دفعات لتعيين 0 كقيمة للعمود. بعد الانتهاء من التحديث ، يمكنك تطبيق تغيير مخطط آخر لتغيير العمود إلى غير قابل للإلغاء وتعيين القيمة الافتراضية.

16
Jason Cumberland

من المحتمل أن تكون فهرسة النص الكامل غير ذات صلة بمشكلتك. السابق ل SQL Server 2012 على ADD COLUMN NOT NULL DEFAULT ... هي عملية غير متصلة بالإنترنت يجب أن تقوم بتشغيل تحديث وتعبئة كل صف بالقيمة الافتراضية الجديدة للعمود المضاف حديثًا. في SQL Server 2012+ ، تكون العملية أسرع كثيرًا ، انظر عبر الإنترنت بدون NULL بعمود القيم يضيف في SQL Server 11 حيث إنه يقوم فقط بتحديث البيانات الوصفية للجدول ولا يقوم في الواقع بتحديث أي صفوف.

بك ALTER TABLE بطيء على الأرجح بسبب التحديث. تذكر ، نظرًا لأن هذه معاملة واحدة ، فسيتم إنشاء سجل ضخم ومن المحتمل أن ينمو السجل الخاص بك الآن ويتم تحريره باستمرار مع توسعه. ومع ذلك ، قد يكون بطيئًا أيضًا بسبب الخلاف العادي: قد لا يتمكن البيان من الحصول على قفل SCH-M على الطاولة. انظر الى sys.dm_exec_requests يجب أن يظهر إذا كان هذا هو الحال ، wait_type و wait_resource ستشير الأعمدة إلى ما إذا كانت العبارة ALTER محظورة أو أنها تحرز تقدماً.

9
Remus Rusanu

الإجابة مضافة أصلاً إلى السؤال من قبل مؤلفها:

وفقًا إجابة جيسون ، قمت بإصدار التحديث التالي بدلاً من ذلك:

ALTER TABLE VisitorData ADD NumericValue bit NULL

تم تنفيذ هذا أخيرًا ، لكنه استغرق 29 دقيقة و 16 ثانية. يجب أن تكون العملية نفسها سريعة جدًا (البيانات الوصفية فقط) ، لذا أتخيل أنه تم قضاء كل هذا الوقت تقريبًا في انتظار الحصول على ما يلزم من LCK_M_SCH_M (تعديل المخطط) قفل.

مع وجود الحقل bit الجديد ، تمكنت من إضافة القيمة الافتراضية إليه بسرعة عبر النص البرمجي:

ALTER TABLE VisitorData ADD
CONSTRAINT DF_VisitorData_NumericValue DEFAULT(0) FOR NumericValue;

أنا بصدد إعداد كل البتات NumericValue في الجدول باستخدام دالة معرفة من قبل المستخدم (انظر أدناه). إنها قيد التقدم وتستغرق حوالي دقيقة واحدة لكل مليون صف في جدول الصف الذي يبلغ 68 مليون صف تقريبًا.

WITH RD_CTE (VisitorD, DataName) 
AS
(
    SELECT TOP 10000 VisitorD, DataName
    FROM VisitorData WITH (NOLOCK)
    WHERE NumericValue IS NULL  
)
UPDATE VisitorData
SET NumericValue = CASE WHEN dbo.ufn_IsReallyNumeric(rd.DataValue) = 1 THEN 1 ELSE 0 END
FROM VisitorData rd WITH (NOLOCK) 
INNER JOIN RD_CTE rdc WITH (NOLOCK) ON rd.VisitorD = rdc.VisitorD  AND rd.DataName = rdc.DataName

GO 6800

بمجرد الانتهاء ، أخطط لتشغيل تعديل المخطط النهائي لجعل عمود البت الجديد هذا غير فارغ:

ALTER TABLE VisitorData ALTER COLUMN NumericValue bit NOT NULL;

نأمل أن يتم تشغيل هذا التحديث الأخير للمخطط بسرعة بمجرد أن تكون جميع القيم غير فارغة ويكون NumericValue الافتراضي في مكانه.

0
user126897