CTE chậm hơn vì nó phải được thực thi không thay đổi (thông qua quét CTE).
Do đó, nó là một rào cản tối ưu hóa ; đối với trình tối ưu hóa, việc tháo dỡ CTE không được phép, ngay cả khi nó sẽ dẫn đến một kế hoạch thông minh hơn với cùng kết quả.
Tuy nhiên, giải pháp CTE có thể được cấu trúc lại thành một truy vấn con được kết hợp (tương tự như bảng tạm thời trong câu hỏi). Trong postgres, một truy vấn con được kết hợp thường nhanh hơn so với biến thể EXISTS (), ngày nay.
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
;
Một cách khác là sử dụng TEMP VIEW
. Đây là về mặt cú pháp tương đương với temp table
trường hợp, nhưng về mặt ngữ nghĩa tương đương với biểu mẫu truy vấn con đã kết hợp (chúng mang lại chính xác cùng một kế hoạch truy vấn, ít nhất là trong trường hợp này). Điều này là do trình tối ưu hóa của Postgres tháo dỡ chế độ xem và kết hợp nó với truy vấn chính ( kéo lên ). Bạn có thể thấy một view
như một loại macro trong 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
);
[CẬP NHẬT:Tôi đã nhầm về việc các CTE cần phải luôn được thực thi để hoàn thành, đây chỉ là trường hợp đối với các CTE sửa đổi dữ liệu]