Forudsat relativt få rækker i options
for mange rækker i records
.
Typisk vil du have en opslagstabel options
der henvises til fra records.option_id
, ideelt set med en fremmednøglebegrænsning. Hvis du ikke gør det, foreslår jeg at oprette en for at håndhæve referentiel integritet:
CREATE TABLE options (
option_id int PRIMARY KEY
, option text UNIQUE NOT NULL
);
INSERT INTO options
SELECT DISTINCT option_id, 'option' || option_id -- dummy option names
FROM records;
Så er der ingen grund til at efterligne en løs indeksscanning længere, og dette bliver meget enkelt og hurtigt . Korrelerede underforespørgsler kan bruge et almindeligt indeks på (option_id, id)
.
SELECT option_id, (SELECT max(id)
FROM records
WHERE option_id = o.option_id) AS max_id
FROM options o
ORDER BY 1;
Dette inkluderer muligheder uden match i tabel records
. Du får NULL for max_id
og du kan nemt fjerne sådanne rækker i en ydre SELECT
hvis det er nødvendigt.
Eller (samme resultat):
SELECT option_id, (SELECT id
FROM records
WHERE option_id = o.option_id
ORDER BY id DESC NULLS LAST
LIMIT 1) AS max_id
FROM options o
ORDER BY 1;
Kan være lidt hurtigere. Underforespørgslen bruger sorteringsrækkefølgen DESC NULLS LAST
- samme som den samlede funktion max()
som ignorerer NULL-værdier. Sorterer kun DESC
ville have NULL først:
- Hvorfor kommer NULL-værdier først, når du bestiller DESC i en PostgreSQL-forespørgsel?
Det perfekte indeks til dette:
CREATE INDEX on records (option_id, id DESC NULLS LAST);
Indekssorteringsrækkefølgen betyder ikke meget, mens kolonner er defineret NOT NULL
.
Der kan stadig være en sekventiel scanning på den lille tabel options
, det er bare den hurtigste måde at hente alle rækker på. ORDER BY
kan indsætte en (kun) indeksscanning for at hente forudsorterede rækker.
Den store tabel records
er kun tilgængelig via (bitmap) indeksscanning eller, hvis det er muligt, kun indeksscanning .
db<>spil her - viser kun to indeksscanninger for den simple sag
Gamle sqlfiddle
Eller brug LATERAL
slutter sig til en lignende effekt i Postgres 9.3+:
- Optimer GROUP BY-forespørgsel for at hente seneste række pr. bruger