33 #define ARRAY_WIDTH_THRESHOLD 0x10000
117 elog(
ERROR,
"array_typanalyze was invoked for non-array type %u",
217 int samplerows,
double totalrows)
222 int null_elem_cnt = 0;
223 int analyzed_rows = 0;
267 num_mcelem = stats->
attr->attstattarget * 10;
273 bucket_width = num_mcelem * 1000 / 7;
285 elements_tab =
hash_create(
"Analyzed elements table",
291 count_hash_ctl.
keysize =
sizeof(int);
294 count_tab =
hash_create(
"Array distinct element count table",
304 for (array_no = 0; array_no < samplerows; array_no++)
314 int64 prev_element_no = element_no;
316 bool count_item_found;
320 value = fetchfunc(stats, array_no, &isnull);
345 &elem_values, &elem_nulls, &num_elems);
351 null_present =
false;
352 for (
j = 0;
j < num_elems;
j++)
365 elem_value = elem_values[
j];
367 (
const void *) &elem_value,
400 item->
delta = b_current - 1;
408 if (element_no % bucket_width == 0)
420 distinct_count = (int) (element_no - prev_element_no);
425 if (count_item_found)
439 while (slot_idx < STATISTIC_NUM_SLOTS && stats->stakind[slot_idx] != 0)
442 elog(
ERROR,
"insufficient pg_statistic slots for array stats");
445 if (analyzed_rows > 0)
447 int nonnull_cnt = analyzed_rows;
448 int count_items_count;
471 cutoff_freq = 9 * element_no / bucket_width;
478 minfreq = element_no;
484 sort_table[track_len++] = item;
492 elog(
DEBUG3,
"compute_array_stats: target # mces = %d, "
493 "bucket width = %d, "
495 "usable entries = %d",
496 num_mcelem, bucket_width, element_no,
i, track_len);
503 if (num_mcelem < track_len)
508 minfreq = sort_table[num_mcelem - 1]->
frequency;
511 num_mcelem = track_len;
517 Datum *mcelem_values;
544 for (
i = 0;
i < num_mcelem;
i++)
552 (
double) nonnull_cnt;
554 mcelem_freqs[
i++] = (double) minfreq / (
double) nonnull_cnt;
555 mcelem_freqs[
i++] = (double) maxfreq / (
double) nonnull_cnt;
556 mcelem_freqs[
i++] = (double) null_elem_cnt / (
double) nonnull_cnt;
560 stats->
stakind[slot_idx] = STATISTIC_KIND_MCELEM;
566 stats->
stavalues[slot_idx] = mcelem_values;
578 if (count_items_count > 0)
580 int num_hist = stats->
attr->attstattarget;
588 num_hist =
Max(num_hist, 2);
600 sorted_count_items[
j++] = count_item;
602 qsort(sorted_count_items, count_items_count,
611 sizeof(
float4) * (num_hist + 1));
612 hist[num_hist] = (double) element_no / (
double) nonnull_cnt;
645 delta = analyzed_rows - 1;
648 frac = (int64) sorted_count_items[0]->frequency * (num_hist - 1);
649 for (
i = 0;
i < num_hist;
i++)
655 frac += (int64) sorted_count_items[
j]->frequency * (num_hist - 1);
657 hist[
i] = sorted_count_items[
j]->
count;
660 Assert(
j == count_items_count - 1);
662 stats->
stakind[slot_idx] = STATISTIC_KIND_DECHIST;
762 return (*t2)->
frequency - (*t1)->frequency;
786 if ((*t1)->count < (*t2)->count)
788 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)
static void compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, int samplerows, double totalrows)
static int element_match(const void *key1, const void *key2, Size keysize)
static int countitem_compare_count(const void *e1, const void *e2)
static int trackitem_compare_element(const void *e1, const void *e2)
static uint32 element_hash(const void *key, Size keysize)
#define ARRAY_WIDTH_THRESHOLD
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 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)
Assert(fmt[strlen(fmt) - 1] !='\n')
Oid get_base_element_type(Oid typid)
void pfree(void *pointer)
MemoryContext CurrentMemoryContext
void * MemoryContextAlloc(MemoryContext context, Size size)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define STATISTIC_NUM_SLOTS
#define qsort(a, b, c, d)
#define DatumGetPointer(X)
#define PointerGetDatum(X)
#define DatumGetUInt32(X)
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)