Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vETkY-00C8dU-HC for pgsql-hackers@arkaria.postgresql.org; Thu, 30 Oct 2025 14:35:37 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1vETkX-008qfW-7M for pgsql-hackers@arkaria.postgresql.org; Thu, 30 Oct 2025 14:35:36 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1vETkW-008qfO-MJ for pgsql-hackers@lists.postgresql.org; Thu, 30 Oct 2025 14:35:35 +0000 Received: from forward501d.mail.yandex.net ([2a02:6b8:c41:1300:1:45:d181:d501]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vETkS-0055Al-2r for pgsql-hackers@postgresql.org; Thu, 30 Oct 2025 14:35:35 +0000 Received: from mail-nwsmtp-smtp-production-main-88.klg.yp-c.yandex.net (mail-nwsmtp-smtp-production-main-88.klg.yp-c.yandex.net [IPv6:2a02:6b8:c43:84a0:0:640:dfd2:0]) by forward501d.mail.yandex.net (Yandex) with ESMTPS id EC7CE80896; Thu, 30 Oct 2025 17:35:26 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-88.klg.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id OZgYTtDLTmI0-VF5S7YIO; Thu, 30 Oct 2025 17:35:26 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tantorlabs.com; s=mail; t=1761834926; bh=cIc2ByH0mw8U7zdKGbjSGITRVVRy9pYxkbcN1AK0uqk=; h=In-Reply-To:Cc:Date:References:To:Subject:Message-ID:From; b=12cVF473Bg1hdhc9dAUA61GXkfQiX6wWOAXGk43hzbYCJEXflVVA4kyxr5VU2s3e8 AE4LpiI1xCD0Q0l+m6YtFit7UHf+74cYqi67KqcjOcC2jHRvMztLt6NH9ORqt9VDqc kIhYCrPgwwhNyjQXtogG4le4+AA9clpwoQcC8HgA= Authentication-Results: mail-nwsmtp-smtp-production-main-88.klg.yp-c.yandex.net; dkim=pass header.i=@tantorlabs.com Content-Type: multipart/alternative; boundary="------------xRz1sqtjIcE0v0sUPS4xYv2A" Message-ID: Date: Thu, 30 Oct 2025 17:35:24 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: V18 change on EXPLAIN ANALYZE To: maciek@sakrejda.org, Tom Lane Cc: Robert Haas , Marcos Pegoraro , pgsql-hackers References: <34604.1758921116@sss.pgh.pa.us> Content-Language: en-US From: Ilia Evdokimov In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------xRz1sqtjIcE0v0sUPS4xYv2A Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi hackers, On 27.09.2025 03:31, Maciek Sakrejda wrote: > However, to get a parallel query in the regression database (I chose > EXPLAIN ANALYZE SELECT * FROM tenk2), I had to change some settings: > > SET min_parallel_table_scan_size = 0; > SET parallel_tuple_cost = 0; > SET parallel_setup_cost = 0; > > Should I mention that in the example? Or should I generate a bigger > table so using these is not necessary? If we say nothing and use the > example, I think it may be confusing if someone wants to use the > example as a starting point for their own exploration of how this > works. Or is there a better query that works out of the box and does > not need changes to the settings? > > It also seems like the EXPLAIN ANALYZE section is getting a little > unwieldy. Should we subdivide it, or is this still okay? Thanks for noticing the documentation gap regarding parallel plans. 1. I think the mention of VERBOSE might be unnecessary, since this is already covered in parallel.sgml, section 'Parallel Plan Tips'. That section explicitly says that EXPLAIN (ANALYZE, VERBOSE) shows per-worker statistics. 2. Instead of introducing another query, why not reuse the one already shown earlier in the same section, just with the GUCs adjusted to make it parallel? For example: SET min_parallel_table_scan_size = 0; SET parallel_tuple_cost = 0; SET parallel_setup_cost = 0; EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------  Gather  (cost=4.65..70.96 rows=10 width=488) (actual time=1.670..6.246 rows=10.00 loops=1)    Workers Planned: 2    Workers Launched: 2    Buffers: shared hit=78 read=6    ->  Nested Loop  (cost=4.65..70.96 rows=4 width=488) (actual time=0.218..0.277 rows=3.33 loops=3)          Buffers: shared hit=78 read=6          ->  Parallel Bitmap Heap Scan on tenk1 t1 (cost=4.36..39.31 rows=4 width=244) (actual time=0.195..0.202 rows=3.33 loops=3)                Recheck Cond: (unique1 < 10)                Heap Blocks: exact=10                Buffers: shared hit=54                ->  Bitmap Index Scan on tenk1_unique1 (cost=0.00..4.36 rows=10 width=0) (actual time=0.449..0.450 rows=10.00 loops=1)                      Index Cond: (unique1 < 10)                      Index Searches: 1                      Buffers: shared hit=2          ->  Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.29..7.90 rows=1 width=244) (actual time=0.020..0.020 rows=1.00 loops=10)                Index Cond: (unique2 = t1.unique2)                Index Searches: 10                Buffers: shared hit=24 read=6  Planning:    Buffers: shared hit=141 read=3  Planning Time: 0.519 ms  Execution Time: 6.302 ms (22 rows) -- Best regards, Ilia Evdokimov, Tantor Labs LLC, https://tantorlabs.com/ --------------xRz1sqtjIcE0v0sUPS4xYv2A Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Hi hackers,

