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;
259 array_extra_data = extra_data;
267 num_mcelem = stats->
attr->attstattarget * 10;
273 bucket_width = num_mcelem * 1000 / 7;
280 MemSet(&elem_hash_ctl, 0,
sizeof(elem_hash_ctl));
286 elements_tab =
hash_create(
"Analyzed elements table",
292 MemSet(&count_hash_ctl, 0,
sizeof(count_hash_ctl));
293 count_hash_ctl.
keysize =
sizeof(int);
296 count_tab =
hash_create(
"Array distinct element count table",
306 for (array_no = 0; array_no < samplerows; array_no++)
316 int64 prev_element_no = element_no;
318 bool count_item_found;
322 value = fetchfunc(stats, array_no, &isnull);
347 &elem_values, &elem_nulls, &num_elems);
353 null_present =
false;
354 for (j = 0; j < num_elems; j++)
367 elem_value = elem_values[j];
369 (
const void *) &elem_value,
402 item->
delta = b_current - 1;
410 if (element_no % bucket_width == 0)
422 distinct_count = (int) (element_no - prev_element_no);
427 if (count_item_found)
441 while (slot_idx < STATISTIC_NUM_SLOTS && stats->stakind[slot_idx] != 0)
444 elog(
ERROR,
"insufficient pg_statistic slots for array stats");
447 if (analyzed_rows > 0)
449 int nonnull_cnt = analyzed_rows;
450 int count_items_count;
473 cutoff_freq = 9 * element_no / bucket_width;
480 minfreq = element_no;
486 sort_table[track_len++] = item;
494 elog(
DEBUG3,
"compute_array_stats: target # mces = %d, " 495 "bucket width = %d, " 497 "usable entries = %d",
498 num_mcelem, bucket_width, element_no, i, track_len);
505 if (num_mcelem < track_len)
510 minfreq = sort_table[num_mcelem - 1]->
frequency;
513 num_mcelem = track_len;
519 Datum *mcelem_values;
546 for (i = 0; i < num_mcelem; i++)
554 (
double) nonnull_cnt;
556 mcelem_freqs[i++] = (double) minfreq / (
double) nonnull_cnt;
557 mcelem_freqs[i++] = (double) maxfreq / (
double) nonnull_cnt;
558 mcelem_freqs[i++] = (double) null_elem_cnt / (
double) nonnull_cnt;
562 stats->
stakind[slot_idx] = STATISTIC_KIND_MCELEM;
568 stats->
stavalues[slot_idx] = mcelem_values;
580 if (count_items_count > 0)
582 int num_hist = stats->
attr->attstattarget;
590 num_hist =
Max(num_hist, 2);
602 sorted_count_items[j++] = count_item;
604 qsort(sorted_count_items, count_items_count,
613 sizeof(
float4) * (num_hist + 1));
614 hist[num_hist] = (double) element_no / (
double) nonnull_cnt;
647 delta = analyzed_rows - 1;
650 frac = (int64) sorted_count_items[0]->frequency * (num_hist - 1);
651 for (i = 0; i < num_hist; i++)
657 frac += (int64) sorted_count_items[j]->frequency * (num_hist - 1);
659 hist[
i] = sorted_count_items[j]->
count;
662 Assert(j == count_items_count - 1);
664 stats->
stakind[slot_idx] = STATISTIC_KIND_DECHIST;
764 return (*t2)->
frequency - (*t1)->frequency;
788 if ((*t1)->count < (*t2)->count)
790 else if ((*t1)->count == (*t2)->count)
#define DatumGetUInt32(X)
static void prune_element_hashtable(HTAB *elements_tab, int b_current)
#define PointerGetDatum(X)
#define TYPECACHE_HASH_PROC_FINFO
Datum * stavalues[STATISTIC_NUM_SLOTS]
static void compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, int samplerows, double totalrows)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define MemSet(start, val, len)
long hash_get_num_entries(HTAB *hashp)
#define PG_GETARG_POINTER(n)
bool std_typanalyze(VacAttrStats *stats)
bool statypbyval[STATISTIC_NUM_SLOTS]
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
static int countitem_compare_count(const void *e1, const void *e2)
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
#define OidIsValid(objectId)
char statypalign[STATISTIC_NUM_SLOTS]
static int element_match(const void *key1, const void *key2, Size keysize)
void pfree(void *pointer)
Oid stacoll[STATISTIC_NUM_SLOTS]
int numnumbers[STATISTIC_NUM_SLOTS]
static ArrayAnalyzeExtraData * array_extra_data
MemoryContext CurrentMemoryContext
Size toast_raw_datum_size(Datum value)
Datum datumCopy(Datum value, bool typByVal, int typLen)
Datum array_typanalyze(PG_FUNCTION_ARGS)
static int trackitem_compare_element(const void *e1, const void *e2)
Oid staop[STATISTIC_NUM_SLOTS]
#define PG_RETURN_BOOL(x)
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
int16 stakind[STATISTIC_NUM_SLOTS]
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Oid statypid[STATISTIC_NUM_SLOTS]
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define STATISTIC_NUM_SLOTS
#define ARRAY_WIDTH_THRESHOLD
#define Assert(condition)
float4 * stanumbers[STATISTIC_NUM_SLOTS]
void(* AnalyzeAttrComputeStatsFunc)(VacAttrStatsP stats, AnalyzeAttrFetchFunc fetchfunc, int samplerows, double totalrows)
Datum(* AnalyzeAttrFetchFunc)(VacAttrStatsP stats, int rownum, bool *isNull)
void * hash_seq_search(HASH_SEQ_STATUS *status)
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
MemoryContext anl_context
#define DatumGetPointer(X)
static uint32 element_hash(const void *key, Size keysize)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Oid get_base_element_type(Oid typid)
int numvalues[STATISTIC_NUM_SLOTS]
void * MemoryContextAlloc(MemoryContext context, Size size)
int16 statyplen[STATISTIC_NUM_SLOTS]
AnalyzeAttrComputeStatsFunc compute_stats
#define TYPECACHE_CMP_PROC_FINFO
#define qsort(a, b, c, d)
void vacuum_delay_point(void)
static int element_compare(const void *key1, const void *key2)
#define DatumGetArrayTypeP(X)
static int trackitem_compare_frequencies_desc(const void *e1, const void *e2)