Ho una tabella di Postgres con ~ 2,1 milioni di righe. Ho eseguito l'aggiornamento di seguito su di esso:
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;
L'esecuzione della query ha richiesto 39 ore. Sto eseguendo questo su un processore portatile i7 Q720 con core 4 (fisico), molta RAM, nient'altro che esegue la maggior parte delle volte. Nessun vincolo di spazio sull'HDD. La tabella era stata recentemente aspirata, analizzata e reindicizzata.
Per tutto il tempo in cui la query era in esecuzione, almeno dopo il WITH
completamento iniziale , l'utilizzo della CPU era generalmente basso e l'HDD era in uso al 100%. L'HDD veniva utilizzato così duramente che qualsiasi altra app veniva eseguita molto più lentamente del normale.
L'impostazione di alimentazione del laptop era ad alte prestazioni (Windows 7 x64).
Ecco l'esplosione:
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
esclude solo poche decine di migliaia di righe. Anche con quella WHERE
clausola, sto ancora operando su oltre 2 milioni di righe.
Il disco rigido è interamente crittografato con TrueCrypt 7.1a. Questo rallenta un po 'le cose, ma non abbastanza per causare una query così tante ore.
Il WITH
esecuzione della parte richiede solo circa 3 minuti.
Il arrest_id
campo non aveva indice per la chiave esterna. In questa tabella sono presenti 8 indici e 2 chiavi esterne. Tutti gli altri campi nella query sono indicizzati.
Il arrest_id
campo non aveva vincoli tranneNOT NULL
.
La tabella ha un totale di 32 colonne.
arrest_id
è di tipo carattere variabile (20) . Mi rendo conto che rank()
produce un valore numerico, ma devo usare i caratteri che variano (20) perché ho altre righe in cuiciting_jurisdiction<>1
usano dati non numerici per questo campo.
Il arrest_id
campo era vuoto per tutte le righe conciting_jurisdiction=1
.
Questo è un laptop personale di fascia alta (a partire da 1 anno fa). Sono l'unico utente. Non sono state eseguite altre query o operazioni. Il blocco sembra improbabile.
Non ci sono trigger da nessuna parte in questa tabella o in qualsiasi altra parte del database.
Altre operazioni su questo database non richiedono mai una quantità eccessiva di tempo. Con una corretta indicizzazione, le SELECT
query sono in genere abbastanza veloci.
Seq Scan
sono un po 'paura ...