mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Invent qsort_interruptible().
Justin Pryzby reported that some scenarios could cause gathering of extended statistics to spend many seconds in an un-cancelable qsort() operation. To fix, invent qsort_interruptible(), which is just like qsort_arg() except that it will also do CHECK_FOR_INTERRUPTS every so often. This bloats the backend by a couple of kB, which seems like a good investment. (We considered just enabling CHECK_FOR_INTERRUPTS in the existing qsort and qsort_arg functions, but there are some callers for which that'd demonstrably be unsafe. Opt-in seems like a better way.) For now, just apply qsort_interruptible() in statistics collection. There's probably more places where it could be useful, but we can always change other call sites as we find problems. Back-patch to v14. Before that we didn't have extended stats on expressions, so that the problem was less severe. Also, this patch depends on the sort_template infrastructure introduced in v14. Tom Lane and Justin Pryzby Discussion: https://postgr.es/m/20220509000108.GQ28830@telsasoft.com
This commit is contained in:
@@ -404,7 +404,7 @@ count_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss)
|
||||
* order.
|
||||
*/
|
||||
static int
|
||||
compare_sort_item_count(const void *a, const void *b)
|
||||
compare_sort_item_count(const void *a, const void *b, void *arg)
|
||||
{
|
||||
SortItem *ia = (SortItem *) a;
|
||||
SortItem *ib = (SortItem *) b;
|
||||
@@ -457,8 +457,8 @@ build_distinct_groups(int numrows, SortItem *items, MultiSortSupport mss,
|
||||
Assert(j + 1 == ngroups);
|
||||
|
||||
/* Sort the distinct groups by frequency (in descending order). */
|
||||
pg_qsort((void *) groups, ngroups, sizeof(SortItem),
|
||||
compare_sort_item_count);
|
||||
qsort_interruptible((void *) groups, ngroups, sizeof(SortItem),
|
||||
compare_sort_item_count, NULL);
|
||||
|
||||
*ndistinct = ngroups;
|
||||
return groups;
|
||||
@@ -528,8 +528,8 @@ build_column_frequencies(SortItem *groups, int ngroups,
|
||||
}
|
||||
|
||||
/* sort the values, deduplicate */
|
||||
qsort_arg((void *) result[dim], ngroups, sizeof(SortItem),
|
||||
sort_item_compare, ssup);
|
||||
qsort_interruptible((void *) result[dim], ngroups, sizeof(SortItem),
|
||||
sort_item_compare, ssup);
|
||||
|
||||
/*
|
||||
* Identify distinct values, compute frequency (there might be
|
||||
@@ -696,8 +696,8 @@ statext_mcv_serialize(MCVList *mcvlist, VacAttrStats **stats)
|
||||
|
||||
PrepareSortSupportFromOrderingOp(typentry->lt_opr, &ssup[dim]);
|
||||
|
||||
qsort_arg(values[dim], counts[dim], sizeof(Datum),
|
||||
compare_scalars_simple, &ssup[dim]);
|
||||
qsort_interruptible(values[dim], counts[dim], sizeof(Datum),
|
||||
compare_scalars_simple, &ssup[dim]);
|
||||
|
||||
/*
|
||||
* Walk through the array and eliminate duplicate values, but keep the
|
||||
|
||||
Reference in New Issue
Block a user