user hit>
When rewriting your function, I realized that you added column aliases:
SELECT ... auth_user.email AS user , customers.name AS customer,
.. which did nothing , since these aliases are invisible outside the function and are not mentioned inside the function. Therefore, they will be ignored. For documentation purposes, better use a comment.
But it also makes your query invalid because user is a fully reserved word and cannot be used as a column alias unless double quoting is specified.
Oddly enough, in my tests, the function seems to work with the wrong alias. Probably because it is ignored (?). But I'm not sure that this could not have any side effects.
Your function is overwritten (otherwise equivalent):
CREATE OR REPLACE FUNCTION get_web_events_by_userid(int) RETURNS TABLE( id int , time_stamp timestamptz , description text , origin text , userlogin text , customer text , client_ip inet ) AS $func$ SELECT w.id , w.time_stamp , w.description , w.origin , u.email
Obviously, the STABLE keyword has changed the result. Function volatility should not be a problem in the described test situation. Typically, a setting does not provide a single, isolated function call. Read the details in the manual. In addition, the standard EXPLAIN does not display query plans for functions inside , you can use the optional auto-explain module for this:
But , as we developed in the next question, changing the function volatility to STABLE allows you to embed a simple SELECT into an external operator, thereby effectively removing the function from the image. This explains why we see the query plan after adding STABLE , and also explains why the query plan is different.
You have a very odd data distribution :
The auth_web_events table contains 100,000,000 entries, auth_user-> 2 entries, clients-> 1 entry
Since you did not specify otherwise, the function assumes an estimate of 1000 lines . But your function actually only returns 2 rows . If all your calls return (in close proximity) to two lines, just declare it with the added ROWS 2 . It is also possible to change the query plan for the VOLATILE variant (even if STABLE is the right choice anyway here).