SQL Batch İşleme ve Yazılım Tarafında Thread Kullanımı: Performansın Gerçek Dinamikleri
📌 Giriş
Büyük veriyle çalışan sistemlerde performans, yalnızca güçlü donanım ile değil, doğru işleme yöntemleriyle elde edilir. Bu noktada iki temel yaklaşım öne çıkar:
SQL tarafında set-based (batch) işlemler
Yazılım tarafında thread (çoklu iş parçacığı) kullanımı
Bu makalede, bu iki yaklaşımın farklarını, avantajlarını, dezavantajlarını ve gerçekçi kullanım senaryolarını örneklerle inceleyeceğiz.
🧠 1. SQL’de Batch İşleme Nedir?
Konuyu basit bir benzetmeyle açıklayalım:
Tek tek işlem (Row-by-Row): Markette her ürünü tek tek kasaya taşımak.
Batch işlem: Tüm ürünleri bir arabaya yükleyip tek seferde kasaya götürmek.
SQL dünyasında batch işlem, çok sayıda satırı tek bir komutla işlemektir.
⚡ Performans Karşılaştırması (100.000 kayıt üzerinde test)
İşlem Tipi Süre Açıklama
FOR döngüsü (tek tek) 1.36 sn 100.000 kez DB’ye gidip gelir
INSERT INTO SELECT 0.04 sn Tek komutla tüm veriyi işler
FORALL (PL/SQL) 0.03 sn Batch + optimize edilmiş yapı
Sonuç: Batch işlemler, row-by-row yaklaşıma göre 20-40 kat arasında hız artışı sağlayabilir.
⚠️ Transaction ve Batch İlişkisi
Büyük batch’ler büyük transaction log, uzun süreli lock ve yüksek rollback maliyeti yaratır.
Bu nedenle gerçek sistemlerde batch’ler chunk’lara bölünmeli ve kontrollü commit yapılmalıdır.
DECLARE @BatchSize INT = 10000;
DECLARE @LastId INT = 0;
DECLARE @RowsAffected INT = 1;
WHILE @RowsAffected > 0
BEGIN
BEGIN TRANSACTION;
INSERT INTO HedefTablo (Kol1, Kol2, …)
SELECT TOP (@BatchSize) Kol1, Kol2, …
FROM BuyukTablo
WHERE Id > @LastId
ORDER BY Id;
SET @RowsAffected = @@ROWCOUNT;
IF @RowsAffected > 0
SET @LastId = (SELECT MAX(Id) FROM HedefTablo
WHERE Id > @LastId); — veya OUTPUT clause ile daha verimli alın
COMMIT TRANSACTION;
— Opsiyonel: Sistem yükünü azaltmak için
— WAITFOR DELAY ’00:00:001′;
END
🧵 2. Thread Nedir ve Ne Zaman Kullanılır?
Thread, bir programın aynı anda birden fazla işi yürütebilme yeteneğidir.
Pratik Formül:
Optimum Thread Sayısı ≈ Çekirdek Sayısı × (1 + Bekleme Süresi / İşlem Süresi)
CPU Bound işler için genellikle çekirdek sayısı (veya +1) yeterlidir.
I/O Bound işler için 2x – 4x çekirdek sayısı daha iyi sonuç verir.
⚠️ Kritik Uyarı (CPU Bound İşler):
CPU-bound işlerde lineer hız artışı (4 çekirdek = 4x hız) nadiren elde edilir.
Amdahl Yasası, lock’lar, bellek çekişmesi ve cache coherency sorunları nedeniyle gerçek kazanç genellikle sınırlıdır.
💻 3. Delphi ile Batch + Thread Kullanımı
type
TIslemThread = class(TThread)
protected
procedure Execute; override;
end;
procedure TIslemThread.Execute;
var
i: Integer;
begin
for i := 1 to 1000000 do
begin
// Yoğun işlem / Batch işlemi burada
if (i mod 5000 = 0) then
TThread.Queue(nil,
procedure
begin
Form1.ProgressBar1.Position := Form1.ProgressBar1.Position + 5000;
end);
end;
end;
Modern Delphi Alternatifleri:
System.Threading.TParallel.For
TTask.Run ve ITask arayüzü
TThread.CreateAnonymousThread
Büyük Dosya İşleme Örneği
1 GB log dosyasını 4 thread ile işlemek ciddi hız kazandırabilir.
Dikkat edilmesi gerekenler:
Satır ortasından bölmemek (buffered okuma)
Encoding uyumu
Disk I/O bottleneck (en yaygın sınırlayıcı faktör)
Thread Güvenliği:
Ortak kaynaklara erişimde TCriticalSection, TMonitor veya Producer-Consumer (Queue) modelini tercih edin. Aşırı lock kullanımı paralelliği öldürür.
🧩 4. .NET Dünyasında Modern Yaklaşım
Parallel.ForEach (Partitioner ile daha verimli)
async/await + Task.WhenAll
System.Threading.Channels
TPL Dataflow
Örnek:
Parallel.ForEach(musteriler, new ParallelOptions { MaxDegreeOfParallelism = 8 }, musteri =>
{
MailGonder(musteri);
});
BackgroundWorker eski bir teknolojidir. Yeni projelerde kesinlikle Task + async/await yaklaşımı önerilir.
⚖️ 5. SQL mi, Thread mi?
🔥 En Kritik Gerçek
SQL motorları set-based işlemler için özel olarak optimize edilmiştir.
Basit ve veri yoğun işlemlerde SQL neredeyse her zaman kazanır.
Karmaşık iş kuralları, dış sistem entegrasyonları ve yüksek I/O beklemelerinde ise thread/async yaklaşımı devreye girer.
🧠 Sonuç
Performans optimizasyonu tek bir yöntemle değil, doğru aracı doğru yerde kullanmakla elde edilir.
SQL Batch → Veri tarafında maksimum hız
Thread / Async → Paralel iş yüklerinde ve dış bağımlılıklarda güç
En iyi sonuç, bu iki yaklaşımın bilinçli ve dengeli şekilde bir arada kullanılmasıyla elde edilir.
Doğru mimari kararlar sistemi sadece hızlandırmakla kalmaz, aynı zamanda sürdürülebilir ve ölçeklenebilir hale getirir.
📊 Benchmark Nasıl Yapılır? (Pratik Örnekler)
Performans iddialarını asla tahmine bırakmayın. Her zaman ölçün.
1. SQL tarafında basit benchmark:
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
— Test edilecek sorgu buraya
INSERT INTO HedefTablo
SELECT … FROM BuyukTablo
WHERE …;
SET STATISTICS TIME OFF;
SET STATISTICS IO OFF;
SQL Server Management Studio’da “Include Actual Execution Plan” ile birlikte kullanın.
Daha profesyonel ölçüm için: Extended Events veya Query Store önerilir.
2. Delphi tarafında basit zaman ölçümü:
var
SW: TStopwatch;
begin
SW := TStopwatch.StartNew;
// Test edilecek kod (thread’li veya threadsiz)
SW.Stop;
Writeln(‘Geçen süre: ‘, SW.ElapsedMilliseconds, ‘ ms’);
end;
3. .NET tarafında profesyonel benchmark
// BenchmarkDotNet kütüphanesi ile (en doğru yöntem)
[MemoryDiagnoser]
public class BatchVsThreadBenchmark
{
[Benchmark]
public void SqlBatchYontemi() { /* … */ }
[Benchmark]
public void ParallelThreadYontemi() { /* … */ }
}
Altın Kural: Hiçbir optimizasyon, gerçek üretim verisi ve üretim benzeri yük altında test edilmeden kabul edilmemelidir.
✍️ Son Söz
Bu makale, gerçek sistemlerde karşılaşılan performans problemlerine pratik bir bakış sunmayı amaçlamaktadır.
Teoriyi araç olarak kullanın, ama son kararı ölçümler versin.
Yazar: Özgür GÜLER – White Eagles



