Yabancı anahtarları bırakmak neden uzun sürüyor?


13

Bir kerede bir veritabanındaki tüm yabancı anahtarları silen bir komut dosyası hazırladım:

ALTER TABLE MyTable1 DROP CONSTRAINT FK_MyTable1_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col2

Beni şaşırtan şey, senaryonun uzun zaman almasıdır: her bir DROP FK için ortalama 20 saniye. Şimdi, bir FK oluşturmanın çok önemli olabileceğini anlıyorum, çünkü sunucu gitmeli ve FK kısıtlamasının en baştan ihlal edilmediğini, ancak düştüğünü kontrol etmeli? Bir sunucu bu kadar uzun süren FK'leri bırakırken ne yapar? Bu hem kendi merakım için hem de işleri daha hızlı hale getirmenin bir yolu olup olmadığını anlamak için. FK'yi (yalnızca devre dışı bırakmak değil) kaldırabilmem, geçiş sırasında çok daha hızlı olmamı ve bu nedenle çalışmama süresini en aza indirmemi sağlayacaktır.


1
Belki başka bir işlem, paylaşılan şema kilitlerini veritabanınıza yerleştirir ve bırakma FK sürecini bu işlemlerin bitmesini beklemeye zorlar? FK damlasını çalıştırmayı ve hemen sp_who2'yi engelleme açısından kontrol etmeyi deneyin.
Daniel Hutmacher

Bahsetmeyi unuttum, bu veritabanında çalışan başka bir işlem yok. Ancak aynı sunucuda başka veritabanları da var.
carlo.borreo

Yanıtlar:


12

Bir kısıtlamayı bırakmak, değişiklik sırasında başkalarının tabloyu sorgulamasını engelleyecek bir Sch-M (Şema Değişikliği) kilidi gerektirir. Muhtemelen bu kilidi almayı bekliyorsunuz ve o tabloya karşı çalışmakta olan tüm sorgular bitene kadar beklemek zorundasınız.
Çalışan bir sorguda tabloda bir Sch-S (Şema Kararlılığı) kilidi vardır ve bu kilit bir Sch-M kilidiyle uyumlu değildir.

Gönderen Kilit Modları, Şema Kilitler

Veritabanı Altyapısı, bir tablo veri tanımlama dili (DDL) işlemi sırasında sütun ekleme veya tablo bırakma gibi şema değişikliği (Sch-M) kilitlerini kullanır. Tutulduğu süre boyunca Sch-M kilidi, masaya eşzamanlı erişimi önler. Bu, Sch-M kilidinin kilit serbest bırakılana kadar tüm dış işlemleri engellediği anlamına gelir.

Tablo kesmesi gibi bazı veri işleme dili (DML) işlemleri, eşzamanlı işlemler tarafından etkilenen tablolara erişimi önlemek için Sch-M kilitlerini kullanır.

Veritabanı Altyapısı, sorguları derlerken ve yürütürken şema kararlılığı (Sch-S) kilitlerini kullanır. Sch-S kilitleri, özel (X) kilitler dahil olmak üzere işlem kilitlerini engellemez. Bu nedenle, bir tabloda X kilitli olanlar da dahil olmak üzere diğer işlemler, bir sorgu derlenirken çalışmaya devam eder. Ancak, eşzamanlı DDL işlemleri ve Sch-M kilitlerini alan eşzamanlı DML işlemleri tabloda gerçekleştirilemez.


Bazen SSMS'de tabloyu vurgulamak bile bir Sch-Skilit oluşturur ve bunun OP sorunlarının temel nedeni olduğundan şüpheleniyorum.
John Eisbrener

5

Size bir örnek vereceğim, böylece neden uzun zaman aldığını görebilirsiniz. Bu sınama için boş bir veritabanı oluşturma.

CREATE DATABASE [TestFK]
GO

2 tablo oluşturma.

 USE [TestFK]
 GO
CREATE TABLE dbo.[Address] (
      ADDRESSID   INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       Address1    VARCHAR(50),
      City        VARCHAR(50),
      [State]     VARCHAR(10),
      ZIP     VARCHAR(10));
GO

CREATE TABLE dbo.Person (
       PersonID    INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
       LastName    VARCHAR(50) NOT NULL,
     FirstName   VARCHAR(50),
      AddressID   INT);
GO

Kişi tablosunda Yabancı Anahtar kısıtı oluşturma.

 USE [TestFK]
 GO
ALTER TABLE dbo.Person ADD CONSTRAINT FK_Person_AddressID FOREIGN KEY (AddressID)
REFERENCES dbo.Address(AddressID)
GO

Her iki tabloya da bazı veriler ekleyin.

USE [TestFK]
GO
INSERT dbo.Address (Address1,City,[State],Zip)
  SELECT '123 Easy St','Austin','TX','78701'
    UNION
 SELECT '456 Lakeview','Sunrise Beach','TX','78643'
GO
INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith','John',1
   UNION
 SELECT 'Smith','Mary',1
   UNION
 SELECT 'Jones','Max',2
GO

Yeni bir sorgu penceresi açın ve bunu çalıştırın (sorgu tamamlandıktan sonra pencereyi kapatmayın).

   USE [TestFK]
   GO
   BEGIN TRAN
   INSERT dbo.Person (LastName,FirstName,AddressID)
    SELECT 'Smith1','John1',1
    UNION
    SELECT 'Smith1','Mary1',1
    UNION
    SELECT 'Jones1','Max1',2

Başka bir sorgu penceresi açın ve bunu çalıştırın.

USE [TestFK]
GO
ALTER TABLE dbo.person DROP CONSTRAINT FK_Person_AddressID

Bırakma kısıtını çalıştırmaya devam edeceğinizi göreceksiniz (bekleyen) ve şimdi neden daha uzun çalıştığını ve hangi kilitleri beklediğini görmek için sorguyu çalıştırın.

SELECT * FROM sys.dm_os_waiting_tasks 
WHERE blocking_session_id IS NOT NULL; 

Ekleme işleminizi tamamladıktan sonra, drop deyimi derhal tamamlanacaktır çünkü artık drop deyimi gerekli kilidi alabilir.

Sizin durumunuz için, hiçbir oturumun, gerekli kısıtlama / kilitleri almasını engelleyecek uyumlu bir kilit tutmadığından emin olmanız gerekir.


Veritabanını başka kimse kullanmıyordu, ancak diğer taraftan, bu veritabanında açık bir pencerem olduğunu dışlayamıyorum. Başka bir deney yapacağım.
carlo.borreo

1
Drop deyiminiz tamamlanmayı beklediğinde, bu sorguyu başka bir pencereden çalıştırın. Bu size ne beklediğinizi verecektir. Sorguyu buradan alın . Örneğimde verdiğimden daha fazla ayrıntıya sahip.
SqlWorldWide
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.