On 7/8/22 03:07, Tom Lane wrote:
Andrey Lepikhov <a.lepik...@postgrespro.ru> writes:
On 12/8/21 04:26, Tomas Vondra wrote:
I wonder if we should teach clauselist_selectivity about UNIQUE indexes,
and improve the cardinality estimates directly, not just costing for
index scans.

I tried to implement this in different ways. But it causes additional
overhead and code complexity - analyzing a list of indexes and match
clauses of each index with input clauses in each selectivity estimation.
I don't like that way and propose a new patch in attachment.

I looked at this briefly.  I do not think that messing with
btcostestimate/genericcostestimate is the right response at all.
The problem can be demonstrated with no index whatever, as in the
attached shortened version of the original example.  I get

I partly agree with you. Yes, I see the problem too. But also we have a problem that I described above: optimizer don't choose a path with minimal selectivity from a set selectivities which shows cardinality less than 1 (see badestimate2.sql).
New patch (see in attachment), fixes this problem.

--
Regards
Andrey Lepikhov
Postgres Professional
From 463c085852be921199b7a6d0987378d55145e41c Mon Sep 17 00:00:00 2001
From: Andrey Lepikhov <a.lepik...@postgrespro.ru>
Date: Mon, 11 Jul 2022 12:25:43 +0500
Subject: [PATCH] Use Index path with the best selectivity estimation

---
 src/backend/optimizer/util/pathnode.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 483c4f4137..a8d7f22343 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -207,6 +207,20 @@ compare_path_costs_fuzzily(Path *path1, Path *path2, double fuzz_factor)
 		/* ... but path2 fuzzily worse on startup, so path1 wins */
 		return COSTS_BETTER1;
 	}
+	if (IsA(path1, IndexPath) && IsA(path2, IndexPath))
+	{
+		/*
+		 * Couldn't differ value of the paths. Last chance - if these paths
+		 * are index paths - use the path with the lower selectivity value.
+		 */
+		if (((IndexPath *) path1)->indexselectivity <
+			((IndexPath *) path2)->indexselectivity)
+			return COSTS_BETTER1;
+
+		if (((IndexPath *) path1)->indexselectivity >
+			((IndexPath *) path2)->indexselectivity)
+			return COSTS_BETTER2;
+	}
 	/* fuzzily the same on both costs */
 	return COSTS_EQUAL;
 
-- 
2.34.1

Attachment: badestimate2.sql
Description: application/sql

Reply via email to