On 27.09.2025 03:31, Maciek Sakrejda wrote:
However, to get a parallel query in the regression database (I chose
EXPLAIN ANALYZE SELECT * FROM tenk2), I had to change some settings:

SET min_parallel_table_scan_size = 0;
SET parallel_tuple_cost = 0;
SET parallel_setup_cost = 0;

Should I mention that in the example? Or should I generate a bigger
table so using these is not necessary? If we say nothing and use the
example, I think it may be confusing if someone wants to use the
example as a starting point for their own exploration of how this
works. Or is there a better query that works out of the box and does
not need changes to the settings?

It also seems like the EXPLAIN ANALYZE section is getting a little
unwieldy. Should we subdivide it, or is this still okay?


Thanks for noticing the documentation gap regarding parallel plans.

1. I think the mention of VERBOSE might be unnecessary, since this is already covered in parallel.sgml, section 'Parallel Plan Tips'. That section explicitly says that EXPLAIN (ANALYZE, VERBOSE) shows per-worker statistics.

2. Instead of introducing another query, why not reuse the one already shown earlier in the same section, just with the GUCs adjusted to make it parallel? For example:

SET min_parallel_table_scan_size = 0;
SET parallel_tuple_cost = 0;
SET parallel_setup_cost = 0;

EXPLAIN ANALYZE
SELECT *
FROM tenk1 t1, tenk2 t2
WHERE t1.unique1 < 10 AND t1.unique2 = t2.unique2;
                                                                QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 Gather  (cost=4.65..70.96 rows=10 width=488) (actual time=1.670..6.246 rows=10.00 loops=1)
   Workers Planned: 2
   Workers Launched: 2
   Buffers: shared hit=78 read=6
   ->  Nested Loop  (cost=4.65..70.96 rows=4 width=488) (actual time=0.218..0.277 rows=3.33 loops=3)
         Buffers: shared hit=78 read=6
         ->  Parallel Bitmap Heap Scan on tenk1 t1  (cost=4.36..39.31 rows=4 width=244) (actual time=0.195..0.202 rows=3.33 loops=3)
               Recheck Cond: (unique1 < 10)
               Heap Blocks: exact=10
               Buffers: shared hit=54
               ->  Bitmap Index Scan on tenk1_unique1  (cost=0.00..4.36 rows=10 width=0) (actual time=0.449..0.450 rows=10.00 loops=1)
                     Index Cond: (unique1 < 10)
                     Index Searches: 1
                     Buffers: shared hit=2
         ->  Index Scan using tenk2_unique2 on tenk2 t2  (cost=0.29..7.90 rows=1 width=244) (actual time=0.020..0.020 rows=1.00 loops=10)
               Index Cond: (unique2 = t1.unique2)
               Index Searches: 10
               Buffers: shared hit=24 read=6
 Planning:
   Buffers: shared hit=141 read=3
 Planning Time: 0.519 ms
 Execution Time: 6.302 ms
(22 rows)

--
Best regards,
Ilia Evdokimov,
Tantor Labs LLC,
https://tantorlabs.com/

--------------xRz1sqtjIcE0v0sUPS4xYv2A--