Suponha que você precise processar um grande (não, não que ... GRANDE) número de registros no PostgreSQL para calcular alguns agregados. No artigo anterior , analisamos várias opções de como isso pode ser organizado e, neste artigo , veremos como não bloquear ninguém em especial , incluindo o "fluxo de entrada" de dados.
Por exemplo, pode-se recalcular saldos e manter vendas consolidadas de mercadorias com seus embarques constantes, ou agregar saldos e giros para contas contábeis, com grandes mudanças nas transações, ou outra coisa ... Em qualquer sistema de gestão, haverá um slide e o VLSI também não é exceção.
Mas todas essas situações têm um ponto comum - o número de mudanças é muito maior do que o número de agregados de destino. Por exemplo: milhares de mercadorias, cada uma com dezenas de milhares de remessas por dia.
Em outras considerações, contaremos com esse modelo de "Amazônia com mercadorias".
Meta - vendas diárias consolidadas
Queremos ter agregados para vendas no contexto de produto / dia / quantidade .
Especificamente, neste caso, faremos agregados "diretamente na base de dados" de forma a podermos recebê-los de forma rápida e holística para vários relatórios.
, , , - ClickHouse, . , , , , , , , ...
- ( ), 2PC- , - .
, - , , - , . , "" , .
?.. ...
, , "" - - , - - , "" , "" .
- "", - "--".
""
"". , - , .
"" . INSERT, UPDATE DELETE
, "" - INSERT
. , PostgreSQL , - unique-.
, " " , - . , - , "" flow-.
"" ""
flow- , / "" "- - ".
, , . , --, , .
, , , "" - … fail, :
DELETE FROM flow WHERE (it, dt) = (1, '2018-07-29') RETURNING *;
, - " ". , 1K/, 10K/.
:
SET statement_timeout = 1000;
, ! , , - flow- , . …
, "" , . " ", .
, flow , , "" .
DECLARE curs CURSOR FOR SELECT ctid, * FROM flow WHERE (it, dt) = (1, '2018-07-29') FOR UPDATE;
-- , ,
FETCH %d FROM curs;
DELETE FROM flow WHERE ctid = ANY(...);
flow ctid - "" .
SAVEPOINT
, "". %d FETCH? - , - ... ?
PostgreSQL " " SAVEPOINT/ROLLBACK TO, "" .
:
, ( - , ).
.
/ - COMMIT' .
, - COMMIT'.
, - , "" ( , ).
, !
BEGIN;
DECLARE curs CURSOR FOR SELECT ctid, * FROM flow WHERE (it, dt) = (1, '2018-07-29') FOR UPDATE;
FETCH 1 FROM curs;
DELETE FROM flow WHERE ctid = ANY(...);
-- processing
INSERT INTO agg ...
SAVEPOINT _1;
FETCH 2 FROM curs;
DELETE FROM flow WHERE ctid = ANY(...);
-- processing
INSERT INTO agg ...
SAVEPOINT _2;
FETCH 4 FROM curs;
DELETE FROM flow WHERE ctid = ANY(...);
-- processing...
INSERT INTO agg ...
-- oops! timeout exception!
ROLLBACK TO _2;
CLOSE curs;
COMMIT;
. , , !