PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Compartilhando seus dados com o PostgreSQL 11


A versão 10 do PostgreSQL adicionou o particionamento de tabela declarativo feature.Na versão 11 (atualmente em beta), você pode combinar isso com datawrappers estrangeiros , fornecendo um mecanismo para fragmentar nativamente suas tabelas em vários servidores PostgreSQL.

Particionamento declarativo


Considere uma tabela que armazena as temperaturas mínimas e máximas diárias das cidades para cada dia:
CREATE TABLE temperatures (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
);

A especificação da tabela é intencionalmente desprovida de restrições de coluna e chave primária para manter as coisas simples - adicionaremos isso mais tarde.

É muito comum descobrir que em muitas aplicações os dados mais recentes são acessados ​​com mais frequência. Pense no ano financeiro atual, neste mês, na última hora e assim por diante. À medida que nossa tabela de “temperaturas” cresce, faz sentido mover os dados antigos para outra tabela, com a mesma estrutura. Podemos, por exemplo, fazer isso:
CREATE TABLE temperatures_2017 (LIKE temperatures);
INSERT INTO temperatures_2017 SELECT * FROM temperatures WHERE
	extract(year from at) = 2017;
DELETE FROM temperatures WHERE extract(year from at) = 2017;

para mover todas as entradas do ano de 2017 para outra tabela. Isso deixa a tabela principal de “temperaturas” menor e mais rápida para o aplicativo trabalhar. em outra mesa.

Mas ter várias tabelas distintas significa que o código do aplicativo agora precisa mudar. Se ele tiver que acessar dados mais antigos, digamos, obtendo as temperaturas mínima e máxima anuais de uma cidade, agora ele precisa descobrir quais tabelas estão presentes no esquema, consultar cada uma delas e combinar os resultados de cada tabela. Podemos fazer isso sem alterar o código do aplicativo?

O particionamento torna isso possível. No PostgreSQL 10, você pode criar a tabela “temperaturas” assim:
CREATE TABLE temperatures (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
)
PARTITION BY RANGE (at);

Isso torna "temperaturas" uma tabela mestra de partição e informa ao PostgreSQL que vamos criar várias tabelas particionadas armazenando dados não sobrepostos, cada uma com um conjunto diferente de valores "at". A tabela mestra em si não contém nenhum dado, mas pode ser consultada e inserida pelo aplicativo – que ignora as partições filhas que contêm os dados reais.

E aqui estão nossas partições:
CREATE TABLE temperatures_2017
    PARTITION OF temperatures
    FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');

CREATE TABLE temperatures_2018
    PARTITION OF temperatures
    FOR VALUES FROM ('2018-01-01') TO ('2019-01-01');

Agora temos duas tabelas, uma que armazenará dados para 2017 e outra para 2018. Observe que o valor "de" é inclusivo, mas o valor "para" não é. Vamos experimentar:
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#        VALUES ('2018-08-03', 'London', 63, 90);
INSERT 0 1
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#        VALUES ('2017-08-03', 'London', 59, 70);
INSERT 0 1
temp=# SELECT * FROM temperatures;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2017-08-03 | London |      59 |      70
 2018-08-03 | London |      63 |      90
(2 rows)

temp=# SELECT * FROM temperatures_2017;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2017-08-03 | London |      59 |      70
(1 row)

temp=# SELECT * FROM temperatures_2018;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2018-08-03 | London |      63 |      90
(1 row)

O “aplicativo” é capaz de inserir e selecionar na tabela principal, mas o PostgreSQL roteia os dados reais para as tabelas filhas apropriadas. (Ah e BTW, essas temperaturas são reais!)

Índices e restrições


Índices e restrições de tabela e coluna são realmente definidos no nível particionável, já que é onde os dados reais residem. Você pode defini-los durante a criação da tabela de partição:
CREATE TABLE temperatures_2017
    PARTITION OF temperatures (
        mintemp NOT NULL,
        maxtemp NOT NULL,
        CHECK (mintemp <= maxtemp),
        PRIMARY KEY (at, city)
    )
    FOR VALUES FROM ('2017-01-01') TO ('2018-01-01');

