फुल-टेक्स्ट इंडेक्स के साथ टेबल पर साधारण एल्टर टेबल कमांड को इतना लंबा समय क्यों लगता है?


14

मेरे पास एक बड़ी (~ 67 मिलियन पंक्तियाँ) नाम-मूल्य तालिका है जिसमें DataValueस्तंभ पर पूर्ण-पाठ अनुक्रमण है ।

अगर मैं निम्नलिखित कमांड चलाने की कोशिश करता हूं:

ALTER TABLE VisitorData ADD NumericValue bit DEFAULT 0 NOT NULL;

यह 1 घंटे 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 में अपग्रेड किया जाएगा)।

जवाबों:


16

स्कीमा में इसे इतना लंबा समय लगता है क्योंकि आप परिवर्तन के दौरान कॉलम को एक डिफ़ॉल्ट मान दे रहे हैं और इसे लागू करने के लिए एक गैर-अशक्त स्तंभ के साथ, और इसे 60+ मिलियन पंक्तियों के लिए कॉलम को आबाद करना होगा, जो एक अविश्वसनीय रूप से महंगा ऑपरेशन है। मुझे यकीन नहीं है कि आपके आवेदन की आवश्यकताएं क्या हैं, लेकिन एक दृष्टिकोण जो स्कीमा को तेजी से बदल देगा, उसे एक अशक्त स्तंभ के रूप में बिना किसी डिफ़ॉल्ट मान के साथ जोड़ना है और फिर 0 के कॉलम के लिए मान के रूप में असाइन करने के लिए बैचों में एक अपडेट करना है। जब आपका अपडेट हो जाता है उसके बाद आप कॉलम को गैर-अशक्त करने के लिए एक और स्कीमा परिवर्तन लागू कर सकते हैं और डिफ़ॉल्ट मान असाइन कर सकते हैं।


9

पूर्ण-पाठ-अनुक्रमण, आपकी समस्या के लिए अप्रासंगिक है। SQL सर्वर 2012 से पहले ADD COLUMN NOT NULL DEFAULT ...एक ऑफ़लाइन ऑपरेशन है जिसे एक अद्यतन चलाना है और प्रत्येक पंक्ति को नए जोड़े गए कॉलम के नए डिफ़ॉल्ट मान के साथ पॉप्युलेट करना है। SQL सर्वर 2012+ में, ऑपरेशन बहुत तेज़ है, SQL Server 11 में मान स्तंभ के साथ ऑनलाइन गैर-NULL देखें क्योंकि यह केवल तालिका के मेटाडेटा को अद्यतन करता है और वास्तव में किसी भी पंक्तियों को अद्यतन नहीं करता है।

ALTER TABLEअपडेट के कारण आपकी संभावना सबसे धीमी है। याद रखें, चूंकि यह एक एकल लेनदेन है, एक विशाल लॉग उत्पन्न होगा और आपका लॉग अब बढ़ने की संभावना है और विस्तार के रूप में लगातार शून्य-एड आउट हो रहा है। हालाँकि, यह साधारण विवाद के कारण भी धीमा हो सकता है: कथन तालिका पर SCH-M लॉक प्राप्त करने में सक्षम नहीं हो सकता है। यह देखते हुए sys.dm_exec_requestsकि क्या यह मामला है, wait_typeऔर wait_resourceयह इंगित करता है कि कॉलम इंगित करेगा कि क्या ALTERकथन अवरुद्ध है या प्रगति कर रहा है।


0

मूल रूप से इसके लेखक द्वारा प्रश्न का उत्तर दिया गया:

जेसन के जवाब के अनुसार , मैंने इसके बजाय निम्नलिखित अपडेट जारी किया:

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 मिलियन पंक्ति तालिका में प्रत्येक 1 मिलियन पंक्तियों के बारे में 1 मिनट ले रहा है।

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डिफ़ॉल्ट स्थान पर है, तो यह अंतिम स्कीमा अद्यतन जल्दी से चलेगा ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.