PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Usuwanie przy użyciu CTE wolniej niż przy użyciu tabeli tymczasowej w Postgresie

CTE jest wolniejsze, ponieważ musi być wykonywane bez zmian (poprzez skanowanie CTE).

TFM (sekcja 7.8.2) stwierdza: Instrukcje modyfikujące dane w WITH są wykonywane dokładnie raz i zawsze aż do zakończenia, niezależnie od tego, czy podstawowe zapytanie odczytuje wszystkie (czy rzeczywiście jakiekolwiek) ich dane wyjściowe.Zauważ, że różni się to od reguły dla SELECT w WITH:jak wspomniano w poprzedniej sekcji, wykonanie SELECT jest przenoszone tylko na tyle, na ile podstawowe zapytanie wymaga jego wyjścia.

Jest to zatem bariera optymalizacji; dla optymalizatora demontaż CTE jest niedozwolony, nawet jeśli skutkowałoby to mądrzejszym planem z takimi samymi wynikami.

Rozwiązanie CTE można jednak przekształcić w połączone podzapytanie (podobnie do tabeli tymczasowej w pytaniu). W postgresie połączone podzapytanie jest zwykle szybsze niż obecnie dostępny wariant 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
        ;

Innym sposobem jest użycie TEMP VIEW . To jest syntaktycznie odpowiednik temp table przypadku, ale semantycznie odpowiednik połączonego formularza podzapytania (dają dokładnie ten sam plan zapytań, przynajmniej w tym przypadku). Dzieje się tak, ponieważ optymalizator Postgresa demontuje widok i łączy go z głównym zapytaniem (pull-up ). Możesz zobaczyć view jako rodzaj makra w 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
        );

[AKTUALIZACJA:Myliłem się co do tego, że CTE muszą być zawsze wykonywane do zakończenia, co ma miejsce tylko w przypadku modyfikacji danych 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. Wywołanie niezdefiniowanej funkcji pg_connect() - Wamp

  2. Jak pobrać identyfikator wstawionego wiersza podczas używania upsert z klauzulą ​​WITH w Posgres 9.5?

  3. Jak wydobyć wartość mediany?

  4. Wstaw, jeśli nie istnieje, w przeciwnym razie zwróć identyfikator w postgresql

  5. jak mieć filtr niewrażliwy na akcenty w django z postgresem?