Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
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.
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.
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.
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ı.
SQL Server 2025 ile T-SQL'e Gelenler: REGEXP Function'ları, Native JSON Tipi, || Operatörü, PRODUCT ve CURRENT_DATE
SQL Server 2025, RE2 tabanlı REGEXP_LIKE/REPLACE/SUBSTR/INSTR/COUNT/MATCHES/SPLIT_TO_TABLE, native json tipi, JSON_ARRAYAGG/JSON_OBJECTAGG, || operatörü, PRODUCT, CURRENT_DATE, UNISTR ve BASE64 getirdi. Regex'in collation'ı yok saymasını, sabit önekli pattern'in index seek'ini, preview fuzzy function'ları ve REGEXP_LIKE'ın compatibility level 170 gereksinimini gerçek çıktılarla gösteriyoruz.
SQL Server 2022 ile T-SQL'e Gelenler: IS DISTINCT FROM, GREATEST/LEAST, WINDOW, GENERATE_SERIES, DATE_BUCKET ve JSON Function'ları
SQL Server 2022, NULL-güvenli karşılaştırma için IS DISTINCT FROM, GREATEST/LEAST, GENERATE_SERIES, DATETRUNC, DATE_BUCKET, karakterli TRIM, sıralı STRING_SPLIT, JSON_OBJECT/JSON_ARRAY ve APPROX_PERCENTILE_CONT getirdi. Her birini önce/sonra koduyla deniyor ve 150 seviyesinde GENERATE_SERIES, WINDOW ve TRIM LEADING'in neden çalışmadığını gerçek hata mesajlarıyla gösteriyoruz.
Aynı Sorgu Dört Lehçede: SQL Server, PostgreSQL, MySQL ve SQLite Arasındaki Farklar
Aynı Bookstore sorguları SQL Server, PostgreSQL, MySQL ve SQLite'ta farklı syntax ve farklı sonuç verir: MySQL'de || bir OR'dur ve 7 / 2 3.5000 eder, PostgreSQL büyük-küçük harfe duyarlıdır. Sayfalamayı, string birleştirmeyi, identity ve RETURNING'i, upsert'i, tarih function'larını, quoting'i, boolean'ı, NULL sıralamasını ve LATERAL'ı dört engine'de gerçek çıktılarla karşılaştırıyoruz.
INSERT, UPDATE, DELETE ve MERGE: OUTPUT, Upsert ve WHERE'siz UPDATE'e Karşı Güvenli Çalışma
T-SQL'in UPDATE ... FROM'u bir hedef row'a birden çok kaynak row eşleşince hata vermez ve hangi değeri yazacağı belirsizdir; MERGE ise 8672 hatasıyla durur. Çok satırlı INSERT'i, OUTPUT ile yeni id'leri, standart correlated UPDATE'i, DELETE ile TRUNCATE'in log farkını, MERGE tuzaklarını, açık upsert'i ve @@ROWCOUNT kontrollü güvenli çalışmayı gerçek çıktılarla anlatıyoruz.
Window Function'lar 2: Running Total, ROWS vs RANGE Frame'leri, LAG/LEAD ve Gaps and Islands
ORDER BY'lı bir window aggregate'in varsayılan frame'i RANGE UNBOUNDED PRECEDING'dir; aynı değerli row'lar aynı toplamı alır ve SQL Server worktable kullanır. Kümülatif toplamı, ROWS ile RANGE'in logical read farkını, eksik günlerle hareketli ortalamayı, LAG/LEAD'i, LAST_VALUE tuzağını, PERCENTILE_CONT ile medyanı ve gaps and islands'ı Bookstore verisinde gerçek çıktıyla gösteriyoruz.
Window Function'lar 1: OVER, PARTITION BY, ROW_NUMBER, RANK ve Grup Başına Top-N
Window function, GROUP BY gibi hesap yapar ama row'ları çökertmez; sonucu her row'un yanına yazar. OVER ve PARTITION BY'ı, ROW_NUMBER, RANK, DENSE_RANK ve NTILE'ın eşitliklerdeki farkını, WHERE'de neden kullanılamadığını, CTE ile grup başına top-N'i, eşitlik kararını ve ROW_NUMBER ile güvenli duplicate silmeyi Bookstore verisinde gerçek çıktıyla gösteriyoruz.
CTE, View ve Recursive Sorgular: WITH ile Okunabilir SQL ve Hiyerarşik Veri
CTE sorguyu isimli adımlarla yukarıdan aşağıya yazdırır ama SQL Server'da materialize edilmez; her referans yeniden çalışır. CTE zincirlerini, view'ı, SELECT * tuzağını, SCHEMABINDING ve WITH CHECK OPTION'ı, kategori ağacını gezen recursive CTE'yi, döngü korumasını ve MAXRECURSION'ı Bookstore verisinde gerçek çıktı ve logical read'lerle gösteriyoruz.
Subquery'ler ve Set Operator'leri: Correlated Subquery, EXISTS, NOT IN Tuzağı ve UNION/INTERSECT/EXCEPT
Subquery bir sorgunun sonucunu başka bir sorguda kullanır; NOT IN ise listede tek bir NULL varsa hiç row döndürmez. Scalar subquery ve 512 hatasını, IN/ANY/ALL'u, correlated subquery'yi, derived table'ı, EXISTS ile NOT EXISTS'i ve UNION, UNION ALL, INTERSECT, EXCEPT'i Bookstore verisinde gerçek çıktı, logical read ve plan karşılaştırmasıyla anlatıyoruz.