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.98.2) (envelope-from ) id 1x7Tta-00000000POM-1oA1 for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 08:24:35 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7TtZ-00000008cis-2vkU for pgsql-bugs@arkaria.postgresql.org; Fri, 18 Sep 2026 08:24:33 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x7Sat-00000008IZ3-33ES for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 07:01:11 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x7Sao-00000000Hd8-48yW for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 07:01:10 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=mUOKbVWELl4sQ+zTS5PyBhzHe2SjezP7wmE3E6q9LhU=; b=XJjTYstWTd0XPG3vH2nP5K+cXj U52azTkeYRYIwEO9q1RFRa1rpOpc19tJ1PhYGAW0dHG9MwdhCuhtQZoZj9GUeou4IEkhrl+ibFrQm HTQK6p8zsoBYZyQU6rC2Kr1SuFrwJSK5asQAjl9nzkkqTcMB0fCvLRKRtvcV+gxVgfQnpI8nQufZP a9M+rhlqyPbSX0cPLeKKb2SYlozGEStJM6yZE4xN0rdplZftn+Asq0FERRhkP1NXH70vTRZddxZqR J8QHVTCbKHwvveZzyqMtQ/PWbswEcWPZxCz7TRONWYdcF7IFtAX5DnOe9h6OSbMFVJ9RikexgMgcq WHyN7YuQ==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x7Sam-001v4Z-31 for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 07:01:06 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x7Sal-000000076Vo-2Vdl for pgsql-bugs@lists.postgresql.org; Fri, 18 Sep 2026 07:01:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19696: DISTINCT ON with a target-list set-returning function causes a 1000-fold selectivity underestimate To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: imchifan@163.com Reply-To: imchifan@163.com, pgsql-bugs@lists.postgresql.org Date: Fri, 18 Sep 2026 07:00:05 +0000 Message-ID: <19696-135220dd92659a4e@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19696 Logged by: Qifan Liu Email address: imchifan@163.com PostgreSQL version: 18.6 Operating system: Linux/amd64 Description: =20 PostgreSQL version: PostgreSQL 20devel at a12600b762c36d91450ce085fa25ef75250bc1c2; PostgreSQL 18.6; PostgreSQL 17.11 Operating system: Linux/amd64 Description ----------- Filtering a one-column DISTINCT ON subquery by its distinct key is estimated as unique even when a set-returning function in the target list expands each key after the Unique node. In this example, the planner estimates one row while the query returns 1000 rows. Such underestimation can lead to poor plan choices. Steps to reproduce ------------------ Run the following with psql: \set ON_ERROR_STOP on DROP TABLE IF EXISTS bugseer_postgres_00002_srf_distinct; CREATE TABLE bugseer_postgres_00002_srf_distinct(k integer); INSERT INTO bugseer_postgres_00002_srf_distinct SELECT (g % 100) + 1 FROM generate_series(1, 10000) AS g; ANALYZE bugseer_postgres_00002_srf_distinct; EXPLAIN (ANALYZE, COSTS ON, TIMING OFF, SUMMARY OFF) SELECT * FROM ( SELECT DISTINCT ON (k) k, generate_series(1, 1000) AS expanded FROM bugseer_postgres_00002_srf_distinct ORDER BY k OFFSET 0 ) AS s WHERE k =3D 1; Actual result ------------- The outer Subquery Scan is estimated at one row but returns 1000 rows: Subquery Scan on s (cost=3D809.39..2610.14 rows=3D1 width=3D8) (actual rows=3D1000.00 loops=3D1) Filter: (s.k =3D 1) Rows Removed by Filter: 99000 -> ProjectSet (cost=3D809.39..1360.14 rows=3D100000 width=3D8) (actual rows=3D100000.00 loops=3D1) -> Unique (cost=3D809.39..859.39 rows=3D100 width=3D4) (actual rows=3D100.00 loops=3D1) Expected result --------------- The outer row estimate should account for the target-list generate_series expansion and estimate 1000 rows rather than treating the DISTINCT ON key as producing at most one output row. Additional information ---------------------- The issue was reproduced on PostgreSQL 20devel, PostgreSQL 18.6, and PostgreSQL 17.11.