Ако приемем, че са относително малко редове в options
за много редове в records
.
Обикновено ще имате таблица с options
който се препраща от records.option_id
, в идеалния случай с ограничение за външен ключ. Ако не го направите, предлагам да създадете такъв, за да наложите референтната цялост:
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;
Тогава вече няма нужда да се емулира свободно сканиране на индекса и това става много просто и бързо . Корелираните подзаявки могат да използват обикновен индекс на (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;
Това включва опции без съвпадение в таблица records
. Получавате NULL за max_id
и можете лесно да премахнете такива редове във външен SELECT
ако е необходимо.
Или (същият резултат):
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;
Може малко по-бързо. Подзаявката използва реда на сортиране DESC NULLS LAST
- същото като агрегатната функция max()
което игнорира NULL стойности. Сортиране само DESC
първо ще има NULL:
- Защо NULL стойностите са на първо място при поръчка на DESC в PostgreSQL заявка?
Идеалният индекс за това:
CREATE INDEX on records (option_id, id DESC NULLS LAST);
Индексният ред на сортиране няма голямо значение, докато колоните са дефинирани NOT NULL
.
Все още може да има последователно сканиране на малката таблица options
, това е най-бързият начин за извличане на всички редове. ORDER BY
може да въведе индексно (само) сканиране за извличане на предварително сортирани редове.
Голямата таблица records
е достъпен само чрез (битова карта) индексно сканиране или, ако е възможно, сканиране само с индекс .
db<>цигулка тук - показва две сканирания само за индекси за простия случай
Стара sqlfiddle
Или използвайте LATERAL
се присъединява за подобен ефект в Postgres 9.3+:
- Оптимизиране на заявката GROUP BY за извличане на последния ред на потребител