deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

SQLite 3.53'ün SET NOT NULL'ı tam tablo yeniden inşasını altı disk yazımına indiriyor

dev.to'da yayımlanan benchmarklar, SQLite 3.53'ün ALTER COLUMN SET NOT NULL işleminin 2 milyon satırda eski tablo yeniden inşasına kıyasla 150–180 kat daha hızlı çalıştığını ve yaklaşık 70.000 yazım yerine altı yazım yaptığını gösteriyor.

SQLite 3.53'ün SET NOT NULL'ı tam tablo yeniden inşasını altı disk yazımına indiriyor

NOT NULL eklemek artık bir metadata değişikliği

Nisan 2026'da yayımlanan SQLite 3.53.0, ALTER TABLE ... ALTER COLUMN ... SET NOT NULL ve DROP NOT NULL ifadelerini ekliyor ve dev.to'da yayımlanan benchmarklar bunun operasyonel olarak neyi değiştirdiği sayısallaştırıyor. Şimdiye kadar bu kısıtı eklemek, bir yedek tablo oluşturmayı, her satırı oraya kopyalamayı, tabloları düşürüp yeniden adlandırmayı ve indexleri elle yeniden oluşturmayı gerektiriyordu. Hedef sütunda bir index bulunan iki milyonluk satırlık test tablosunda bu yeniden inşa, üç denemede yaklaşık 1,5 ile 1,8 saniye arasında sürdü. Yeni tek ifade ise saniyenin yüzde biri kadar bir sürede tamamlandı; yazar bu farkı 150 ila 180 kat olarak ölçtü.

strace altında yeniden inşa 69.843 pwrite64 çağrısı yaparken, SET NOT NULL toplam 8.716 baytlık altı yazım gerçekleştirdi. Yeni ifade, sqlite_master içindeki şema kaydını yeniden yazıyor ve satır verisi sayfalarını hiç taşımıyor. Buna karşılık yeniden inşa her satırı iki kez yazıyor: bir kez yeni tabloya, bir kez de index yeniden oluşturulurken. Elle index oluşturma adımını atlarsanız, sorgular hiçbir uyarı olmadan tablonun tamamını taramak zorunda kalıyor. SET NOT NULL ise mevcut indexleri yerinde bırakıyor.

Testler 3.53.4 CLI ile yapıldı; yazar, Ubuntu'nun apt depolarında hâlâ SQLite 3.45.1 bulunduğunu, bu sürümün yeni sözdizimini doğrudan reddettiğini belirtiyor.

Satırlar yine de kontrol edilir, bir index kapsamıyorsa

SQLite'ın sürüm notları, işlemin runtime'ının tablonun verisiyle orantılı olduğunu belirtiyor, çünkü mevcut her satırın NULL açısından kontrol edilmesi gerekiyor. dev.to ölçümleri bunun ne zaman geçerli olduğunu gösteriyor. Sekiz milyonluk satırlık bir tabloda, indexi olan bir sütun yalnızca 13 sayfa okuması gerektirdi: NULL'lar SQLite'ın b-tree'lerinde en başta sıralandığı için sütunu doğrulamak, tablonun kendisi yerine indexin başını incelemek anlamına geliyor. Indexi olmayan bir sütunda aynı tablo 25.372 okuma gerektirdi. Soğuk cache süreleri indexli durumda yaklaşık 0,010 saniye, indexsiz durumda 0,11 saniye çıktı — ikisi de bir yeniden inşanın çok altında, ancak tablo boyutuyla ölçeklenen yalnızca indexsiz yol.

Hata mesajları sizi tahmin etmeye bırakıyor

Sütunda zaten bir NULL varsa ALTER doğru şekilde reddediliyor. Ancak hata mesajı, sütun adı, kısıt türü veya satır tanımlayıcısı içermeyen çıplak bir "constraint failed"; oysa aynı kısıtı ihlal eden bir INSERT, "NOT NULL constraint failed: t.b" üretiyor. Geniş bir tabloda bir seferde bir sütun sıkılaştırılırken, yazarın da belirttiği gibi, sorunlu satırları kendiniz bulmanız gerekiyor; örneğin sütun IS NULL olan rowid'leri seçen bir sorguyla.

Belgelenmemiş CHECK kısıtı desteği

Test ederken yazar, sqlite.org'un ALTER TABLE referansı yalnızca SET NOT NULL ve DROP NOT NULL'ı belgelendirdiği ve CHECK kısıtlarının ADD COLUMN ile geldiğini söylediği için parse hatası bekleyerek ANSI tarzı ADD CONSTRAINT ad CHECK (...) biçimini denedi. İşe yaradı: mevcut satırlar doğrulandı, kısıtı ihlal eden bir insert düzgün adlandırılmış bir hatayla reddedildi ve DROP CONSTRAINT onu sorunsuzca kaldırdı. Referans sayfada yapılan bir aramada bu ifadelerden hiçbirinin anılmasına rastlanmadı.

Tarama sırasında okuyucular engellenmiyor

Kilitleme diğer herhangi bir yazım gibi davranıyor. busy_timeout sıfırdaysa ve başka bir yerde bir write transaction açıksa ALTER hemen başarısız oluyor; bir timeout yapılandırılmışsa kuyruğa giriyor ve kilit boşalınca çalışıyor.

Öne çıkan sonuç eşzamanlı okuyucularla ilgili. Indexsiz sekiz milyonluk satır kontrolü sürerken, ikinci bir bağlantıdan gelen bir count sorgusu hem rollback-journal hem de WAL modlarında anında tamamlandı. Doğrulama aşaması yalnızca shared lock alıyor ve exclusive lock, küçük şema yazımı için en sonda ortaya çıkıyor; böylece okuma yoğun uygulamalar migration'ı sorguları durdurmadan çalıştırabiliyor.

Yazıda ayrıca, belgelendirilmiş no-op davranışın — yani kısıtı zaten taşıyan bir sütuna SET NOT NULL uygulamanın — testlerde doğrulandığı bildiriliyor.

Neden önemli

Null olabilir sütunları zorunlu hale getirmek temel bir şema hijyeni uygulamasıdır ve SQLite bunu daha önce orantısız derecede pahalı kılıyordu: tam tablo kopyası, unutulması kolay elle index yeniden oluşturma adımı ve her satır için iki katına çıkan I/O. Sürüm 3.53 bunu bir şema kaydı güncellemesi artı bir null kontrolüne indiriyor ve sütun indexliyse kontrol neredeyse bedava. Bu, bir bakım penceresi migration'ını, canlı ve okuma yoğun bir dağıtımın sorunsuzca hazmedebileceği bir şeye dönüştürüyor.

Pratik uyarılar geçerliliğini koruyor: paketlenmiş SQLite sürümleri güncel yayımın epey gerisinde, dolayısıyla yeni sözdizimi mevcut yığınınızda çözümlenmeyebilir; ayrıca hata mesajı bu kadar bilgilendirici olmadığından önceden NULL taraması yapmak tavsiye edilir.

  • #sqlite
  • #database
  • #sql
  • #schema-migration
  • #performance