/* Default selectivity for given operator */ #define DEFAULT_SEL(operator) \
((operator) == OID_ARRAY_OVERLAP_OP ? \
DEFAULT_OVERLAP_SEL : DEFAULT_CONTAIN_SEL)
static Selectivity calc_arraycontsel(VariableStatData *vardata, Datum constval,
Oid elemtype, Oid operator); static Selectivity mcelem_array_selec(ArrayType *array,
TypeCacheEntry *typentry,
Datum *mcelem, int nmcelem,
float4 *numbers, int nnumbers,
float4 *hist, int nhist,
Oid operator); static Selectivity mcelem_array_contain_overlap_selec(Datum *mcelem, int nmcelem,
float4 *numbers, int nnumbers,
Datum *array_data, int nitems,
Oid operator, TypeCacheEntry *typentry); static Selectivity mcelem_array_contained_selec(Datum *mcelem, int nmcelem,
float4 *numbers, int nnumbers,
Datum *array_data, int nitems,
float4 *hist, int nhist,
Oid operator, TypeCacheEntry *typentry); staticfloat *calc_hist(const float4 *hist, int nhist, int n); staticfloat *calc_distr(constfloat *p, int n, int m, float rest); staticint floor_log2(uint32 n); staticbool find_next_mcelem(Datum *mcelem, int nmcelem, Datum value, int *index, TypeCacheEntry *typentry); staticint element_compare(constvoid *key1, constvoid *key2, void *arg); staticint float_compare_desc(constvoid *key1, constvoid *key2);
/* *leftopmustbeaconstant,elsepunt.
*/ if (!IsA(leftop, Const))
{
ReleaseVariableStats(vardata); return -1.0;
} if (((Const *) leftop)->constisnull)
{ /* qual can't succeed if null on left */
ReleaseVariableStats(vardata); return (Selectivity) 0.0;
}
constval = ((Const *) leftop)->constvalue;
/* Get element type's default comparison function */
typentry = lookup_type_cache(elemtype, TYPECACHE_CMP_PROC_FINFO); if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
{
ReleaseVariableStats(vardata); return -1.0;
}
cmpfunc = &typentry->cmp_proc_finfo;
/* *Iftheoperatoris<>,swapANY/ALL,theninverttheresultlater.
*/ if (!isEquality)
useOr = !useOr;
/* Get array element stats for var, if available */ if (HeapTupleIsValid(vardata.statsTuple) &&
statistic_proc_security_check(&vardata, cmpfunc->fn_oid))
{
Form_pg_statistic stats;
AttStatsSlot sslot;
AttStatsSlot hslot;
/* MCELEM will be an array of same type as element */ if (get_attstatsslot(&sslot, vardata.statsTuple,
STATISTIC_KIND_MCELEM, InvalidOid,
ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS))
{ /* For ALL case, also get histogram of distinct-element counts */ if (useOr ||
!get_attstatsslot(&hslot, vardata.statsTuple,
STATISTIC_KIND_DECHIST, InvalidOid,
ATTSTATSSLOT_NUMBERS))
memset(&hslot, 0, sizeof(hslot));
/* *arraycontjoinsel--joinselectivityforarray@>,&&,<@operators
*/
Datum
arraycontjoinsel(PG_FUNCTION_ARGS)
{ /* For the moment this is just a stub */
Oid operator = PG_GETARG_OID(1);
PG_RETURN_FLOAT8(DEFAULT_SEL(operator));
}
/* *Calculateselectivityfor"arraycolumn@>const","arraycolumn&&const" *or"arraycolumn<@const"basedonthestatistics * *Thisfunctionismainlyresponsibleforextractingthepg_statisticdata *tobeused;wethenpasstheproblemontomcelem_array_selec().
*/ static Selectivity
calc_arraycontsel(VariableStatData *vardata, Datum constval,
Oid elemtype, Oid operator)
{
Selectivity selec;
TypeCacheEntry *typentry;
FmgrInfo *cmpfunc;
ArrayType *array;
/* Get element type's default comparison function */
typentry = lookup_type_cache(elemtype, TYPECACHE_CMP_PROC_FINFO); if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid)) return DEFAULT_SEL(operator);
cmpfunc = &typentry->cmp_proc_finfo;
/* MCELEM will be an array of same type as column */ if (get_attstatsslot(&sslot, vardata->statsTuple,
STATISTIC_KIND_MCELEM, InvalidOid,
ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS))
{ /* *For"array<@const"casewealsoneedhistogramofdistinct *elementcounts.
*/ if (operator != OID_ARRAY_CONTAINED_OP ||
!get_attstatsslot(&hslot, vardata->statsTuple,
STATISTIC_KIND_DECHIST, InvalidOid,
ATTSTATSSLOT_NUMBERS))
memset(&hslot, 0, sizeof(hslot));
/* Use the most-common-elements slot for the array Var. */
selec = mcelem_array_selec(array, typentry,
sslot.values, sslot.nvalues,
sslot.numbers, sslot.nnumbers,
hslot.numbers, hslot.nnumbers, operator);
free_attstatsslot(&hslot);
free_attstatsslot(&sslot);
} else
{ /* No most-common-elements info, so do without */
selec = mcelem_array_selec(array, typentry,
NULL, 0, NULL, 0, NULL, 0, operator);
}
/* *MCEstatscountonlynon-nullrows,soadjustfornullrows.
*/
selec *= (1.0 - stats->stanullfrac);
} else
{ /* No stats at all, so do without */
selec = mcelem_array_selec(array, typentry,
NULL, 0, NULL, 0, NULL, 0, operator); /* we assume no nulls here, so no stanullfrac correction */
}
/* If constant was toasted, release the copy we made */ if (PointerGetDatum(array) != constval)
pfree(array);
return selec;
}
/* *Arrayselectivityestimationbasedonmostcommonelementsstatistics * *Thisfunctionjustdeconstructsandsortsthearrayconstant'scontents, *andthenpassestheproblemontomcelem_array_contain_overlap_selecor *mcelem_array_contained_selecdependingontheoperator.
*/ static Selectivity
mcelem_array_selec(ArrayType *array, TypeCacheEntry *typentry,
Datum *mcelem, int nmcelem,
float4 *numbers, int nnumbers,
float4 *hist, int nhist,
Oid operator)
{
Selectivity selec; int num_elems;
Datum *elem_values; bool *elem_nulls; bool null_present; int nonnull_nitems; int i;
/* Collapse out any null elements */
nonnull_nitems = 0;
null_present = false; for (i = 0; i < num_elems; i++)
{ if (elem_nulls[i])
null_present = true; else
elem_values[nonnull_nitems++] = elem_values[i];
}
/* Sort extracted elements using their default comparison function. */
qsort_arg(elem_values, nonnull_nitems, sizeof(Datum),
element_compare, typentry);
/* Separate cases according to operator */ if (operator == OID_ARRAY_CONTAINS_OP || operator == OID_ARRAY_OVERLAP_OP)
selec = mcelem_array_contain_overlap_selec(mcelem, nmcelem,
numbers, nnumbers,
elem_values, nonnull_nitems, operator, typentry); elseif (operator == OID_ARRAY_CONTAINED_OP)
selec = mcelem_array_contained_selec(mcelem, nmcelem,
numbers, nnumbers,
elem_values, nonnull_nitems,
hist, nhist, operator, typentry); else
{
elog(ERROR, "arraycontsel called for unrecognized operator %u", operator);
selec = 0.0; /* keep compiler quiet */
}
if (numbers)
{ /* Grab the lowest observed frequency */
minfreq = numbers[nmcelem];
} else
{ /* Without statistics make some default assumptions */
minfreq = 2 * (float4) DEFAULT_CONTAIN_SEL;
}
/* Decide whether it is faster to use binary search or not. */ if (nitems * floor_log2((uint32) nmcelem) < nmcelem + nitems)
use_bsearch = true; else
use_bsearch = false;
/* Value of Poisson distribution for 0 occurrences */
t = exp(-rest);
/* *Calculateconvolutionofpreviouslycomputeddistributionandthe *Poissondistribution.
*/ for (i = 0; i <= m; i++)
{ for (j = 0; j <= m - i; j++)
row[j + i] += prev_row[j] * t;
/* Get Poisson distribution value for (i + 1) occurrences */
t *= rest / (float) (i + 1);
}
}
pfree(prev_row); return row;
}
/* Fast function for floor value of 2 based logarithm calculation. */ staticint
floor_log2(uint32 n)
{ int logval = 0;
if (n == 0) return -1; if (n >= (1 << 16))
{
n >>= 16;
logval += 16;
} if (n >= (1 << 8))
{
n >>= 8;
logval += 8;
} if (n >= (1 << 4))
{
n >>= 4;
logval += 4;
} if (n >= (1 << 2))
{
n >>= 2;
logval += 2;
} if (n >= (1 << 1))
{
logval += 1;
} return logval;
}
/* *find_next_mcelembinary-searchesamostcommonelementsarray,starting *from*index,forthefirstmember>=value.Itsavesthepositionofthe *matchinto*indexandreturnstrueifit'sanexactmatch.(Note:we *assumethemcelemelementsaredistinctsotherecan'tbemorethanone *exactmatch.)
*/ staticbool
find_next_mcelem(Datum *mcelem, int nmcelem, Datum value, int *index,
TypeCacheEntry *typentry)
{ int l = *index,
r = nmcelem - 1,
i,
res;
while (l <= r)
{
i = (l + r) / 2;
res = element_compare(&mcelem[i], &value, typentry); if (res == 0)
{
*index = i; returntrue;
} elseif (res < 0)
l = i + 1; else
r = i - 1;
}
*index = l; returnfalse;
}
/* *Comparisonfunctionforelements. * *Weusetheelementtype'sdefaultbtreeopclass,anditsdefaultcollation *ifthetypeiscollation-sensitive. * *XXXconsiderusingSortSupportinfrastructure
*/ staticint
element_compare(constvoid *key1, constvoid *key2, void *arg)
{
Datum d1 = *((const Datum *) key1);
Datum d2 = *((const Datum *) key2);
TypeCacheEntry *typentry = (TypeCacheEntry *) arg;
FmgrInfo *cmpfunc = &typentry->cmp_proc_finfo;
Datum c;
c = FunctionCall2Coll(cmpfunc, typentry->typcollation, d1, d2); return DatumGetInt32(c);
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.54Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.