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

Изтрийте с помощта на CTE по-бавно, отколкото с помощта на временна таблица в Postgres

CTE е по-бавен, защото трябва да се изпълни непроменен (чрез CTE сканиране).

TFM (раздел 7.8.2) гласи: Инструкциите за модифициране на данни в WITH се изпълняват точно веднъж и винаги до завършване, независимо от това дали първичната заявка чете целия (или изобщо някакъв) от техния изход. Забележете, че това е различно от правилото за SELECT в WITH:както е посочено в предишния раздел, изпълнението на SELECT е се пренася само дотолкова, доколкото основната заявка изисква своя резултат.

Следователно това е пречка за оптимизиране; за оптимизатора демонтирането на CTE не е разрешено, дори ако това би довело до по-интелигентен план със същите резултати.

CTE-решението обаче може да бъде преработено в обединена подзаявка (подобно на временната таблица във въпроса). В postgres обединената подзаявка обикновено е по-бърза от варианта EXISTS() днес.

DELETE FROM customer del
USING ( SELECT id
        , row_number() over(partition by uuid order by created_date desc)
                 as rn
        FROM customer
        ) sub
WHERE sub.id = del.id
AND sub.rn > 1
        ;

Друг начин е да използвате TEMP VIEW . Това е синтактично еквивалентно на temp table случай, но семантично еквивалентно на присъединения формуляр за подзаявка (те дават точно същият план за заявка, поне в този случай). Това е така, защото оптимизаторът на Postgres демонтира изгледа и го комбинира с основната заявка (издърпване ). Можете да видите view като вид макрос в PG.

CREATE TEMP VIEW targets
AS SELECT id
        , row_number() over(partition by uuid ORDER BY created_date DESC) AS rn
FROM customer;

EXPLAIN
DELETE FROM customer
WHERE id IN ( SELECT id
            FROM targets
            WHERE rn > 1
        );

[АКТУАЛИЗИРАНО:Сгреших относно необходимостта от CTE винаги да се изпълняват до завършване, което важи само за CTE, модифициращи данни]



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. JSONB прави ли PostgreSQL масивите безполезни?

  2. Laravel:Грешка [PDOException]:Не можа да се намери драйвер в PostgreSQL

  3. Колко голямо е твърде голямо за PostgreSQL таблица?

  4. Таблица за разделяне въз основа на първата буква на поле varchar

  5. SQLAlchemy проверява SSL връзката