Thanks Rui. The performance of using function is close to the plain SQL.

Why Query planner is choosing different path with DB view?


explain analyze select foo(101,0);
                                           QUERY
PLAN
------------------------------------------------------------------------------------------------
 ProjectSet  (cost=0.00..5.27 rows=1000 width=32) (actual
time=10.340..10.374 rows=101 loops=1)
   ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001
rows=1 loops=1)
 Planning time: 0.035 ms
 Execution time: 10.436 ms
(4 rows)



On Mon, Apr 1, 2019 at 4:14 PM Rui DeSousa <r...@crazybean.net> wrote:

> Try using a function that returns the result set.
>
> i.e.
>
> create or replace function foo(_limit int, _offset int)
>   returns setof sample_table
> as $$
> begin
>   return query
>     select *
>     from sample_table
>     order by created_date
>     limit _limit
>     offset _offset
>   ;
> end;
> $$ language plpgsql
>   volatile
> ;
>
>
> Given your query; return a table instead of a set. i.e.:
>
> returns table (
>    id int
>   , parent_id int
>   .
>   .
>   .
>   , response_body text
> )
> as $$
>
>
> Query example:
>
> select * from foo(100, 50);
>
>
> On Apr 1, 2019, at 9:56 AM, Raj Gandhi <raj01gan...@gmail.com> wrote:
>
> Any other idea how to resolve the performance issue with the database view?
>
> On Fri, Mar 29, 2019 at 7:38 PM Raj Gandhi <raj01gan...@gmail.com> wrote:
>
>> Merlin,  I tried the hack you suggested but that didn't work. Planner
>> used the same path.
>>
>> The same query works much faster when using the raw SQL instead of  DB
>> view:
>>
>> Here is the definition of DB View ‘job’
>>  SELECT w.id,
>>     w.parent_id,
>>     w.status AS state,
>>     w.percent_complete AS progress_percentage,
>>     w.start_time,
>>     w.end_time,
>>     w.est_completion_time AS estimated_completion_time,
>>     w.root_id,
>>     w.internal AS is_internal,
>>     w.order_id AS step_order,
>>     c.resource_type,
>>     c.resource_id,
>>     c.id AS command_id,
>>     c.client_cookie,
>>     c.user_name AS "user",
>>     c.metadata,
>>     c.client_address,
>>     response_body(r.*, w.*) AS response_body
>>    FROM work_unit w
>>      LEFT JOIN command c ON c.work_unit_id = w.id
>>      LEFT JOIN command_response r ON r.command_id::text = c.id::text;
>>
>>
>>
>>
>> *Query that uses the DB view:*
>> SELECT id, start_time
>> FROM job
>> order by id  LIMIT 101 OFFSET 0;
>>
>>
>> Explain plan: https://explain.depesz.com/s/gzjQ
>>
>>  *Query using the raw SQL*
>> <SQL from Job DB View definition>
>> ORDER BY id LIMIT 101 OFFSET 0;
>>
>>
>> Explain plan:https://explain.depesz.com/s/KgwO
>>
>>
>>
>>
>> On Fri, Mar 29, 2019 at 11:26 AM Merlin Moncure <mmonc...@gmail.com>
>> wrote:
>>
>>> On Thu, Mar 28, 2019 at 5:44 PM Raj Gandhi <raj01gan...@gmail.com>
>>> wrote:
>>> >
>>> > + pgsql-performance
>>> >
>>> > On Thu, Mar 28, 2019 at 6:41 PM Raj Gandhi <raj01gan...@gmail.com>
>>> wrote:
>>> >>
>>> >> Hi everyone,
>>> >>
>>> >>
>>> >>
>>> >> I’m using LIMIT offset with DB view. Looks like query planner is
>>> applying the LIMIT for DB view at the end after processing all rows.
>>> >>
>>> >> When running same SQL that was used to create the DB view, LIMIT is
>>> applied earlier so the query is much faster.
>>> >>
>>> >>
>>> >>
>>> >> Explain plan using DB view
>>> >>
>>> >> https://explain.depesz.com/s/gzjQ
>>> >>
>>> >>
>>> >>
>>> >> Explain plan using raw SQL
>>> >>
>>> >> https://explain.depesz.com/s/KgwO
>>> >>
>>> >>
>>> >>
>>> >> In both tests LIMIT was 100 with offset  = 0.
>>> >>
>>> >> Is there any way to force DB view to apply limit earlier?
>>>
>>> huh. OFFSET does indeed force a materialize plan.   This is a widely
>>> used tactic to hack the planner ('OFFSET 0').
>>>
>>> Maybe try converting your query from something like:
>>>
>>> SELECT * FROM foo LIMIT m OFFSET N;
>>> to
>>> WITH data AS
>>> (
>>>   SELECT * FROM foo LIMIT m + n
>>> )
>>> SELECT * FROM foo OFFSET n;
>>>
>>> I didn't try this, and it may not help, but it's worth a shot.
>>>
>>> merlin
>>>
>>
>

Reply via email to