Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ważne
Usługa Azure Cosmos DB for PostgreSQL nie jest już obsługiwana w przypadku nowych projektów. Nie używaj tej usługi dla nowych projektów. Zamiast tego użyj jednej z tych dwóch usług:
Użyj usługi Azure Cosmos DB for NoSQL dla rozproszonego rozwiązania bazy danych przeznaczonego dla scenariuszy o dużej skali z umową dotyczącą poziomu usług dostępności 99,999% (SLA), natychmiastowym skalowaniem automatycznym i automatycznym przejściem w tryb failover w wielu regionach.
Użyj funkcji Elastic Clusters usługi Azure Database for PostgreSQL na potrzeby fragmentowanej bazy danych PostgreSQL przy użyciu rozszerzenia Citus typu open source.
Dystrybucja tabel
Aby utworzyć tabelę rozproszoną, należy najpierw zdefiniować schemat tabeli. W tym celu można zdefiniować tabelę przy użyciu instrukcji CREATE TABLE w taki sam sposób, jak w przypadku regularnej tabeli PostgreSQL.
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
);
Następnie możesz użyć funkcji create_distributed_table(), aby określić kolumnę rozkładu tabeli i utworzyć fragmenty robocze.
SELECT create_distributed_table('github_events', 'repo_id');
Wywołanie funkcji informuje usługę Azure Cosmos DB for PostgreSQL, że tabela github_events powinna być dystrybuowana w kolumnie repo_id (poprzez hashowanie wartości kolumny).
Domyślnie tworzy on 32 fragmenty, gdzie każdy fragment jest właścicielem części miejsca skrótu i jest replikowany na podstawie domyślnej wartości konfiguracji citus.shard_replication_factor. Repliki fragmentów utworzone w ramach procesu roboczego mają te same definicje schematu, indeksu i ograniczenia tabeli co tabela w koordynatorze. Po utworzeniu replik funkcja zapisuje wszystkie rozproszone metadane na koordynatorze.
Każdy utworzony fragment ma przypisany unikatowy identyfikator fragmentu, a wszystkie jego repliki mają ten sam identyfikator fragmentu. Fragmenty są reprezentowane w węźle procesu roboczego jako zwykłe tabele PostgreSQL o nazwie "tablename_shardid", gdzie nazwa tabeli jest nazwą tabeli rozproszonej, a identyfikator fragmentu jest unikatowym przypisanym identyfikatorem. Możesz połączyć się z instancjami pracownika Postgres, aby wyświetlić lub uruchomić polecenia na poszczególnych kawałkach.
Teraz możesz wstawić dane do tabeli rozproszonej i uruchamiać na niej zapytania. Możesz również dowiedzieć się więcej na temat funkcji zdefiniowanej przez użytkownika (UDF) używanej w tej sekcji w odwołaniu do tabeli i fragmentu DDL.
Tabele referencyjne
Poprzednia metoda dystrybuuje tabele do wielu poziomych fragmentów. Inną możliwością jest rozproszenie tabel w pojedynczym fragmencie i replikowanie fragmentu do każdego węzła roboczego. Tabele rozproszone w ten sposób są nazywane tabelami referencyjnymi. Są one używane do przechowywania danych, do których należy często uzyskiwać dostęp przez wiele węzłów w klastrze.
Typowe kandydaty do tabel referencyjnych to:
- Mniejsze tabele, które muszą łączyć się z większymi tabelami rozproszonymi.
- Tabele w aplikacjach wielodostępnych, które nie mają kolumny z identyfikatorem najemcy lub nie są powiązane z najemcą. (Lub, podczas migracji, nawet w przypadku niektórych tabel skojarzonych z dzierżawą).
- Tabele, które wymagają unikatowych ograniczeń w wielu kolumnach i są wystarczająco małe.
Załóżmy na przykład, że witryna eCommerce obsługująca wielu najemców musi obliczyć podatek od sprzedaży dla transakcji w którymkolwiek z jej sklepów. Informacje podatkowe nie są specyficzne dla żadnej dzierżawy. Warto umieścić go w udostępnionej tabeli. Tabela referencyjna skoncentrowana na usa może wyglądać następująco:
-- 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');
Teraz zapytania, takie jak obliczanie podatku dla koszyka zakupów, mogą łączyć się z states tabelą bez narzutów sieciowych i mogą dodać klucz obcy do kodu stanu w celu uzyskania lepszej weryfikacji.
Oprócz dystrybucji tabeli jako pojedynczego replikowanego fragmentu, funkcja UDF create_reference_table oznacza ją jako tabelę referencyjną w tabelach metadanych usługi Azure Cosmos DB dla PostgreSQL. Usługa Azure Cosmos DB for PostgreSQL automatycznie wykonuje zatwierdzenia dwufazowe (2PC) w celu modyfikacji tabel oznaczonych w ten sposób, co zapewnia silne gwarancje spójności.
Aby zapoznać się z innym przykładem używania tabel referencyjnych, zobacz samouczek dotyczący wielodostępnej bazy danych.
Dystrybucja danych koordynatora
Jeśli istniejąca baza danych PostgreSQL jest konwertowana na węzeł koordynacji dla klastra, dane w jego tabelach mogą być dystrybuowane wydajnie i z minimalnymi przerwami w działaniu aplikacji.
Opisana create_distributed_table wcześniej funkcja działa zarówno na pustych, jak i niepustych tabelach, a dla tej drugiej automatycznie dystrybuuje wiersze tabeli w całym klastrze. Wiesz, czy kopiuje dane przez obecność komunikatu "UWAGA: Kopiowanie danych z tabeli lokalnej..." Na przykład:
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)
Zapisy w tabeli są blokowane podczas migrowania danych, a oczekujące zapisy są obsługiwane jako zapytania rozproszone po zatwierdzeniu funkcji. (Jeśli funkcja zakończy się niepowodzeniem, zapytania staną się ponownie lokalne). Odczyty mogą być kontynuowane w normalny sposób i staną się zapytaniami rozproszonymi po zatwierdzeniu funkcji.
Podczas dystrybucji tabel A i B, gdzie A ma klucz obcy do B, najpierw dystrybuuj tabelę docelową klucza B. Wykonanie tej czynności w niewłaściwej kolejności powoduje błąd:
ERROR: cannot create foreign key constraint
DETAIL: Referenced table must be a distributed table or a reference table.
Jeśli nie można dystrybuować w odpowiedniej kolejności, porzucaj klucze obce, dystrybuuj tabele i utwórz ponownie klucze obce.
Podczas migracji danych z zewnętrznej bazy danych, takiej jak z usługi Amazon RDS do usługi Azure Cosmos DB for PostgreSQL, najpierw utwórz tabele rozproszone usługi Azure Cosmos DB for PostgreSQL za pośrednictwem create_distributed_tablemetody , a następnie skopiuj dane do tabeli.
Kopiowanie do tabel rozproszonych umożliwia uniknięcie wyczerpania miejsca w węźle koordynatora.
Kolokowanie tabel
Kolokacja oznacza umieszczanie i utrzymywanie powiązanych informacji na tych samych maszynach. Umożliwia wydajne wykonywanie zapytań przy jednoczesnym wykorzystaniu skalowalności poziomej dla całego zestawu danych. Aby uzyskać więcej informacji, zobacz kolokacja.
Tabele są umieszczane w grupach. Aby ręcznie kontrolować przypisanie grupy kolokacji tabeli, użyj opcjonalnego parametru colocate_with w create_distributed_table. Jeśli nie interesuje Cię kolokacja tabeli, pomiń ten parametr. Domyślnie jest to wartość 'default', która grupuje tabelę z dowolną inną domyślną tabelą kolokacji o tym samym typie kolumny dystrybucji, liczbie fragmentów i współczynniku replikacji. Jeśli chcesz przerwać lub zaktualizować tę niejawną kolokację, możesz użyć polecenia 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');
Jeśli nowa tabela nie jest powiązana z innymi w niejawnej grupie kolokacji, określ wartość colocated_with => 'none'.
-- not co-located with other tables
SELECT create_distributed_table('A', 'foo', colocate_with => 'none');
Dzielenie niepowiązanych tabel na własne grupy kolokacji zwiększa efektywność równoważenia fragmentów, ponieważ fragmenty w tej samej grupie muszą być przenoszone razem.
Gdy tabele są rzeczywiście powiązane (na przykład po ich sprzężeniu), warto jawnie je razem umieścić. Zyski odpowiedniej kolokacji są ważniejsze niż jakiekolwiek ponowne równoważenie obciążenia.
Aby jawnie kolokować wiele tabel, rozłóż jeden, a następnie umieść inne w swojej grupie kolokacji. Na przykład:
-- 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');
Informacje o grupach kolokacji są przechowywane w tabeli pg_dist_colocation , a pg_dist_partition ujawnia, które tabele są przypisywane do których grup.
Usuwanie tabel
Aby usunąć tabele rozproszone, możesz użyć standardowego polecenia PostgreSQL DROP TABLE. Podobnie jak w przypadku zwykłych tabel, funkcja DROP TABLE usuwa wszystkie indeksy, reguły, wyzwalacze i ograniczenia, które istnieją dla tabeli docelowej. Ponadto usuwa również odłamki na węzłach roboczych i czyści ich metadane.
DROP TABLE github_events;
Modyfikowanie tabel
Usługa Azure Cosmos DB for PostgreSQL automatycznie propaguje wiele rodzajów instrukcji DDL. Modyfikowanie tabeli rozproszonej w węźle koordynatora aktualizuje również fragmenty na węzłach roboczych. Inne instrukcje DDL wymagają ręcznego propagowania, a niektóre z nich są zabronione, na przykład te, które zmodyfikowałyby kolumnę dystrybucji. Próba uruchomienia DDL, który nie kwalifikuje się do automatycznego propagowania, powoduje błąd i pozostawia tabele na węźle koordynatora bez zmian.
Oto przegląd kategorii instrukcji DDL, które się rozprzestrzeniają.
Dodawanie/modyfikowanie kolumn
Usługa Azure Cosmos DB for PostgreSQL propaguje większość poleceń ALTER TABLE automatycznie. Dodawanie kolumn lub zmienianie ich wartości domyślnych działa tak, jak w przypadku pojedynczej bazy danych PostgreSQL:
-- Adding a column
ALTER TABLE products ADD COLUMN description text;
-- Changing default value
ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;
Istotne zmiany w istniejącej kolumnie, takie jak zmiana jej nazwy lub zmiana typu danych również są odpowiednie. Jednak nie można zmienić typu danych kolumny dystrybucji . Ta kolumna określa sposób dystrybucji danych tabeli za pośrednictwem klastra i modyfikowanie jego typu danych wymagałoby przeniesienia danych.
Próba wykonania tej czynności powoduje błąd:
-- 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
*/
Dodawanie/usuwanie ograniczeń
Korzystanie z usługi Azure Cosmos DB for PostgreSQL umożliwia kontynuowanie korzystania z bezpieczeństwa relacyjnej bazy danych, w tym ograniczeń bazy danych (zobacz dokumentację bazy danych PostgreSQL). Ze względu na charakter systemów rozproszonych, Azure Cosmos DB for PostgreSQL nie będzie stosować ograniczeń unikatowości ani spójności referencyjnej między węzłami roboczymi.
Aby skonfigurować klucz obcy między kolokowaną tabelą rozproszoną, zawsze uwzględnij kolumnę dystrybucji w kluczu. Dołączenie kolumny dystrybucji może obejmować tworzenie kluczowego związku.
Klucze obce mogą być tworzone w następujących sytuacjach:
- między dwiema lokalnymi (nieprostrybucyjnymi) tabelami,
- między dwiema tabelami referencyjnymi,
- między dwiema współlokowanymi tabelami rozproszonymi, gdy klucz zawiera kolumnę podziału lub
- jako tabela rozproszona odwołująca się do tabeli referencyjnej
Klucze obce z tabel odwołań do tabel rozproszonych nie są obsługiwane.
Uwaga
Klucze podstawowe i ograniczenia unikatowości muszą zawierać kolumnę dystrybucji. Dodanie ich do kolumny bez dystrybucji spowoduje wygenerowanie błędu
W tym przykładzie pokazano, jak utworzyć klucze podstawowe i obce w tabelach rozproszonych:
--
-- 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);
Podobnie uwzględnij kolumnę dystrybucji w ograniczeniach unikatowości:
-- 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);
Ograniczenia „niepuste” można zastosować do każdej kolumny (dystrybuowanej lub nie), ponieważ nie wymagają one wyszukiwań między pracownikami.
ALTER TABLE ads ALTER COLUMN image_url SET NOT NULL;
Używanie NIEPRAWIDŁOWYch ograniczeń
W niektórych sytuacjach może być przydatne wymuszenie ograniczeń dla nowych wierszy, podczas gdy istniejące wiersze niezgodne mogą pozostać bez zmian. Usługa Azure Cosmos DB dla PostgreSQL obsługuje tę funkcję w przypadku ograniczeń CHECK i kluczy obcych, używając oznaczenia ograniczeń "NOT VALID" w bazie danych PostgreSQL.
Rozważmy na przykład aplikację, która przechowuje profile użytkowników w tabeli referencyjnej.
-- 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');
Z biegiem czasu wyobraź sobie, że kilka nie-adresów dostaje się do tabeli.
INSERT INTO users VALUES
('foo@example.com'), ('hacker12@aol.com'), ('lol');
Chcemy zweryfikować adresy, ale usługa PostgreSQL zwykle nie zezwala na dodanie ograniczenia CHECK, które kończy się niepowodzeniem dla istniejących wierszy. Jednak zezwala na ograniczenie oznaczone jako nieprawidłowe:
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;
Teraz nowe wiersze są chronione.
INSERT INTO users VALUES ('fake');
/*
ERROR: new row for relation "users_102010" violates
check constraint "syntactic_email_102010"
DETAIL: Failing row contains (fake).
*/
Później, w godzinach innych niż szczytowe, administrator bazy danych może spróbować naprawić nieprawidłowe wiersze i ponownie zweryfikować ograniczenie.
-- later, attempt to validate all rows
ALTER TABLE users
VALIDATE CONSTRAINT syntactic_email;
Dokumentacja bazy danych PostgreSQL zawiera więcej informacji na temat NOT VALID i VALIDATE CONSTRAINT w sekcji ALTER TABLE .
Dodawanie/usuwanie indeksów
Usługa Azure Cosmos DB for PostgreSQL obsługuje dodawanie i usuwanie indeksów:
-- Adding an index
CREATE INDEX clicked_at_idx ON clicks USING BRIN (clicked_at);
-- Removing an index
DROP INDEX clicked_at_idx;
Dodanie indeksu wymaga blokady zapisu, co może być niepożądane w wielotenantowym systemie rejestrów. Aby zminimalizować przestój aplikacji, utwórz indeks współbieżnie. Ta metoda wymaga większej całkowitej pracy niż kompilacja indeksu standardowego i trwa dłużej. Jednak ponieważ umożliwia ona kontynuowanie normalnych operacji podczas tworzenia indeksu, ta metoda jest przydatna do dodawania nowych indeksów w środowisku produkcyjnym.
-- Adding an index without locking table writes
CREATE INDEX CONCURRENTLY clicked_at_idx ON clicks USING BRIN (clicked_at);
Typy i funkcje
Tworzenie niestandardowych typów SQL oraz funkcji zdefiniowanych przez użytkownika rozprzestrzenia się do węzłów roboczych. Jednak utworzenie takich obiektów bazy danych w transakcji z operacjami rozproszonymi wiąże się z kompromisami.
Usługa Azure Cosmos DB for PostgreSQL równolegle wykonuje operacje, takie jak create_distributed_table(), przez fragmenty, wykorzystując wiele połączeń na każdy proces roboczy. Podczas tworzenia obiektu bazy danych usługa Azure Cosmos DB for PostgreSQL propaguje go do węzłów roboczych przy użyciu jednego połączenia na proces roboczy. Połączenie dwóch operacji w jednej transakcji może powodować problemy, ponieważ połączenia równoległe nie będą mogły zobaczyć obiektu, który został utworzony za pośrednictwem jednego połączenia, ale nie został jeszcze zatwierdzony.
Rozważ blok transakcji, który tworzy typ, tabelę, ładuje dane i dystrybuuje tabelę:
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;
Przed Citus 11.0, Citus odraczał tworzenie typu na węzłach roboczych, a zatwierdzał go oddzielnie podczas tworzenia tabeli rozproszonej. Umożliwiło to kopiowanie danych w create_distributed_table() w sposób równoległy. Jednak oznaczało to również, że typ nie zawsze był obecny na węzłach roboczych Citus — a jeśli transakcja została wycofana, typ nadal pozostawał na tych węzłach roboczych.
W przypadku Citus 11.0 domyślne zachowanie zmienia się, aby priorytetem była spójność schematu między węzłami koordynatora a węzłami roboczymi. Nowe zachowanie ma wadę: jeśli propagacja obiektu ma miejsce po równoległym poleceniu w tej samej transakcji, nie można już ukończyć transakcji, co zostało wyróżnione przez błąd w bloku kodu poniżej:
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
Jeśli wystąpi ten problem, istnieją dwa proste obejścia:
- Użyj
citus.create_object_propagationw połączeniu zautomaticaby odroczyć tworzenie typu w tej sytuacji, w którym to przypadku może wystąpić pewna niespójność między obiektami bazy danych w różnych węzłach. - Ustaw
citus.multi_shard_modify_modenasequentialaby wyłączyć równoległość poszczególnych węzłów. Ładowanie danych w tej samej transakcji może być wolniejsze.