PostgreSQL için Azure Cosmos DB'de tabloları dağıtma ve değiştirme

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

Tabloları dağıtma

Dağıtılmış tablo oluşturmak için önce tablo şemasını tanımlamanız gerekir. Bunu yapmak için CREATE TABLE deyimini kullanarak, normal PostgreSQL tablosuyla yaptığınız gibi bir tablo tanımlayabilirsiniz.

CREATE TABLE github_events
(
    event_id bigint,
    event_type text,
    event_public boolean,
    repo_id bigint,
    payload jsonb,
    repo jsonb,
    actor jsonb,
    org jsonb,
    created_at timestamp
);

Ardından, tablo dağıtım sütununu belirtmek ve çalışan parçalarını oluşturmak için create_distributed_table() işlevini kullanabilirsiniz.

SELECT create_distributed_table('github_events', 'repo_id');

İşlev çağrısı PostgreSQL için Azure Cosmos DB'ye github_events tablosunun repo_id sütununa dağıtılması gerektiğini bildirir (sütun değerini karmalayarak).

Varsayılan olarak toplam 32 parça oluşturur; burada her parça karma alanın bir bölümüne sahip olur ve varsayılan citus.shard_replication_factor yapılandırma değerine göre çoğaltılır. Çalışanda oluşturulan parça çoğaltmaları, koordinatördeki tabloyla aynı tablo şemasına, dizine ve kısıtlama tanımlarına sahiptir. Çoğaltmalar oluşturulduktan sonra işlev tüm dağıtılmış meta verileri koordinatöre kaydeder.

Oluşturulan her parçaya benzersiz bir parça kimliği atanır ve tüm çoğaltmaları aynı parça kimliğine sahiptir. Parçalar çalışan düğümünde 'tablename_shardid' adlı normal PostgreSQL tabloları olarak gösterilir; burada tablo adı dağıtılmış tablonun adı, parça kimliği ise atanan benzersiz kimliktir. Tek tek parçalar üzerinde komutları görüntülemek veya çalıştırmak için çalışan postgres örneklerine bağlanabilirsiniz.

Artık dağıtılmış tabloya veri eklemeye ve üzerinde sorgu çalıştırmaya hazırsınız. Bu bölümde kullanılan UDF hakkında daha fazla bilgiyi tablo ve parça DDL başvurusunda da öğrenebilirsiniz.

Başvuru Tabloları

Yukarıdaki yöntem tabloları birden çok yatay parçaya dağıtır. Başka bir olasılık da tabloları tek bir parçaya dağıtmak ve parçanın her çalışan düğümüne çoğaltılmasıdır. Bu şekilde dağıtılan tablolara başvuru tabloları adı verilir . Bunlar, bir kümedeki birden çok düğüm tarafından sık erişilmesi gereken verileri depolamak için kullanılır.

Başvuru tabloları için yaygın adaylar şunlardır:

  • Daha büyük dağıtılmış tablolara katılması gereken daha küçük tablolar.
  • Çok kiracılı uygulamalarda kiracı kimliği sütunu olmayan veya kiracıyla ilişkilendirilmeyen tablolar. (Veya geçiş sırasında, kiracıyla ilişkilendirilmiş bazı tablolar için bile.)
  • Birden çok sütunda benzersiz kısıtlamalara ihtiyaç duyan ve yeterince küçük olan tablolar.

Örneğin, çok kiracılı bir e-ticaret sitesinin mağazalarından herhangi birindeki işlemler için satış vergisini hesaplaması gerektiğini varsayalım. Vergi bilgileri herhangi bir kiracıya özgü değildir. Paylaşılan bir tabloya koymak mantıklıdır. ABD merkezli başvuru tablosu şöyle görünebilir:

-- a reference table

CREATE TABLE states (
  code char(2) PRIMARY KEY,
  full_name text NOT NULL,
  general_sales_tax numeric(4,3)
);

-- distribute it to all workers

SELECT create_reference_table('states');

Artık bir alışveriş sepeti için vergi hesaplama gibi sorgular ağ yükü olmadan tabloya states katılabilir ve daha iyi doğrulama için eyalet koduna yabancı anahtar ekleyebilir.

