Có thể khai báo biến động chức năng IMMUTABLE làm hại hiệu suất?


9

Các hàm Postgres được khai báo với phân loại biến động VOLATILE, STABLEhoặcIMMUTABLE . Dự án được biết là rất nghiêm ngặt với các nhãn này cho các chức năng tích hợp. Và với lý do chính đáng. Ví dụ nổi bật: các chỉ mục biểu thức chỉ cho phép các IMMUTABLEhàm và chúng phải thực sự bất biến để tránh kết quả không chính xác.

Các hàm do người dùng định nghĩa vẫn miễn phí được khai báo khi chủ sở hữu chọn. Hướng dẫn tư vấn:

Để có kết quả tối ưu hóa tốt nhất, bạn nên gắn nhãn các chức năng của mình với danh mục biến động nghiêm ngặt nhất có giá trị đối với chúng.

... Và thêm một danh sách rộng lớn những thứ có thể sai với nhãn biến động không chính xác.

Tuy nhiên, có những trường hợp giả mạo bất biến có ý nghĩa. Hầu hết khi bạn biết chức năng, trên thực tế, là bất biến trong phạm vi của bạn. Thí dụ:

Tất cả các tác động có thể có về tính toàn vẹn dữ liệu sang một bên , ảnh hưởng đến hiệu suất là gì? Người ta có thể cho rằng khai báo một chức năng IMMUTABLEchỉ có thể có lợi cho hiệu suất . Là vậy sao?

Có thể khai báo chức năng biến động IMMUTABLE gây hại hiệu suất?

Giả sử Postgres 10 hiện tại để thu hẹp nó, nhưng tất cả các phiên bản gần đây đều đáng quan tâm.


1
Như một lưu ý phụ, toàn bộ "thực sự bất biến" trên các chỉ số biểu thức là một pita thực sự. Đó là một giao diện người dùng khủng khiếp. Chúng ta nên có thể cho FORCEhọ một trong hai cách. 100% các DBA PostgreSQL có kinh nghiệm nói dối để làm việc xung quanh giao diện người dùng đó với các chức năng bao bọc. Ít nhất là với FORCE, chúng tôi sẽ không cần giấy gói và chúng tôi sẽ không phải nói dối về biến động fn được tuyên bố.
Evan Carroll

1
Tôi giả sử FORCEđược cho là làm cho các chỉ mục biểu thức chấp nhận các hàm không bất biến (trong khi đánh dấu chúng là điểm tiềm năng của sự thất bại). Vâng, đó có vẻ như là một giải pháp thanh lịch hơn các hàm bao hàm bất biến.
Erwin Brandstetter

Tôi gần như không biết gì về PostGres nhưng không biến động Dự phòng dễ bay hơi? Nó có nghĩa là gì? Nghiêm túc không mong đợi điều này là đáng tin cậy, vì nó điên ?
Anthony

@Anthony: Tôi đã làm rõ thêm một số. Theo liên kết đến hướng dẫn để biết chi tiết.
Erwin Brandstetter

Câu trả lời:


7

Có, nó có thể gây hại cho hiệu suất.

Các hàm SQL đơn giản có thể được "nội tuyến" trong truy vấn gọi. Trích dẫn Wiki Postgres :

Các hàm SQL (tức là LANGUAGE SQL) sẽ, trong các điều kiện nhất định, có các thân hàm của chúng được đặt vào truy vấn gọi thay vì được gọi trực tiếp. Điều này có thể có lợi thế hiệu suất đáng kể vì cơ thể chức năng tiếp xúc với trình hoạch định truy vấn cuộc gọi, có thể áp dụng các tối ưu hóa như gập liên tục, đẩy xuống chất lượng, v.v.

Nhấn mạnh đậm của tôi.

Để thực thi tính đúng đắn, có một số điều kiện tiên quyết. Một trong số họ :

nếu hàm được khai báo IMMUTABLE, thì biểu thức không được gọi bất kỳ hàm hoặc toán tử không bất biến nào

Có nghĩa là, các hàm SQL sử dụng bất kỳ hàm không thay đổi nào nhưng vẫn được khai báo IMMTUTABLEsẽ bị loại trừ khỏi tối ưu hóa này. Bị kích thích bởi những câu trả lời liên quan trên SO, tôi đã chạy thử nghiệm rộng rãi:

Về cơ bản so sánh hai biến thể của một hàm SQL đơn giản (ánh xạ ngày thành một integer, bỏ qua năm không quan trọng cho mục đích):

CREATE FUNCTION f_mmdd_tc_s(date) RETURNS int LANGUAGE sql STABLE    AS
$$SELECT to_char($1, 'MMDD')::int$$;

CREATE FUNCTION f_mmdd_tc_i(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT to_char($1, 'MMDD')::int$$;  -- cannot be inlined!

Hàm Postgres to_char()chỉ STABLE, không IMMUTABLE(tất cả các trường hợp quá tải của nó - vì những lý do nằm ngoài phạm vi của câu trả lời này ). Vì vậy, cái thứ hai là giả IMMUTABLEvà hóa ra là chậm hơn 5x trong một thử nghiệm đơn giản:

db <> fiddle ở đây

Ví dụ cụ thể này có thể được thay thế bằng tương đương:

CREATE FUNCTION f_mmdd(date) RETURNS int LANGUAGE sql IMMUTABLE AS
$$SELECT (EXTRACT(month FROM $1) * 100 + EXTRACT(day FROM $1))::int$$;

Sẽ có vẻ đắt hơn với hai cuộc gọi chức năng và tính toán nhiều hơn. Tuy nhiên, IMMUTABLEnhãn là đúng (cộng, chức năng sử dụng nhanh hơn và ép buộc textđể integerlà tốn kém hơn, quá).

Nhanh gấp 2 lần biến thể nhanh hơn ở trên (nhanh gấp 10 lần so với biến thể chậm hơn). Vấn đề là: Sử dụng các IMMUTABLEchức năng nếu có thể , sau đó bạn không phải "gian lận" để bắt đầu.


Phát hiện tuyệt vời! Có ngay lập tức theo dõi nó: dba.stackexchange.com/q/212198/2639
Evan Carroll

Bạn biết những gì tôi nghĩ rằng tôi đã bỏ lỡ ở đây, mà tôi đã không biết. Đó STABLEcũng là nội tuyến. Tôi nghĩ rằng trình tối ưu hóa sẽ chỉ có IMMUTABLEchức năng trực tuyến .
Evan Carroll

VOLATILEcũng như vậy
Erwin Brandstetter

Wiki cho biết chức năng này được khai báo là STABLE hoặc IMMUTABLE wiki.postgresql.org/wiki/Inlining_of_Query_fifts
Evan Carroll

.. trong "Điều kiện nội tuyến cho các hàm bảng ". Không cho các hàm vô hướng. Tôi đã chứng minh điều đó trong fiddle: dbfiddle.uk/
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.