21 #include "utils/fmgrprotos.h"
33 #define ARRAY_WIDTH_THRESHOLD 0x10000
117 elog(
ERROR,
"array_typanalyze was invoked for non-array type %u",
217 int samplerows,
double totalrows)
221 int null_elem_cnt = 0;
222 int analyzed_rows = 0;
272 bucket_width = num_mcelem * 1000 / 7;
284 elements_tab =
hash_create(
"Analyzed elements table",
290 count_hash_ctl.
keysize =
sizeof(int);
293 count_tab =
hash_create(
"Array distinct element count table",
303 for (array_no = 0; array_no < samplerows; array_no++)
313 int64 prev_element_no = element_no;
315 bool count_item_found;
319 value = fetchfunc(stats, array_no, &isnull);
343 &elem_values, &elem_nulls, &num_elems);
349 null_present =
false;
350 for (
j = 0;
j < num_elems;
j++)
363 elem_value = elem_values[
j];
398 item->
delta = b_current - 1;
406 if (element_no % bucket_width == 0)
418 distinct_count = (int) (element_no - prev_element_no);
423 if (count_item_found)
437 while (slot_idx < STATISTIC_NUM_SLOTS && stats->stakind[slot_idx] != 0)
440 elog(
ERROR,
"insufficient pg_statistic slots for array stats");
443 if (analyzed_rows > 0)
445 int nonnull_cnt = analyzed_rows;
446 int count_items_count;
469 cutoff_freq = 9 * element_no / bucket_width;
476 minfreq = element_no;
482 sort_table[track_len++] = item;
490 elog(
DEBUG3,
"compute_array_stats: target # mces = %d, "
491 "bucket width = %d, "
493 "usable entries = %d",
494 num_mcelem, bucket_width, element_no,
i, track_len);
501 if (num_mcelem < track_len)
506 minfreq = sort_table[num_mcelem - 1]->
frequency;
509 num_mcelem = track_len;
515 Datum *mcelem_values;
542 for (
i = 0;
i < num_mcelem;
i++)
550 (
double) nonnull_cnt;
552 mcelem_freqs[
i++] = (double) minfreq / (
double) nonnull_cnt;
553 mcelem_freqs[
i++] = (double) maxfreq / (
double) nonnull_cnt;
554 mcelem_freqs[
i++] = (double) null_elem_cnt / (
double) nonnull_cnt;
558 stats->
stakind[slot_idx] = STATISTIC_KIND_MCELEM;
564 stats->
stavalues[slot_idx] = mcelem_values;
576 if (count_items_count > 0)
586 num_hist =
Max(num_hist, 2);
598 sorted_count_items[
j++] = count_item;
610 sizeof(
float4) * (num_hist + 1));
611 hist[num_hist] = (double) element_no / (
double) nonnull_cnt;
644 delta = analyzed_rows - 1;
647 frac = (int64) sorted_count_items[0]->frequency * (num_hist - 1);
648 for (
i = 0;
i < num_hist;
i++)
654 frac += (int64) sorted_count_items[
j]->frequency * (num_hist - 1);
656 hist[
i] = sorted_count_items[
j]->
count;
659 Assert(
j == count_items_count - 1);
661 stats->
stakind[slot_idx] = STATISTIC_KIND_DECHIST;
761 return (*t2)->
frequency - (*t1)->frequency;
785 if ((*t1)->count < (*t2)->count)
787 else if ((*t1)->count == (*t2)->count)
#define DatumGetArrayTypeP(X)
Datum array_typanalyze(PG_FUNCTION_ARGS)
static int trackitem_compare_frequencies_desc(const void *e1, const void *e2, void *arg)
static void compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, int samplerows, double totalrows)
static int trackitem_compare_element(const void *e1, const void *e2, void *arg)
static int element_match(const void *key1, const void *key2, Size keysize)
static uint32 element_hash(const void *key, Size keysize)
#define ARRAY_WIDTH_THRESHOLD
static int countitem_compare_count(const void *e1, const void *e2, void *arg)
static int element_compare(const void *key1, const void *key2)
static ArrayAnalyzeExtraData * array_extra_data
static void prune_element_hashtable(HTAB *elements_tab, int b_current)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
#define Assert(condition)
#define OidIsValid(objectId)
bool std_typanalyze(VacAttrStats *stats)
Datum datumCopy(Datum value, bool typByVal, int typLen)
Size toast_raw_datum_size(Datum value)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
long hash_get_num_entries(HTAB *hashp)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
#define PG_GETARG_POINTER(n)
#define PG_RETURN_BOOL(x)
Oid get_base_element_type(Oid typid)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
void * MemoryContextAlloc(MemoryContext context, Size size)
#define STATISTIC_NUM_SLOTS
void qsort_interruptible(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
static uint32 DatumGetUInt32(Datum X)
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
static int32 DatumGetInt32(Datum X)
MemoryContextSwitchTo(old_ctx)
int16 stakind[STATISTIC_NUM_SLOTS]
MemoryContext anl_context
Oid statypid[STATISTIC_NUM_SLOTS]
Oid staop[STATISTIC_NUM_SLOTS]
Oid stacoll[STATISTIC_NUM_SLOTS]
char statypalign[STATISTIC_NUM_SLOTS]
float4 * stanumbers[STATISTIC_NUM_SLOTS]
bool statypbyval[STATISTIC_NUM_SLOTS]
int16 statyplen[STATISTIC_NUM_SLOTS]
int numvalues[STATISTIC_NUM_SLOTS]
Datum * stavalues[STATISTIC_NUM_SLOTS]
int numnumbers[STATISTIC_NUM_SLOTS]
AnalyzeAttrComputeStatsFunc compute_stats
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define TYPECACHE_HASH_PROC_FINFO
#define TYPECACHE_CMP_PROC_FINFO
void vacuum_delay_point(void)
Datum(* AnalyzeAttrFetchFunc)(VacAttrStatsP stats, int rownum, bool *isNull)
void(* AnalyzeAttrComputeStatsFunc)(VacAttrStatsP stats, AnalyzeAttrFetchFunc fetchfunc, int samplerows, double totalrows)