UDF, bir tabloyu tek bir çoğaltılmış parça olarak dağıtmanın create_reference_table yanı sıra, Bunu PostgreSQL için Azure Cosmos DB meta veri tablolarında bir başvuru tablosu olarak işaretler. PostgreSQL için Azure Cosmos DB, bu şekilde işaretlenmiş tablolarda yapılan değişiklikler için otomatik olarak iki aşamalı işlemeler (2PC) gerçekleştirir ve bu da güçlü tutarlılık garantileri sağlar.

Başvuru tablolarını kullanmanın başka bir örneği için çok kiracılı veritabanı öğreticisine bakın.

Koordinatör Verilerini Dağıtma

Mevcut bir PostgreSQL veritabanı bir kümenin koordinatör düğümüne dönüştürülürse, tablolarındaki veriler verimli bir şekilde ve uygulamada en az kesintiyle dağıtılabilir.

Daha create_distributed_table önce açıklanan işlev hem boş hem de boş olmayan tablolarda çalışır ve ikincisi için tablo satırlarını kümenin tamamında otomatik olarak dağıtır. "BİlDİrİm: Yerel tablodan veri kopyalama..." iletisinin varlığıyla verileri kopyalayıp kopyalamayacağını bilirsiniz. Mesela:

CREATE TABLE series AS SELECT i FROM generate_series(1,1000000) i;
SELECT create_distributed_table('series', 'i');
NOTICE:  Copying data from local table...
 create_distributed_table
 --------------------------

 (1 row)

Veriler geçirilirken tablodaki yazma işlemleri engellenir ve işlev işlendikten sonra bekleyen yazma işlemleri dağıtılmış sorgular olarak işlenir. (İşlev başarısız olursa sorgular yeniden yerel hale gelir.) Okuma işlemleri normal şekilde devam edebilir ve işlev işlendikten sonra dağıtılmış sorgulara dönüşür.

A'nın B'ye yabancı anahtarı olan A ve B tablolarını dağıtırken, önce anahtar hedef tablosunu B'ye dağıtın. Yanlış sırada yapmak hataya neden olur:

ERROR:  cannot create foreign key constraint
DETAIL:  Referenced table must be a distributed table or a reference table.

Doğru sırada dağıtmak mümkün değilse yabancı anahtarları bırakın, tabloları dağıtın ve yabancı anahtarları yeniden oluşturun.

Amazon RDS'den PostgreSQL için Azure Cosmos DB gibi bir dış veritabanından veri geçirirken, önce aracılığıyla create_distributed_tablePostgreSQL için Azure Cosmos DB dağıtılmış tablolarını oluşturun ve ardından verileri tabloya kopyalayın. Dağıtılmış tablolara kopyalama, koordinatör düğümünde yer dolmasını önler.

Tabloları birlikte konumlandırma

Birlikte bulundurma, ilgili bilgilerin aynı makinelere yerleştirilmesi anlamına gelir. Veri kümesinin tamamı için yatay ölçeklenebilirlikten yararlanırken verimli sorgular sağlar. Daha fazla bilgi için bkz . birlikte bulundurma.

Tablolar gruplar halinde birlikte bulunur. Tablonun birlikte bulundurma grubu atamasını el ile denetlemek için isteğe bağlı colocate_with parametresini create_distributed_tablekullanın. Tablonun birlikte bulundurmasını önemsemiyorsanız bu parametreyi atlayın. Varsayılan olarak değerini kullanır. Bu değer 'default', tabloyu aynı dağıtım sütunu türüne, parça sayısına ve çoğaltma faktörüne sahip olan diğer bir varsayılan birlikte bulundurma tablosuyla gruplandırır. Bu örtük birlikte bulundurmayı kesmek veya güncelleştirmek istiyorsanız kullanabilirsiniz update_distributed_table_colocation().

-- these tables are implicitly co-located by using the same
-- distribution column type and shard count with the default
-- co-location group

SELECT create_distributed_table('A', 'some_int_col');
SELECT create_distributed_table('B', 'other_int_col');

Yeni bir tablo örtük birlikte bulundurma grubundaki diğerleriyle ilişkili değilse belirtin colocated_with => 'none'.

-- not co-located with other tables

SELECT create_distributed_table('A', 'foo', colocate_with => 'none');

aynı gruptaki parçaların birlikte taşınması gerektiğinden, ilişkisiz tabloların kendi ortak konum gruplarına bölünmesi parça yeniden dengeleme performansını geliştirir.