O PostgreSQL 11 permite definir índices na tabela pai e criará índices em tabelas de partição existentes e futuras. Leia mais aqui.

Envoltório de dados estrangeiros


A funcionalidade de wrapper de dados estrangeiros existe no Postgres há algum tempo. O PostgreSQL permite acessar dados armazenados em outros servidores e sistemas usando esse mecanismo. O que nos interessa é “postgres_fdw”, que é o que nos permitirá acessar um servidor Postgres de outro.

“postgres_fdw” é uma extensão presente na distribuição padrão, que pode ser instalada com o comando regular CREATE EXTENSION:
CREATE EXTENSION postgres_fdw;

Vamos supor que você tenha outro servidor PostgreSQL “box2” com um banco de dados chamado “box2db”. Você pode criar um “servidor estrangeiro” para isso:
CREATE SERVER box2 FOREIGN DATA WRAPPER postgres_fdw
    OPTIONS (host 'box2', dbname 'box2db');

Vamos também mapear nosso usuário “alice” (o usuário com o qual você está conectado) para o usuário box2 “box2alice”. Isso permite que “alice” seja “box2alice” ao acessar tabelas remotas:
CREATE USER MAPPING FOR alice SERVER box2
    OPTIONS (user 'box2alice');

Agora você pode acessar tabelas (também visualizações, matviews etc) no box2. Primeiro, crie uma mesa no box2 e depois uma “mesa estrangeira” no seu servidor. A tabela externa não contém nenhum dado real, mas serve como um proxy para acessar a tabela na caixa2.
-- on box2
CREATE TABLE foo (a int);

-- on your server
IMPORT FOREIGN SCHEMA public LIMIT TO (foo)
    FROM SERVER box2 INTO public;

A tabela estrangeira em seu servidor pode participar de transações da mesma forma que as tabelas normais. Os aplicativos não precisam saber que as tabelas com as quais ele interage são locais ou estrangeiras - embora se seu aplicativo executar um SELECT que possa extrair muitas linhas de uma tabela estrangeira, isso pode tornar as coisas mais lentas. e agregados ao servidor remoto.

Combinando particionamento e FDW


E agora a parte divertida:configurar partições em servidores remotos.

Primeiro, vamos criar a tabela de partição física no box2:
-- on box2
CREATE TABLE temperatures_2016 (
    at      date,
    city    text,
    mintemp integer,
    maxtemp integer
);

E então crie a partição no seu servidor, como uma tabela estrangeira:
CREATE FOREIGN TABLE temperatures_2016
    PARTITION OF temperatures
    FOR VALUES FROM ('2016-01-01') TO ('2017-01-01')
    SERVER box2;

Agora você pode inserir e consultar do seu próprio servidor:
temp=# INSERT INTO temperatures (at, city, mintemp, maxtemp)
temp-#     VALUES ('2016-08-03', 'London', 63, 73);
INSERT 0 1
temp=# SELECT * FROM temperatures ORDER BY at;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2016-08-03 | London |      63 |      73
 2017-08-03 | London |      59 |      70
 2018-08-03 | London |      63 |      90
(3 rows)

temp=# SELECT * FROM temperatures_2016;
     at     |  city  | mintemp | maxtemp
------------+--------+---------+---------
 2016-08-03 | London |      63 |      73
(1 row)

Aí está! Ser capaz de inserir linhas em uma partição remota é novo na versão 11. Com esse recurso, agora você pode ter seus dados fragmentados logicamente (partições) e fisicamente (FDW).

Gerenciamento de dados


Comandos como VACUUM e ANALYZE funcionam como você esperaria com tabelas mestras de partição – todas as tabelas filhas locais estão sujeitas a VACUUM e ANALYZE. As partições podem ser desanexadas, seus dados são manipulados sem a restrição de partição e, em seguida, reanexados. As próprias tabelas filhas de partição podem ser particionadas.

A movimentação de dados (“reestilhaçamento”) pode ser feita com instruções SQL regulares (inserir, excluir, copiar etc.). Índices e gatilhos locais de partição podem ser criados.

A adição de redundância aos seus shards é facilmente alcançada com replicação lógica ou de streaming.