Geçtiğimiz günlerde, Telescope verilerini beklemeden temizlemek için geliştirdiğim küçük bir paket olan laravel-telescope-flusher‘dan bahsetmiştim. Bu paket, Packagist’te 1,000 yükleme sayısını geçti 🎉, bu nedenle orijinal gönderiyi gerçek verilerle desteklemek için oturdum ve bir milyon Telescope kaydı olan yeni bir MySQL 8.0 kurdum ve telescope:clear, telescope:prune ve telescope:flush komutlarını zamanladım. Spoiler: beklediğimden daha büyük bir fark var.
telescope:clear‘in yavaş olmasının hızlı özeti
telescope:clear‘in yavaş olmasının hızlı özetiİki şey bu durumu etkiliyor. Öncelikle döngü:
// vendor/laravel/telescope/src/Storage/DatabaseEntriesRepository.php
public function clear()
{
do {
$deleted = $this->table('telescope_entries')->take($this->chunkSize)->delete();
} while ($deleted !== 0);
// ...telescope_monitoring için de aynı
}
$chunkSize = 1000. Bir milyon satır = on saatlik DELETE ifadeleri, her biri tekrar yazma günlüğüne, geri alma günlüğüne ve çift yazma tamponuna yazıyor.
İkinci olarak (orijinal yazımda gözden kaçırdığım bir nokta): telescope_entries_tags üzerinde entry_uuid üzerine bir yabancı anahtar var ve ON DELETE CASCADE olduğu için, her ana silme işlemi bir etiket tablosundaki cascade silme işlemini tetikliyor. Bir milyon kayıt için bu 3 milyon fazla silme işlemi demek.
telescope:prune --hours=24 ise aynı döngüyü WHERE filtresiyle kullanıyor. Aynı sorun burada da var.
Ve DELETE diski geri vermez
Ve
DELETE diski geri vermezBunu ilk geçişte fark etmemiştim. telescope:clear tamamlandığında, information_schema.tables tablonun veri uzunluğunu sıfır gibi raporluyor. İşlemin bittiği düşünülüyor. Ancak dosyaya baktığınızda:
ls -lah /var/lib/mysql/telescope_test/telescope_*.ibd
.ibd dosyaları hâlâ büyük. InnoDB DELETE işleminden sonra alanı OS’ye geri vermez – yalnızca gelecekteki eklemeler için sayfaları yeniden kullanılabilir olarak işaretler. Dosyayı gerçekten küçültmek için OPTIMIZE TABLE (tablayı yeniden inşa eder) veya ALTER TABLE ... ENGINE=InnoDB kullanmanız gerekir.
telescope:clear bunları yapmaz. Bu nedenle, geliştirme diskiniz dolu kalır.
Performans testi
Performans testi
Kurulum: Docker’daki MySQL 8.0, varsayılan yapılandırma. Veriler: 1,000,000 telescope_entries (~2 KB JSON içeriği), 3,000,000 satır telescope_entries_tags üzerinde, gerçek bir yabancı anahtar ile cascade. Performans test script’i bench/‘da bulunabilir – kendiniz çalıştırabilirsiniz.
Her iki çalıştırma için başlangıç durumu aynıydı:
telescope_entries rows=1000000 logical=2.33 GB .ibd=2.4 GB
telescope_entries_tags rows=3000000 logical=672 MB .ibd=688 MB
telescope_monitoring rows=50 logical=16 KB .ibd=112 KB
TOTAL rows=4000050 logical=2.99 GB .ibd=3.1 GB
Sonuçlar:
| Adım | telescope:clear | telescope:flush |
|---|---|---|
| Geçen zaman | 9025 s (≈150 dakika) | 1.21 s |
| Sonrasında mantıksal boyut | 128 KB | 128 KB |
.ibd dosyaları diskte sonrasında | 3.1 GB (değişmeden) | 428 KB |
Bu, yaklaşık 7400× daha hızlı ve gerçekten elde ettiğiniz 3 GB alan demek. Her iki çalışmada da info_schema aynı boyutu bildiriyor, bu arada. Bu tuzak. Sadece ls -lah komutunu .ibd dosyaları üzerinde çalıştırmak gerçeği söyler.
prune --hours=0 ise clear ile hemen hemen aynı sürede çalışıyor (aynı döngü, aynı FK cascade), dolayısıyla tamamlanmasını sağlamadım. Sonucun şekli aynı.
flush‘in farklı yaptığı şey
flush‘in farklı yaptığı şeyPaketin tüm komutu bu kadar kısa ki, yapıştırabilirsiniz:
DB::getSchemaBuilder()->withoutForeignKeyConstraints(function () {
DB::table('telescope_entries')->truncate();
DB::table('telescope_entries_tags')->truncate();
DB::table('telescope_monitoring')->truncate();
});
if (DB::getDriverName() === 'mysql') {
DB::statement('OPTIMIZE TABLE telescope_entries');
}
Burası sihirli değil. TRUNCATE bir meta veri işlemi. InnoDB üzerinde anında işleniyor, her satır için ekstra iş yapmıyor, cascade de yok. withoutForeignKeyConstraints sarmalayıcı gerekli çünkü TRUNCATE cascade’leri tetiklemez, bu nedenle FK kontrolünü kendiniz kapatmalısınız. OPTIMIZE TABLE ise tablonun varlığını yeniden inşa eder ve taze, küçük bir .ibd dosyası üretir.
Ek bir App::isLocal() koruyucusu var – TRUNCATE geri dönüşümsüzdür, bunu yalnızca geliştirme sırasında yapmak istersiniz.
Ne zaman neyi kullanmalısınız
Ne zaman neyi kullanmalısınız
| Yaklaşım | Kullanım durumu |
|---|---|
telescope:clear | Varsayılan yerel temizlik. Çalışır, büyük tablolarda yavaş, diskte alan bırakır. |
telescope:prune --hours=24 | Zamanlanmış saklama – son N saati koru. Aynı disk problemi, ancak tablo boyutu zamanla sınırlı kalır. |
telescope:flush (paket) | Geliştirme nükleasyonu. Telescope çok büyüyüp gitmesini istediğinizde saniyeler içinde silin. |
Ben üretimde Telescope kullanmıyorum, siz de kullanmamalısınız, bu nedenle yerel koruyucu bir kısıtlama değildir.
TL;DR
TL;DR
telescope:clear= parça parçaDELETE LIMIT 1000+ etiketler üzerinde kaskad FK. 1M kayıtla: 2.5 saat.- InnoDB DELETE işleminden sonra
.ibddosyasını küçültmez.info_schemayalan söyler,ls -lahgerçekleri gösterir. telescope:flush=TRUNCATE+OPTIMIZE TABLE. 1.21 s aynı verilerle, diskte 3 GB → 428 KB.- Eğer
info_schematablonun boş olduğunu söylüyorsa amadftam tersini belirtiyorsa, bu InnoDB sayfalarıdır, hayal gücünüz değildir.
Kaynaklar
Kaynaklar
Yazarın Notu
Yazarın Notu
Beni takip ettiğiniz için teşekkürler!
Beni dev.to, linkedin üzerinden bulabilirsiniz veya yaptıklarımı github‘dan kontrol edebilirsiniz.
Gerçek dünya Laravel notları.
Kaynak: Orijinal Makale


