Заявките не са строго еквивалентни
За да направите контекста ясен:
max(id)изключваNULLстойности. НоORDER BY ... LIMIT 1не.NULLстойностите се сортират последни във възходящ ред и първи в низходящ. Така чеIndex Scan Backwardможе да не намери най-голямата стойност (споредmax()) първи, но произволен брой отNULLстойности.
Формалният еквивалент на:
SELECT max(id) FROM testview;
не е:
SELECT id FROM testview ORDER BY id DESC LIMIT 1;
но:
SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;
Последната заявка не получава плана за бърза заявка. Но би било с индекс със съвпадащ ред на сортиране:(id DESC NULLS LAST) .
Това е различно за агрегатните функции min() и max() . Те получават бърз план при насочване към таблица test1 директно използвайки обикновения PK индекс на (id) . Но не и когато се базира на изгледа (или директно на основната заявка за присъединяване - изгледът не е блокерът). Индекс, сортиращ NULL стойности на правилното място, едва ли има някакъв ефект.
Ние познайте този id в тази заявка никога не може да бъде NULL . Колоната е дефинирана NOT NULL . И обединяването в изгледа на практика е INNER JOIN което не може да въведе NULL стойности за id .
Ние също знайте, че индексът на test.id не може да съдържа NULL стойности.
Но програмата за планиране на заявки на Postgres не е AI. (Нито се опитва да бъде, това може бързо да излезе извън ръцете.) Виждам два недостатъка :
min()иmax()вземете бързия план само при насочване към таблицата, независимо от реда на сортиране на индекса, се добавя условие за индекс:Index Cond: (id IS NOT NULL)ORDER BY ... LIMIT 1получава бързия план само с точно съвпадащ ред на сортиране на индекса.
Не съм сигурен дали това може да се подобри (лесно).
db<>fiddle тук - демонстриране на всичко по-горе
Индекси
Този индекс е напълно безполезен:
CREATE INDEX ON "test" ("id");
PK на test.id е внедрен с уникален индекс в колоната, който вече покрива всичко, което допълнителният индекс може да направи за вас.
Може да има още, чакаме въпросът да се изясни.
Изкривен тестов случай
Тестовият случай е твърде далеч от действителния случай на употреба, за да има смисъл.
При тестовата настройка всяка таблица има 100k реда, няма гаранция, че всяка стойност в joincol има съвпадение от другата страна и двете колони могат да бъдат NULL
Вашият реален случай има 10 милиона реда в table1 и <100 реда в table2 , всяка стойност в table1.joincol има съвпадение в table2.joincol , и двете са дефинирани NOT NULL и table2.joincol е уникален. Класическа връзка "един към много". Трябва да има UNIQUE ограничение на table2.joincol и FK ограничение t1.joincol --> t2.joincol .
Но в момента всичко това е изкривено във въпроса. Очакваме, докато това бъде почистено.