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 1ut3r1-00FKHy-2x for pgsql-performance@arkaria.postgresql.org; Mon, 01 Sep 2025 12:41:47 +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 1ut3qy-0065k7-AV for pgsql-performance@arkaria.postgresql.org; Mon, 01 Sep 2025 12:41:44 +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 1ut3qx-0065jz-Rt for pgsql-performance@lists.postgresql.org; Mon, 01 Sep 2025 12:41:44 +0000 Received: from mail.postgrespro.ru ([93.174.132.70]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1ut3qt-0000e5-2C for pgsql-performance@lists.postgresql.org; Mon, 01 Sep 2025 12:41:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mx2023; t=1756730496; bh=h6hq8hVnYJVKsqKozzcouy8yWRB13rtEukFZeUldUqY=; h=Message-ID:Date:User-Agent:Subject:To:References:From:In-Reply-To: From; b=E/JDnPJraP32/wWPhyvGvsPQQPXb0bnesUVkS50m++v1b87vOGu60fd17Z2zGrJxk KxpB8d68FhPB1mNuJ5YMFEkMshO6I1XEP9AC3p3UI4LU196LVM1YkZEz+9KbPTzVkd LnYbfu8/8L/4F4NTU7GFdZcJeJfxB67Ic2R4Twj/BqEIt8kZLdbzR4/b1EBtdGhEGv 3kaV4xnqTQc1VF0lTcIHdd0DLkM0uMIUfvWz+0/C5oNRqnyMPFuc4wSm/0Q6oWhlpo E4c0JCXq4+knlvhvdsc6UMCRrs48llD0y5UDWESA5CJFWsiYL4Ugn21lCm+XHHkcXy tjyMGbDiJHHpA== Received: from [10.0.85.1] (unknown [151.236.12.133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (Client did not present a certificate) (Authenticated sender: a.rybakina@postgrespro.ru) by mail.postgrespro.ru (Postfix/465) with ESMTPSA id 7FD4960349; Mon, 1 Sep 2025 15:41:35 +0300 (MSK) Message-ID: Date: Mon, 1 Sep 2025 15:41:29 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Planner makes sub-optimal execution plan To: =?UTF-8?B?0JDQu9C10LrRgdC10Lkg0JHQvtGA0YnRkdCy?= , pgsql-performance@lists.postgresql.org References: Content-Language: en-US From: Alena Rybakina In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-KSMG-AntiPhishing: NotDetected X-KSMG-AntiSpam-Interceptor-Info: not scanned X-KSMG-AntiSpam-Status: not scanned, disabled by settings X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 2.1.0.7854, bases: 2025/09/01 10:09:00 #27717796 X-KSMG-AntiVirus-Status: NotDetected, skipped X-KSMG-LinksScanning: not scanned, disabled by settings X-KSMG-Message-Action: skipped X-KSMG-Rule-ID: 1 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi! Thank you for sharing this interesting case! On 01.09.2025 12:07, Алексей Борщёв wrote: > EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY, SETTINGS, TIMING) > SELECT > MIN(docum.dt) AS "dt__min", > MAX(docum.dt_real) AS "dt_real__max" > FROM docum > WHERE docum.dt_real >= '2025-08-14T09:44:09.033592'::timestamp; > -- The plan I've got is: > Result (cost=8.38..8.39 rows=1 width=16) (actual > time=2660.034..2660.036 rows=1 loops=1) > Output: (InitPlan 1).col1, (InitPlan 2).col1 > Buffers: shared hit=9358751 read=30994 written=1 > InitPlan 1 > -> Limit (cost=0.43..7.91 rows=1 width=8) (actual > time=2660.006..2660.007 rows=1 loops=1) > Output: docum.dt > Buffers: shared hit=9358747 read=30994 written=1 > -> Index Scan using docum_dt_7ee1d676 on public.docum > (cost=0.43..420487.43 rows=56222 width=8) (actual > time=2660.004..2660.005 rows=1 loops=1) > Output: docum.dt > Index Cond: (docum.dt IS NOT NULL) > Filter: (docum.dt_real >= '2025-08-14 > 09:44:09.033592'::timestamp without time zone) > Rows Removed by Filter: 11342966 > Buffers: shared hit=9358747 read=30994 written=1 > InitPlan 2 > -> Limit (cost=0.43..0.46 rows=1 width=8) (actual > time=0.022..0.022 rows=1 loops=1) > Output: docum_1.dt_real > Buffers: shared hit=4 > -> Index Only Scan Backward using docum_dt_real_2b81c58c on > public.docum docum_1 (cost=0.43..1689.22 rows=59245 width=8) (actual > time=0.021..0.021 rows=1 loops=1) > Output: docum_1.dt_real > Index Cond: (docum_1.dt_real >= '2025-08-14 > 09:44:09.033592'::timestamp without time zone) > Heap Fetches: 0 > Buffers: shared hit=4 > Settings: work_mem = '16MB', search_path = 'public, public, "$user"' > Planning: > Buffers: shared hit=12 > Planning Time: 0.148 ms > Execution Time: 2660.056 ms After disabling MIN/MAX optimization in the grouping_planner function: /*          * Preprocess MIN/MAX aggregates, if any.  Note: be careful about          * adding logic between here and the query_planner() call.  Anything          * that is needed in MIN/MAX-optimizable cases will have to be          * duplicated in planagg.c.          */         //if (parse->hasAggs)         //    preprocess_minmax_aggregates(root); I got a better query plan, but I’m still investigating what went wrong. Also, creating a partial index helped because of the use of indexonlyscan: CREATE INDEX CONCURRENTLY docum_dt_recent   ON docum (dt)   WHERE dt_real >= timestamp '2025-08-01 00:00:00'; postgres=# EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY, SETTINGS, TIMING) SELECT     MIN(docum.dt) AS "dt__min",     MAX(docum.dt_real) AS "dt_real__max" FROM docum WHERE docum.dt_real >= '2025-08-14T09:44:09.033592'::timestamp; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------  Result  (cost=1.11..1.12 rows=1 width=16) (actual time=206.206..206.207 rows=1.00 loops=1)    Output: (InitPlan 1).col1, (InitPlan 2).col1    Buffers: shared hit=212507    InitPlan 1      ->  Limit  (cost=0.42..0.64 rows=1 width=8) (actual time=206.154..206.155 rows=1.00 loops=1)            Output: docum.dt            Buffers: shared hit=212503            ->  Index Scan using docum_dt_recent on public.docum  (cost=0.42..12391.88 rows=55710 width=8) (actual time=206.150..206.150 rows=1.00 loops=1)                  Output: docum.dt                  Index Cond: (docum.dt IS NOT NULL)                  Filter: (docum.dt_real >= '2025-08-14 09:44:09.033592'::timestamp without time zone)                  Rows Removed by Filter: 256799                  Index Searches: 1                  Buffers: shared hit=212503    InitPlan 2      ->  Limit  (cost=0.43..0.46 rows=1 width=8) (actual time=0.042..0.042 rows=1.00 loops=1)            Output: docum_1.dt_real            Buffers: shared hit=4            ->  Index Only Scan Backward using docum_dt_real on public.docum docum_1  (cost=0.43..1671.62 rows=58696 width=8) (actual time=0.041..0.041 rows=1.00 loops=1)                  Output: docum_1.dt_real                  Index Cond: (docum_1.dt_real >= '2025-08-14 09:44:09.033592'::timestamp without time zone)                  Heap Fetches: 0                  Index Searches: 1                  Buffers: shared hit=4  Planning:    Buffers: shared hit=30 read=10  Planning Time: 2.512 ms  Execution Time: 206.290 ms (28 rows) -- Regards, Alena Rybakina Postgres Professional