Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Bir Sorgunun SQL Server İçindeki Yolculuğu: Relational Engine, Storage Engine, Buffer Pool ve Transaction Log
Bir sorgu SQL Server'da TDS ile gelir, Relational Engine'de parse, bind ve optimize edilip plan cache'e girer; Storage Engine page'leri buffer pool üzerinden okur, değişiklikler önce transaction log'a yazılır (WAL) ve data file'a checkpoint ile sonra gider. Seri boyunca kullanılacak 5,6 milyon satırlık deterministik Bookstore lab verisi, 2025 edition'ları ve compatibility level'ın motor sürümünden farkı.
Page'ler, Heap ve Clustered Index: SQL Server Veriyi Diskte Nasıl Tutar?
SQL Server veriyi 8 KB'lık page'lerde tutar; clustered index tablonun kendisi olan sığ bir B-tree'dir, heap ise sırasız page'ler ve güncellemede forwarded record demektir. Gerçek page'ler, ROW_OVERFLOW/LOB, clustering key seçimi, Guid.CreateVersion7 değerlerinin SQL Server sıralamasında NEWID kadar rastgele olduğunu gösteren deney ve fill factor ile page density ölçümleri.
Nonclustered Index Tasarımı: Key Sırası, INCLUDE, Covering Index ve Key Lookup
İyi bir nonclustered index önce eşitlik, sonra aralık kolonlarını key'e koyar ve sorgunun geri kalan kolonlarını INCLUDE ile taşır; aksi hâlde key lookup maliyeti yüzünden optimizer tabloyu taramayı seçer. Bookstore'un sipariş arama sorgusu 7.707'den 25 logical read'e iniyor; tipping point, filtered index'in EF Core literal'leriyle ilişkisi, computed column, HasIndex karşılıkları ve yazma maliyeti ölçümleriyle.
Statistics ve Cardinality Estimation: Histogram, Density ve Yanlış Tahminin Bedeli
Optimizer satır sayısını statistics'ten tahmin eder: değer histogramda bir adımsa tahmin kusursuzdur, adım içindeyse ortalamadır, bilinmiyorsa density vector'e düşer. 1 milyon siparişlik Bookstore verisinde histogram okuma, otomatik güncelleme eşiğinin (31.623 değişiklik) deneyle doğrulanması, ascending key yüzünden 24 kat pahalı plan, birbirine bağlı kolonlarda CE model'leri ve CE feedback.
Execution Plan Okumak 1: Estimated vs Actual Plan, Operator'ler ve Join Algoritmaları
Execution plan sağdan sola, içten dışa okunur; ilk bakılacak şey cost yüzdesi değil, tahmini ve gerçek satır sayısı ile her operator'ün kaç kez çalıştığıdır. EF Core Include sorgusunun actual plan'ında cost yüzdesinin yanılttığı yer, seek/scan/lookup, nested loops, merge ve hash join'in aynı sorguda ölçülen maliyetleri, stream ve hash aggregate ve iki index'le 2.549'dan 689 logical read'e iniş.
Execution Plan Okumak 2: Memory Grant, Spill, Parallelism ve Implicit Conversion Uyarıları
Plan uyarıları tahminin bedelini gösterir: küçük tahmin memory grant'i yetersiz bırakıp tempdb'ye spill ettirir, düşük cost threshold küçük sorguları 10 thread'e dağıtır, nvarchar parameter varchar kolonda 3 page'lik aramayı 3.117 page'e çıkarır. Memory grant feedback, exchange operator'leri, CX wait'leri, 2025'te varsayılan açık DOP feedback, EF Core ve Dapper ile implicit conversion, batch mode ve adaptive join.
Plan Cache, Parameterization ve Parameter Sniffing: Belirtiler, Teşhis ve Çözümler
Parameter sniffing, cache'teki planın ilk gelen parametre değerine göre derlenip çarpık veride diğer değerlere uymamasıdır: aynı procedure müşteri 1 için bir sırada 7.709, diğerinde 612.850 logical read yaptı. Ad hoc/prepared plan'lar, simple ve forced parameterization, RECOMPILE ve OPTIMIZE FOR'un bedeli, 2022'nin PSP optimization'ı, 2025'in OPPO'su ve ORM parametre uzunluklarının plan cache'i şişirmesi.
Query Store ve Intelligent Query Processing: Regresyonu Bulmak, Plan Zorlamak ve Kod Değiştirmeden Hint Vermek
Query Store sorgu metinlerini, planları ve çalışma istatistiklerini veritabanında kalıcı tutar; böylece plan cache'in unuttuğu "dün nasıldı" sorusunu cevaplar, kötüleşen planı zorlamaya ve kodu değiştirmeden hint eklemeye izin verir. Regresyon sorgusu, plan zorlamanın bedeli, FORCE_LAST_GOOD_PLAN, EF Core sorgusuna Query Store hint'iyle RECOMPILE, 2025'in ABORT_QUERY_EXECUTION'ı ve IQP ailesi.
Transaction'lar ve Transaction Log: ACID'in Motor Tarafı, XACT_ABORT, Savepoint ve Accelerated Database Recovery
SQL Server'da atomiklik kendiliğinden gelmez: XACT_ABORT OFF iken hatalı ifadeden sonraki COMMIT yarım işi kalıcı yapar, iç COMMIT hiçbir şeyi commit etmez, tek bir açık transaction SIMPLE recovery'de bile log'un truncate edilmesini durdurur. XACT_ABORT ve TRY/CATCH/THROW kalıbı, savepoint, LSN/VLF/recovery model, 200.000 satırlık rollback'in ADR ile 200.031'den 1 log record'a inişi ve TransactionScope'un Linux/macOS'ta distributed transaction hatası.
Isolation Level'lar ve Row Versioning: READ COMMITTED, RCSI, SNAPSHOT, REPEATABLE READ ve SERIALIZABLE
Isolation level'lar, eşzamanlı transaction'ların hangi anomaliyi görebileceğini locking ya da row versioning ile belirler: varsayılan READ COMMITTED okuyucuyu yazana bekletir, RCSI son commit edilmiş sürümü verir, SNAPSHOT transaction başındaki görüntüyü tutar ve çakışmada 3960 verir. İki oturumlu deneylerle dirty read, non-repeatable read, phantom, lost update, write skew, versioning'in 14 byte'lık bedeli ve .NET'ten IsolationLevel seçmek.
Lock'lar ve Blocking: Lock Mode'ları, Granularity, Lock Escalation ve Blocking Zincirini Bulmak
Tek satırlık bir UPDATE bile dört lock tutar ve SQL Server lock isteklerini sıraya koyar; bu yüzden zincirin kökünü sys.dm_exec_requests ve sys.dm_exec_sessions ile ararsın. Lock mode'ları ve compatibility matrisi, laboratuvarda 6.249 lock'ta ölçülen escalation, UPDLOCK/SERIALIZABLE ile güvenli upsert, READPAST ile queue table, LOCK_TIMEOUT ve migration'ın Sch-M ile bütün okuyucuları durdurması gerçek çıktılarla.
Deadlock'lar: Deadlock Graph'ı Okumak, Yaygın Pattern'ler ve .NET'te Retry
SQL Server deadlock'ta geri alması en ucuz transaction'ı kurban seçer ve 1205 döner; çözüm graph'ı okumak, erişim sırasını sabitlemek, covering index ya da RCSI ile reader-writer döngüsünü kırmak ve bütün transaction'ı iş kuralını yeniden kontrol ederek tekrar denemektir. Ters sıra, HOLDLOCK'lu upsert ve key lookup deadlock'ları, DEADLOCK_PRIORITY, EF Core'un execution strategy'si ve Polly ile retry'ın iptali ezdiği gerçek bir örnek.