aboutsummaryrefslogtreecommitdiff
path: root/src/backend/statistics/mcv.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-07-12 16:30:36 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-07-12 16:30:36 -0400
commite64cdab003027acef29e713087fb667e2319f679 (patch)
tree70f558736a70f872f201e278bd4400ba8c1d2b15 /src/backend/statistics/mcv.c
parent920072339f304a7da0b5de966117420c96ad78cb (diff)
downloadpostgresql-e64cdab003027acef29e713087fb667e2319f679.tar.gz
postgresql-e64cdab003027acef29e713087fb667e2319f679.zip
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
Diffstat (limited to 'src/backend/statistics/mcv.c')
-rw-r--r--src/backend/statistics/mcv.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c
index 1ef30344285..f10642df4f7 100644
--- a/src/backend/statistics/mcv.c
+++ b/src/backend/statistics/mcv.c
@@ -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