Tablolar gerçekten ilişkili olduğunda (örneğin, birleştirilirken), bunları açıkça birlikte kullanmak mantıklı olabilir. Uygun birlikte bulundurmanın kazanımları, yeniden dengeleme ek yüklerinden daha önemlidir.

Birden çok tabloyu açıkça birlikte kullanmak için, birini dağıtın ve diğerlerini birlikte bulundurma grubuna yerleştirin. Örneğin:

-- distribute stores
SELECT create_distributed_table('stores', 'store_id');

-- add to the same group as stores
SELECT create_distributed_table('orders', 'store_id', colocate_with => 'stores');
SELECT create_distributed_table('products', 'store_id', colocate_with => 'stores');

Birlikte bulundurma grupları hakkındaki bilgiler pg_dist_colocation tablosunda depolanırken, pg_dist_partition hangi gruplara hangi tabloların atandığı ortaya çıkar.

Tabloları bırakma

Dağıtılmış tablolarınızı kaldırmak için standart PostgreSQL DROP TABLE komutunu kullanabilirsiniz. Normal tablolarda olduğu gibi DROP TABLE da hedef tablo için var olan tüm dizinleri, kuralları, tetikleyicileri ve kısıtlamaları kaldırır. Ayrıca, parçaları çalışan düğümlerine bırakır ve meta verilerini temizler.

DROP TABLE github_events;

Tabloları değiştirme

PostgreSQL için Azure Cosmos DB, birçok tür DDL deyimini otomatik olarak yayılım. Koordinatör düğümünde dağıtılmış bir tabloyu değiştirmek, çalışanlardaki parçaları da güncelleştirir. Diğer DDL deyimleri el ile yayılma gerektirir ve dağıtım sütununu değiştirebilenler gibi bazı diğer deyimler yasaktır. Otomatik yayma için uygun olmayan DDL'yi çalıştırmaya çalışmak bir hataya neden olur ve koordinatör düğümündeki tabloları değişmeden bırakır.

Burada, yayılan DDL deyimlerinin kategorilerinin başvurusu yer alır.

Sütunları Ekleme/Değiştirme

PostgreSQL için Azure Cosmos DB, ALTER TABLE komutlarının çoğunu otomatik olarak yayılır. Tek makineli PostgreSQL veritabanında olduğu gibi sütunları ekleme veya varsayılan değerlerini değiştirme işlemleri şöyle çalışır:

-- Adding a column

ALTER TABLE products ADD COLUMN description text;

-- Changing default value

ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;

Var olan bir sütunda yeniden adlandırma veya veri türünü değiştirme gibi önemli değişiklikler de uygundur. Ancak dağıtım sütununun veri türü değiştirilemez. Bu sütun, tablo verilerinin kümeye nasıl dağıtacağını belirler ve veri türünü değiştirmek için verilerin taşınması gerekir.

Bunu yapmak bir hataya neden olur:

-- assumining store_id is the distribution column
-- for products, and that it has type integer

ALTER TABLE products
ALTER COLUMN store_id TYPE text;

/*
ERROR:  XX000: cannot execute ALTER TABLE command involving partition column
LOCATION:  ErrorIfUnsupportedAlterTableStmt, multi_utility.c:2150
*/

Kısıtlamaları Ekleme/Kaldırma

PostgreSQL için Azure Cosmos DB'yi kullanmak, veritabanı kısıtlamaları da dahil olmak üzere ilişkisel bir veritabanının güvenliğinin keyfini çıkarmaya devam etmenizi sağlar (bkz. PostgreSQL belgeleri). Dağıtılmış sistemlerin doğası gereği PostgreSQL için Azure Cosmos DB, çalışan düğümleri arasında benzersizlik kısıtlamalarına veya bilgi tutarlılığına çapraz başvuruda bulunmayacak.

Birlikte bulunan dağıtılmış tablolar arasında yabancı anahtar ayarlamak için her zaman anahtara dağıtım sütununu ekleyin. Dağıtım sütunu dahil olmak üzere anahtar bileşiminin yapılması gerekebilir.

Yabancı anahtarlar şu durumlarda oluşturulabilir:

  • iki yerel (dağıtılmamış) tablo arasında,
  • iki başvuru tablosu arasında,
  • anahtar dağıtım sütununu içerdiğinde iki birlikte bulunan dağıtılmış tablo arasında veya
  • başvuru tablosuna başvuran dağıtılmış tablo olarak

