🔍 İXTİF Site Performans Analizi v2

📅 Tarih: 2025-11-29 23:46 | 🎯 Site: ixtif.com (Tenant 2) | 📊 Kaynak: Laravel Telescope Detaylı Analiz | 👤 Analiz: Claude AI

🚨 TELESCOPE İLE TESPİT EDİLEN KRİTİK SORUNLAR

Homepage (/) Performans Raporu:

📊 Telescope Metrikleri

1,440x
Currency Query Tekrarı (N+1)
700+
Settings Query Tekrarı
11.1s
En Yavaş Query (Shop Products)
139.5 MB
Homepage Memory Kullanımı
500ms+
JSON_EXTRACT Query Süresi
6,373
Toplam Query Sayısı (Telescope)

🔥 EN YAVAŞ QUERY'LER (Telescope Database Analizi)

1. Shop Products Category Filter 11,075ms

SELECT * FROM `shop_products` WHERE `category_id` = 1 AND `is_active` = 1 AND `parent_product_id` IS NULL AND `shop_products`.`deleted_at` IS NULL ORDER BY `sort_order` ASC LIMIT 4

Sorun: Index kullanılmıyor, full table scan yapılıyor.

Çözüm: Composite index ekle: (category_id, is_active, parent_product_id, deleted_at, sort_order)

2. Shop Products JSON Title Search 6,395ms

SELECT * FROM `shop_products` WHERE JSON_UNQUOTE(JSON_EXTRACT(title, '$.\"tr\"')) LIKE '%Manuel%' AND `shop_products`.`deleted_at` IS NULL

Sorun: JSON field'da LIKE arama yapılıyor. Index çalışmıyor!

Çözüm: Virtual column oluştur veya full-text search kullan (Meilisearch zaten var!)

3. Blog Slug JSON Search 826-894ms

SELECT * FROM `blogs` WHERE json_contains(`slug`, '\"iletisim\"', '$.\"tr\"') AND `is_active` = 1 AND `blogs`.`deleted_at` IS NULL LIMIT 1

Sorun: JSON slug arama. Her seferinde 800ms+

Çözüm: Slug için ayrı column ekle (slug_tr, slug_en) veya generated column kullan

4. Session Query 2,325ms

SELECT * FROM `sessions` WHERE `id` = 'olewvhwInMBwEKLpFMxr2qT1OojVCNGkfwVUYCjK' LIMIT 1

Sorun: Session tablosu şişmiş olabilir. Index kontrol edilmeli.

Çözüm: Session cleanup job çalıştır, index kontrol et

