> Não ... É que já tive más experiencias com NOT IN... Onde o LEFT foi
> melhor, mas não me lembro exatamente a estrutura das tabelas nem
> índices...

        Bom, tem o EXISTS também, que creio ser ainda mais simples.

        Talvez versões antigas?  Não parece haver grandes problemas com o
otimizado nas v8.

Se não me engano era na 7.3 ...


> SELECT * FROM tzrepl.tzr_log L
> LEFT OUTER JOIN tzrepl.tzr_replicated_log RL
> ON RL.id_log = RL.id_log
> WHERE RL.id_log IS NULL;
> -- 861971 registros em 24078ms

> SELECT * FROM tzrepl.tzr_log L
> WHERE id_log NOT IN(SELECT id_log FROM tzrepl.tzr_replicated_log)
>  --861971 registros em  19407ms

        Como eu suspeitava, você melhorou alguma coisa o plano de execução.
Importa-se de publicá-lo na lista?

"Nested Loop Left Join  (cost=23488.35..85777903.72 rows=21432909 width=238)"
"  Filter: ("inner".id_log IS NULL)"
"  ->  Seq Scan on tzr_log l  (cost=0.00..22779.71 rows=861971 width=182)"
"  ->  Materialize  (cost=23488.35..23538.08 rows=4973 width=56)"
"        ->  Seq Scan on tzr_replicated_log rl  (cost=0.00..23483.38
rows=4973 width=56)"
"              Filter: (id_log = id_log)"


"Seq Scan on tzr_log l  (cost=25877.49..7033033820.69 rows=430986 width=182)"
"  Filter: (NOT (subplan))"
"  SubPlan"
"    ->  Materialize  (cost=25877.49..39709.39 rows=994590 width=4)"
"          ->  Seq Scan on tzr_replicated_log  (cost=0.00..20996.90
rows=994590 width=4)"




> Achei os números bem aceitáveis [1], principalmente por estar em um
> servidor de Teste (Bem ruinzinho por sinal)... Mas meu medo é que
> conforme esse registros aumentem (e vão aumentar muito), isto comece a
> ficar muito lento...

        Exato.


> Em produção eu utilizo também uma chave para filtrar os
> replicated_log, o que reduziria um pouco este número ( < 718309 ) ...
> Estava pensando em colocar mais uma coluna (num_repl) em tzr_log, que
> seria incrementada a cada registro inserido em replicated_log e assim
> poderia adicionar mais uma condição ao select para tentar diminuir o
> SCAN (num_repl < (select SUM(oid) FROM tzr_nodes) ...
> Isto é uma boa prática ?? O que sugerem ??

        Não sei se entendi, mas não parece ser bom não…

Vou tentar explicar melhor ....

tenho as seguintes Tabelas :

Nodes :

oid
ip_addr inet
port int
dbname name
pass varchar(255)
....

Log:
id_log int
type int
command text
time timestamp
(num_repl) **
....

Replicated Log
id_repl int
id_log int FK
nodeoid oid FK
time timestamp
....

Quando eu insiro/altero/deleto um registro em qualquer uma das tabelas
configuradas, este aciona uma trigger que grava o LOG da operação ....

Tenho um serviço em "C", que busca na base PG (tabela Nodes) e
verifica status do nó (online/offline)  e replica os Logs não
replicados para este ( Que é justamente a query acima em questão,
apenas com o filtro do nó na replicated_log *)


* SELECT * FROM tzrepl.tzr_log L
WHERE id_log NOT IN(SELECT id_log FROM tzrepl.tzr_replicated_log
[WHERE node_oid = 123456] )

Com isso eu restrinjo a quantidade de linhas de comparação do subselect....
Se eu colocasse um o campo num_repl, eu adicionaria uma condição no select :

SELECT * FROM  tzrepl.tzr_log L
                      WHERE
                                   num_repl < (SELECT count(oid) FROM
tzrepl.tzr_nodes)
                                    AND id_log NOT IN(SELECT id_log
FROM tzrepl.tzr_replicated_log [WHERE node_oid = 123456])

e assim eu obteria apenas os registros que ainda não foram replicados
para "todos" os nós.

Pensei também em deletar os registros já replicados, mas aí eu
perderia uma característica importante do meu sistema que seria a
facilidade de incorporar nós.
Pois com os logs todos gerados, seria apenas adicionar um registro na
tabela de Nós que ele replicaria todos os registros para este novo nó.

Espero que consiga entender .... Se não conseguir eu tento explicar
denovo.. Sem problemas...



> Tenho uma tabela de nós (tzr_nodes), outra de log (tzr_log) e outra de
> logs replicados (tzr_replicated_log)...

        Nós 1:N replicated N:1 log?
Sim ...




> Quando eu insiro, altero ou deleto um registro insiro este na tabela
> de logs e replico este para o(s) nós que estão na tabela de nós e
> insiro um registro em logs replicados com o id do log e o id do nó
> para cada replicação que é efetuada com sucesso ...

        Ah, é você que está tentando implementar uma replicação na unha?

        Toda vez que aparece alguém com essa idéia eu aviso que é fria… não é o
primeiro, e infelizmente não será o último.  Vide a entrevista que o
Telles publicou hoje.

Você ja me avisou ... Mas eu sou meio teimoso ... Na real já está
rodando em teste... Só estou melhorando a performance ...


> >         O melhor dos mundos seria, por exemplo, percorrer a tzr_log e, a 
partir
> > de seu índice, o índice da tzr_replicated_log, evitando a tabela
> > tzr_replicated_log em si.
>
> Existe como implementar isso ?

        Sim… se você tem os índices adequados, e não usa dados da replicated,
mas apenas quer saber da existência ou não da chave indexada, deveria
ser automático.  Se não funcionar, talvez seja o caso de verificar com
alguém mais esperto que eu, pode ser até um defeito de otimizador
(duvido).
Na realidade eu utilizo apenas o ID_LOG para obter os detalhes do
mesmo (Colunas/valores).
E tenho um índice para ele em ambas as tabelas :

EXPLAIN SELECT l.id_log FROM tzrepl.tzr_log L
WHERE id_log =1

"Index Scan using idx_tzr_log on tzr_log l  (cost=0.00..6.01 rows=1 width=4)"
"  Index Cond: (id_log = 1)"


EXPLAIN SELECT id_log FROM tzrepl.tzr_replicated_log WHERE id_log =1

"Bitmap Heap Scan on tzr_replicated_log  (cost=7324.07..16243.10
rows=4973 width=4)"
"  Recheck Cond: (id_log = 1)"
"  ->  Bitmap Index Scan on idx_tzr_replicated_log
(cost=0.00..7324.07 rows=4973 width=0)"
"        Index Cond: (id_log = 1)"


Mas aqui, ele não utiliza o(s) indice(s) :

EXPLAIN SELECT l.id_log FROM tzrepl.tzr_log L
WHERE id_log NOT IN(SELECT id_log FROM tzrepl.tzr_replicated_log)
"Seq Scan on tzr_log l  (cost=25877.49..7033033820.69 rows=430986 width=4)"
"  Filter: (NOT (subplan))"
"  SubPlan"
"    ->  Materialize  (cost=25877.49..39709.39 rows=994590 width=4)"
"          ->  Seq Scan on tzr_replicated_log  (cost=0.00..20996.90
rows=994590 width=4)"
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a