Eu tenho uma tabela do Postgres com ~ 2.1 milhões de linhas. Eu executei a atualização abaixo:
WITH stops AS (
SELECT id,
rank() OVER (ORDER BY offense_timestamp,
defendant_dl,
offense_street_number,
offense_street_name) AS stop
FROM consistent.master
WHERE citing_jurisdiction=1
)
UPDATE consistent.master
SET arrest_id=stops.stop
FROM stops
WHERE master.id = stops.id;
Essa consulta levou 39 horas para ser executada. Estou executando isso em um processador de laptop i7 Q720 de 4 núcleos (físico), muita RAM, nada mais executando a grande maioria das vezes. Sem restrições de espaço no disco rígido. A mesa havia sido recentemente aspirada, analisada e reindexada.
Durante todo o tempo em que a consulta estava em execução, pelo menos após a WITH
conclusão inicial , o uso da CPU era geralmente baixo e o HDD estava em uso 100%. O disco rígido estava sendo usado com tanta força que qualquer outro aplicativo rodava consideravelmente mais devagar que o normal.
A configuração de energia do laptop estava em alto desempenho (Windows 7 x64).
Aqui está o EXPLAIN:
Update on master (cost=822243.22..1021456.89 rows=2060910 width=312)
CTE stops
-> WindowAgg (cost=529826.95..581349.70 rows=2060910 width=33)
-> Sort (cost=529826.95..534979.23 rows=2060910 width=33)
Sort Key: consistent.master.offense_timestamp, consistent.master.defendant_dl, consistent.master.offense_street_number, consistent.master.offense_street_name
-> Seq Scan on master (cost=0.00..144630.06 rows=2060910 width=33)
Filter: (citing_jurisdiction = 1)
-> Hash Join (cost=240893.51..440107.19 rows=2060910 width=312)
Hash Cond: (stops.id = consistent.master.id)
-> CTE Scan on stops (cost=0.00..41218.20 rows=2060910 width=48)
-> Hash (cost=139413.45..139413.45 rows=2086645 width=268)
-> Seq Scan on master (cost=0.00..139413.45 rows=2086645 width=268)
citing_jurisdiction=1
exclui apenas algumas dezenas de milhares de linhas. Mesmo com essa WHERE
cláusula, ainda estou operando em mais de 2 milhões de linhas.
O disco rígido é criptografado com o TrueCrypt 7.1a. Que atrasa as coisas um pouco, mas não o suficiente para causar uma consulta para tomar que muitas horas.
A WITH
peça leva apenas cerca de 3 minutos para ser executada.
O arrest_id
campo não tinha índice para chave estrangeira. Existem 8 índices e 2 chaves estrangeiras nesta tabela. Todos os outros campos da consulta são indexados.
O arrest_id
campo não tinha restrições, exceto NOT NULL
.
A tabela possui 32 colunas no total.
arrest_id
é do tipo variando de caracteres (20) . Percebo que rank()
produz um valor numérico, mas tenho que usar caracteres variáveis (20) porque tenho outras linhas em citing_jurisdiction<>1
que esses dados não são numéricos para esse campo.
O arrest_id
campo estava em branco para todas as linhas com citing_jurisdiction=1
.
Este é um laptop pessoal sofisticado (de 1 ano atrás). Eu sou o único usuário. Nenhuma outra consulta ou operação estava em execução. O bloqueio parece improvável.
Não há gatilhos em nenhum lugar nesta tabela ou em qualquer outro lugar no banco de dados.
Outras operações nesse banco de dados nunca levam uma quantidade abundante de tempo. Com a indexação adequada, as SELECT
consultas geralmente são bastante rápidas.
Seq Scan
são um pouco assustador ...