PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Влияние на производителността на изгледа върху агрегатната функция спрямо ограничаването на набора от резултати

Заявките не са строго еквивалентни

За да направите контекста ясен:

  • 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 .

Но в момента всичко това е изкривено във въпроса. Очакваме, докато това бъде почистено.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изгледи на PostgreSQL:Препратка към едно изчисляемо поле в друго изчисляемо поле

  2. Мога ли да задам (в рамките на dbase) ограничение на размера на поле bytea в PostgreSQL?

  3. PostgreSQL - не можа да идентифицира оператор за равенство за тип json

  4. Отмяна на транзакция при задействане ГРЕШКА

  5. PostgreSQL създава индекс при прехвърляне от низ към дата