Kullanıcıların gerçek zamanlı veri analitiğine erişmesini sağlamak, birçok modern uygulamanın temel yeteneğidir. En sevdiğiniz SaaS platformunu kullandığınızı hayal edin; muhtemelen gerçek zamanlı verileri ve geçmiş bilgileri sunan sezgisel bir kontrol paneli vardır. Muhtemelen platformla etkileşime geçerek özelleştirilmiş raporlar oluşturabilir, ayrıntılı ölçümleri keşfedebilir ve haftalar veya aylara yayılan eğilimleri görselleştirebilirsiniz.
Bir kullanıcı olarak bu platformun yavaş olmasını kesinlikle istemezsiniz. Bu, bu ürünleri destekleyen veritabanının, karmaşık analitik sorgular da dahil olmak üzere büyük hacimli veriler üzerinde sorguları çalıştırmada hızlı olması gerektiği anlamına gelir.
Sırasında
Materyalleştirme tekniğine dayalı olarak, PostgreSQL materyalleştirilmiş görünümler ön hesaplamada genellikle sorguları çalıştırır ve sonuçları bir tablo olarak saklar. Görünüme her başvurulduğunda temel sorguyu çalıştıran standart PostgreSQL görünümlerinin aksine, materyalleştirilmiş görünümler kaynak sorgunun sonucunu veritabanında sürdürür. Bunun en güzel yanı, veritabanınızın her çalıştırdığınızda sorguyu yürütmek zorunda olmamasıdır: sonuçlara zaten diskte erişilebilir; sorgunuzun yanıtını çok daha hızlı alırsınız.
Bu, yoğun kaynak gerektiren sorgulara yönelik sorgu yanıtlarını optimize etmenin harika bir yoludur. Örneğin, büyük hacimli verilerin işlenmesini, toplamaları veya birden çok birleştirmeyi içerebilecek sorgular.
Gerçekleştirilmiş görünümlerle çalışmak son derece basittir. Bir görünüm oluşturmak için CREATE MATERIALIZED VIEW
ifadesini ve tercih ettiğiniz sorguyu kullanırsınız.
Gerçekleştirilmiş görünümünüz oluşturulduktan sonra onu normal bir PostgreSQL tablosu olarak sorgulayabilirsiniz:
CREATE MATERIALIZED VIEW customer_orders AS SELECT customer_id, COUNT(*) as total_orders FROM orders GROUP BY customer_id;
-- Query the materialized view SELECT * FROM customer_orders;
Bu materyalleştirilmiş görünüm, siz onu yenileyene kadar hızla eskiyecektir: temel tabloya yeni veriler ekleseniz (veya verileri güncelliyor ya da silseniz) bile, materyalleştirilmiş görünüm bu değişiklikleri otomatik olarak içermez; oluşturulduğu andaki anlık görüntüdür. Gerçekleştirilmiş görünümü güncellemek için, REFRESH MATERIALIZED VIEW
çalıştırmanız gerekir.
REFRESH MATERIALIZED VIEW customer_orders;
Bu son nokta (yenilemelerin nasıl ele alındığı), bir sonraki bölümde tartışacağımız gibi, somutlaştırılmış görüşlerin Aşil topuğudur.
Söylediğimiz gibi, PostgreSQL materyalleştirilmiş görünümleri, özellikle bu sorgular büyük miktarda veriyi kapsıyorsa, sık çalıştırılan sorguları hızlandırmak için güçlü bir araçtır. Ancak somutlaştırılmış görüşlerin ideal olmayan bir yönü vardır: Gerçekleştirilmiş görüşlerinizi güncel tutmak için yenilenmeleri gerekir.
Bu tek sorun üç önemli sınırlama yaratır:
Gerçekleştirilmiş bir görünümü yenilerken sorgu, veri kümesinin tamamı üzerinde yeniden hesaplanır. Özet olarak, bir yenileme çalıştırdığınızda, eski somutlaştırılmış veriler silinir ve ardından yeni, yeniden somutlaştırılmış verilerle değiştirilir. Uygulama
Daha önce de belirtildiği gibi, gerçekleştirilmiş görünümler en son verileri otomatik olarak içermeyecektir. REFRESH MATERIALIZED VIEW
çalıştırılarak yenilenmeleri gerekir. Yenilemeleri üretim ortamında manuel olarak çalıştırmak mümkün değildir: çok daha gerçekçi bir kurulum, yenilemeyi otomatikleştirmek olacaktır.
Ne yazık ki, materyalleştirilmiş görünümler yerleşik otomatik yenileme işlevine sahip değildir; dolayısıyla PostgreSQL'de materyalleştirilmiş görünümler için otomatik yenileme zamanlaması oluşturmak bir çeşit zamanlayıcı gerektirir. Bu, veritabanı içinde bir uzantıyla veya veritabanı dışında cron gibi bir zamanlayıcıyla yapılabilir. Ancak yenilemelerin pahalı olması ve uzun zaman alması nedeniyle yönetilir. Görünümü yeterince hızlı yenileyemediğiniz bir durumla karşılaşmanız çok kolaydır.
Gerçekleştirilmiş görünümlerin statik doğasının bir sonucu, sorgulandığında, son yenilemeden bu yana eklenen veya değiştirilen verileri (bu yenileme bir zamanlamaya göre gerçekleşse bile) kaçıracaklarıdır. Planlama pencereniz bir saate ayarlanmışsa, toplamınız en fazla bir saat artı güncellemenin güncel olmadığı gerçek süreden oluşacaktır. Ancak günümüzde pek çok uygulama, sürekli bir veri akışının alınmasını gerektirir ve çoğu zaman bu uygulamaların, görünümü sorgularken doğru bilgileri aldıklarından emin olmak için kullanıcılarına güncel sonuçlar sunması gerekir.
Gerçekleşmiş görüşlerin bu sınırlamalar tarafından kısıtlanması üzücüdür. Sık sık yeni verilerin geldiği, canlı bir veri kümesinden bir SaaS platformu oluşturuyorsanız, somutlaştırılmış görünümlerin tamamen silinmesi mi gerekir?
Cevap hayır. Timescale'de, somutlaştırılmış görünümleri modern uygulamalara daha uygun hale getirmek için etkili bir şekilde geliştiren bir çözüm geliştirdik: sürekli toplamalar.
Gerçekleştirilmiş görünümlerin yalnızca statik anlık görüntüler olmadığı, aynı zamanda dinamik ve verimli bir şekilde güncellendiği bir dünya hayal edin. Başka hiçbir şey hakkında endişelenmeden aradığınız sorgu performansı iyileştirmesine erişebilirsiniz. Görünüşe göre Timescale'in sürekli toplamlarını tanımladık.
Sürekli toplamalar (TimescaleDB uzantısı aracılığıyla tüm PostgreSQL veritabanlarında ve Timescale platformu aracılığıyla AWS'de mevcuttur), verimli, otomatik yenileme özellikleri ve gerçek zamanlı bir öğeyle geliştirilmiş, somutlaştırılmış görünümlerdir. Neredeyse tam olarak gerçekleştirilmiş görünümlere benziyorlar ve hissediyorlar ancak aşağıdakilere izin veriyorlar:
Sürekli bir toplama oluşturmak, somutlaştırılmış bir görünüm oluşturmaya çok benzer (ve aynı zamanda normal bir PostgreSQL tablosu olarak da sorgulanabilir):
CREATE MATERIALIZED VIEW hourly_sales WITH (timescaledb.continuous) AS SELECT time_bucket(INTERVAL '1 hour', sale_time) as hour, product_id, SUM(units_sold) as total_units_sold FROM sales_data GROUP BY hour, product_id;
Ancak hayata geçirilmiş görünümlerden farklı olarak yenileme politikası oluşturmak basittir. Veritabanı içerisinde yenileme aralığını kolaylıkla tanımlayarak sürekli toplamalarınızın otomatik ve periyodik olarak güncellenmesini sağlayabilirsiniz.
Aşağıdaki örnek, sürekli toplamı her 30 dakikada bir güncellemek için bir yenileme ilkesi oluşturur. end_offset
parametresi, yenilenecek verilerin zaman aralığını tanımlar ve schedule_interval
, sürekli toplamanın ne sıklıkta yenileneceğini ayarlar:
-- Setting up a refresh policy SELECT add_continuous_aggregate_policy('hourly_sales', end_offset => INTERVAL '1 minute', schedule_interval => INTERVAL '30 minutes');
Bu yenileme politikası devreye girdiğinde süreç, sade, somutlaştırılmış bir görünüm kullanmaya kıyasla çok daha verimli olacaktır. REFRESH MATERIALIZED VIEW
çalıştırmanın aksine, sürekli bir toplama yenilendiğinde, Timescale tüm eski verileri bırakmaz ve toplamayı buna göre yeniden hesaplamaz: motor, sorguyu yalnızca en son yenileme periyoduna (örneğin, 30 dakika) göre çalıştırır ve ekler. gerçekleşmesine.
Benzer şekilde, bu son dönemde gerçekleştirilen UPDATE
ve DELETE
tanımlanır ve onları içeren yığın (bölüm) yeniden hesaplanır. (Zaman Ölçeği'ne dayalı sürekli toplamalar
Ancak sürekli toplamalar, güncel sonuçları görüntüleme sorununu nasıl çözer? Son yenilemeden sonra yeni veriler eklenirse ve sürekli toplamı sorgularsam ne olur?
Bu işlevselliğe izin vermek için şunu ekledik:
Bu işlevsellik, somutlaştırılmış görünümleri statik anlık görüntülerden dinamik varlıklara dönüştürerek, depolanan verilerin yalnızca tarihsel bir yansıma değil, aynı zamanda temeldeki veri kümelerinin güncel bir temsili olmasını sağlar.
Bunların hepsi kulağa hoş gelse bile, (umarız) bir örnekle çok daha iyi bir araya gelecektir.
Ulaşım acenteleri ve araç paylaşımı şirketleri tarafından kullanılan bir platform hayal edin. Bu platform, önemli metriklerin en son durumunu içeren bir tablo ve metriklerin o gün ve hafta bağlamında nasıl performans gösterdiğini gösteren iki görselleştirme de dahil olmak üzere, şirketlerin filolarının durumuna ilişkin genel bir bakış görebilecekleri bir gösterge panosu içerir.
Bu uygulamaya güç sağlamak için öncelikle yolculuklarla ilgili verilerin sürekli olarak eklendiği bir hipertabloya sahip olmamız gerekir. Hipertablo şöyle görünebilir:
CREATE TABLE rides ( ride_id SERIAL PRIMARY KEY, vehicle_id INT, start_time TIMESTAMPTZ NOT NULL, end_time TIMESTAMPTZ NOT NULL, distance FLOAT NOT NULL, price_paid FLOAT NOT NULL ); SELECT create_hypertable('rides', 'start_time');
Hipertablolar çok hızlıdır ve ölçeklenebilirdir; bu tablo, milyarlarca satıra sahip olsa bile performansını koruyacaktır.
Canlı bir genel bakış sunarak tabloyu güçlendirmek için verileri 30 dakikaya bölmek üzere sürekli bir toplama kullanırız. Bu, sürecin hızlı ve duyarlı olmasını sağlayacaktır:
-- Create continuous aggregate for live overview CREATE MATERIALIZED VIEW live_dashboard WITH (timescaledb.continuous, timescaledb.materialized_only=false)) AS SELECT vehicle_id, time_bucket(INTERVAL '30 minute', start_time) as minute, COUNT(ride_id) as number_of_rides, AVG(price_paid) as average_price FROM rides GROUP BY vehicle_id, minute;
-- Set up a refresh policy SELECT add_continuous_aggregate_policy('live_dashboard', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL '15 minute');
Önceki kodda, end_offset
parametresi, toplamanın hemen en son verileri yenilemeye çalışmamasını sağlar ve veri varışındaki herhangi bir gecikmeyi telafi etmek için bir miktar arabellek süresi sağlar. end_offset
10 minutes
ayarlanması, toplamanın en az 10 dakikalık verileri yenileyeceği ve veri akışındaki küçük gecikmeler nedeniyle güncellemeleri kaçırmamasını sağlayacağı anlamına gelir. Gerçek dünyadaki bir kullanım durumunda, bu değeri veri hattınızda gözlemlediğiniz ortalama gecikmeye göre ayarlarsınız.
Günlük görünümü sunan görselleştirmeyi güçlendirmek için ikinci bir sürekli küme oluşturacağız. Bu grafikte veriler saat bazında görüntülendiğinden, öncekinde olduğu gibi dakika başına ayrıntı düzeyine ihtiyacımız yok:
-- Create continuous aggregate for daily overview CREATE MATERIALIZED VIEW hourly_metrics WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT vehicle_id, time_bucket(INTERVAL '1 hour', start_time) as hour, COUNT(ride_id) as number_of_rides, SUM(price_paid) as total_revenue FROM rides WHERE start_time > NOW() - INTERVAL '1 day' GROUP BY vehicle_id, hour;
-- Define refresh policy SELECT add_continuous_aggregate_policy('hourly_metrics', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL `1 hour`);
Son olarak, haftalık görünümü sunan grafiği güçlendirmek için, bu sefer verileri gün bazında toplayan bir sürekli toplama daha oluşturacağız:
-- Create continuous aggregate to power chart with weekly overview CREATE MATERIALIZED VIEW daily_metrics WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT vehicle_id, time_bucket(INTERVAL '1 day', start_time) as day, COUNT(ride_id) as number_of_rides, SUM(price_paid) as total_revenue FROM rides WHERE start_time > NOW() - INTERVAL '1 week' GROUP BY vehicle_id, day;
-- Define refresh policy SELECT add_continuous_aggregate_policy('daily_metrics', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL '1 day);
PS Sürekli agregaları tanımlama deneyimini daha da verimli hale getirmek için,
PostgreSQL başlangıçta büyük canlı veri kümelerini işlemesi gereken uygulamalar için tasarlanmasa bile tahmin edin ne oldu; bu tür iş yükleri artık her yerde. Ancak PostgreSQL bu göreve yardımcı olacak özelliklerle birlikte gelir. Gerçekleştirilmiş görünümler, sorgu sonuçlarının önceden hesaplanmasına ve hızlı erişim için diskte saklanmasına olanak tanıdığından en güçlü görünümler arasındadır.
Ancak somutlaştırılmış görüşlerin üç önemli sınırlaması vardır. İlk olarak, yenilemeleri tetiklemek hesaplama açısından oldukça verimsizdir. İkincisi, bu otomatik yenilemeleri ayarlamak bile sorunsuz bir süreç değildir. Üçüncüsü, gerçekleşen görünümler, son yenilemeden bu yana eklenen veya değiştirilen verileri hariç tuttuklarından güncel sonuçları göstermez.
Bu sınırlamalar, somutlaştırılmış görünümleri birçok modern uygulama için pratik olmayan bir çözüm haline getirmektedir. Bunu çözmek için sürekli agregalar oluşturduk. Bunlar, yenilemelerin otomatik olarak gerçekleşmesi için kolayca bir yenileme politikası tanımlayabileceğiniz PostgreSQL gerçekleştirilmiş görünümlerdir. Bu yenilemeler de artımlıdır ve bu nedenle çok daha verimlidir. Son olarak, sürekli toplamalar, son yenilemeden bu yana eklenen ve değiştirilen ham verilerle hayata geçirilen verileri birleştirmenize olanak tanıyarak yalnızca güncel sonuçları almanızı sağlar.
Donanımınızda PostgreSQL çalıştırıyorsanız sürekli toplamalara şu adresten erişebilirsiniz:
Carlota Soto ve Mat Arye tarafından yazılmıştır.