Hızlı bir şekilde NULL sütununu NULL DEĞİL olarak değiştirin


11

Milyonlarca satır ve NULL değerlere izin veren bir sütun içeren bir tablo var. Ancak hiçbir satır şu anda bu sütun için bir NULL değeri vardır (Bu bir sorgu ile oldukça hızlı bir şekilde doğrulayabilirsiniz). Ancak komutu yürüttüğümde

ALTER TABLE MyTable ALTER COLUMN MyColumn BIGINT NOT NULL;

sorgu sonsuza dek göreceli olarak konuşur. Aslında bir kontrol kısıtlaması eklemek iki kattan fazla süren 10 ila 20 dakika sürer. Tablonun meta verilerini anında güncellemenin bir yolu var mı, özellikle de hiçbir satırın bu sütun için NULL değeri olmadığını bildiğim için?

Yanıtlar:


12

@ ypercube'un cevabı bunu yalnızca meta veri değişikliği olarak kısmen yönetir.

Kısıtlama eklemek, NOCHECKdoğrulamak için hiçbir satırın okunmayacağı anlamına gelir ve sütunun NULLdeğer içermediği bir konumdan başlıyorsanız (ve kısıtlamayı denetleme ve ekleme arasında hiçbiri eklenmeyeceğini biliyorsanız), kısıtlama NULLgelecekteki INSERTveya UPDATEişlemlerden yaratılan değerlerin önüne geçtiği için bu işe yarar.

Bununla birlikte, kısıtlamanın eklenmesinin eşzamanlı işlemler üzerinde hala bir etkisi olabilir. ALTER TABLEBir kazanmak gerekir Sch-Milk kilidi. Bunu beklerken, diğer tüm tablo erişimleri burada açıklandığı gibi engellenecektir .

Sch-MKilit alındıktan sonra işlem oldukça hızlı olmalıdır.

Bununla ilgili bir sorun, sütunun aslında NULLs olmadığını bilmenize rağmen , kısıtlamanın sorgu optimize edici tarafından güvenilmemesidir, bu da planların alt optimal olabileceği anlamına gelir.

CREATE TABLE T (X INT NULL)

INSERT INTO T 
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values

ALTER TABLE T WITH NOCHECK
  ADD  CONSTRAINT X_NOT_NULL 
    CHECK (X IS NOT NULL) ; 

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

Plan

Bunu daha basit ile karşılaştırın

ALTER TABLE T ALTER COLUMN X INT NOT NULL

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

Plan

Sütun tanımını bu şekilde değiştirmekle karşılaşabileceğiniz olası bir sorun, yalnızca koşulu karşıladıklarını doğrulamak için tüm satırları okuması değil, aynı zamanda satırlara kaydedilmiş güncellemeler gerçekleştirebilmesidir .

Muhtemel bir yarım ev çek kısıtlaması eklemek olabilir WITH CHECK. Bu, WITH NOCHECKtüm satırları okuması gerektiğinden daha yavaş olacaktır, ancak sorgu optimize edicisinin yukarıdaki sorguda daha basit bir plan vermesine izin verir ve olası günlüğe kaydedilmiş güncellemeler sorununu önlemelidir.


7

Sütunu değiştirmek yerine CHECK, NOCHECKseçenekle bir tablo kısıtlaması ekleyebilirsiniz :

ALTER TABLE MyTable WITH NOCHECK
  ADD  CONSTRAINT MyColumn_NOT_NULL 
    CHECK (MyColumn IS NOT NULL) ;

1
Bu, sütunu oluşturan NULLancak sorgu optimize edici tarafından kullanılamayan gelecekteki güncellemeleri veya eklemeleri önleyecektir .
Martin Smith

@MartinSmith Ah evet, ben sadece benzer soru cevap ve yorumları okuyun: SQL Server'da büyük bir tabloya bir NOT NULL sütun nasıl eklerim? Lütfen, sorunlara bir cevap veya daha iyi bir çözüm ekleyin, ben de benimkini kaldıracağım.
ypercubeᵀᴹ

2
Daha iyi bir çözümüm yok. Kısmi bir çözüm sağladığı için bunu iptal ettim. OP'nin yapmak istediği tüm geçersiz verileri önlemekse (ve kilit ALTER COLUMNalındıktan Sch-Msonra satırların taranması gerekmez) daha hızlı olmalıdır . Sadece aynı olmadığına dikkat çekiyor (örneğin, bir NOT INsorguda kullanılırsa plan daha karmaşık olacaktır)
Martin Smith
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.