Re: help debugging an issue with selectivity
| От | Rob Sargent |
|---|---|
| Тема | Re: help debugging an issue with selectivity |
| Дата | |
| Msg-id | AA983D51-CF44-4CD9-9812-AEB850CBEAF1@gmail.com обсуждение исходный текст |
| Ответ на | help debugging an issue with selectivity (Greg Hennessy <greg.hennessy@gmail.com>) |
| Список | pgsql-general |
/— intentional top post—/ Have you been a very bad boy and usurped an existing email thread? > On Mar 17, 2026, at 11:29 AM, Greg Hennessy <greg.hennessy@gmail.com> wrote: > > I am not sure if this belongs in pgsql-general or pgsql-hackers, I am trying first in psgl-general. > > I am trying to understand setting a selectivity function that gets applied to an operator (to hopefully > provide better information for the planner/optmizer). This is for the q3c extension, source code found at > https://github.com/segasai/q3c. > > There are functions for selectivity, and for an operator. > > -- A dummy type used in the selectivity operator > create type q3c_type as (ra double precision, dec double precision, > ra1 double precision, dec1 double precision); > > -- A dummy operator function (always returns true) > CREATE OR REPLACE FUNCTION q3c_seloper(double precision, q3c_type) > RETURNS bool > AS 'MODULE_PATHNAME', 'pgq3c_seloper' > LANGUAGE C STRICT IMMUTABLE COST 1000; > > -- A selectivity function for the q3c operator > CREATE OR REPLACE FUNCTION q3c_sel(internal, oid, internal, int4) > RETURNS float8 > AS 'MODULE_PATHNAME', 'pgq3c_sel' > LANGUAGE C IMMUTABLE STRICT ; > > -- A selectivity function for the q3c operator > CREATE OR REPLACE FUNCTION q3c_seljoin(internal, oid, internal, int2, internal) > RETURNS float8 > AS 'MODULE_PATHNAME', 'pgq3c_seljoin' > LANGUAGE C IMMUTABLE STRICT ; > > -- distance operator with correct selectivity > CREATE OPERATOR ==<<>>== ( > LEFTARG = double precision, > RIGHTARG = q3c_type, > PROCEDURE = q3c_seloper, > RESTRICT = q3c_sel, > JOIN = q3c_seljoin > ); > > The C portions are declared as: > > /* The actual selectivity function, it returns the ratio of the > * search circle to the whole sky area > */ > PG_FUNCTION_INFO_V1(pgq3c_sel); > Datum pgq3c_sel(PG_FUNCTION_ARGS) > > where the actual calculation portion is (not showing the setup portion): > > ratio = 3.14 * rad * rad / 41252.; /* pi*r^2/whole_sky_area */ > /* clamp at 0, 1*/ > CLAMP_PROBABILITY(ratio); > elog(WARNING, "HERE0 pgq3c_sel.... %e", ratio); > PG_RETURN_FLOAT8(ratio); > } > > The join function is declared as: > PG_FUNCTION_INFO_V1(pgq3c_seljoin); > Datum pgq3c_seljoin(PG_FUNCTION_ARGS) > { > > where the meat portion is: > ratio = 3.14 * rad * rad / 41252.; /* pi*r^2/whole_sky_area */ > /* clamp at 0, 1*/ > CLAMP_PROBABILITY(ratio); > elog(WARNING, "HERE0 pgq3c_seljoin.... %e", ratio); > PG_RETURN_FLOAT8(ratio); > } > > The two elog statements aren't in the orig code, I've added them to help me trace > the code. As far as I can tell, the these selectivity functions are called in > src/backend/optimizer/path/clausesel.c in the routine clause_selectivity_ext. > If I add similar elog statements, at about line 836, the code says: > > if (treat_as_join_clause(root, clause, rinfo, varRelid, sjinfo)) > { > /* Estimate selectivity for a join clause. */ > if (opno > 6000) > elog(WARNING, "clause_selectivity: join_selectivity opno %d",opno); > s1 = join_selectivity(root, opno, > opclause->args, > opclause->inputcollid, > jointype, > sjinfo); > if (opno > 6000){ > elog(WARNING, "join_selectivity: s1 %f", s1); > } > } > else > { > /* Estimate selectivity for a restriction clause. */ > if (opno > 6000) > elog(WARNING, "clause_selectivity: restriction_selectivity opno %d", opno); > s1 = restriction_selectivity(root, opno, > opclause->args, > opclause->inputcollid, > varRelid); > if (opno > 6000){ > elog(WARNING, "restriction_selectivity: s1 %lf", s1); > } > } > > > When I actually execute this, I get output to the terminal of the form: > WARNING: join_selectivity: operator id 16818 jointype 0 0 > WARNING: HERE0 pgq3c_seljoin.... 5.873266e-12 > WARNING: datum result 4438812783922730423 0.000000 > WARNING: HERE0 pgq3c_seljoin.... 5.873266e-12 > WARNING: join_selectivity: 0.000000 16818 jointype 0 > WARNING: join_selectivity: s1 0.000000 > WARNING: clause_selectivity: s1 0.000000 > > where it seems to me the q3c code is returning a non zero value, but in the guts of > postgres what is found is a zero value. If I want to verify I have the correct opr, > which is 16818, I can verify via: > q3c_test=# select oid,oprname,oprnamespace,oprowner,oprkind,oprleft,oprright,oprresult,oprcode from pg_operator where oid= 16818; > oid | oprname | oprnamespace | oprowner | oprkind | oprleft | oprright | oprresult | oprcode > -------+----------+--------------+----------+---------+---------+----------+-----------+------------- > 16818 | ==<<>>== | 2200 | 16391 | b | 701 | 16814 | 16 | q3c_seloper > > which yeilds what I expect. > > The join_selectivity is essentially a call in src/backend/optimizer/util/plancat.c of: > result = DatumGetFloat8(OidFunctionCall5Coll(oprjoin, > inputcollid, > PointerGetDatum(root), > ObjectIdGetDatum(operatorid), > PointerGetDatum(args), > Int16GetDatum(jointype), > PointerGetDatum(sjinfo))); > > if (result < 0.0 || result > 1.0) > elog(ERROR, "invalid join selectivity: %f", result); > > while restriction_selectivity is a call to: > result = DatumGetFloat8(OidFunctionCall4Coll(oprrest, > inputcollid, > PointerGetDatum(root), > ObjectIdGetDatum(operatorid), > PointerGetDatum(args), > Int32GetDatum(varRelid))); > > This is the point where I run out of steam. The basic issue I have is that q3c code is attempting > to return a small, but non-zero value for the selectivity in two functions, but the guts of > postgresql has both the join_selectivity and restriction_selectivity function return zero where > I think they shouldn't. > > Any advice in how to make progress on this is welcome. I'm using 19devel (I can probably do a > git merge to move to a more up to date version), and I'm running Fedora release 43 in case which > exact OS I'm using is relavent. > > Greg > > >
В списке pgsql-general по дате отправления: