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.96) (envelope-from ) id 1vdhZF-003edY-2F for pgsql-performance@arkaria.postgresql.org; Thu, 08 Jan 2026 04:24:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vdhZD-00HWnv-0v for pgsql-performance@arkaria.postgresql.org; Thu, 08 Jan 2026 04:24:12 +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.96) (envelope-from ) id 1vdhZC-00HWnm-2j for pgsql-performance@lists.postgresql.org; Thu, 08 Jan 2026 04:24:11 +0000 Received: from mail-pj1-x102a.google.com ([2607:f8b0:4864:20::102a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vdhZB-005Cyv-0u for pgsql-performance@lists.postgresql.org; Thu, 08 Jan 2026 04:24:11 +0000 Received: by mail-pj1-x102a.google.com with SMTP id 98e67ed59e1d1-34c24f4dfb7so1589942a91.0 for ; Wed, 07 Jan 2026 20:24:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1767846247; x=1768451047; darn=lists.postgresql.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=Qo/TnvI58eIp8Na74imexAwi5NBkXwMWQVckvyn+pbA=; b=WwduqGGdCj8kR7g5E3bxJzBFvtDxinQwILOeOuuIGVeUXA1XkYTtfrrpeW+e2P41Lo UqQWXA1gQz8z4Oo7yxTthGKbIw6nBMncXnfep5a5kHxjGr3O/nm2HM/TQU5VDQThewXT khIEAV1axs+wqukUGlJT8wbwOxq9dk/SPlgKWYKHEmm2FEZvnQcPMGICU2lRQTO2Uv0J 6fb047kCknwZ7dsGikMHRFIV6hHGvZtllwRwHC1M1EyOXTzmNW3RaxFk5b0EI01UWbgX TqFXWnlU8eicld818P80/X2F6/LVb/sz1hVnMu6U7PEE9BNYhddUR0EvUahugw3M7dW5 bBEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1767846247; x=1768451047; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Qo/TnvI58eIp8Na74imexAwi5NBkXwMWQVckvyn+pbA=; b=jbLBLbpZKhXR20755Ioag5WAIqisrum6kGNczodUgFfP2c2hWinz66lzgdr23/YBlG NK33vmOXhjsgDIwAxOoTTERdm+693c9MIi7qvLtkv3APTZCFjUrLNoH3vDqOTyoAUvrK axBel3ejdIu98s5yVE3nCu2rXxH6nVa/uCaSaj+N+dhfiFmKG04Db4NhLP+dRyoLf5EJ EVLcES0PQ45pAbiIoQz9mBhuBusgOOoN8VS4ZNd78CN4YKJQDMAOWvdoPJSZZnGUUODu v4Umy8tdbLvx5cQgoVO3mjQOKOAFgio3tQcDhj8g+ojH/yAQeI25BQe5p/Wi3i3cWITS nHJg== X-Gm-Message-State: AOJu0Yxm+sLmGo7Xs+q5o82FMzadgqhpbl+PJ8GlI1TOBjk3urNd4RM0 8CFPb07GuOowLOQSTHMSGa/1Hl8S7kVfL7f3YJd+FgVyRj9UD/zCYLPW X-Gm-Gg: AY/fxX61IOzU66L5lKvkG69wfp+mURW/jWi0aAJgjkgUZjtKjRSE+QNovgMCz/znolZ kqiXnwimziILoyWfu+Xe7CBEj/WQlA7FMuPj6xPA7oBurYMLN7QrjyO1OblX+uyCXTEQKwZHXI/ UGoASn9g0Gf79PayxV+winJdev7itRZLfPsTDxsvzdT02plf/VVt8pzUM70NWQYtJEEiclRguW7 8to1aOndcUy7LbDGt9EpE2gpPe838ORUy4y1IXOp8sQohcTVL2hUQsA+PliG1q9rOYjAq2hMqF4 Xbczu66xDZaTquaGhniURT0YZDrXIUCAt6fAARIg7//5GYl+BWRms7g/hCvAW1I0VuHzZG01clf i1uJFYcmWWLHNjLV/UEkMx6xLLYzwDmPSD8q8Xe3zLHY/UaDRvvtAQ7HB+cEkB4CiqxaF7jwOo6 8fndUnQ3AGwInBdBxBv/Z3hgDWMj+OIGGnojPPqofpvPVVfKhzm7VA7WwOUtGct5mR+g== X-Google-Smtp-Source: AGHT+IEucsZb0jptUTNMlWr/NfqVMrkUN1cQ6n2wdjFnlNYvnOv3Od8bAoeTwvgNo+pDK+ejqObHHA== X-Received: by 2002:a17:90b:5211:b0:340:54a1:d703 with SMTP id 98e67ed59e1d1-34f68cefbedmr4258751a91.35.1767846246870; Wed, 07 Jan 2026 20:24:06 -0800 (PST) Received: from ?IPV6:2404:4400:414b:1700:b092:c6d0:7613:982b? ([2404:4400:414b:1700:b092:c6d0:7613:982b]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-34f6b29e117sm1525319a91.2.2026.01.07.20.24.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 07 Jan 2026 20:24:06 -0800 (PST) Message-ID: Date: Thu, 8 Jan 2026 17:24:02 +1300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Unexpected planner choice in simple JOIN To: David Rowley Cc: pgsql-performance@lists.postgresql.org References: <71afdb09-0583-4af2-a3b3-50da4f987b9b@gmail.com> Content-Language: en-US From: Mark Kirkwood In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Good suggestion. The results are...interesting: test0=# SET min_parallel_index_scan_size =0; SET Time: 0.172 ms test0=# EXPLAIN ANALYZE SELECT t0.id0, t1.val FROM tab0 AS t0 JOIN tab1 AS t1 ON (t0.id0 = t1.id0) WHERE t0.id0 < 5;    QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------  Gather  (cost=1097.91..40206.84 rows=5000 width=98) (actual time=0.362..5.565 rows=3500.00 loops=1)    Workers Planned: 1    Workers Launched: 1    Buffers: shared hit=114    ->  Nested Loop  (cost=97.91..38706.84 rows=2941 width=98) (actual time=0.034..0.479 rows=1750.00 loops=2)          Buffers: shared hit=114          ->  Parallel Index Only Scan using tab0_pkey on tab0 t0  (cost=0.29..4.36 rows=3 width=4) (actual time=0.008..0.009 rows=2.50 loops=2)                Index Cond: (id0 < 5)                Heap Fetches: 0                Index Searches: 1                Buffers: shared hit=3          ->  Bitmap Heap Scan on tab1 t1 (cost=97.61..12867.78 rows=3305 width=98) (actual time=0.036..0.140 rows=700.00 loops=5)                Recheck Cond: (t0.id0 = id0)                Heap Blocks: exact=97                Buffers: shared hit=111                ->  Bitmap Index Scan on tab1_id0_hash (cost=0.00..96.79 rows=3305 width=0) (actual time=0.030..0.030 rows=700.00 loops=5)                      Index Cond: (id0 = t0.id0)                      Index Searches: 5                      Buffers: shared hit=14  Planning:    Buffers: shared hit=222  Planning Time: 0.763 ms  Execution Time: 5.716 ms (23 rows) Time: 7.248 ms test0=# SET max_parallel_workers_per_gather=0; SET Time: 0.131 ms test0=# EXPLAIN ANALYZE SELECT t0.id0, t1.val FROM tab0 AS t0 JOIN tab1 AS t1 ON (t0.id0 = t1.id0) WHERE t0.id0 < 5;  QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------  Nested Loop  (cost=97.91..64508.51 rows=5000 width=98) (actual time=0.044..0.903 rows=3500.00 loops=1)    Buffers: shared hit=113    ->  Index Only Scan using tab0_pkey on tab0 t0 (cost=0.29..4.38 rows=5 width=4) (actual time=0.003..0.005 rows=5.00 loops=1)          Index Cond: (id0 < 5)          Heap Fetches: 0          Index Searches: 1          Buffers: shared hit=3    ->  Bitmap Heap Scan on tab1 t1  (cost=97.61..12867.78 rows=3305 width=98) (actual time=0.028..0.132 rows=700.00 loops=5)          Recheck Cond: (t0.id0 = id0)          Heap Blocks: exact=97          Buffers: shared hit=110          ->  Bitmap Index Scan on tab1_id0_hash (cost=0.00..96.79 rows=3305 width=0) (actual time=0.021..0.021 rows=700.00 loops=5)                Index Cond: (id0 = t0.id0)                Index Searches: 5                Buffers: shared hit=13  Planning:    Buffers: shared hit=9  Planning Time: 0.190 ms  Execution Time: 1.025 ms (19 rows) Time: 1.459 ms However disabling gather workers gets a much better plan. Now I can switch the child index to btree if you think that is significant. Best wishes Mark On 08/01/2026 17:14, David Rowley wrote: > On Thu, 8 Jan 2026 at 17:03, Mark Kirkwood wrote: >> I don't think so - while the case I posted used a hash index on the >> child table, exactly the sane behaviour happens if it is a btree (I >> probably should have mentioned that sorry). Background is I discovered >> this while playing about with hash indexes...which I must say - someone >> has done excellent work on as in this *particular cases* they are >> getting me better query performance! > Ok, it seems related to the min_parallel_index_scan_size GUC. If you > zero that, do you get a better plan? > > I think the problem is that because the best form of plan for joining > this tiny set of rows to the huge table is a parameterised nested > loop, to parallelise that loop, you need a Parallel node on the outer > side of the Nested Loop. If the index's size is below > min_parallel_index_scan_size then we won't build a partial path for > it. > > David