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

Оптимизиране на груповата максимална заявка

Ако приемем, че са относително малко редове в 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 за извличане на последния ред на потребител


  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. Връщане на списък с часови зони, поддържани от PostgreSQL

  3. 2 начина за добавяне на водещи нули в PostgreSQL

  4. Неуспешна инсталация на PostgresSQL:неуспешна инициализация на клъстер на база данни MAC OS

  5. PostgreSQL Connection Pooling:Част 1 – Плюсове и минуси