2017-02-23 15 views
6

Nếu tôi có truy vấn như sau:Có phải bưu cục COALESCE lười biếng không?

SELECT COALESCE(
    (SELECT value FROM precomputed WHERE ...), 
    alwaysComputeValue(...) 
); 

Biểu thức thứ hai sẽ được đánh giá? Cũng có thể điều này phụ thuộc vào kế hoạch thực hiện hay nó độc lập?

+4

Câu hỏi hay. Tôi muốn nói: kiểm tra kế hoạch. – wildplasser

Trả lời

4

Khái niệm nó là lười biếng:

Giống như một biểu thức CASE, COLALESCE chỉ đánh giá các đối số cần thiết để xác định kết quả; có nghĩa là, các đối số ở bên phải của đối số không null đầu tiên không được đánh giá.

https://www.postgresql.org/docs/9.6/static/functions-conditional.html

Tuy nhiên, nếu biểu thức bên phải là không bị tổn hại sau đó nó nên không có sự khác biệt cho dù đó là lười biếng hay không, vì vậy trong trường hợp này nó sẽ cho phép đối với các kế hoạch truy vấn háo hức đánh giá đối số bên phải nếu nó ổn định hoặc không thay đổi, nếu điều này có vẻ là một tối ưu hóa hợp lý.

Một trường hợp rõ ràng là với SELECT COALESCE(a, b) FROM table nó sẽ có khả năng lấy lại ab lĩnh vực của tất cả các hàng chứ không phải lấy a và sau đó lấy b nếu cần thiết.

Cách duy nhất để có bất kỳ hiệu ứng quan sát nào ở đây là nếu bạn đã viết một hàm dễ bay hơi và cố ý gắn nhãn sai nó là stable hoặc immutable. Sau đó, nó sẽ là có thể để được đánh giá nếu ở bên phải của một coalesce trong đó tay trái không phải là rỗng. (Sẽ có thể cho một hàm thực sự ổn định, nhưng nếu nó ổn định nó sẽ không có tác dụng phụ, và nếu nó không có tác dụng phụ cho dù nó xảy ra hay không sẽ không thể quan sát được).

Given:

CREATE OR REPLACE FUNCTION immutable_func(arg integer) 
RETURNS integer 
AS $BODY$ 
BEGIN 
    RAISE NOTICE 'Immutable function called with %', arg; 
    RETURN arg; 
END; 
$BODY$ LANGUAGE plpgsql IMMUTABLE; 

WITH data AS 
(
    SELECT 10 AS num 
    UNION ALL SELECT 5 
    UNION ALL SELECT 20 
) 
select coalesce(num, immutable_func(2)) 
from data 

Các kế hoạch đều biết rằng nó sẽ có kết quả tương tự cho immutable_func(2) cho mỗi hàng và gọi đó là một lần duy nhất cho toàn bộ truy vấn, cho chúng ta thông điệp Immutable function called with 2. Vì vậy, nó đã thực sự được đánh giá mặc dù nó không nằm trong quy tắc của "đối số ở bên phải của đối số không null đầu tiên không được đánh giá". Việc trả tiền là trong trường hợp (hợp lý để mong đợi) của nhiều null num nó sẽ vẫn chỉ chạy một lần.

Điều này chống lại chữ của hành vi được ghi nhận là tốt, bởi vì chúng tôi đã nói với nó rằng việc tối ưu hóa như vậy là hợp lệ. Nếu điều này gây ra sự cố, lỗi sẽ có chức năng được đánh dấu là IMMUTABLE không phải trong đánh giá háo hức.

Nó cũng có thể là một phần. Với SELECT COALESCE(a, Some_Func(b)) FROM table nó sẽ không được đánh giá Some_Func(b) háo hức, nhưng nó sẽ được truy xuất b để có thể làm như vậy.

Bất cứ khi nào nó thực sự ảnh hưởng đến hành vi quan sát (không gian lận), quy tắc được tuân theo.

+0

Wow, câu trả lời quá dài, nhưng .. Tôi biết nó có thể được đánh giá * theo lý thuyết * nếu tôi đánh dấu chức năng bất biến hoặc ổn định và đặt chi phí thấp cho kế hoạch, * nhưng * điều này có thể thực sự xảy ra không? :-) – langpavel

+0

Có thể. Sẽ cập nhật câu trả lời. –

4

Từ the documentation:

Giống như một biểu thức CASE, liên hiệp chỉ đánh giá các đối số cần thiết để xác định kết quả; có nghĩa là, các đối số ở bên phải của đối số không null đầu tiên không được đánh giá.

Các vấn đề liên quan