# Analiz Raporu #1189

Hedef: sorgu 0x6C906FE3084F4D2D · dönem 2026-10-03 → 2026-10-09

Veritabanı: DB-11 · Güven: medium · Model: gemma4:12b (gemma4) · Prompt v11

## Özet
Sorgunun yavaşlığına neden olan temel sorunlar, eksik bir indeks nedeniyle oluşan geçici indeks oluşturma (Index Spool) ve her dış satır için tekrar edilen maliyetli alt sorgu işlemleridir.

## Uyarılar
- İstem modelin context sınırına dayandı (9.079 token; context 12.288 − üretim sınırı 3.225): istemin başı (sistem kuralları) kesilmiş olabilir; karakter/token ölçümü alınmadı. Profilin context değerini büyütün ya da Analysis.CharsPerToken'ı düşürün.
- Bağlam bütçesi yetmedi; analiz eksik bağlamla yapıldı: "Benzer sorgular (QDS profilleri, aynı ortam)" kırpıldı (5.664 / 11.543 karakter çıkarıldı). Tam bağlam için LLM profilinin bağlam boyunu artırın (şu an 12.288 token).
- Güven high → medium: tablo, kolon ve index bilgisi (metadata) yok.

## Kök nedenler
- QUERY_STORE_PLAN_IN_MEM tablosunda eksik olan (query_id, plan_id) indekslemesi nedeniyle optimizer her çalışma sırasında bu bilgileri içeren geçici bir indeks inşa etmektedir (Eager Index Spool). (F1)
- Alt sorgu (subquery) kullanımı nedeniyle, dış sorgudaki her bir satır için QUERY_STORE_RUNTIME_STATS_IN_MEM ve QUERY_STORE_RUNTIME_STATS_V2_IN_MEM gibi tabloları içeren maliyetli alt ağaçlar tekrar tekrar çalıştırılmaktadır. (F2)

## Bulgular
| Id | Ciddiyet | Kural | Başlık | Kanıt |
|---|---|---|---|---|
| F1 | High | INDEX_SPOOL | Geçici index (Eager Index Spool) — kalıcı index eksik | Optimizer QUERY_STORE_PLAN_IN_MEM için sorgu sırasında geçici index kuruyor (her çalıştırmada yeniden; maliyet payı %100): NodeId 15: anahtar [query_id, plan_id], 54.469 kez aranıyor, 1.000 satır okunup kuruluyor. Kalıcı index adayı: QUERY_STORE_PLAN_IN_MEM (query_id, plan_id); mevcut index'lerle örtüşme kontrol edilmeli. |
| F2 | High | REPEATED_SUBTREE | Dış satır başına tekrar çalışan pahalı alt ağaç | NodeId 18 Row Count Spool alt ağacı 194.561 kez çalışıyor (dış tarafın her satırı için), maliyet payı %100; tablolar: QUERY_STORE_RUNTIME_STATS_IN_MEM, QUERY_STORE_RUNTIME_STATS_V2_IN_MEM, sys.plan_persist_runtime_stats, sys.plan_persist_runtime_stats_v2; en pahalı iç operatör Table-valued function (NodeId 25, %14,3). SELECT listesindeki ilişkili alt sorguysa JOIN/OUTER APPLY'a çevirmek ya da çalıştığı satır sayısını azaltmak değerlendirilmeli. |

## Plan özeti
```
Plan tipi: tahmini; statement sayısı 1; toplam maliyet 1,271; tahmini satır 54.469
CE sürümü: 170; DOP: ?; paralel değil: MaxDOPSetToOne
Memory grant (KB): istenen 672 (tahmini plan; verilen/kullanılan yalnız actual planda)
Operatörler (maliyet sırasıyla):
- [17] Index Seek sys.plan_persist_plan.plan_persist_plan_idx1 — %14,294 maliyet, tahmini 1 satır; seek: [Union1022]
- [20] Index Seek sys.plan_persist_runtime_stats_v2.plan_persist_runtime_stats_v2_idx1 — %14,294 maliyet, tahmini 1 satır; seek: [Union1072] AND [@Arg1] AND [@Arg2]
- [21] Clustered Index Seek sys.plan_persist_runtime_stats.plan_persist_runtime_stats_cidx — %14,294 maliyet, tahmini 1 satır; seek: [Union1072] AND [@Arg1] AND [@Arg2]
- [23] Table-valued function QUERY_STORE_RUNTIME_STATS_V2_IN_MEM — %14,294 maliyet, tahmini 100 satır
- [25] Table-valued function QUERY_STORE_RUNTIME_STATS_IN_MEM — %14,294 maliyet, tahmini 100 satır
- [15] Index Spool — %14,283 maliyet, tahmini 2,7 satır; seek: [Union1022] AND (-1)
- [7] Clustered Index Scan sys.plan_persist_plan.plan_persist_plan_cidx — %8,824 maliyet, tahmini 54.169 satır
- [1] Nested Loops — %2,561 maliyet, tahmini 54.469 satır
- [6] Merge Join — %1,427 maliyet, tahmini 54.169 satır
- [12] Constant Scan — %0,613 maliyet, tahmini 1 satır
- [8] Sort — %0,303 maliyet, tahmini 1.000 satır
- [11] Filter — %0,294 maliyet, tahmini 1 satır; residual: [Union1030]=(1)
- [2] Concatenation — %0,061 maliyet, tahmini 54.469 satır
- [0] Compute Scalar — %0,061 maliyet, tahmini 54.469 satır
- [5] Compute Scalar — %0,061 maliyet, tahmini 54.169 satır
- [4] Table-valued function QUERY_STORE_PLAN_IN_MEM — %0,011 maliyet, tahmini 1.000 satır
- [9] Table-valued function QUERY_STORE_PLAN_IN_MEM — %0,011 maliyet, tahmini 1.000 satır
- [16] Table-valued function QUERY_STORE_PLAN_IN_MEM — %0,011 maliyet, tahmini 1.000 satır
- [3] Filter — %0,005 maliyet, tahmini 300 satır; residual: QUERY_STORE_PLAN_IN_MEM.[plan_id]<(-1)
- [10] Concatenation — %0 maliyet, tahmini 1 satır
- [13] Nested Loops — %0 maliyet, tahmini 1 satır
- [14] Concatenation — %0 maliyet, tahmini 2,7 satır
- [18] Row Count Spool — %0 maliyet, tahmini 12,4 satır
- [19] Concatenation — %0 maliyet, tahmini 12,4 satır
- [22] Filter — %0 maliyet, tahmini 5,2 satır; residual: QUERY_STORE_RUNTIME_STATS_V2_IN_MEM.[runtime_stats_interval_id]>[@Arg1] AND QUERY_STORE_RUNTIME_STATS_V2_IN_MEM.[runtime_stats_interval_id]<=[@Arg2]
- [24] Filter — %0 maliyet, tahmini 5,2 satır; residual: QUERY_STORE_RUNTIME_STATS_IN_MEM.[runtime_stats_interval_id]>[@Arg1] AND QUERY_STORE_RUNTIME_STATS_IN_MEM.[runtime_stats_interval_id]<=[@Arg2]
```