🔁 N+1 QUERY PROBLEMLERİ (Tekrar Eden Query'ler)

Query Pattern Tekrar Sayısı Ort. Süre Etki
shop_currencies WHERE currency_id = 2 1,440x 2.17ms Kritik Her ürün için!
settings_values WHERE setting_id = 59 703x 5.79ms Kritik WhatsApp setting
settings WHERE key = 'site_title' 687x 2.90ms Kritik Her sayfa render
shop_categories WHERE category_id = 1 402x 2.38ms Yüksek Her ürün için!
tenants WHERE id = 2 222x 53.54ms Kritik Tenant yavaş!
💡 N+1 Açıklaması: Currency query 1,440 kez tekrar ediyor çünkü her ürün için ayrı query atılıyor. with('currency') ile eager loading yapılmalı veya currency cache'lenmeli.

⚡ ÇÖZ ÜM ÖNERİLERİ (Öncelik Sırası)

🔴 1. KRITIK: N+1 Query Problemlerini Çöz

Beklenen Kazanç: ~3-4 saniye (1440 query → 1 query)

Currency N+1 Çözümü:
❌ Mevcut (Yavaş)
// Her ürün için ayrı query! foreach ($products as $product) { $currency = $product->currency; // 1440 kez query! }
✅ Öneri (Hızlı)
// Tek query ile tüm currency'leri yükle $products = ShopProduct::with('currency') ->where('show_on_homepage', true) ->get(); // Sadece 1-2 query!
Settings Cache Çözümü:
// Settings'i cache'le (Laravel Cache::remember) Cache::remember('site_settings', 3600, function() { return Setting::where('is_active', true) ->with('values') ->get() ->keyBy('key'); }); // 687 query → 1 query + cache!

🔴 2. KRITIK: JSON Query Optimizasyonu

Beklenen Kazanç: 500ms+ per query

Virtual Column Ekle:
-- Migration: Slug için generated column ALTER TABLE `blogs` ADD COLUMN `slug_tr` VARCHAR(255) AS (JSON_UNQUOTE(JSON_EXTRACT(slug, '$.tr'))) STORED, ADD INDEX `blogs_slug_tr_index` (`slug_tr`); ALTER TABLE `shop_products` ADD COLUMN `title_tr` VARCHAR(255) AS (JSON_UNQUOTE(JSON_EXTRACT(title, '$.tr'))) STORED, ADD FULLTEXT INDEX `shop_products_title_tr_fulltext` (`title_tr`); -- Artık JSON_EXTRACT yerine direkt column kullan! SELECT * FROM blogs WHERE slug_tr = 'iletisim' LIMIT 1; -- 894ms → ~5ms!

Alternatif: Meilisearch zaten var! Arama için JSON query yerine Meilisearch kullan.

🟡 3. Database Index Ekle

Beklenen Kazanç: 11,075ms → ~50ms (221x hızlanma)

-- Shop Products için composite index CREATE INDEX shop_products_optimized_idx ON shop_products(category_id, is_active, parent_product_id, deleted_at, sort_order); -- Blogs için composite index CREATE INDEX blogs_active_published_deleted_idx ON blogs(is_active, published_at, deleted_at); -- Sessions için index (varsa kontrol et) CREATE INDEX sessions_id_index ON sessions(id);

🟡 4. Settings Helper Optimizasyonu

Sorun: setting('site_title') her çağrıldığında database query atıyor

// app/helpers.php içinde setting() fonksiyonunu optimize et function setting(string $key, $default = null) { static $cache = null; // İlk çağrıda tüm settings'i yükle ve cache'le if ($cache === null) { $cache = Cache::remember('all_settings', 3600, function() { return Setting::where('is_active', true) ->with('values') ->get() ->keyBy('key'); }); } return $cache->get($key)?->value ?? $default; } // 687 query → 1 query + memory cache!

🟢 5. Response Cache Düzelt

Sorun: Redis'de cache kontrol ediliyor ama hit olmuyor

  • Route middleware'inde ResponseCache middleware'i var mı kontrol et
  • Cache key generation doğru mu kontrol et (tenant_id dahil mi?)
  • Authenticated user için cache bypass edilmiş olabilir
  • Cache TTL süresini kontrol et

📈 Beklenen Performans İyileştirmesi

Optimizasyon Mevcut Hedef Kazanç
N+1 Query (Currency) 1440 x 2.17ms = 3,124ms 1 query x 2ms = 2ms ~3 saniye
Settings Cache 687 x 5.79ms = 3,978ms 1 query = 6ms ~4 saniye
JSON Query Optimize ~500ms per query ~5ms per query 100x
Database Index 11,075ms ~50ms 221x
TOPLAM (Homepage) 2,440ms ~200ms 12x HIZLANMA

🎯 Acil Aksiyon Planı

Adım 1: Settings Cache (15 dakika - En Hızlı Kazanç)

  • app/helpers.php içinde setting() fonksiyonunu yukarıdaki gibi optimize et
  • php artisan cache:clear çalıştır
  • Test et: 687 query → 1 query + cache
  • Beklenen: ~4 saniye kazanç

Adım 2: Currency Eager Loading (30 dakika)

  • Homepage controller'da with('currency') ekle
  • Ürün listesi query'lerini kontrol et
  • Test et: 1440 query → 1 query
  • Beklenen: ~3 saniye kazanç

Adım 3: Virtual Column Ekle (45 dakika)

  • Migration oluştur (blogs, shop_products)
  • Generated column ekle (slug_tr, title_tr)
  • Index oluştur
  • Query'leri güncelle (JSON_EXTRACT → slug_tr)
  • Beklenen: 500ms+ per query kazanç

Adım 4: Composite Index Ekle (20 dakika)

  • Migration oluştur
  • ALGORITHM=INPLACE, LOCK=NONE kullan
  • Test et (EXPLAIN query)
  • Beklenen: 11s → 50ms
💡 Tahmini Toplam Süre: 2 saat. İlk 2 adım uygulanırsa bile 7 saniye kazanç sağlanacaktır!