Skip to content
Snippets Groups Projects
Commit 947c3bd7 authored by Raphael Collet's avatar Raphael Collet
Browse files

[FIX] expression: avoid ORDER BY clause in subqueries


This fixes a performance issue: ORDER BY clauses in subqueries can make
the query unexpectedly slow.  We should avoid this situation, since
ORM-generated queries have an ORDER BY clause which is not relevant in
the context of a subquery.

The following example was found:

    SELECT "pos_payment"."id" AS "id"
      FROM "pos_payment"
     WHERE ("pos_payment"."pos_order_id" in
              (SELECT "pos_order".id
                 FROM "pos_order"
                WHERE ("pos_order"."company_id" in (1))
             ORDER BY "pos_order"."id"))
       AND "pos_payment".id IN (1285508)

Here are the query plans made by PostgreSQL on this query with and
without the ORDER BY clause.  The query time went from 1240ms to
0.402ms, which is 3000 times faster!

EXPLAIN ANALYZE SELECT "pos_payment"."id" as "id" FROM "pos_payment" WHERE ("pos_payment"."pos_order_id" in (SELECT "pos_order".id FROM "pos_order" WHERE ("pos_order"."company_id" in (1)) ORDER BY  "pos_order"."id"  )) AND "pos_payment".id IN (1285508);
                                                                    QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------
 Merge Semi Join  (cost=2.88..82726.85 rows=1 width=4) (actual time=1239.361..1239.364 rows=1 loops=1)
   Merge Cond: (pos_payment.pos_order_id = pos_order.id)
   ->  Sort  (cost=2.46..2.46 rows=1 width=8) (actual time=0.021..0.022 rows=1 loops=1)
         Sort Key: pos_payment.pos_order_id
         Sort Method: quicksort  Memory: 25kB
         ->  Index Scan using pos_payment_pkey on pos_payment  (cost=0.43..2.45 rows=1 width=8) (actual time=0.014..0.015 rows=1 loops=1)
               Index Cond: (id = 1285508)
   ->  Index Scan using pos_order_pkey on pos_order  (cost=0.43..66770.53 rows=1282120 width=4) (actual time=0.013..1148.194 rows=1182463 loops=1)
         Filter: (company_id = 1)
 Planning time: 0.272 ms
 Execution time: 1239.396 ms
(11 rows)

EXPLAIN ANALYZE SELECT "pos_payment"."id" as "id" FROM "pos_payment" WHERE ("pos_payment"."pos_order_id" in (SELECT "pos_order".id FROM "pos_order" WHERE ("pos_order
"."company_id" in (1)) )) AND "pos_payment".id IN (1285508);
                                                             QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.85..4.89 rows=1 width=4) (actual time=0.047..0.049 rows=1 loops=1)
   ->  Index Scan using pos_payment_pkey on pos_payment  (cost=0.43..2.45 rows=1 width=8) (actual time=0.027..0.028 rows=1 loops=1)
         Index Cond: (id = 1285508)
   ->  Index Scan using pos_order_pkey on pos_order  (cost=0.43..2.45 rows=1 width=4) (actual time=0.018..0.018 rows=1 loops=1)
         Index Cond: (id = pos_payment.pos_order_id)
         Filter: (company_id = 1)
 Planning time: 0.322 ms
 Execution time: 0.080 ms
(8 rows)

closes odoo/odoo#77234

Signed-off-by: default avatarRaphael Collet (rco) <rco@openerp.com>
Co-authored-by: default avatarStanislas Sobieski <(sts@odoo.com)>
parent c9009bde
No related branches found
No related tags found
No related merge requests found
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment