Longo ATUALIZAÇÃO no PostgreSQL
-
05-07-2019 - |
Pergunta
Fui correndo um UPDATE em uma tabela contendo 250 milhões de linhas com 3 índice '; Essa atualização usa outra tabela contendo 30 milhões de linhas. Ele foi executado por cerca de 36 horas agora. Eu estou querendo saber se a sua é uma maneira de descobrir o quão próximo está a ser feito para se pretende levar um milhão de dias para fazer a sua coisa, eu vou matá-lo; No entanto, se ele só precisa de mais um dia ou dois, eu vou deixá-lo correr. Aqui está o-consulta comando:
UPDATE pagelinks SET pl_to = page_id
FROM page
WHERE
(pl_namespace, pl_title) = (page_namespace, page_title)
AND
page_is_redirect = 0
;
A explicar não é o problema aqui e só eu mencionar que têm vários índices grande da tabela a fim de um pouco justificar o tempo que leva para atualizá-lo. Mas aqui é o EXPLICAR qualquer maneira:
Merge Join (cost=127710692.21..135714045.43 rows=452882848 width=57)
Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
-> Sort (cost=3193335.39..3219544.38 rows=10483593 width=41)
Sort Key: page.page_namespace, (page.page_title)::text
-> Seq Scan on page (cost=0.00..439678.01 rows=10483593 width=41)
Filter: (page_is_redirect = 0::numeric)
-> Sort (cost=124517356.82..125285665.74 rows=307323566 width=46)
Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
-> Seq Scan on pagelinks (cost=0.00..6169460.66 rows=307323566 width=46)
Agora eu também enviou uma consulta de comando paralelo, a fim de GOTA um dos pagelinks' índices; é claro que está à espera para a atualização ao fim (mas eu senti como tentar de qualquer maneira!). Daí, eu não pode selecionar qualquer coisa de pagelinks , por medo de danificar os dados (a menos que você acha que seria seguro para matar o processo postmaster DROP INDEX?).
Então, eu estou querendo saber se a sua é uma tabela que iria manter o controle da quantidade de tuplas mortas ou algo para Seria bom saber o quão rápido ou quão longe o UPDATE está na conclusão de sua tarefa.
Thx (PostgreSQL não é tão inteligente quanto eu pensava, mas precisa de heurísticas)
Solução
Você leu a documentação do PostgreSQL para " Usando EXPLICAR ", para interpretar a saída você está mostrando?
Eu não sou um usuário regular PostgreSQL, mas eu só li que doc, e em seguida, em comparação com o EXPLAIN
saída você está mostrando. Sua consulta UPDATE
parece estar usando nenhum índice, e é forçado a fazer mesa de exames para classificar tanto page
e pagelinks
. O tipo é, sem dúvida, grande o suficiente para precisar de arquivos temporários em disco, que eu acho que são criados sob seu temp_tablespace
.
Então eu vejo as páginas de banco de dados estimados ler. O de nível superior do que a produção EXPLAIN
diz (cost=127710692.21..135714045.43)
. As unidades aqui são em disco I / O acessos. Então ele vai para acessar o disco mais de 135 milhões de vezes para fazer isso UPDATE
.
Note que os discos 10.000 rpm Mesmo com 5ms tempo de busca pode alcançar na melhor das hipóteses 200 I / O operações por segundo em condições ideais. Isto significaria que o seu UPDATE
levaria 188 horas (7,8 dias) de disco I / O, mesmo que você poderia sustentar disco I / O para esse período saturada (ou seja contínua lê / escreve sem quebras). Isso é impossível, e eu esperaria o rendimento real para estar fora por pelo menos uma ordem de magnitude, especialmente desde que você não tem nenhuma dúvida vindo a utilizar este servidor para todos os tipos de outro trabalho no mesmo período. Então eu acho que você é apenas uma fração do caminho através de seu UPDATE
.
Se fosse comigo, eu teria matado esta consulta no primeiro dia, e encontrou uma outra maneira de realizar a UPDATE
que fez melhor uso de índices e não exigir em disco de classificação. Você provavelmente não pode fazê-lo em uma única instrução SQL.
Quanto à sua DROP INDEX
, eu acho que é simplesmente bloquear, à espera de acesso exclusivo para a mesa, e enquanto é neste estado que eu acho que você provavelmente pode matá-lo.
Outras dicas
Este é muito antiga, mas se você quiser uma maneira para que você Monitores sua atualização ... Lembre-se que as sequências são afetados globalmente, assim você só pode criar um para Monitores essa atualização em outra sessão, fazendo isso:
create sequence yourprogress;
UPDATE pagelinks SET pl_to = page_id
FROM page
WHERE
(pl_namespace, pl_title) = (page_namespace, page_title)
AND
page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;
Em seguida, em outra sessão apenas fazer isso (não se preocupe com as transacções, como as sequências são afetados globalmente):
select last_value from yourprogress;
Isto irá mostrar quantas linhas estão sendo afetadas, para que possa estimar quanto tempo você vai tomar.
Com apenas final reiniciar sua seqüência para fazer outra tentativa:
alter sequence yourprogress restart with 1;
Ou apenas soltá-lo:
drop sequence yourprogress;
Você precisa de índices ou, como Bill apontou, ele terá de fazer varreduras seqüenciais em todas as mesas.
CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);