Başvuru tablolarından dağıtılmış tablolara yabancı anahtarlar desteklenmez.

Not

Birincil anahtarlar ve benzersizlik kısıtlamaları dağıtım sütununu içermelidir. Bunları dağıtım dışı bir sütuna eklemek hata oluşturur

Bu örnekte, dağıtılmış tablolarda birincil ve yabancı anahtarların nasıl oluşturulacağı gösterilmektedir:

--
-- Adding a primary key
-- --------------------

-- We'll distribute these tables on the account_id. The ads and clicks
-- tables must use compound keys that include account_id.

ALTER TABLE accounts ADD PRIMARY KEY (id);
ALTER TABLE ads ADD PRIMARY KEY (account_id, id);
ALTER TABLE clicks ADD PRIMARY KEY (account_id, id);

-- Next distribute the tables

SELECT create_distributed_table('accounts', 'id');
SELECT create_distributed_table('ads',      'account_id');
SELECT create_distributed_table('clicks',   'account_id');

--
-- Adding foreign keys
-- -------------------

-- Note that this can happen before or after distribution, as long as
-- there exists a uniqueness constraint on the target column(s) which
-- can only be enforced before distribution.

ALTER TABLE ads ADD CONSTRAINT ads_account_fk
  FOREIGN KEY (account_id) REFERENCES accounts (id);
ALTER TABLE clicks ADD CONSTRAINT clicks_ad_fk
  FOREIGN KEY (account_id, ad_id) REFERENCES ads (account_id, id);

Benzer şekilde, dağıtım sütununu benzersizlik kısıtlamalarına dahil edin:

-- Suppose we want every ad to use a unique image. Notice we can
-- enforce it only per account when we distribute by account id.

ALTER TABLE ads ADD CONSTRAINT ads_unique_image
  UNIQUE (account_id, image_url);

Null olmayan kısıtlamalar, çalışanlar arasında arama gerektirmediğinden herhangi bir sütuna (dağıtım veya değil) uygulanabilir.

ALTER TABLE ads ALTER COLUMN image_url SET NOT NULL;

DEĞİl GEÇERSİ Kısıtlamaları Kullanma

Bazı durumlarda, mevcut uyumsuz satırların değişmeden kalmasına izin verirken yeni satırlar için kısıtlamaları zorunlu kılmak yararlı olabilir. PostgreSQL için Azure Cosmos DB, PostgreSQL'in "GEÇERSİz DEĞİl" kısıtlama belirlemesini kullanarak CHECK kısıtlamaları ve yabancı anahtarlar için bu özelliği destekler.

Örneğin, kullanıcı profillerini bir başvuru tablosunda depolayan bir uygulamayı düşünün.

-- we're using the "text" column type here, but a real application
-- might use "citext" which is available in a postgres contrib module

CREATE TABLE users ( email text PRIMARY KEY );
SELECT create_reference_table('users');

Zaman içinde birkaç adres olmayanın tabloya girildiğini düşünün.

INSERT INTO users VALUES
   ('foo@example.com'), ('hacker12@aol.com'), ('lol');

Adresleri doğrulamak istiyoruz, ancak PostgreSQL normalde mevcut satırlar için başarısız olan bir CHECK kısıtlaması eklememize izin vermez. Ancak geçerli değil olarak işaretlenen bir kısıtlamaya izin verir:

ALTER TABLE users
ADD CONSTRAINT syntactic_email
CHECK (email ~
   '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$'
) NOT VALID;

Yeni satırlar artık korunuyor.

INSERT INTO users VALUES ('fake');

/*
ERROR:  new row for relation "users_102010" violates
        check constraint "syntactic_email_102010"
DETAIL:  Failing row contains (fake).
*/

Daha sonra yoğun olmayan saatlerde veritabanı yöneticisi hatalı satırları düzeltmeyi ve kısıtlamayı yeniden doğrulamayı dener.

-- later, attempt to validate all rows
ALTER TABLE users
VALIDATE CONSTRAINT syntactic_email;

PostgreSQL belgelerinde ALTER TABLE bölümünde GEÇERSİ DEĞİl ve DOĞRULAMA KıSıTLAMASI hakkında daha fazla bilgi bulunur.

