전체 텍스트 인덱스가있는 테이블에서 간단한 ALTER TABLE 명령이 왜 그렇게 오래 걸립니까?


14

DataValue열에 전체 텍스트 인덱싱이있는 큰 (~ 67 백만 행) 이름 값 테이블이 있습니다 .

다음 명령을 실행하려고하면 :

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로 곧 업그레이드 될 예정)를 사용하고 있습니다.

답변:


15

변경하는 동안 열에 기본값을 할당하고 널 입력 불가능한 열을 적용하여 스키마를 너무 오래 변경하면 열이 6 천만 개 이상인 행을 채워야하므로 엄청나게 비싼 작업입니다. 응용 프로그램 요구 사항이 무엇인지 확실하지 않지만 스키마를 더 빠르게 변경하는 방법은 기본값이없는 nullable 열로 추가 한 다음 일괄 업데이트를 수행하여 열 값으로 0을 할당하는 것입니다. 업데이트가 완료되면 다른 스키마 변경을 적용하여 열을 널 입력 불가능으로 변경하고 기본값을 지정할 수 있습니다.


9

전체 텍스트 인덱싱은 문제와 관련이 없습니다. SQL Server 2012 이전 ADD COLUMN NOT NULL DEFAULT ...에는 업데이트를 실행하고 각 행을 새로 추가 된 열의 새 기본값으로 채워야하는 오프라인 작업입니다. SQL Server 2012+에서는 작업 속도가 훨씬 빠릅니다 . 테이블의 메타 데이터 만 업데이트하고 실제로 행을 업데이트하지 않으므로 SQL Server 11의 NULL이 아닌 온라인 열 추가 항목을 참조하십시오 .

귀하는 ALTER TABLE때문에 업데이트의 가장 가능성이 느립니다. 단일 트랜잭션이므로 큰 로그가 생성되고 로그가 확장 될수록 로그가 커지고 계속 제로화 될 가능성이 있습니다. 그러나 일반적인 경합으로 인해 느려질 수도 있습니다. 명령문이 테이블에서 SCH-M 잠금을 획득하지 못할 수 있습니다. sys.dm_exec_requests이 경우에 해당하는지 살펴보면 wait_typewait_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 분이 진행되고 있습니다.

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

완료되면 새 비트 열을 null이 아닌 최종 스키마 조정을 실행할 계획입니다.

ALTER TABLE VisitorData ALTER COLUMN NumericValue bit NOT NULL;

모든 값이 널이 아니고 NumericValue기본값이 설정 되면이 마지막 스키마 업데이트가 빠르게 실행되기를 바랍니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.