Da du slutter dig til to store tabeller, og der ikke er nogen betingelser, der kan bortfiltrere rækker, vil den eneste effektive join-strategi være en hash-join, og intet indeks kan hjælpe med det.
Først vil der være en sekventiel scanning af en af tabellerne, hvorfra en hash-struktur er bygget, derefter vil der være en sekventiel scanning over den anden tabel, og hashen vil blive probet for hver række fundet. Hvordan kunne et indeks hjælpe med det?
Du kan forvente, at en sådan operation vil tage lang tid, men der er nogle måder, hvorpå du kan fremskynde operationen:
-
Fjern alle indekser og begrænsninger på
tx_input1
før du begynder. Din forespørgsel er et af eksemplerne, hvor et indeks overhovedet ikke hjælper, men faktisk gør ondt ydeevne, fordi indekserne skal opdateres sammen med tabellen. Genskab indekserne og begrænsningerne, når du er færdig medUPDATE
. Afhængigt af antallet af indekser på bordet, kan du forvente en anstændig til massiv præstationsgevinst. -
Forøg
work_mem
parameter for denne ene operation medSET
kommando så højt du kan. Jo mere hukommelse hash-operationen kan bruge, jo hurtigere vil den være. Med et bord så stort vil du sandsynligvis stadig ende med at have midlertidige filer, men du kan stadig forvente en anstændig ydelsesforøgelse. -
Forøg
checkpoint_segments
(ellermax_wal_size
fra version 9.6 til) til en høj værdi, så der er færre kontrolpunkter underUPDATE
operation. -
Sørg for, at tabelstatistikken på begge tabeller er nøjagtige, så PostgreSQL kan komme med et godt estimat for antallet af hash-buckets, der skal oprettes.
Efter UPDATE
, hvis det påvirker et stort antal rækker, kan du overveje at køre VACUUM (FULL)
på tx_input1
for at slippe af med den resulterende bordbloat. Dette vil låse bordet i længere tid, så gør det under et vedligeholdelsesvindue. Det vil reducere størrelsen af tabellen og som en konsekvens fremskynde sekventielle scanninger.