Re: Sort operation displays more tuples than it contains its subnode

From: David Rowley <dgrowleyml(at)gmail(dot)com>
To: "a(dot)rybakina" <a(dot)rybakina(at)postgrespro(dot)ru>
Cc: PostgreSQL Developers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Sort operation displays more tuples than it contains its subnode
Date: 2024-05-22 21:08:35
Message-ID: CAApHDvq72iFMdMbZd+5ac_2bP1=80+g5m0xkAp+zGn6iCEZt-w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, 23 May 2024 at 08:48, a.rybakina <a(dot)rybakina(at)postgrespro(dot)ru> wrote:
> -> Sort (cost=613.48..632.86 rows=7754 width=8) (actual time=7.612..21.214 rows=77531 loops=1)
> Sort Key: broke_down_course.sno, broke_down_course.cno
> Sort Method: quicksort Memory: 374kB
> -> Seq Scan on broke_down_course (cost=0.00..112.54 rows=7754 width=8) (actual time=0.016..1.366 rows=7754 loops=1)

> Maybe, my reproduction looks questionable, sorry for that, but I seriously don't understand why we have so many tuples here in Sort node.

This is because of the "mark and restore" that occurs because of the
Merge Join. This must happen for joins because every tuple matching
the join condition must join to every other tuple that matches the
join condition. That means, if you have 3 tuples with the same key on
either side, you get 9 rows, not 3 rows.

Here's a simple example of the behaviour you describe shrunk down so
that it's more easily understandable:

create table t(a int);
insert into t values(1),(1),(1);
set enable_hashjoin=0;
set enable_nestloop=0;
explain (analyze, costs off) select * from t inner join t t1 on t.a=t1.a;
QUERY PLAN
------------------------------------------------------------------------
Merge Join (actual time=0.036..0.038 rows=9 loops=1)
Merge Cond: (t.a = t1.a)
-> Sort (actual time=0.025..0.025 rows=3 loops=1)
Sort Key: t.a
Sort Method: quicksort Memory: 25kB
-> Seq Scan on t (actual time=0.017..0.018 rows=3 loops=1)
-> Sort (actual time=0.007..0.007 rows=7 loops=1)
Sort Key: t1.a
Sort Method: quicksort Memory: 25kB
-> Seq Scan on t t1 (actual time=0.003..0.003 rows=3 loops=1)

Note the sort has rows=7 and the Seq Scan on t1 rows=3 and an output of 9 rows.

If you look at the code in [1], you can see the restoreMark() calls to
achieve this.

David

[1] https://en.wikipedia.org/wiki/Sort-merge_join

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2024-05-22 21:17:48 Re: Sort operation displays more tuples than it contains its subnode
Previous Message a.rybakina 2024-05-22 20:31:21 Sort operation displays more tuples than it contains its subnode