SQL (ANSI)ProgramlamaKıdemli Veritabanı Mühendisi

Zamansal örtüşme yoğunluğunun analizi gerektiren senaryolarda, kaynağın kullanımının mutlak zirveye ulaştığı kesin anları, yalnızca **ANSI SQL** küme tabanlı mantık kullanarak nasıl hesaplayabilirsiniz?

Hintsage yapay zeka asistanı ile mülakatları geçin

Sorunun Yanıtı

Sorunun Tarihi

Bu zorluk, özellikle otel rezervasyon platformları, bulut altyapısı otomatik ölçeklendirme ve tıbbi tesis planlama gibi sistemlerde kapasite planlaması ve kaynak tahsisi alanlarından kaynaklanmaktadır. İlk çözümler, zaman çizelgelerinde yinelemekte ciddi performans kayıplarıyla karşılaşan imleç tabanlı yineleme veya harici uygulama mantığına dayanıyordu. ANSI SQL:2003 pencere fonksiyonlarının ortaya çıkması, veri tabanlarının karmaşık aralık aritmetiğini verimli bir şekilde motor içinde ele almasına olanak tanıyarak zamansal analize tamamen ilişkisel yaklaşımlar geliştirdi.

Problem

start_time ve end_time zaman damgaları ile kaynak rezervasyonları tablosu verildiğinde, tek bir anda aktif olan maksimum eş zamanlı rezervasyon sayısını belirlemek ve bu zirve anlarının hangi özgül zaman dilimlerinde gerçekleştiğini belirlemek amacıyla çalışılması gerekmektedir. Karmaşıklık, çünkü standart toplama zaman verilerini çökertebilirken, basit birleşimler zaman dilimleri üst üste bindiğinde kartesian patlamasına neden olmaktadır. Sağlam bir çözüm, aralık başlangıcını ve sonunu ayrık olaylar olarak ele almalı ve her geçiş noktasında aktif kaynakların koşullu toplamını hesaplamalıdır.

Çözüm

Kanonik yaklaşım, aralıkları ayrık olaylara dönüştürmek için UNION ALL kullanarak başlangıçları (+1 ağırlık) ve sonları (-1 ağırlık) ayırır, ardından eş zamanlılığı takip etmek için SUM() OVER (ORDER BY timestamp) yoluyla kümülatif toplam uygulamaktadır. Eş zamanlı başlangıçları/sonları kesin bir şekilde işlemek için, aynı zaman damgasındaki son olayları başlangıç olaylarından önce işlemek gerekmektedir (ikincil sıralama anahtarı kullanarak). Son olarak, maksimum eş zamanlılık değerini süzmek için bunu bir CTE içinde sarın.

WITH events AS ( SELECT start_time AS ts, 1 AS delta, 0 AS is_end FROM reservations UNION ALL SELECT end_time AS ts, -1 AS delta, 1 AS is_end FROM reservations ), concurrency AS ( SELECT ts, SUM(delta) OVER (ORDER BY ts, is_end, delta ROWS UNBOUNDED PRECEDING) AS concurrent_count FROM events ) SELECT MAX(concurrent_count) AS peak_concurrency FROM concurrency;

Zirve kullanımının özel zaman dilimlerini bulmak için, maksimumla eşleşen ardışık zaman damgaları arasındaki dönemleri belirlemek için tekrar birleştirmeniz gerekecektir.

Hayattan Bir Durum

Bir SaaS platformu, jobs tablosunda started_at ve completed_at zaman damgalarıyla milyonlarca video kodlama işini izliyordu. Operasyon ekibi, GPU kullanımının %100'e ulaştığı tam dönemleri belirlemek için kuyruk planlamasını optimize etmek istedi.

Düşünülen bir yaklaşım, bir imleç kullanarak kronolojik olarak yinelemek, başlatmalarda bir sayacı artırmak ve bitişlerde azaltmaktı. Geliştiriciler için zor olmayarak, bu yöntem sırayla satırları işleyip, üretim verileri üzerinde 45 dakikadan fazla zaman alırken tablolara kilitlenmeye neden oldu. Ayrıca, okuma tutarlılığını sağlamak için karmaşık işlem yönetimi gerektirdi.

Diğer bir alternatif, her dakika için bir satır oluşturarak bir zaman serisi tablosu oluşturmak ve bunu aralıklarla birleştirmek (BETWEEN yüklemleri kullanarak) oldu. Bu doğru sonuçlar üretiyordu ama bir yıl boyunca dakika düzeyinde hassasiyet sağlamak için milyarlarca satıra ihtiyaç duyuyor, geçici depolama alanını terabaytlarca tüketiyor ve alt dakika zirve dalgalanmalarını yakalamıyordu.

Ekip, olay tabanlı UNION ALL yaklaşımını ve ANSI SQL pencere fonksiyonlarını seçti. Başlangıçları ve bitişleri +1/-1 olayları olarak ele alarak, sorgu zaman damgası sütunları üzerindeki standart B-ağaç dizinleri kullanılarak 12 saniyede çalıştırıldı. Bu yöntem, işler bitmeden diğerlerinin başladığı kenar durumlarını doğru bir şekilde ele aldı.

Analiz, zirve eş zamanlılığının, 02:00 ile 02:07 UTC arasında gece toplu işleme sırasında gerçekleştiğini ve 847 eşzamanlı iş ile ulaşıldığını ortaya koydu. Bu pencere için dinamik kuyruk sınırlaması uygulayarak, zincirleme arızaların önüne geçtiler ve altyapı aşırı tahsisatını %30 oranında azalttılar.

Adayların Sıklıkla Atlattığı Unsurlar

Sıfır süreli aralıklarla (start_time = end_time) nasıl başa çıkarsınız ve eş zamanlılık sayısını yanlış bir şekilde artırmaktan kaçınırsınız?

Sıfır süreli aralıklar, eş zamanlı yükü artırmaması gereken anlık olayları temsil eder. Eğer standart aralıklar olarak ele alınırsa, kendi bitiş olayları sırasında aktif olarak sayılabilirler. Çözüm, sıkı bir sıralama anahtarının atanmasını gerektirir: zaman damgaları çakıştığında bitiş olaylarını (-1) öncelikli olarak işleyin, başlangıç olaylarından (+1) önce ve iş mantığına bağlı olarak sıfır süreli aralıkları olay akışından tamamen hariç tutun ya da onlara 0 delta atayın. ANSI SQL'de, bu bir ayrımcı sütun ekleyerek uygulanır: ORDER BY ts, is_end ASC, delta ASC, sonlandırmaların sayımı azaltmadan yeni tahsisatların aynı zaman damgasında artırılmasını sağlayarak.

Başlangıç ve bitiş olaylarını birleştirirken UNION yerine UNION ALL kullanmadığınızda neden olay tabanlı yaklaşımın yanlış sonuçlar döndürme olasılığı vardır?

UNION, otomatik olarak DISTINCT işlemi yapar ve yinelenen zaman damgalarını çökertebilir. Eğer iki rezervasyon tam olarak 2023-10-01 10:00:00'da başlıyorsa, UNION bunu tek bir satıra indirgediği için kümülatif toplam bir +1 artışını kaçırır. Bu, eş zamanlılığı yanlış saymaya yol açar. UNION ALL, her bireysel aralık sınırını ayrı bir olay olarak korur, bu matematiksel olarak gereklidir çünkü her rezervasyon toplam yüke bağımsız olarak katkı sağlar. Adaylar genellikle bu ayrımı gözden kaçırır, zaman damgalarının benzersiz olduğunu varsayarak toplamanın doğru yapılmasını sağlamak için çeşitliliğin gerekli olduğunu unutur.

Maksimum değeri (sadece maksimum değer değil) zirve eş zamanlılık zaman dilimlerini hesaplarken, birden fazla ardışık zaman dilimi aynı zirve değeri paylaştığında çıktıda boşluklardan nasıl kaçınırsınız?

Maksimum eş zamanlılık değerini belirledikten sonra, bunu elde edilen tüm zaman damgalarıyla birleştirmek, her nokta için ayrı satırlar anlamına gelir. Sürekli süre bloklarının yeniden yapılandırılabilmesi için, Gaps and Islands tekniğini uygulamalısınız: önceki satırın da zirve olup olmadığını kontrol etmek için LAG() kullanın ve sonraki satırın zirve olup olmadığını kontrol etmek için LEAD() kullanın. Yalnızca önceki değer değiştiğinde (ada başlangıçları) ya da sonraki değer değiştiğinde (ada sonları) satırları çıkartın. Ardından bunları ROW_NUMBER() kullanarak başlatma-bitirme çiftleri oluşturmak için eşleştirin. Adaylar genellikle ham zaman damgası listeleri çıkartır ya da sayım değerinde GROUP BY kullanır, bu ardışık zaman bilgilerini kaybeder ve ayrı zirve olaylarını tek bir sürekli zirve süresinden ayırt etmek için gerekli olan bilgiyi kaybeder.