Mam tabelę Postgres z ~ 2,1 miliona wierszy. Uruchomiłem na nim poniższą aktualizację:
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;
Uruchomienie tego zapytania zajęło 39 godzin. Używam tego na 4 (fizycznym) rdzeniu laptopa i7 Q720, dużo pamięci RAM, nic więcej nie działa przez większość czasu. Brak ograniczeń miejsca na dysku twardym. Tabela została niedawno odkurzona, przeanalizowana i ponownie zindeksowana.
Przez cały czas działania zapytania, przynajmniej po zakończeniu początkowego WITH
, zużycie procesora było zwykle niskie, a dysk twardy był w użyciu w 100%. Dysk twardy był używany tak intensywnie, że każda inna aplikacja działała znacznie wolniej niż normalnie.
Ustawienia zasilania laptopa były na wysokiej wydajności (Windows 7 x64).
Oto WYJAŚNIENIE:
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
wyklucza tylko kilkadziesiąt tysięcy wierszy. Nawet z tą WHERE
klauzulą nadal działam w ponad 2 milionach wierszy.
Dysk twardy jest w całości zaszyfrowany za pomocą TrueCrypt 7.1a. Która spowalnia rzeczy nieco w dół, ale nie na tyle, aby spowodować zapytanie do podjęcia że wiele godzin.
Uruchomienie tej WITH
części zajmuje około 3 minut.
arrest_id
Pola nie miał indeks dla klucza obcego. W tej tabeli znajduje się 8 indeksów i 2 klucze obce. Wszystkie pozostałe pola w zapytaniu są indeksowane.
arrest_id
Pola nie miał ograniczeń, z wyjątkiem NOT NULL
.
Tabela zawiera łącznie 32 kolumny.
arrest_id
ma różny typ znaków (20) . Zdaję sobie sprawę, że rank()
tworzy wartość liczbową, ale muszę używać znaków różniących się (20), ponieważ mam inne wiersze, w których citing_jurisdiction<>1
w tym polu są używane dane nienumeryczne.
arrest_id
Pole było puste dla wszystkich rzędach citing_jurisdiction=1
.
Jest to osobisty laptop z wyższej półki (od 1 roku). Jestem jedynym użytkownikiem. Żadne inne zapytania ani operacje nie były uruchomione. Blokowanie wydaje się mało prawdopodobne.
Nigdzie w tej tabeli ani nigdzie indziej w bazie danych nie ma żadnych wyzwalaczy.
Inne operacje na tej bazie danych nigdy nie zajmują zbyt dużo czasu. Przy właściwym indeksowaniu SELECT
zapytania są zwykle dość szybkie.
Seq Scan
trochę przerażające ...