it-swarm.asia

Mengapa perintah ALTER TABLE sederhana begitu lama di meja dengan indeks teks lengkap?

Saya memiliki tabel nilai-nama besar (~ 67 juta baris) yang memiliki pengindeksan teks lengkap pada kolom DataValue.

Jika saya mencoba menjalankan perintah berikut:

ALTER TABLE VisitorData ADD NumericValue bit DEFAULT 0 NOT NULL;

Ini berjalan selama 1 jam 10 menit dan masih belum selesai pada tabel VisitorData yang berisi ~ 67 juta baris.

  1. Mengapa ini berlangsung lama dan tidak selesai?
  2. Apa yang bisa saya lakukan?

Berikut adalah rincian tentang tabel:

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

Jenis menunggu yang terjadi selama ALTER TABLE perintah adalah LCK_M_SCH_M (modifikasi skema), sesuai hasil kueri di bawah ini:

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

Saya bekerja dengan server produksi yang menjalankan SQL Server 2005 SP 2 (akan segera ditingkatkan ke 2008 SP2).

14
BobbyR-1of4

Skema mengubahnya membutuhkan waktu lama karena Anda menetapkan nilai default ke kolom selama perubahan dan memaksakannya dengan kolom yang tidak dapat dibatalkan, dan harus mengisi kolom untuk 60+ juta baris, yang merupakan operasi yang sangat mahal. Saya tidak yakin apa persyaratan aplikasi Anda tetapi sebuah pendekatan yang akan membuat skema berubah lebih cepat adalah menambahkannya sebagai kolom yang dapat dibatalkan tanpa nilai default dan kemudian melakukan pembaruan dalam batch untuk menetapkan 0 sebagai nilai untuk kolom. Setelah pembaruan selesai, Anda dapat menerapkan perubahan skema lain untuk mengubah kolom menjadi non-nullable dan menetapkan nilai default.

16

Pengindeksan teks lengkap, kemungkinan, tidak relevan dengan masalah Anda. Sebelum ke SQL Server 2012, ADD COLUMN NOT NULL DEFAULT ... adalah operasi offline yang harus menjalankan pembaruan dan mengisi setiap baris dengan nilai default baru dari kolom yang baru ditambahkan. Dalam SQL Server 2012+, operasinya jauh lebih cepat, lihat Online non-NULL dengan kolom nilai tambah dalam SQL Server 11 karena hanya memperbarui metadata tabel dan tidak benar-benar memperbarui baris apa pun.

Anda ALTER TABLE kemungkinan besar lambat karena pembaruan. Ingat, karena itu adalah transaksi tunggal, log yang sangat besar akan dihasilkan dan log Anda kemungkinan akan tumbuh sekarang dan terus-menerus di-zero out saat mengembang. Namun, itu mungkin juga lambat karena pertikaian biasa: pernyataan itu mungkin tidak dapat memperoleh kunci SCH-M di atas meja. Melihat ke sys.dm_exec_requests harus menunjukkan jika ini masalahnya, wait_type dan wait_resource kolom akan menunjukkan apakah pernyataan ALTER diblokir atau mengalami kemajuan.

9
Remus Rusanu

Jawaban awalnya ditambahkan ke pertanyaan oleh penulisnya:

Per jawaban Jason , saya menerbitkan pembaruan berikut sebagai gantinya:

ALTER TABLE VisitorData ADD NumericValue bit NULL

Ini akhirnya berhasil, tetapi butuh 29 menit, 16 detik. Operasi itu sendiri harus sangat cepat (hanya metadata) jadi saya membayangkan bahwa hampir semua waktu itu dihabiskan menunggu untuk mendapatkan yang diperlukan LCK_M_SCH_M (modifikasi skema) kunci.

Dengan bidang bit baru di tempat, saya dapat dengan cepat menambahkan nilai default melalui skrip:

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

Saya sedang dalam proses sekarang mengatur semua NumericValue bit dalam tabel menggunakan fungsi yang ditentukan pengguna (lihat di bawah). Ini sedang berlangsung dan membutuhkan waktu sekitar 1 menit per setiap 1 juta baris dalam tabel baris ~ 68 juta.

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

Setelah itu selesai, saya berencana untuk menjalankan penyesuaian skema terakhir untuk membuat kolom bit baru itu menjadi nol:

ALTER TABLE VisitorData ALTER COLUMN NumericValue bit NOT NULL;

Mudah-mudahan, pembaruan skema terakhir ini akan berjalan cepat setelah semua nilai bukan nol dan NumericValue default sudah ada.

0
user126897