PostgreSQL için Azure Cosmos DB'de tablo birlikte bulundurma

ŞUNLAR IÇIN GEÇERLIDIR: PostgreSQL için Azure Cosmos DB (PostgreSQL'e citus veritabanı uzantısıyla desteklenir)

Birlikte bulundurma, ilgili bilgileri aynı düğümlerde birlikte depolama anlamına gelir. Gerekli tüm veriler herhangi bir ağ trafiği olmadan kullanılabilir olduğunda sorgular hızla gerçekleştirilir. Farklı düğümlerde ilgili verilerin birlikte bulunması, sorguların her düğümde paralel olarak verimli bir şekilde çalışmasını sağlar.

Karma dağıtılmış tablolar için veri birlikte bulundurma

PostgreSQL için Azure Cosmos DB'de, dağıtım sütunundaki değerin karması parçanın karma aralığı içindeyse bir satır parçada depolanır. Aynı karma aralığına sahip parçalar her zaman aynı düğüme yerleştirilir. Eşit dağıtım sütunu değerlerine sahip satırlar her zaman tablolar arasında aynı düğümdedir. Karma dağıtılmış tablolar kavramı satır tabanlı parçalama olarak da bilinir. Şema tabanlı parçalamada, dağıtılmış şema içindeki tablolar her zaman birlikte bulunur.

Diagram shows shards with the same hash range placed on the same node for events shards and page shards.

Birlikte bulundurmanın pratik bir örneği

Çok kiracılı bir web analizi SaaS'sinin parçası olabilecek aşağıdaki tabloları göz önünde bulundurun:

CREATE TABLE event (
  tenant_id int,
  event_id bigint,
  page_id int,
  payload jsonb,
  primary key (tenant_id, event_id)
);

CREATE TABLE page (
  tenant_id int,
  page_id int,
  path text,
  primary key (tenant_id, page_id)
);

Şimdi müşteriye yönelik bir pano tarafından verilebilen sorguları yanıtlamak istiyoruz. Örnek bir sorgu: "Kiracı altıda '/blog' ile başlayan tüm sayfalar için geçen haftaki ziyaret sayısını döndür."

Verilerimiz tek bir PostgreSQL sunucusundaysa SQL tarafından sunulan zengin ilişkisel işlemleri kullanarak sorgumuzu kolayca ifade edebiliriz:

SELECT page_id, count(event_id)
FROM
  page
LEFT JOIN  (
  SELECT * FROM event
  WHERE (payload->>'time')::timestamptz >= now() - interval '1 week'
) recent
USING (tenant_id, page_id)
WHERE tenant_id = 6 AND path LIKE '/blog%'
GROUP BY page_id;

Bu sorgunun çalışma kümesi belleğe sığdıkça, tek sunuculu bir tablo uygun bir çözümdür. PostgreSQL için Azure Cosmos DB ile veri modelini ölçeklendirme fırsatlarını ele alalım.

Tabloları kimliklerine göre dağıtma

Kiracı sayısı ve her kiracı için depolanan veriler arttıkça tek sunuculu sorgular yavaşlamaya başlar. Çalışma kümesi belleğe uyum sağlamayı durdurur ve CPU bir performans sorununa dönüşür.

Bu durumda, PostgreSQL için Azure Cosmos DB'yi kullanarak verileri birçok düğüm arasında parçalayabiliriz. Parçaya karar vermek için yapmamız gereken ilk ve en önemli seçim dağıtım sütunudur. Olay tablosu ve page_idpage tablo için kullanmak event_id üzere basit bir seçimle başlayalım:

-- naively use event_id and page_id as distribution columns

SELECT create_distributed_table('event', 'event_id');
SELECT create_distributed_table('page', 'page_id');

Veriler farklı çalışanlara dağıtıldığında, tek bir PostgreSQL düğümünde yaptığımız gibi birleştirme gerçekleştiremiyoruz. Bunun yerine iki sorgu yayınlamamız gerekir:

-- (Q1) get the relevant page_ids
SELECT page_id FROM page WHERE path LIKE '/blog%' AND tenant_id = 6;

-- (Q2) get the counts
SELECT page_id, count(*) AS count
FROM event
WHERE page_id IN (/*…page IDs from first query…*/)
  AND tenant_id = 6
  AND (payload->>'time')::date >= now() - interval '1 week'
GROUP BY page_id ORDER BY count DESC LIMIT 10;

Daha sonra, iki adımda elde edilen sonuçların uygulama tarafından birleştirilmesi gerekir.

Sorguları çalıştırmak, düğümlere dağılmış parçalardaki verilere başvurmalıdır.

Diagram shows an inefficient approach that uses multiple queries against the event and page tables in two nodes.

Bu durumda, veri dağıtımı önemli dezavantajlar oluşturur:

  • Her bir parçanın sorgulanması ve birden çok sorgu çalıştırılmasının yükü.
  • Q1'in istemciye birçok satır döndürmesi yükü.
  • Q2 büyük hale gelir.
  • Birden çok adımda sorgu yazma gereksinimi, uygulamada değişiklik yapılmasını gerektirir.

Veriler dağıtıldığından sorgular paralel hale getirilebilir. Bu, yalnızca sorgunun yaptığı iş miktarının birçok parçanın sorgulanmasından önemli ölçüde fazla olması durumunda faydalıdır.

Tabloları kiracıya göre dağıtma

PostgreSQL için Azure Cosmos DB'de, aynı dağıtım sütunu değerine sahip satırların aynı düğümde olması garanti edilir. Baştan başlayarak tablolarımızı tenant_id dağıtım sütunu olarak oluşturabiliriz.

-- co-locate tables by using a common distribution column
SELECT create_distributed_table('event', 'tenant_id');
SELECT create_distributed_table('page', 'tenant_id', colocate_with => 'event');

Artık PostgreSQL için Azure Cosmos DB, özgün tek sunuculu sorguyu değiştirmeden yanıtlayabilir (Q1):

SELECT page_id, count(event_id)
FROM
  page
LEFT JOIN  (
  SELECT * FROM event
  WHERE (payload->>'time')::timestamptz >= now() - interval '1 week'
) recent
USING (tenant_id, page_id)
WHERE tenant_id = 6 AND path LIKE '/blog%'
GROUP BY page_id;

tenant_id filtreleme ve birleştirme nedeniyle PostgreSQL için Azure Cosmos DB, söz konusu kiracının verilerini içeren birlikte konumlandırılmış parça kümesi kullanılarak sorgunun tamamının yanıtlanabileceğini bilir. Tek bir PostgreSQL düğümü sorguyu tek bir adımda yanıtlayabilir.

Diagram shows a single query to one node, which is a more efficient approach.

Bazı durumlarda, sorguların ve tablo şemalarının kiracı kimliğini benzersiz kısıtlamalara ve birleştirme koşullarına dahil etmek için değiştirilmesi gerekir. Bu değişiklik genellikle basittir.

Sonraki adımlar