Dizin Ekleme/Kaldırma

PostgreSQL için Azure Cosmos DB dizin eklemeyi ve kaldırmayı destekler:

-- Adding an index

CREATE INDEX clicked_at_idx ON clicks USING BRIN (clicked_at);

-- Removing an index

DROP INDEX clicked_at_idx;

Dizin eklemek, çok kiracılı bir "kayıt sistemi" içinde istenmeyen bir yazma kilidi alır. Uygulama kapalı kalma süresini en aza indirmek için bunun yerine dizini eşzamanlı olarak oluşturun. Bu yöntem, standart dizin derlemesinden daha fazla toplam çalışma gerektirir ve tamamlanması daha uzun sürer. Ancak, dizin oluşturulurken normal işlemlerin devam etmesine izin verdiğinden, bu yöntem üretim ortamında yeni dizinler eklemek için kullanışlıdır.

-- Adding an index without locking table writes

CREATE INDEX CONCURRENTLY clicked_at_idx ON clicks USING BRIN (clicked_at);

Türler ve İşlevler

Özel SQL türleri ve kullanıcı tanımlı işlevler oluşturma, çalışan düğümlerine gönderilir. Ancak, dağıtılmış işlemler ile bir işlemde bu tür veritabanı nesneleri oluşturmak için dengeler gerekir.

PostgreSQL için Azure Cosmos DB, çalışan başına birden çok bağlantı kullanarak parçalar arasında gibi create_distributed_table() işlemleri paralelleştirir. Öte yandan, bir veritabanı nesnesi oluştururken PostgreSQL için Azure Cosmos DB bunu çalışan başına tek bir bağlantı kullanarak çalışan düğümlerine yayılır. İki işlemin tek bir işlemde birleştirilmesi sorunlara neden olabilir çünkü paralel bağlantılar tek bir bağlantı üzerinden oluşturulan nesneyi göremez ancak henüz işlenmez.

Tür oluşturan, tablo oluşturan, verileri yükleyen ve tabloyu dağıtan bir işlem bloğu düşünün:

BEGIN;

-- type creation over a single connection:
CREATE TYPE coordinates AS (x int, y int);
CREATE TABLE positions (object_id text primary key, position coordinates);

-- data loading thus goes over a single connection:
SELECT create_distributed_table(‘positions’, ‘object_id’);

SET client_encoding TO 'UTF8';
\COPY positions FROM ‘positions.csv’

COMMIT;

Citus 11.0'ın öncesinde Citus, çalışan düğümlerinde tür oluşturmayı erteler ve dağıtılmış tabloyu oluştururken ayrı olarak işlerdi. Bu, içinde veri kopyalama create_distributed_table() işleminin paralel olarak gerçekleşmesini etkinleştirdi. Ancak, türün Citus çalışan düğümlerinde her zaman mevcut olmadığı anlamına da geliyordu; veya işlem geri alınırsa, tür çalışan düğümlerinde kalacaktı.

Citus 11.0 ile, düzenleyici ve çalışan düğümleri arasındaki şema tutarlılığını önceliklendirmek için varsayılan davranış değişir. Yeni davranışın bir dezavantajı vardır: Nesne yayma işlemi aynı işlemdeki paralel bir komut sonrasında gerçekleşirse, aşağıdaki kod bloğundaki ERROR tarafından vurgulandığı gibi işlem artık tamamlanamaz:

BEGIN;
CREATE TABLE items (key text, value text);
-- parallel data loading:
SELECT create_distributed_table(‘items’, ‘key’);
SET client_encoding TO 'UTF8';
\COPY items FROM ‘items.csv’
CREATE TYPE coordinates AS (x int, y int);

ERROR:  cannot run type command because there was a parallel operation on a distributed table in the transaction

Bu sorunla karşılaşırsanız iki basit geçici çözüm vardır:

  1. Bu durumda türün oluşturulmasını ertelemek için automatic olarak ayarlayıncitus.create_object_propagation; bu durumda farklı düğümlerde hangi veritabanı nesnelerinin bulunduğu arasında bazı tutarsızlıklar olabilir.
  2. Düğüm başına paralelliği devre dışı bırakmak için olarak ayarlayın citus.multi_shard_modify_mode sequential . Aynı işlemdeki veri yükü daha yavaş olabilir.

Sonraki adımlar