Ich habe eine Postgres-Tabelle mit ~ 2,1 Millionen Zeilen. Ich habe das folgende Update durchgeführt:
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;
Die Ausführung dieser Abfrage dauerte 39 Stunden. Ich verwende dies auf einem 4 (physischen) Kern i7 Q720 Laptop-Prozessor, viel RAM, sonst läuft die überwiegende Mehrheit der Zeit nichts. Keine Festplattenspeicherbeschränkungen. Die Tabelle wurde kürzlich gesaugt, analysiert und neu indiziert.
Während der gesamten Zeit, in der die Abfrage ausgeführt wurde, war die WITH
CPU-Auslastung in der Regel niedrig und die Festplatte war zu 100% belegt. Die Festplatte war so stark ausgelastet, dass jede andere App deutlich langsamer lief als normal.
Die Leistungseinstellung des Laptops war Hochleistung (Windows 7 x 64).
Hier ist der 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
schließt nur einige Zehntausende von Zeilen aus. Trotz dieser WHERE
Klausel arbeite ich immer noch mit über 2 Millionen Zeilen.
Die Festplatte ist vollständig mit TrueCrypt 7.1a verschlüsselt. Dass verlangsamen Dinge ein wenig nach unten, aber nicht genug , um eine Abfrage zu veranlassen , zu nehmen , dass viele Stunden.
Die WITH
Ausführung des Teils dauert nur ca. 3 Minuten.
Das arrest_id
Feld hatte keinen Index für Fremdschlüssel. Diese Tabelle enthält 8 Indizes und 2 Fremdschlüssel. Alle anderen Felder in der Abfrage werden indiziert.
Das arrest_id
Feld hatte keine Einschränkungen außer NOT NULL
.
Die Tabelle enthält insgesamt 32 Spalten.
arrest_id
ist vom Typ Zeichen variiert (20) . Mir ist klar, dass rank()
ein numerischer Wert erzeugt wird, aber ich muss Zeichenvariation (20) verwenden, weil ich andere Zeilen habe, in citing_jurisdiction<>1
denen nicht numerische Daten für dieses Feld verwendet werden.
Das arrest_id
Feld war für alle Zeilen mit leer citing_jurisdiction=1
.
Dies ist ein persönlicher High-End-Laptop (Stand vor 1 Jahr). Ich bin der einzige Benutzer. Es wurden keine anderen Abfragen oder Vorgänge ausgeführt. Das Sperren scheint unwahrscheinlich.
Es gibt keine Trigger in dieser Tabelle oder irgendwo anders in der Datenbank.
Andere Vorgänge in dieser Datenbank benötigen nie sonderlich viel Zeit. Bei richtiger Indizierung sind SELECT
Abfragen normalerweise recht schnell.
Seq Scan
sind ein bisschen beängstigend ...