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=1wyklucza tylko kilkadziesiąt tysięcy wierszy. Nawet z tą WHEREklauzulą 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 WITHczęści zajmuje około 3 minut.
arrest_idPola 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_idPola nie miał ograniczeń, z wyjątkiem NOT NULL.
Tabela zawiera łącznie 32 kolumny.
arrest_idma 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<>1w tym polu są używane dane nienumeryczne.
arrest_idPole 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 SELECTzapytania są zwykle dość szybkie.
Seq Scantrochę przerażające ...