## Index önerileri
### Yeni index: QUERY_STORE_PLAN_IN_MEM (query_id, plan_id) — NotValidated
Gerekçe: F1 bulgusuna istinaden, QUERY_STORE_PLAN_IN_MEM tablosunda eksik olan bu indeksin oluşturulması, sorgu sırasında oluşturulan 'Eager Index Spool' işlemini ortadan kaldırarak performansı artıracaktır. · Beklenen etki: High · Bulgular: F1
Doğrulama: Tablo metadata'da yok: QUERY_STORE_PLAN_IN_MEM (harici sorgu ya da farklı DB); kolonlar, tipler ve mevcut index'ler doğrulanamadı, script üretilmedi.

## T-SQL refactor — model önerisi — Warning
Doğrulama: Eşdeğerlik: test edilemedi — bu DB için Test DB eşlemesi yok (Envanter > eşdeğerlik testi DB'si)
sys.query_store_plan orijinal sorguda da metadata'da yoktu; doğrulanamadı.
sys.query_store_runtime_stats orijinal sorguda da metadata'da yoktu; doğrulanamadı.
Değişiklikler:
- Alt sorgudaki tekrarlanan alt ağaçları (F2) engellemek için, iç sorguyu bir türetilmiş tablo (derived table) yapısına dönüştürerek `query_id` bazlı gruplama yapıldı. Bu sayede maliyetli fonksiyonlar her satır için değil, yalnızca benzersiz query_id'ler için bir kez değerlendirilir.
Semantik riskler:
- Alt sorgudaki GROUP BY kullanımı, orijinal sorgudaki (eğer varsa) mükerrer satır yapısını değiştirebilir; ancak query_id üzerinde benzersiz sonuç beklenmektedir.
```sql
SELECT 1, N'DB-11', p.plan_id, p.query_id, p.query_plan_hash, p.is_forced_plan, p.compatibility_level,
               CONVERT(datetime, SWITCHOFFSET(p.last_compile_start_time, 0)), CONVERT(datetime, SWITCHOFFSET(p.last_execution_time, 0)),
               p.force_failure_count, p.last_force_failure_reason_desc
        FROM sys.query_store_plan AS p
        WHERE p.is_forced_plan = 1
           OR p.query_id IN (SELECT sub.query_id FROM (SELECT pp.query_id FROM sys.query_store_plan AS pp 
                             JOIN sys.query_store_runtime_stats AS rs ON rs.plan_id = pp.plan_id 
                             WHERE rs.runtime_stats_interval_id > @Arg1 AND rs.runtime_stats_interval_id <= @Arg2
                             GROUP BY pp.query_id) AS sub)
```

## Benzer profiller
Bu desen 6 sunucu/DB'de 10 sorguda da görülüyor (vektör benzerliği; en yakınları LLM bağlamına da girdi):
- Profile SQL-1/DB-12 0x6C906FE3084F4D2D — uzaklık 0.018
- Profile SQL-1/DB-3 0x6C906FE3084F4D2D — uzaklık 0.034
- Profile SQL-1/DB-2 0x6C906FE3084F4D2D — uzaklık 0.034
- Profile SQL-1/DB-1 0x6C906FE3084F4D2D — uzaklık 0.036
- Profile SQL-1/DB-9 0x6C906FE3084F4D2D — uzaklık 0.036
- Profile SQL-1/DB-10 0x6C906FE3084F4D2D — uzaklık 0.036
- Profile SQL-1/DB-3 0x1FD8CBF850393199 — uzaklık 0.041
- Profile SQL-1/DB-1 0x1FD8CBF850393199 — uzaklık 0.041
- Profile SQL-1/DB-9 0x1FD8CBF850393199 — uzaklık 0.042
- Profile SQL-1/DB-10 0x1FD8CBF850393199 — uzaklık 0.042

## Analizi güçlendirecek ek bilgiler
- Plan tahmini (estimated): actual plan verilirse gerçek satır ve çalışma sayılarıyla tahmin hataları doğrulanır; kurallar şu an optimizer tahminlerine dayanıyor.
- Sorgu parametreli ve değerleri bilinmiyor: yavaş çalışmanın parametre değerleri (ya da değerleri içeren actual plan) kardinalite tahmin hatasını ve parametre hassasiyetini açıklar.
