Tại sao lệnh ALTER TABLE đơn giản lại mất quá nhiều thời gian trên bảng với chỉ mục toàn văn?


13

Tôi có một bảng giá trị tên lớn (~ 67 triệu hàng) có lập chỉ mục toàn văn bản trên DataValuecột.

Nếu tôi cố chạy lệnh sau:

ALTER TABLE VisitorData ADD NumericValue bit DEFAULT 0 NOT NULL;

Nó chạy trong 1 giờ 10 phút và vẫn không hoàn thành trên một VisitorDatabảng chứa ~ 67 triệu hàng.

  1. Tại sao điều này mất quá nhiều thời gian và không hoàn thành?
  2. Tôi có thể làm gì với nó?

Dưới đây là chi tiết hơn về bảng:

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

Các loại chờ xảy ra trong ALTER TABLElệnh là LCK_M_SCH_M(sửa đổi lược đồ), theo kết quả truy vấn bên dưới:

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

Tôi đang làm việc với các máy chủ sản xuất đang chạy SQL Server 2005 SP 2 (sắp được nâng cấp lên 2008 SP2).

Câu trả lời:


14

Lược đồ thay đổi mất quá nhiều thời gian vì bạn đang gán một giá trị mặc định cho cột trong quá trình thay đổi và thực thi điều đó với một cột không thể rỗng và nó phải tạo cột cho hơn 60 triệu hàng, đây là một hoạt động cực kỳ tốn kém. Tôi không chắc yêu cầu ứng dụng của bạn là gì nhưng một cách tiếp cận sẽ làm cho lược đồ thay đổi nhanh hơn là thêm nó vào dưới dạng cột không có giá trị mặc định và sau đó thực hiện cập nhật theo lô để gán 0 làm giá trị cho cột. Sau khi cập nhật xong, bạn có thể áp dụng một thay đổi lược đồ khác để thay đổi cột thành không thể rỗng và gán giá trị mặc định.


9

Lập chỉ mục toàn văn có khả năng không liên quan đến vấn đề của bạn. Trước SQL Server 2012, đây ADD COLUMN NOT NULL DEFAULT ...là một hoạt động ngoại tuyến phải chạy một bản cập nhật và điền vào mỗi hàng với giá trị mặc định mới của cột mới được thêm vào. Trong SQL Server 2012+, thao tác nhanh hơn nhiều, hãy xem Trực tuyến không NULL với cột giá trị được thêm vào SQL Server 11 vì nó chỉ cập nhật siêu dữ liệu của bảng và không thực sự cập nhật bất kỳ hàng nào.

Bạn ALTER TABLErất có thể chậm vì cập nhật. Hãy nhớ rằng, vì đó là một giao dịch duy nhất, một nhật ký khổng lồ sẽ được tạo ra và nhật ký của bạn có thể sẽ tăng lên ngay bây giờ và liên tục bị xóa sổ khi nó mở rộng. Tuy nhiên, nó cũng có thể chậm vì tranh chấp thông thường: tuyên bố có thể không có được khóa SCH-M trên bàn. Nhìn vào sys.dm_exec_requestssẽ hiển thị nếu đây là trường hợp, các cột wait_typewait_resourcesẽ cho biết nếu ALTERcâu lệnh bị chặn hoặc đang tiến triển.


0

Trả lời ban đầu được thêm vào câu hỏi của tác giả của nó:

Theo câu trả lời của Jason , tôi đã đưa ra bản cập nhật sau:

ALTER TABLE VisitorData ADD NumericValue bit NULL

Điều này cuối cùng đã thực hiện, nhưng mất 29 phút, 16 giây. Bản thân thao tác phải khá nhanh (chỉ siêu dữ liệu) vì vậy tôi tưởng tượng rằng hầu hết thời gian đó đã dành để chờ đợi để có được khóa LCK_M_SCH_M(sửa đổi lược đồ) cần thiết .

Với trường mới bit, tôi có thể nhanh chóng thêm giá trị mặc định vào nó thông qua tập lệnh:

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

Tôi đang trong quá trình thiết lập tất cả các NumericValuebit trong bảng bằng hàm do người dùng định nghĩa (xem bên dưới). Nó đang được tiến hành và mất khoảng 1 phút cho mỗi 1 triệu hàng trong bảng ~ 68 triệu hàng.

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

Sau khi hoàn thành, tôi dự định chạy điều chỉnh lược đồ cuối cùng để làm cho cột bit mới đó trở thành null:

ALTER TABLE VisitorData ALTER COLUMN NumericValue bit NOT NULL;

Hy vọng, bản cập nhật lược đồ cuối cùng này sẽ chạy nhanh khi tất cả các giá trị không có giá trị và NumericValuemặc định được đặt đúng chỗ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.