From b92e622396bd6262c3a3ab9f8d52b255d593a2ff Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:32:23 +0200 Subject: [PATCH 001/242] Vectorized hash grouping on one column some experiments --- tsl/src/nodes/vector_agg/CMakeLists.txt | 1 + tsl/src/nodes/vector_agg/exec.c | 26 +- .../vector_agg/function/agg_const_helper.c | 4 +- .../vector_agg/function/agg_many_helper.c | 31 ++ .../function/float48_accum_single.c | 55 ++- tsl/src/nodes/vector_agg/function/functions.c | 24 ++ tsl/src/nodes/vector_agg/function/functions.h | 11 +- .../vector_agg/function/int128_accum_single.c | 13 + .../function/int24_avg_accum_single.c | 12 + .../vector_agg/function/int24_sum_single.c | 12 + .../function/minmax_arithmetic_single.c | 31 +- .../vector_agg/function/sum_float_single.c | 12 + tsl/src/nodes/vector_agg/grouping_policy.h | 5 +- .../nodes/vector_agg/grouping_policy_batch.c | 11 +- .../nodes/vector_agg/grouping_policy_hash.c | 340 ++++++++++++++++++ tsl/src/nodes/vector_agg/plan.c | 29 +- 16 files changed, 578 insertions(+), 39 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/function/agg_many_helper.c create mode 100644 tsl/src/nodes/vector_agg/grouping_policy_hash.c diff --git a/tsl/src/nodes/vector_agg/CMakeLists.txt b/tsl/src/nodes/vector_agg/CMakeLists.txt index e621571d5f5..c3a85bbd30f 100644 --- a/tsl/src/nodes/vector_agg/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/CMakeLists.txt @@ -2,5 +2,6 @@ add_subdirectory(function) set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exec.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_batch.c + ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_hash.c ${CMAKE_CURRENT_SOURCE_DIR}/plan.c) target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 381944f5172..eae2babe0ac 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -122,11 +122,27 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } } - List *grouping_column_offsets = linitial(cscan->custom_private); - vector_agg_state->grouping = - create_grouping_policy_batch(vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns, - /* partial_per_batch = */ grouping_column_offsets != NIL); + /// List *grouping_child_output_offsets = linitial(cscan->custom_private); + if (list_length(vector_agg_state->output_grouping_columns) == 1) + { + GroupingColumn *col = + (GroupingColumn *) linitial(vector_agg_state->output_grouping_columns); + DecompressContext *dcontext = &decompress_state->decompress_context; + CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; + if (desc->type == COMPRESSED_COLUMN) + { + vector_agg_state->grouping = + create_grouping_policy_hash(vector_agg_state->agg_defs, + vector_agg_state->output_grouping_columns); + } + } + + if (vector_agg_state->grouping == NULL) + { + vector_agg_state->grouping = + create_grouping_policy_batch(vector_agg_state->agg_defs, + vector_agg_state->output_grouping_columns); + } } static void diff --git a/tsl/src/nodes/vector_agg/function/agg_const_helper.c b/tsl/src/nodes/vector_agg/function/agg_const_helper.c index a1abe481aec..c83d38526be 100644 --- a/tsl/src/nodes/vector_agg/function/agg_const_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_const_helper.c @@ -11,13 +11,13 @@ * implementation otherwise. */ static void -FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int n, +FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int nn, MemoryContext agg_extra_mctx) { const uint64 valid = constisnull ? 0 : 1; const CTYPE value = valid ? DATUM_TO_CTYPE(constvalue) : 0; - for (int i = 0; i < n; i++) + for (int i = 0; i < nn; i++) { FUNCTION_NAME(vector_impl)(agg_state, 1, &value, &valid, NULL, agg_extra_mctx); } diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_helper.c new file mode 100644 index 00000000000..a0cc7f3513f --- /dev/null +++ b/tsl/src/nodes/vector_agg/function/agg_many_helper.c @@ -0,0 +1,31 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +static void +FUNCTION_NAME(many)(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); + const int n = vector->length; + const CTYPE *values = vector->buffers[1]; + const uint64 *valid = vector->buffers[0]; + for (int row = 0; row < n; row++) + { + if (offsets[row] == 0) + { + continue; + } + + if (!arrow_row_is_valid(valid, row)) + { + continue; + } + + FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); + FUNCTION_NAME(one)(state, values[row]); + } + MemoryContextSwitchTo(old); +} diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index 13075b29807..c54c0405384 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -194,13 +194,13 @@ FUNCTION_NAME(combine)(double *inout_N, double *inout_Sx, #endif static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, +FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const uint64 *valid1, const uint64 *valid2, MemoryContext agg_extra_mctx) { /* * Vector registers can be up to 512 bits wide. */ -#define UNROLL_SIZE ((int) (512 / 8 / sizeof(CTYPE))) +#define UNROLL_SIZE ((int) ((512 / 8) / sizeof(CTYPE))) /* * Each inner iteration works with its own accumulators to avoid data @@ -212,7 +212,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui double Sxxarray[UNROLL_SIZE] = { 0 }; #endif - int row = 0; + size_t row = 0; #ifdef NEED_SXX /* @@ -220,7 +220,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui * to make the actual update function branchless, namely the computation of * Sxx which works differently for the first row. */ - for (int inner = 0; inner < UNROLL_SIZE; inner++) + for (size_t inner = 0; inner < UNROLL_SIZE; inner++) { for (; row < n; row++) { @@ -240,7 +240,8 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui * Scroll to the row that is a multiple of UNROLL_SIZE. This is the correct * row at which to enter the unrolled loop below. */ - for (int inner = row % UNROLL_SIZE; inner > 0 && inner < UNROLL_SIZE && row < n; inner++, row++) + for (size_t inner = row % UNROLL_SIZE; inner > 0 && inner < UNROLL_SIZE && row < n; + inner++, row++) { UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } @@ -252,7 +253,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui Assert(row % UNROLL_SIZE == 0 || row == n); for (; row < UNROLL_SIZE * (n / UNROLL_SIZE); row += UNROLL_SIZE) { - for (int inner = 0; inner < UNROLL_SIZE; inner++) + for (size_t inner = 0; inner < UNROLL_SIZE; inner++) { UPDATE(valid1, valid2, @@ -269,7 +270,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui */ for (; row < n; row++) { - const int inner = row % UNROLL_SIZE; + const size_t inner = row % UNROLL_SIZE; UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } @@ -289,14 +290,44 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui COMBINE(&state->N, &state->Sx, &state->Sxx, Narray[0], Sxarray[0], Sxxarray[0]); } +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + /* + * This code follows the Postgres float8_accum() transition function, see + * the comments there. + */ + const double newN = state->N + 1.0; + const double newSx = state->Sx + value; +#ifdef NEED_SXX + if (state->N > 0.0) + { + const double tmp = value * newN - newSx; + state->Sxx += tmp * tmp / (state->N * newN); + } + else + { + state->Sxx = 0 * value; + } +#endif + + state->N = newN; + state->Sx = newSx; +} + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" -VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), - .agg_init = FUNCTION_NAME(init), - .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), - .agg_vector = FUNCTION_NAME(vector) }; +VectorAggFunctions FUNCTION_NAME(argdef) = { + .state_bytes = sizeof(FUNCTION_NAME(state)), + .agg_init = FUNCTION_NAME(init), + .agg_emit = FUNCTION_NAME(emit), + .agg_const = FUNCTION_NAME(const), + .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), +}; #undef UPDATE #undef COMBINE diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 6cbb7dccf0d..a5bb1226929 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -110,12 +110,36 @@ count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter } } +static void +count_any_many(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + const int n = vector->length; + const uint64 *valid = vector->buffers[0]; + for (int row = 0; row < n; row++) + { + if (offsets[row] == 0) + { + continue; + } + + if (!arrow_row_is_valid(valid, row)) + { + continue; + } + + CountState *state = (offsets[row] + (CountState *) agg_states); + state->count++; + } +} + VectorAggFunctions count_any_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_emit = count_emit, .agg_const = count_any_const, .agg_vector = count_any_vector, + .agg_many = count_any_many, }; /* diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 773bffe584c..70ec3d5a2c7 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -17,18 +17,21 @@ typedef struct size_t state_bytes; /* Initialize the aggregate function state pointed to by agg_value and agg_isnull. */ - void (*agg_init)(void *agg_state); + void (*agg_init)(void *restrict agg_state); /* Aggregate a given arrow array. */ - void (*agg_vector)(void *agg_state, const ArrowArray *vector, const uint64 *filter, + void (*agg_vector)(void *restrict agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx); /* Aggregate a constant (like segmentby or column with default value). */ - void (*agg_const)(void *agg_state, Datum constvalue, bool constisnull, int n, + void (*agg_const)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, MemoryContext agg_extra_mctx); + void (*agg_many)(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, + MemoryContext agg_extra_mctx); + /* Emit a partial result. */ - void (*agg_emit)(void *agg_state, Datum *out_result, bool *out_isnull); + void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; VectorAggFunctions *get_vector_aggregate(Oid aggfnoid); diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index e50a743c901..39bd665f3c9 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -96,7 +96,19 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #endif } +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->N++; + state->sumX += value; +#ifdef NEED_SUMX2 + state->sumX2 += ((int128) value) * ((int128) value); +#endif +} + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { @@ -105,6 +117,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = FUNCTION_NAME(emit), .agg_const = FUNCTION_NAME(const), .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 551730c1912..2051fe006d5 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -28,7 +28,18 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->sum += batch_sum; } +typedef Int24AvgAccumState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->count++; + state->sum += value; +} + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { @@ -37,6 +48,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = int24_avg_accum_emit, .agg_const = FUNCTION_NAME(const), .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index e84c873aed2..c96a45fc96f 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -51,7 +51,18 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->isnull &= !have_result; } +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + Int24SumState *state = (Int24SumState *) agg_state; + state->result += value; + state->isnull = false; +} + +typedef Int24SumState FUNCTION_NAME(state); + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { @@ -60,6 +71,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = int_sum_emit, .agg_const = FUNCTION_NAME(const), .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index f21521f12bd..127b5176291 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -41,14 +41,35 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui MemoryContextSwitchTo(old); } +typedef MinMaxState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + if (!state->isvalid || PREDICATE(DATUM_TO_CTYPE(state->value), value) || isnan((double) value)) + { + /* + * Note that float8 Datum is by-reference on 32-bit systems, and this + * function is called in the extra aggregate data memory context. + */ + state->value = CTYPE_TO_DATUM(value); + state->isvalid = true; + } +} + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" -VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(MinMaxState), - .agg_init = minmax_init, - .agg_emit = minmax_emit, - .agg_const = FUNCTION_NAME(const), - .agg_vector = FUNCTION_NAME(vector) }; +VectorAggFunctions FUNCTION_NAME(argdef) = { + .state_bytes = sizeof(MinMaxState), + .agg_init = minmax_init, + .agg_emit = minmax_emit, + .agg_const = FUNCTION_NAME(const), + .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), +}; #endif #undef PG_TYPE diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 59a5cfe1fc7..41565feabfc 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -80,7 +80,18 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->result += sum_accu[0]; } +typedef FloatSumState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->isnull = false; + state->result += value; +} + #include "agg_const_helper.c" +#include "agg_many_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { @@ -89,6 +100,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = FUNCTION_NAME(emit), .agg_const = FUNCTION_NAME(const), .agg_vector = FUNCTION_NAME(vector), + .agg_many = FUNCTION_NAME(many), }; #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 108584f19ef..8aaf9c99f47 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -37,5 +37,6 @@ typedef struct GroupingPolicy void (*gp_destroy)(GroupingPolicy *gp); } GroupingPolicy; -extern GroupingPolicy *create_grouping_policy_batch(List *agg_defs, List *grouping_columns, - bool partial_per_batch); +extern GroupingPolicy *create_grouping_policy_batch(List *agg_defs, List *grouping_columns); + +extern GroupingPolicy *create_grouping_policy_hash(List *agg_defs, List *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index ee42a5b6e1e..a37747f5166 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -28,7 +28,6 @@ typedef struct List *output_grouping_columns; Datum *output_grouping_values; bool *output_grouping_isnull; - bool partial_per_batch; bool have_results; /* @@ -42,10 +41,9 @@ typedef struct static const GroupingPolicy grouping_policy_batch_functions; GroupingPolicy * -create_grouping_policy_batch(List *agg_defs, List *output_grouping_columns, bool partial_per_batch) +create_grouping_policy_batch(List *agg_defs, List *output_grouping_columns) { GroupingPolicyBatch *policy = palloc0(sizeof(GroupingPolicyBatch)); - policy->partial_per_batch = partial_per_batch; policy->funcs = grouping_policy_batch_functions; policy->output_grouping_columns = output_grouping_columns; policy->agg_defs = agg_defs; @@ -180,7 +178,6 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * means we're grouping by segmentby, and these values will be valid * until the next call to the vector agg node. */ - Assert(policy->partial_per_batch); policy->output_grouping_values[i] = *values->output_value; policy->output_grouping_isnull[i] = *values->output_isnull; } @@ -192,7 +189,11 @@ static bool gp_batch_should_emit(GroupingPolicy *gp) { GroupingPolicyBatch *policy = (GroupingPolicyBatch *) gp; - return policy->partial_per_batch && policy->have_results; + /* + * If we're grouping by segmentby columns, we have to output partials for + * every batch. + */ + return policy->output_grouping_columns != NIL && policy->have_results; } static bool diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c new file mode 100644 index 00000000000..bffb77912f7 --- /dev/null +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -0,0 +1,340 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This grouping policy aggregates entire compressed batches. It can be used to + * aggregate with no grouping, or to produce partial aggregates per each batch + * to group by segmentby columns. + */ + +#include + +#include +#include + +#include "grouping_policy.h" + +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" + +typedef struct +{ + Datum key; + uint32 status; + uint32 agg_state_index; +} HashEntry; + +static uint64_t +hash64(uint64_t x) +{ + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + return x; +} + +#define SH_PREFIX h +#define SH_ELEMENT_TYPE HashEntry +#define SH_KEY_TYPE Datum +#define SH_KEY key +#define SH_HASH_KEY(tb, key) hash64(key) +#define SH_EQUAL(tb, a, b) a == b +#define SH_SCOPE static inline +#define SH_DECLARE +#define SH_DEFINE +#include "lib/simplehash.h" + +struct h_hash; + +typedef struct +{ + GroupingPolicy funcs; + List *agg_defs; + List *output_grouping_columns; + bool partial_per_batch; + struct h_hash *table; + bool have_null_key; + struct h_iterator iter; + bool returning_results; + + /* + * A memory context for aggregate functions to allocate additional data, + * i.e. if they store strings or float8 datum on 32-bit systems. Valid until + * the grouping policy is reset. + */ + MemoryContext agg_extra_mctx; + + uint64 aggstate_bytes_per_key; + uint64 allocated_aggstate_rows; + List *per_agg_states; +} GroupingPolicyHash; + +static const GroupingPolicy grouping_policy_hash_functions; + +GroupingPolicy * +create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) +{ + GroupingPolicyHash *policy = palloc0(sizeof(GroupingPolicyHash)); + policy->funcs = grouping_policy_hash_functions; + policy->output_grouping_columns = output_grouping_columns; + policy->agg_defs = agg_defs; + policy->agg_extra_mctx = + AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); + policy->allocated_aggstate_rows = 1000; + ListCell *lc; + foreach (lc, agg_defs) + { + VectorAggDef *def = lfirst(lc); + policy->aggstate_bytes_per_key += def->func->state_bytes; + + policy->per_agg_states = + lappend(policy->per_agg_states, + palloc0(def->func->state_bytes * policy->allocated_aggstate_rows)); + } + + policy->table = h_create(CurrentMemoryContext, 1000, NULL); + policy->have_null_key = false; + + policy->returning_results = false; + + return &policy->funcs; +} + +static void +gp_hash_reset(GroupingPolicy *obj) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) obj; + + MemoryContextReset(policy->agg_extra_mctx); + + policy->returning_results = false; + + h_reset(policy->table); + policy->have_null_key = false; +} + +static void +compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_def, void *agg_states, + int32 *offsets, MemoryContext agg_extra_mctx) +{ + ArrowArray *arg_arrow = NULL; + Datum arg_datum = 0; + bool arg_isnull = true; + + /* + * We have functions with one argument, and one function with no arguments + * (count(*)). Collect the arguments. + */ + if (agg_def->input_offset >= 0) + { + CompressedColumnValues *values = &batch_state->compressed_columns[agg_def->input_offset]; + Assert(values->decompression_type != DT_Invalid); + Assert(values->decompression_type != DT_Iterator); + + if (values->arrow != NULL) + { + arg_arrow = values->arrow; + } + else + { + Assert(values->decompression_type == DT_Scalar); + arg_datum = *values->output_value; + arg_isnull = *values->output_isnull; + } + } + + /* + * Now call the function. + */ + if (arg_arrow != NULL) + { + /* Arrow argument. */ + agg_def->func->agg_many(agg_states, offsets, arg_arrow, agg_extra_mctx); + } + else + { + /* + * Scalar argument, or count(*). + */ + for (int i = 0; i < batch_state->total_batch_rows; i++) + { + if (!arrow_row_is_valid(batch_state->vector_qual_result, i)) + { + continue; + } + + if (offsets[i] == 0) + { + continue; + } + + void *state = (offsets[i] * agg_def->func->state_bytes + (char *) agg_states); + agg_def->func->agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); + } + } +} + +static void +gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + + Assert(!policy->returning_results); + + /* + * State index zero is invalid, and state index one is for null key. We have + * to initialize it at the first run. + */ + const uint64 last_initialized_state_index = + policy->table->members ? policy->table->members + 2 : 1; + uint64 next_unused_state_index = policy->table->members + 2; + + int32 offsets[1000] = { 0 }; + Assert(batch_state->total_batch_rows <= 1000); + + /* + * For the partial aggregation node, the grouping columns are always in the + * output, so we don't have to separately look at the list of the grouping + * columns. + */ + Assert(list_length(policy->output_grouping_columns) == 1); + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues *gv = &batch_state->compressed_columns[g->input_offset]; + // Assert(gv->decompression_type == 8 /* lolwut */); + Assert(gv->decompression_type > 0); + const void *vv = gv->arrow->buffers[1]; + const uint64 *key_validity = gv->arrow->buffers[0]; + const uint64 *filter = batch_state->vector_qual_result; + for (int row = 0; row < batch_state->total_batch_rows; row++) + { + Datum key = { 0 }; + memcpy(&key, gv->decompression_type * row + (char *) vv, gv->decompression_type); + if (!arrow_row_is_valid(filter, row)) + { + continue; + } + + if (arrow_row_is_valid(key_validity, row)) + { + bool found = false; + HashEntry *entry = h_insert(policy->table, key, &found); + if (!found) + { + entry->agg_state_index = next_unused_state_index++; + } + offsets[row] = entry->agg_state_index; + } + else + { + policy->have_null_key = true; + offsets[row] = 1; + } + } + + ListCell *aggdeflc; + ListCell *aggstatelc; + + if (next_unused_state_index > last_initialized_state_index) + { + if (next_unused_state_index > policy->allocated_aggstate_rows) + { + policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) + { + VectorAggDef *def = lfirst(aggdeflc); + lfirst(aggstatelc) = + repalloc(lfirst(aggstatelc), + policy->allocated_aggstate_rows * def->func->state_bytes); + } + } + + forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) + { + VectorAggDef *def = lfirst(aggdeflc); + for (uint64 i = last_initialized_state_index; i < next_unused_state_index; i++) + { + void *aggstate = def->func->state_bytes * i + (char *) lfirst(aggstatelc); + def->func->agg_init(aggstate); + } + } + } + + forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) + { + compute_single_aggregate(batch_state, + lfirst(aggdeflc), + lfirst(aggstatelc), + offsets, + policy->agg_extra_mctx); + } +} + +static bool +gp_hash_should_emit(GroupingPolicy *gp) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + if (policy->table->members + policy->have_null_key > 0) + { + return true; + } + return false; +} + +static bool +gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + + if (!policy->returning_results) + { + /* FIXME doesn't work on final result emission w/o should_emit. */ + policy->returning_results = true; + h_start_iterate(policy->table, &policy->iter); + } + + HashEntry null_key_entry = { .agg_state_index = 1 }; + HashEntry *entry = h_iterate(policy->table, &policy->iter); + bool key_is_null = false; + if (entry == NULL && policy->have_null_key) + { + policy->have_null_key = false; + entry = &null_key_entry; + key_is_null = true; + } + + if (entry == NULL) + { + policy->returning_results = false; + return false; + } + + const int naggs = list_length(policy->agg_defs); + for (int i = 0; i < naggs; i++) + { + VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); + void *agg_states = list_nth(policy->per_agg_states, i); + void *agg_state = entry->agg_state_index * agg_def->func->state_bytes + (char *) agg_states; + agg_def->func->agg_emit(agg_state, + &aggregated_slot->tts_values[agg_def->output_offset], + &aggregated_slot->tts_isnull[agg_def->output_offset]); + } + + Assert(list_length(policy->output_grouping_columns) == 1); + GroupingColumn *col = linitial(policy->output_grouping_columns); + aggregated_slot->tts_values[col->output_offset] = entry->key; + aggregated_slot->tts_isnull[col->output_offset] = key_is_null; + + return true; +} + +static const GroupingPolicy grouping_policy_hash_functions = { + .gp_reset = gp_hash_reset, + .gp_add_batch = gp_hash_add_batch, + .gp_should_emit = gp_hash_should_emit, + .gp_do_emit = gp_hash_do_emit, +}; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index ac150b7ea99..c1ff9eac806 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -154,13 +154,13 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) custom->scan.plan.extParam = bms_copy(agg->plan.extParam); custom->scan.plan.allParam = bms_copy(agg->plan.allParam); - List *grouping_col_offsets = NIL; + List *grouping_child_output_offsets = NIL; for (int i = 0; i < agg->numCols; i++) { - grouping_col_offsets = - lappend_int(grouping_col_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); + grouping_child_output_offsets = + lappend_int(grouping_child_output_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); } - custom->custom_private = list_make1(grouping_col_offsets); + custom->custom_private = list_make1(grouping_child_output_offsets); return (Plan *) custom; } @@ -323,6 +323,27 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) return true; } + if (agg->numCols == 1) + { + int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); + TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + fprintf(stderr, "target entry:\n"); + my_print(entry); + + bool is_segmentby = false; + if (is_vector_var(custom, entry->expr, &is_segmentby)) + { + Var *var = castNode(Var, entry->expr); + int16 typlen; + bool typbyval; + get_typlenbyval(var->vartype, &typlen, &typbyval); + if (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) + { + return true; + } + } + } + for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); From 74d4419dea4d686ef46913d751f84342e67a7acf Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:39:46 +0200 Subject: [PATCH 002/242] benchmark vectorized grouping (2024-10-02 no. 6) From baedf7f09fe95c9532a3cf0bfbb434d8970d3010 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:10:25 +0200 Subject: [PATCH 003/242] fixes --- tsl/src/compression/arrow_c_data_interface.h | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 18 ++++++++++++++---- tsl/src/nodes/vector_agg/plan.c | 2 -- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index a0362f85328..6a1d7ae114d 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -190,7 +190,7 @@ pad_to_multiple(uint64 pad_to, uint64 source_value) } static inline size_t -arrow_num_valid(uint64 *bitmap, size_t total_rows) +arrow_num_valid(const uint64 *bitmap, size_t total_rows) { if (bitmap == NULL) { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index bffb77912f7..e11cdbd3995 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -72,6 +72,8 @@ typedef struct uint64 aggstate_bytes_per_key; uint64 allocated_aggstate_rows; List *per_agg_states; + + uint64 stat_input_valid_rows; } GroupingPolicyHash; static const GroupingPolicy grouping_policy_hash_functions; @@ -116,6 +118,8 @@ gp_hash_reset(GroupingPolicy *obj) h_reset(policy->table); policy->have_null_key = false; + + policy->stat_input_valid_rows = 0; } static void @@ -236,6 +240,8 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } } + policy->stat_input_valid_rows += arrow_num_valid(key_validity, batch_state->total_batch_rows); + ListCell *aggdeflc; ListCell *aggstatelc; @@ -278,10 +284,11 @@ static bool gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - if (policy->table->members + policy->have_null_key > 0) - { - return true; - } + (void) policy; +// if (policy->table->members + policy->have_null_key > 0) +// { +// return true; +// } return false; } @@ -295,6 +302,9 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); +// fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio\n", +// policy->stat_input_valid_rows, policy->table->members + policy->have_null_key, +// policy->stat_input_valid_rows / (float) (policy->table->members + policy->have_null_key)); } HashEntry null_key_entry = { .agg_state_index = 1 }; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index c1ff9eac806..f358d7a5a28 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -327,8 +327,6 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); TargetEntry *entry = list_nth(agg->plan.targetlist, offset); - fprintf(stderr, "target entry:\n"); - my_print(entry); bool is_segmentby = false; if (is_vector_var(custom, entry->expr, &is_segmentby)) From 35dbd361a428b0b572140606999d97abe1ee83a0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:10:30 +0200 Subject: [PATCH 004/242] benchmark vectorized grouping (2024-10-02 no. 7) From 74fffd3f4cbf94f1a6e376d31180dc1411f41bd1 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:07:58 +0200 Subject: [PATCH 005/242] some ugly stuff --- tsl/src/nodes/vector_agg/exec.c | 3 +- .../vector_agg/function/agg_many_helper.c | 8 +- tsl/src/nodes/vector_agg/function/functions.c | 19 +- tsl/src/nodes/vector_agg/function/functions.h | 5 +- .../nodes/vector_agg/grouping_policy_hash.c | 257 ++++++++++++++---- tsl/test/expected/vector_agg_functions.out | 26 +- 6 files changed, 248 insertions(+), 70 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index eae2babe0ac..548b6ca623f 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -129,7 +129,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) (GroupingColumn *) linitial(vector_agg_state->output_grouping_columns); DecompressContext *dcontext = &decompress_state->decompress_context; CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; - if (desc->type == COMPRESSED_COLUMN) + if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && + (size_t) desc->value_bytes <= sizeof(Datum)) { vector_agg_state->grouping = create_grouping_policy_hash(vector_agg_state->agg_defs, diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_helper.c index a0cc7f3513f..ef8acd28181 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_helper.c @@ -5,7 +5,7 @@ */ static void -FUNCTION_NAME(many)(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, +FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, MemoryContext agg_extra_mctx) { MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); @@ -14,6 +14,9 @@ FUNCTION_NAME(many)(void *restrict agg_states, int32 *restrict offsets, const Ar const uint64 *valid = vector->buffers[0]; for (int row = 0; row < n; row++) { + FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); + CTYPE value = values[row]; + if (offsets[row] == 0) { continue; @@ -24,8 +27,7 @@ FUNCTION_NAME(many)(void *restrict agg_states, int32 *restrict offsets, const Ar continue; } - FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); - FUNCTION_NAME(one)(state, values[row]); + FUNCTION_NAME(one)(state, value); } MemoryContextSwitchTo(old); } diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index a5bb1226929..7c4e9af4e3b 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -49,11 +49,28 @@ count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, state->count += n; } +static void +count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int n, Datum constvalue, + bool constisnull, MemoryContext agg_extra_mctx) +{ + CountState *states = (CountState *) agg_states; + for (int row = 0; row < n; row++) + { + if (offsets[row] == 0) + { + continue; + } + + states[offsets[row]].count++; + } +} + VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_const = count_star_const, .agg_emit = count_emit, + .agg_many_scalar = count_star_many_scalar, }; /* @@ -111,7 +128,7 @@ count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter } static void -count_any_many(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, +count_any_many(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, MemoryContext agg_extra_mctx) { const int n = vector->length; diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 70ec3d5a2c7..9f080a8b823 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -27,9 +27,12 @@ typedef struct void (*agg_const)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, MemoryContext agg_extra_mctx); - void (*agg_many)(void *restrict agg_states, int32 *restrict offsets, const ArrowArray *vector, + void (*agg_many)(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, MemoryContext agg_extra_mctx); + void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int n, + Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx); + /* Emit a partial result. */ void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index e11cdbd3995..aab2ba2b280 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -124,7 +124,7 @@ gp_hash_reset(GroupingPolicy *obj) static void compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_def, void *agg_states, - int32 *offsets, MemoryContext agg_extra_mctx) + uint32 *offsets, MemoryContext agg_extra_mctx) { ArrowArray *arg_arrow = NULL; Datum arg_datum = 0; @@ -163,67 +163,54 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de else { /* - * Scalar argument, or count(*). + * Scalar argument, or count(*). The latter has an optimized + * implementation for this case. */ - for (int i = 0; i < batch_state->total_batch_rows; i++) + if (agg_def->func->agg_many_scalar != NULL) { - if (!arrow_row_is_valid(batch_state->vector_qual_result, i)) + agg_def->func->agg_many_scalar(agg_states, + offsets, + batch_state->total_batch_rows, + arg_datum, + arg_isnull, + agg_extra_mctx); + } + else + { + for (int i = 0; i < batch_state->total_batch_rows; i++) { - continue; - } + if (offsets[i] == 0) + { + continue; + } - if (offsets[i] == 0) - { - continue; + void *state = (offsets[i] * agg_def->func->state_bytes + (char *) agg_states); + agg_def->func->agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); } - - void *state = (offsets[i] * agg_def->func->state_bytes + (char *) agg_states); - agg_def->func->agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); } } } -static void -gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) +static pg_attribute_always_inline uint32 +fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, Datum *key, bool *valid)) { - GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - - Assert(!policy->returning_results); - - /* - * State index zero is invalid, and state index one is for null key. We have - * to initialize it at the first run. - */ - const uint64 last_initialized_state_index = - policy->table->members ? policy->table->members + 2 : 1; - uint64 next_unused_state_index = policy->table->members + 2; - - int32 offsets[1000] = { 0 }; - Assert(batch_state->total_batch_rows <= 1000); - - /* - * For the partial aggregation node, the grouping columns are always in the - * output, so we don't have to separately look at the list of the grouping - * columns. - */ - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); - CompressedColumnValues *gv = &batch_state->compressed_columns[g->input_offset]; + CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; // Assert(gv->decompression_type == 8 /* lolwut */); - Assert(gv->decompression_type > 0); - const void *vv = gv->arrow->buffers[1]; - const uint64 *key_validity = gv->arrow->buffers[0]; - const uint64 *filter = batch_state->vector_qual_result; + const uint64 *restrict filter = batch_state->vector_qual_result; for (int row = 0; row < batch_state->total_batch_rows; row++) { + bool key_valid = false; Datum key = { 0 }; - memcpy(&key, gv->decompression_type * row + (char *) vv, gv->decompression_type); + get_key(column, row, &key, &key_valid); + if (!arrow_row_is_valid(filter, row)) { continue; } - if (arrow_row_is_valid(key_validity, row)) + if (key_valid) { bool found = false; HashEntry *entry = h_insert(policy->table, key, &found); @@ -240,7 +227,174 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } } - policy->stat_input_valid_rows += arrow_num_valid(key_validity, batch_state->total_batch_rows); + policy->stat_input_valid_rows += + arrow_num_valid(column.buffers[0], batch_state->total_batch_rows); + return next_unused_state_index; +} + +// static pg_attribute_always_inline +// void get_key_generic(CompressedColumnValues *column, int row, Datum *key, bool *valid) +//{ +// Assert(column->decompression_type > 0); +// const void *values = column->arrow->buffers[1]; +// const uint64 *key_validity = column->arrow->buffers[0]; +// *valid = arrow_row_is_valid(key_validity, row); +// memcpy(key, column->decompression_type * row + (char *) values, column->decompression_type); +// } + +static pg_attribute_always_inline void +get_key_arrow_fixed(CompressedColumnValues column, int row, int key_bytes, Datum *restrict key, + bool *restrict valid) +{ + Assert(column.decompression_type == key_bytes); + const void *values = column.buffers[1]; + const uint64 *key_validity = column.buffers[0]; + *valid = arrow_row_is_valid(key_validity, row); + memcpy(key, key_bytes * row + (char *) values, key_bytes); +} + +static pg_attribute_always_inline void +get_key_arrow_fixed_2(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid) +{ + get_key_arrow_fixed(column, row, 2, key, valid); +} + +static pg_attribute_always_inline void +get_key_arrow_fixed_4(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid) +{ + get_key_arrow_fixed(column, row, 4, key, valid); +} + +static pg_attribute_always_inline void +get_key_arrow_fixed_8(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid) +{ + /* FIXME for float8 not by value */ + get_key_arrow_fixed(column, row, 8, key, valid); +} + +static pg_attribute_always_inline void +get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) +{ + Assert(column.decompression_type == DT_Scalar); + *key = *column.output_value; + *valid = !*column.output_isnull; +} + +static pg_noinline uint32 +fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, + uint32 *restrict offsets) +{ + return fill_offsets_impl(policy, + batch_state, + key_column_index, + next_unused_state_index, + offsets, + get_key_arrow_fixed_8); +} + +static pg_noinline uint32 +fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, + uint32 *restrict offsets) +{ + return fill_offsets_impl(policy, + batch_state, + key_column_index, + next_unused_state_index, + offsets, + get_key_arrow_fixed_4); +} + +static pg_noinline uint32 +fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, + uint32 *restrict offsets) +{ + return fill_offsets_impl(policy, + batch_state, + key_column_index, + next_unused_state_index, + offsets, + get_key_arrow_fixed_2); +} + +static pg_noinline uint32 +fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, uint32 *restrict offsets) +{ + return fill_offsets_impl(policy, + batch_state, + key_column_index, + next_unused_state_index, + offsets, + get_key_scalar); +} + +static void +gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + + Assert(!policy->returning_results); + + /* + * State index zero is invalid, and state index one is for null key. We have + * to initialize it at the first run. + */ + const uint32 last_initialized_state_index = + policy->table->members ? policy->table->members + 2 : 1; + uint32 next_unused_state_index = policy->table->members + 2; + + uint32 offsets[1000] = { 0 }; + Assert(batch_state->total_batch_rows <= 1000); + + /* + * For the partial aggregation node, the grouping columns are always in the + * output, so we don't have to separately look at the list of the grouping + * columns. + */ + Assert(list_length(policy->output_grouping_columns) == 1); + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; + + switch ((int) key_column->decompression_type) + { + case DT_Scalar: + next_unused_state_index = fill_offsets_scalar(policy, + batch_state, + g->input_offset, + next_unused_state_index, + offsets); + break; + case 8: + next_unused_state_index = fill_offsets_arrow_fixed_8(policy, + batch_state, + g->input_offset, + next_unused_state_index, + offsets); + break; + case 4: + next_unused_state_index = fill_offsets_arrow_fixed_4(policy, + batch_state, + g->input_offset, + next_unused_state_index, + offsets); + break; + case 2: + next_unused_state_index = fill_offsets_arrow_fixed_2(policy, + batch_state, + g->input_offset, + next_unused_state_index, + offsets); + break; + default: + Assert(false); + break; + } ListCell *aggdeflc; ListCell *aggstatelc; @@ -285,10 +439,10 @@ gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; (void) policy; -// if (policy->table->members + policy->have_null_key > 0) -// { -// return true; -// } + // if (policy->table->members + policy->have_null_key > 0) + // { + // return true; + // } return false; } @@ -302,9 +456,10 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); -// fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio\n", -// policy->stat_input_valid_rows, policy->table->members + policy->have_null_key, -// policy->stat_input_valid_rows / (float) (policy->table->members + policy->have_null_key)); + // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio\n", + // policy->stat_input_valid_rows, policy->table->members + policy->have_null_key, + // policy->stat_input_valid_rows / (float) (policy->table->members + + // policy->have_null_key)); } HashEntry null_key_entry = { .agg_state_index = 1 }; diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index b600fa6018b..9e9f8115e57 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -314,7 +314,7 @@ select ss, min(cfloat4) from aggfns group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | -49.9756 + 1 | NaN 2 | -49.9756 3 | -Infinity 4 | -49.9756 @@ -2006,13 +2006,13 @@ select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+----------- 0 | -5395.24 - 1 | -5377.92 + 1 | -5377.93 2 | -5382.66 3 | -Infinity 4 | -5415.12 5 | -5415.12 - 6 | -5447.29 - 7 | -5447.29 + 6 | -5447.3 + 7 | -5447.3 8 | -5410.38 9 | -5439.41 (10 rows) @@ -3554,7 +3554,7 @@ select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+---------- 0 | -49.9756 - 1 | -49.9756 + 1 | NaN 2 | -49.9756 3 | -49.9756 4 | -49.9756 @@ -3625,16 +3625,16 @@ select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- - 0 | 2752.7 + 0 | 2752.71 1 | NaN 2 | Infinity - 3 | 2727.98 - 4 | 2764.68 - 5 | 2802.89 - 6 | 2807.59 + 3 | 2727.99 + 4 | 2764.69 + 5 | 2802.9 + 6 | 2807.6 7 | 2826.29 - 8 | 2784.1 - 9 | 2784.1 + 8 | 2784.11 + 9 | 2784.11 (10 rows) select avg(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -5174,7 +5174,7 @@ select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | -49.9756 + 1 | NaN 2 | -49.9756 3 | -Infinity 4 | -49.9756 From f8db4545b5a7274714bee351c2e8bc2cf0108c97 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:15:08 +0200 Subject: [PATCH 006/242] benchmark vectorized grouping (2024-10-02 no. 9) From 00a9d11659154af6e7a2b38f0dc691fcb156ae99 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:26:57 +0200 Subject: [PATCH 007/242] someething --- tsl/src/import/ts_simplehash.h | 1047 +++++++++++++++++ .../function/float48_accum_single.c | 9 +- tsl/src/nodes/vector_agg/function/functions.c | 9 +- tsl/src/nodes/vector_agg/function/functions.h | 4 +- .../vector_agg/function/int128_accum_single.c | 13 +- .../function/int24_avg_accum_templates.c | 11 +- .../vector_agg/function/int24_sum_templates.c | 11 +- .../vector_agg/function/minmax_templates.c | 11 +- .../vector_agg/function/sum_float_templates.c | 11 +- .../nodes/vector_agg/grouping_policy_batch.c | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 68 +- tsl/test/expected/vectorized_aggregation.out | 34 +- 12 files changed, 1159 insertions(+), 71 deletions(-) create mode 100644 tsl/src/import/ts_simplehash.h diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h new file mode 100644 index 00000000000..2a630f24017 --- /dev/null +++ b/tsl/src/import/ts_simplehash.h @@ -0,0 +1,1047 @@ +/* + * simplehash.h + * + * When included this file generates a "templated" (by way of macros) + * open-addressing hash table implementation specialized to user-defined + * types. + * + * It's probably not worthwhile to generate such a specialized implementation + * for hash tables that aren't performance or space sensitive. + * + * Compared to dynahash, simplehash has the following benefits: + * + * - Due to the "templated" code generation has known structure sizes and no + * indirect function calls (which show up substantially in dynahash + * profiles). These features considerably increase speed for small + * entries. + * - Open addressing has better CPU cache behavior than dynahash's chained + * hashtables. + * - The generated interface is type-safe and easier to use than dynahash, + * though at the cost of more complex setup. + * - Allocates memory in a MemoryContext or another allocator with a + * malloc/free style interface (which isn't easily usable in a shared + * memory context) + * - Does not require the overhead of a separate memory context. + * + * Usage notes: + * + * To generate a hash-table and associated functions for a use case several + * macros have to be #define'ed before this file is included. Including + * the file #undef's all those, so a new hash table can be generated + * afterwards. + * The relevant parameters are: + * - SH_PREFIX - prefix for all symbol names generated. A prefix of 'foo' + * will result in hash table type 'foo_hash' and functions like + * 'foo_insert'/'foo_lookup' and so forth. + * - SH_ELEMENT_TYPE - type of the contained elements + * - SH_KEY_TYPE - type of the hashtable's key + * - SH_DECLARE - if defined function prototypes and type declarations are + * generated + * - SH_DEFINE - if defined function definitions are generated + * - SH_SCOPE - in which scope (e.g. extern, static inline) do function + * declarations reside + * - SH_RAW_ALLOCATOR - if defined, memory contexts are not used; instead, + * use this to allocate bytes. The allocator must zero the returned space. + * - SH_USE_NONDEFAULT_ALLOCATOR - if defined no element allocator functions + * are defined, so you can supply your own + * The following parameters are only relevant when SH_DEFINE is defined: + * - SH_KEY - name of the element in SH_ELEMENT_TYPE containing the hash key + * - SH_EQUAL(table, a, b) - compare two table keys + * - SH_HASH_KEY(table, key) - generate hash for the key + * - SH_STORE_HASH - if defined the hash is stored in the elements + * - SH_GET_HASH(tb, a) - return the field to store the hash in + * + * While SH_STORE_HASH (and subsequently SH_GET_HASH) are optional, because + * the hash table implementation needs to compare hashes to move elements + * (particularly when growing the hash), it's preferable, if possible, to + * store the element's hash in the element's data type. If the hash is so + * stored, the hash table will also compare hashes before calling SH_EQUAL + * when comparing two keys. + * + * For convenience the hash table create functions accept a void pointer + * that will be stored in the hash table type's member private_data. This + * allows callbacks to reference caller provided data. + * + * For examples of usage look at tidbitmap.c (file local definition) and + * execnodes.h/execGrouping.c (exposed declaration, file local + * implementation). + * + * Hash table design: + * + * The hash table design chosen is a variant of linear open-addressing. The + * reason for doing so is that linear addressing is CPU cache & pipeline + * friendly. The biggest disadvantage of simple linear addressing schemes + * are highly variable lookup times due to clustering, and deletions + * leaving a lot of tombstones around. To address these issues a variant + * of "robin hood" hashing is employed. Robin hood hashing optimizes + * chaining lengths by moving elements close to their optimal bucket + * ("rich" elements), out of the way if a to-be-inserted element is further + * away from its optimal position (i.e. it's "poor"). While that can make + * insertions slower, the average lookup performance is a lot better, and + * higher fill factors can be used in a still performant manner. To avoid + * tombstones - which normally solve the issue that a deleted node's + * presence is relevant to determine whether a lookup needs to continue + * looking or is done - buckets following a deleted element are shifted + * backwards, unless they're empty or already at their optimal position. + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/lib/simplehash.h + */ + +#include "port/pg_bitutils.h" + +/* helpers */ +#define SH_MAKE_PREFIX(a) CppConcat(a, _) +#define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX), name) +#define SH_MAKE_NAME_(a, b) CppConcat(a, b) + +/* name macros for: */ + +/* type declarations */ +#define SH_TYPE SH_MAKE_NAME(hash) +#define SH_ITERATOR SH_MAKE_NAME(iterator) + +/* function declarations */ +#define SH_CREATE SH_MAKE_NAME(create) +#define SH_DESTROY SH_MAKE_NAME(destroy) +#define SH_RESET SH_MAKE_NAME(reset) +#define SH_INSERT SH_MAKE_NAME(insert) +#define SH_INSERT_HASH SH_MAKE_NAME(insert_hash) +#define SH_DELETE_ITEM SH_MAKE_NAME(delete_item) +#define SH_DELETE SH_MAKE_NAME(delete) +#define SH_LOOKUP SH_MAKE_NAME(lookup) +#define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash) +#define SH_GROW SH_MAKE_NAME(grow) +#define SH_START_ITERATE SH_MAKE_NAME(start_iterate) +#define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at) +#define SH_ITERATE SH_MAKE_NAME(iterate) +#define SH_ALLOCATE SH_MAKE_NAME(allocate) +#define SH_FREE SH_MAKE_NAME(free) +#define SH_STAT SH_MAKE_NAME(stat) + +/* internal helper functions (no externally visible prototypes) */ +#define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters) +#define SH_NEXT SH_MAKE_NAME(next) +#define SH_PREV SH_MAKE_NAME(prev) +#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance) +#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket) +#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash) +#define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal) +#define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal) + +/* generate forward declarations necessary to use the hash table */ +#ifdef SH_DECLARE + +/* type definitions */ +typedef struct SH_TYPE +{ + /* + * Size of data / bucket array, 64 bits to handle UINT32_MAX sized hash + * tables. Note that the maximum number of elements is lower + * (SH_MAX_FILLFACTOR) + */ + uint64 size; + + /* how many elements have valid contents */ + uint32 members; + + /* mask for bucket and size calculations, based on size */ + uint32 sizemask; + + /* boundary after which to grow hashtable */ + uint32 grow_threshold; + + /* hash buckets */ + SH_ELEMENT_TYPE *restrict data; + +#ifndef SH_RAW_ALLOCATOR + /* memory context to use for allocations */ + MemoryContext ctx; +#endif + + /* user defined data, useful for callbacks */ + void *private_data; +} SH_TYPE; + +typedef struct SH_ITERATOR +{ + uint32 cur; /* current element */ + uint32 end; + bool done; /* iterator exhausted? */ +} SH_ITERATOR; + +/* externally visible function prototypes */ +#ifdef SH_RAW_ALLOCATOR +/* _hash _create(uint32 nelements, void *private_data) */ +SH_SCOPE SH_TYPE *SH_CREATE(uint32 nelements, void *private_data); +#else +/* + * _hash _create(MemoryContext ctx, uint32 nelements, + * void *private_data) + */ +SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data); +#endif + +/* void _destroy(_hash *tb) */ +SH_SCOPE void SH_DESTROY(SH_TYPE *tb); + +/* void _reset(_hash *tb) */ +SH_SCOPE void SH_RESET(SH_TYPE *tb); + +/* void _grow(_hash *tb, uint64 newsize) */ +SH_SCOPE void SH_GROW(SH_TYPE *tb, uint64 newsize); + +/* *_insert(_hash *tb, key, bool *found) */ +SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found); + +/* + * *_insert_hash(_hash *tb, key, uint32 hash, + * bool *found) + */ +SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash, bool *found); + +/* *_lookup(_hash *tb, key) */ +SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE *tb, SH_KEY_TYPE key); + +/* *_lookup_hash(_hash *tb, key, uint32 hash) */ +SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash); + +/* void _delete_item(_hash *tb, *entry) */ +SH_SCOPE void SH_DELETE_ITEM(SH_TYPE *tb, SH_ELEMENT_TYPE *entry); + +/* bool _delete(_hash *tb, key) */ +SH_SCOPE bool SH_DELETE(SH_TYPE *tb, SH_KEY_TYPE key); + +/* void _start_iterate(_hash *tb, _iterator *iter) */ +SH_SCOPE void SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter); + +/* + * void _start_iterate_at(_hash *tb, _iterator *iter, + * uint32 at) + */ +SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE *tb, SH_ITERATOR *iter, uint32 at); + +/* *_iterate(_hash *tb, _iterator *iter) */ +SH_SCOPE SH_ELEMENT_TYPE *SH_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter); + +/* void _stat(_hash *tb */ +SH_SCOPE void SH_STAT(SH_TYPE *tb); + +#endif /* SH_DECLARE */ + +/* generate implementation of the hash table */ +#ifdef SH_DEFINE + +#ifndef SH_RAW_ALLOCATOR +#include "utils/memutils.h" +#endif + +/* max data array size,we allow up to PG_UINT32_MAX buckets, including 0 */ +#define SH_MAX_SIZE (((uint64) PG_UINT32_MAX) + 1) + +/* normal fillfactor, unless already close to maximum */ +#ifndef SH_FILLFACTOR +#define SH_FILLFACTOR (0.9) +#endif +/* increase fillfactor if we otherwise would error out */ +#define SH_MAX_FILLFACTOR (0.98) +/* grow if actual and optimal location bigger than */ +#ifndef SH_GROW_MAX_DIB +#define SH_GROW_MAX_DIB 25 +#endif +/* grow if more than elements to move when inserting */ +#ifndef SH_GROW_MAX_MOVE +#define SH_GROW_MAX_MOVE 150 +#endif +#ifndef SH_GROW_MIN_FILLFACTOR +/* but do not grow due to SH_GROW_MAX_* if below */ +#define SH_GROW_MIN_FILLFACTOR 0.1 +#endif + +#ifdef SH_STORE_HASH +#define SH_COMPARE_KEYS(tb, ahash, akey, b) \ + (ahash == SH_GET_HASH(tb, b) && SH_EQUAL(tb, b->SH_KEY, akey)) +#else +#define SH_COMPARE_KEYS(tb, ahash, akey, b) (SH_EQUAL(tb, b->SH_KEY, akey)) +#endif + +/* + * Wrap the following definitions in include guards, to avoid multiple + * definition errors if this header is included more than once. The rest of + * the file deliberately has no include guards, because it can be included + * with different parameters to define functions and types with non-colliding + * names. + */ +#ifndef SIMPLEHASH_H +#define SIMPLEHASH_H + +#ifdef FRONTEND +#define sh_error(...) pg_fatal(__VA_ARGS__) +#define sh_log(...) pg_log_info(__VA_ARGS__) +#else +#define sh_error(...) elog(ERROR, __VA_ARGS__) +#define sh_log(...) elog(LOG, __VA_ARGS__) +#endif + +#endif + +/* + * Compute sizing parameters for hashtable. Called when creating and growing + * the hashtable. + */ +static inline void +SH_COMPUTE_PARAMETERS(SH_TYPE *tb, uint64 newsize) +{ + uint64 size; + + /* supporting zero sized hashes would complicate matters */ + size = Max(newsize, 2); + + /* round up size to the next power of 2, that's how bucketing works */ + size = pg_nextpower2_64(size); + Assert(size <= SH_MAX_SIZE); + + /* + * Verify that allocation of ->data is possible on this platform, without + * overflowing Size. + */ + if (unlikely((((uint64) sizeof(SH_ELEMENT_TYPE)) * size) >= SIZE_MAX / 2)) + sh_error("hash table too large"); + + /* now set size */ + tb->size = size; + tb->sizemask = (uint32) (size - 1); + + /* + * Compute the next threshold at which we need to grow the hash table + * again. + */ + if (tb->size == SH_MAX_SIZE) + tb->grow_threshold = ((double) tb->size) * SH_MAX_FILLFACTOR; + else + tb->grow_threshold = ((double) tb->size) * SH_FILLFACTOR; +} + +/* return the optimal bucket for the hash */ +static pg_attribute_always_inline uint32 +SH_INITIAL_BUCKET(SH_TYPE *tb, uint32 hash) +{ + return hash & tb->sizemask; +} + +/* return next bucket after the current, handling wraparound */ +static inline uint32 +SH_NEXT(SH_TYPE *tb, uint32 curelem, uint32 startelem) +{ + curelem = (curelem + 1) & tb->sizemask; + + Assert(curelem != startelem); + + return curelem; +} + +/* return bucket before the current, handling wraparound */ +static inline uint32 +SH_PREV(SH_TYPE *tb, uint32 curelem, uint32 startelem) +{ + curelem = (curelem - 1) & tb->sizemask; + + Assert(curelem != startelem); + + return curelem; +} + +/* return distance between bucket and its optimal position */ +static inline uint32 +SH_DISTANCE_FROM_OPTIMAL(SH_TYPE *tb, uint32 optimal, uint32 bucket) +{ + if (optimal <= bucket) + return bucket - optimal; + else + return (tb->size + bucket) - optimal; +} + +static inline uint32 +SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE *entry) +{ +#ifdef SH_STORE_HASH + return SH_GET_HASH(tb, entry); +#else + return SH_HASH_KEY(tb, entry->SH_KEY); +#endif +} + +/* default memory allocator function */ +static inline void *SH_ALLOCATE(SH_TYPE *type, Size size); +static inline void SH_FREE(SH_TYPE *type, void *pointer); + +#ifndef SH_USE_NONDEFAULT_ALLOCATOR + +/* default memory allocator function */ +static inline void * +SH_ALLOCATE(SH_TYPE *type, Size size) +{ +#ifdef SH_RAW_ALLOCATOR + return SH_RAW_ALLOCATOR(size); +#else + return MemoryContextAllocExtended(type->ctx, size, MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); +#endif +} + +/* default memory free function */ +static inline void +SH_FREE(SH_TYPE *type, void *pointer) +{ + pfree(pointer); +} + +#endif + +/* + * Create a hash table with enough space for `nelements` distinct members. + * Memory for the hash table is allocated from the passed-in context. If + * desired, the array of elements can be allocated using a passed-in allocator; + * this could be useful in order to place the array of elements in a shared + * memory, or in a context that will outlive the rest of the hash table. + * Memory other than for the array of elements will still be allocated from + * the passed-in context. + */ +#ifdef SH_RAW_ALLOCATOR +SH_SCOPE SH_TYPE * +SH_CREATE(uint32 nelements, void *private_data) +#else +SH_SCOPE SH_TYPE * +SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data) +#endif +{ + SH_TYPE *tb; + uint64 size; + +#ifdef SH_RAW_ALLOCATOR + tb = (SH_TYPE *) SH_RAW_ALLOCATOR(sizeof(SH_TYPE)); +#else + tb = (SH_TYPE *) MemoryContextAllocZero(ctx, sizeof(SH_TYPE)); + tb->ctx = ctx; +#endif + tb->private_data = private_data; + + /* increase nelements by fillfactor, want to store nelements elements */ + size = Min((double) SH_MAX_SIZE, ((double) nelements) / SH_FILLFACTOR); + + SH_COMPUTE_PARAMETERS(tb, size); + + tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size); + + return tb; +} + +/* destroy a previously created hash table */ +SH_SCOPE void +SH_DESTROY(SH_TYPE *tb) +{ + SH_FREE(tb, tb->data); + pfree(tb); +} + +/* reset the contents of a previously created hash table */ +SH_SCOPE void +SH_RESET(SH_TYPE *tb) +{ + memset(tb->data, 0, sizeof(SH_ELEMENT_TYPE) * tb->size); + tb->members = 0; +} + +/* + * Grow a hash table to at least `newsize` buckets. + * + * Usually this will automatically be called by insertions/deletions, when + * necessary. But resizing to the exact input size can be advantageous + * performance-wise, when known at some point. + */ +SH_SCOPE void +SH_GROW(SH_TYPE *tb, uint64 newsize) +{ + uint64 oldsize = tb->size; + SH_ELEMENT_TYPE *olddata = tb->data; + SH_ELEMENT_TYPE *newdata; + uint32 i; + uint32 startelem = 0; + uint32 copyelem; + + Assert(oldsize == pg_nextpower2_64(oldsize)); + Assert(oldsize != SH_MAX_SIZE); + Assert(oldsize < newsize); + + /* compute parameters for new table */ + SH_COMPUTE_PARAMETERS(tb, newsize); + + tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size); + + newdata = tb->data; + + /* + * Copy entries from the old data to newdata. We theoretically could use + * SH_INSERT here, to avoid code duplication, but that's more general than + * we need. We neither want tb->members increased, nor do we need to do + * deal with deleted elements, nor do we need to compare keys. So a + * special-cased implementation is lot faster. As resizing can be time + * consuming and frequent, that's worthwhile to optimize. + * + * To be able to simply move entries over, we have to start not at the + * first bucket (i.e olddata[0]), but find the first bucket that's either + * empty, or is occupied by an entry at its optimal position. Such a + * bucket has to exist in any table with a load factor under 1, as not all + * buckets are occupied, i.e. there always has to be an empty bucket. By + * starting at such a bucket we can move the entries to the larger table, + * without having to deal with conflicts. + */ + + /* search for the first element in the hash that's not wrapped around */ + for (i = 0; i < oldsize; i++) + { + SH_ELEMENT_TYPE *oldentry = &olddata[i]; + uint32 hash; + uint32 optimal; + + if (SH_ENTRY_EMPTY(oldentry)) + { + startelem = i; + break; + } + + hash = SH_ENTRY_HASH(tb, oldentry); + optimal = SH_INITIAL_BUCKET(tb, hash); + + if (optimal == i) + { + startelem = i; + break; + } + } + + /* and copy all elements in the old table */ + copyelem = startelem; + for (i = 0; i < oldsize; i++) + { + SH_ELEMENT_TYPE *oldentry = &olddata[copyelem]; + + if (!SH_ENTRY_EMPTY(oldentry)) + { + uint32 hash; + uint32 startelem; + uint32 curelem; + SH_ELEMENT_TYPE *newentry; + + hash = SH_ENTRY_HASH(tb, oldentry); + startelem = SH_INITIAL_BUCKET(tb, hash); + curelem = startelem; + + /* find empty element to put data into */ + while (true) + { + newentry = &newdata[curelem]; + + if (SH_ENTRY_EMPTY(newentry)) + { + break; + } + + curelem = SH_NEXT(tb, curelem, startelem); + } + + /* copy entry to new slot */ + memcpy(newentry, oldentry, sizeof(SH_ELEMENT_TYPE)); + } + + /* can't use SH_NEXT here, would use new size */ + copyelem++; + if (copyelem >= oldsize) + { + copyelem = 0; + } + } + + SH_FREE(tb, olddata); +} + +/* + * This is a separate static inline function, so it can be reliably be inlined + * into its wrapper functions even if SH_SCOPE is extern. + */ +static pg_attribute_always_inline SH_ELEMENT_TYPE * +SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool *found) +{ + uint32 startelem; + uint32 curelem; + SH_ELEMENT_TYPE *restrict data; + uint32 insertdist; + +restart: + insertdist = 0; + + /* + * We do the grow check even if the key is actually present, to avoid + * doing the check inside the loop. This also lets us avoid having to + * re-find our position in the hashtable after resizing. + * + * Note that this also reached when resizing the table due to + * SH_GROW_MAX_DIB / SH_GROW_MAX_MOVE. + */ + if (unlikely(tb->members >= tb->grow_threshold)) + { + if (unlikely(tb->size == SH_MAX_SIZE)) + sh_error("hash table size exceeded"); + + /* + * When optimizing, it can be very useful to print these out. + */ + /* SH_STAT(tb); */ + SH_GROW(tb, tb->size * 2); + /* SH_STAT(tb); */ + } + + /* perform insert, start bucket search at optimal location */ + data = tb->data; + startelem = SH_INITIAL_BUCKET(tb, hash); + curelem = startelem; + while (true) + { + uint32 curdist; + uint32 curhash; + uint32 curoptimal; + SH_ELEMENT_TYPE *entry = &data[curelem]; + + /* any empty bucket can directly be used */ + if (SH_ENTRY_EMPTY(entry)) + { + tb->members++; + entry->SH_KEY = key; +#ifdef SH_STORE_HASH + SH_GET_HASH(tb, entry) = hash; +#endif + *found = false; + return entry; + } + + /* + * If the bucket is not empty, we either found a match (in which case + * we're done), or we have to decide whether to skip over or move the + * colliding entry. When the colliding element's distance to its + * optimal position is smaller than the to-be-inserted entry's, we + * shift the colliding entry (and its followers) forward by one. + */ + + if (SH_COMPARE_KEYS(tb, hash, key, entry)) + { + Assert(!SH_ENTRY_EMPTY(entry)); + *found = true; + return entry; + } + + curhash = SH_ENTRY_HASH(tb, entry); + curoptimal = SH_INITIAL_BUCKET(tb, curhash); + curdist = SH_DISTANCE_FROM_OPTIMAL(tb, curoptimal, curelem); + + if (insertdist > curdist) + { + SH_ELEMENT_TYPE *lastentry = entry; + uint32 emptyelem = curelem; + uint32 moveelem; + int32 emptydist = 0; + + /* find next empty bucket */ + while (true) + { + SH_ELEMENT_TYPE *emptyentry; + + emptyelem = SH_NEXT(tb, emptyelem, startelem); + emptyentry = &data[emptyelem]; + + if (SH_ENTRY_EMPTY(emptyentry)) + { + lastentry = emptyentry; + break; + } + + /* + * To avoid negative consequences from overly imbalanced + * hashtables, grow the hashtable if collisions would require + * us to move a lot of entries. The most likely cause of such + * imbalance is filling a (currently) small table, from a + * currently big one, in hash-table order. Don't grow if the + * hashtable would be too empty, to prevent quick space + * explosion for some weird edge cases. + */ + if (unlikely(++emptydist > SH_GROW_MAX_MOVE) && + ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) + { + tb->grow_threshold = 0; + goto restart; + } + } + + /* shift forward, starting at last occupied element */ + + /* + * TODO: This could be optimized to be one memcpy in many cases, + * excepting wrapping around at the end of ->data. Hasn't shown up + * in profiles so far though. + */ + moveelem = emptyelem; + while (moveelem != curelem) + { + SH_ELEMENT_TYPE *moveentry; + + moveelem = SH_PREV(tb, moveelem, startelem); + moveentry = &data[moveelem]; + + memcpy(lastentry, moveentry, sizeof(SH_ELEMENT_TYPE)); + lastentry = moveentry; + } + + /* and fill the now empty spot */ + tb->members++; + + entry->SH_KEY = key; +#ifdef SH_STORE_HASH + SH_GET_HASH(tb, entry) = hash; +#endif + *found = false; + return entry; + } + + curelem = SH_NEXT(tb, curelem, startelem); + insertdist++; + + /* + * To avoid negative consequences from overly imbalanced hashtables, + * grow the hashtable if collisions lead to large runs. The most + * likely cause of such imbalance is filling a (currently) small + * table, from a currently big one, in hash-table order. Don't grow + * if the hashtable would be too empty, to prevent quick space + * explosion for some weird edge cases. + */ + if (unlikely(insertdist > SH_GROW_MAX_DIB) && + ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) + { + tb->grow_threshold = 0; + goto restart; + } + } +} + +/* + * Insert the key key into the hash-table, set *found to true if the key + * already exists, false otherwise. Returns the hash-table entry in either + * case. + */ +static pg_attribute_always_inline SH_ELEMENT_TYPE * +SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found) +{ + uint32 hash = SH_HASH_KEY(tb, key); + + return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); +} + +/* + * Insert the key key into the hash-table using an already-calculated + * hash. Set *found to true if the key already exists, false + * otherwise. Returns the hash-table entry in either case. + */ +SH_SCOPE SH_ELEMENT_TYPE * +SH_INSERT_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash, bool *found) +{ + return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); +} + +/* + * This is a separate static inline function, so it can be reliably be inlined + * into its wrapper functions even if SH_SCOPE is extern. + */ +static inline SH_ELEMENT_TYPE * +SH_LOOKUP_HASH_INTERNAL(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash) +{ + const uint32 startelem = SH_INITIAL_BUCKET(tb, hash); + uint32 curelem = startelem; + + while (true) + { + SH_ELEMENT_TYPE *entry = &tb->data[curelem]; + + if (SH_ENTRY_EMPTY(entry)) + { + return NULL; + } + + Assert(!SH_ENTRY_EMPTY(entry)); + + if (SH_COMPARE_KEYS(tb, hash, key, entry)) + return entry; + + /* + * TODO: we could stop search based on distance. If the current + * buckets's distance-from-optimal is smaller than what we've skipped + * already, the entry doesn't exist. Probably only do so if + * SH_STORE_HASH is defined, to avoid re-computing hashes? + */ + + curelem = SH_NEXT(tb, curelem, startelem); + } +} + +/* + * Lookup up entry in hash table. Returns NULL if key not present. + */ +SH_SCOPE SH_ELEMENT_TYPE * +SH_LOOKUP(SH_TYPE *tb, SH_KEY_TYPE key) +{ + uint32 hash = SH_HASH_KEY(tb, key); + + return SH_LOOKUP_HASH_INTERNAL(tb, key, hash); +} + +/* + * Lookup up entry in hash table using an already-calculated hash. + * + * Returns NULL if key not present. + */ +SH_SCOPE SH_ELEMENT_TYPE * +SH_LOOKUP_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash) +{ + return SH_LOOKUP_HASH_INTERNAL(tb, key, hash); +} + +/* + * Initialize iterator. + */ +SH_SCOPE void +SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter) +{ + uint64 startelem = PG_UINT64_MAX; + + /* + * Search for the first empty element. As deletions during iterations are + * supported, we want to start/end at an element that cannot be affected + * by elements being shifted. + */ + for (uint32 i = 0; i < tb->size; i++) + { + SH_ELEMENT_TYPE *entry = &tb->data[i]; + + if (SH_ENTRY_EMPTY(entry)) + { + startelem = i; + break; + } + } + + /* we should have found an empty element */ + Assert(startelem < SH_MAX_SIZE); + + /* + * Iterate backwards, that allows the current element to be deleted, even + * if there are backward shifts + */ + iter->cur = startelem; + iter->end = iter->cur; + iter->done = false; +} + +/* + * Initialize iterator to a specific bucket. That's really only useful for + * cases where callers are partially iterating over the hashspace, and that + * iteration deletes and inserts elements based on visited entries. Doing that + * repeatedly could lead to an unbalanced keyspace when always starting at the + * same position. + */ +SH_SCOPE void +SH_START_ITERATE_AT(SH_TYPE *tb, SH_ITERATOR *iter, uint32 at) +{ + /* + * Iterate backwards, that allows the current element to be deleted, even + * if there are backward shifts. + */ + iter->cur = at & tb->sizemask; /* ensure at is within a valid range */ + iter->end = iter->cur; + iter->done = false; +} + +/* + * Iterate over all entries in the hash-table. Return the next occupied entry, + * or NULL if done. + * + * During iteration the current entry in the hash table may be deleted, + * without leading to elements being skipped or returned twice. Additionally + * the rest of the table may be modified (i.e. there can be insertions or + * deletions), but if so, there's neither a guarantee that all nodes are + * visited at least once, nor a guarantee that a node is visited at most once. + */ +SH_SCOPE SH_ELEMENT_TYPE * +SH_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter) +{ + while (!iter->done) + { + SH_ELEMENT_TYPE *elem; + + elem = &tb->data[iter->cur]; + + /* next element in backward direction */ + iter->cur = (iter->cur - 1) & tb->sizemask; + + if ((iter->cur & tb->sizemask) == (iter->end & tb->sizemask)) + iter->done = true; + if (!SH_ENTRY_EMPTY(elem)) + { + return elem; + } + } + + return NULL; +} + +/* + * Report some statistics about the state of the hashtable. For + * debugging/profiling purposes only. + */ +SH_SCOPE void +SH_STAT(SH_TYPE *tb) +{ + uint32 max_chain_length = 0; + uint32 total_chain_length = 0; + double avg_chain_length; + double fillfactor; + uint32 i; + + uint32 *collisions = (uint32 *) palloc0(tb->size * sizeof(uint32)); + uint32 total_collisions = 0; + uint32 max_collisions = 0; + double avg_collisions; + + for (i = 0; i < tb->size; i++) + { + uint32 hash; + uint32 optimal; + uint32 dist; + SH_ELEMENT_TYPE *elem; + + elem = &tb->data[i]; + + if (SH_ENTRY_EMPTY(elem)) + continue; + + hash = SH_ENTRY_HASH(tb, elem); + optimal = SH_INITIAL_BUCKET(tb, hash); + dist = SH_DISTANCE_FROM_OPTIMAL(tb, optimal, i); + + if (dist > max_chain_length) + max_chain_length = dist; + total_chain_length += dist; + + collisions[optimal]++; + } + + for (i = 0; i < tb->size; i++) + { + uint32 curcoll = collisions[i]; + + if (curcoll == 0) + continue; + + /* single contained element is not a collision */ + curcoll--; + total_collisions += curcoll; + if (curcoll > max_collisions) + max_collisions = curcoll; + } + + /* large enough to be worth freeing, even if just used for debugging */ + pfree(collisions); + + if (tb->members > 0) + { + fillfactor = tb->members / ((double) tb->size); + avg_chain_length = ((double) total_chain_length) / tb->members; + avg_collisions = ((double) total_collisions) / tb->members; + } + else + { + fillfactor = 0; + avg_chain_length = 0; + avg_collisions = 0; + } + + sh_log("size: " UINT64_FORMAT + ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, " + "total_collisions: %u, max_collisions: %u, avg_collisions: %f", + tb->size, + tb->members, + fillfactor, + total_chain_length, + max_chain_length, + avg_chain_length, + total_collisions, + max_collisions, + avg_collisions); +} + +#endif /* SH_DEFINE */ + +/* undefine external parameters, so next hash table can be defined */ +#undef SH_PREFIX +#undef SH_KEY_TYPE +#undef SH_KEY +#undef SH_ELEMENT_TYPE +#undef SH_HASH_KEY +#undef SH_SCOPE +#undef SH_DECLARE +#undef SH_DEFINE +#undef SH_GET_HASH +#undef SH_STORE_HASH +#undef SH_USE_NONDEFAULT_ALLOCATOR +#undef SH_EQUAL + +/* undefine locally declared macros */ +#undef SH_MAKE_PREFIX +#undef SH_MAKE_NAME +#undef SH_MAKE_NAME_ +#undef SH_FILLFACTOR +#undef SH_MAX_FILLFACTOR +#undef SH_GROW_MAX_DIB +#undef SH_GROW_MAX_MOVE +#undef SH_GROW_MIN_FILLFACTOR +#undef SH_MAX_SIZE + +/* types */ +#undef SH_TYPE +#undef SH_ITERATOR + +/* external function names */ +#undef SH_CREATE +#undef SH_DESTROY +#undef SH_RESET +#undef SH_INSERT +#undef SH_INSERT_HASH +#undef SH_DELETE_ITEM +#undef SH_DELETE +#undef SH_LOOKUP +#undef SH_LOOKUP_HASH +#undef SH_GROW +#undef SH_START_ITERATE +#undef SH_START_ITERATE_AT +#undef SH_ITERATE +#undef SH_ALLOCATE +#undef SH_FREE +#undef SH_STAT + +/* internal function names */ +#undef SH_COMPUTE_PARAMETERS +#undef SH_COMPARE_KEYS +#undef SH_INITIAL_BUCKET +#undef SH_NEXT +#undef SH_PREV +#undef SH_DISTANCE_FROM_OPTIMAL +#undef SH_ENTRY_HASH +#undef SH_INSERT_HASH_INTERNAL +#undef SH_LOOKUP_HASH_INTERNAL diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index c54c0405384..6a07c28e238 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -55,10 +55,13 @@ typedef struct } FUNCTION_NAME(state); static void -FUNCTION_NAME(init)(void *agg_state) +FUNCTION_NAME(init)(void *restrict agg_states, int n) { - FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - *state = (FUNCTION_NAME(state)){ 0 }; + FUNCTION_NAME(state) *states = (FUNCTION_NAME(state) *) agg_states; + for (int i = 0; i < n; i++) + { + states[i] = (FUNCTION_NAME(state)){ 0 }; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 7c4e9af4e3b..1ebb5b06b22 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -27,10 +27,13 @@ typedef struct } CountState; static void -count_init(void *agg_state) +count_init(void *restrict agg_states, int n) { - CountState *state = (CountState *) agg_state; - state->count = 0; + CountState *states = (CountState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].count = 0; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 9f080a8b823..4d679e14277 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -16,8 +16,8 @@ typedef struct /* Size of the aggregate function state. */ size_t state_bytes; - /* Initialize the aggregate function state pointed to by agg_value and agg_isnull. */ - void (*agg_init)(void *restrict agg_state); + /* Initialize the aggregate function states. */ + void (*agg_init)(void *restrict agg_states, int n); /* Aggregate a given arrow array. */ void (*agg_vector)(void *restrict agg_state, const ArrowArray *vector, const uint64 *filter, diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index 39bd665f3c9..bf0f90e5044 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -25,14 +25,17 @@ typedef struct } FUNCTION_NAME(state); static void -FUNCTION_NAME(init)(void *agg_state) +FUNCTION_NAME(init)(void *restrict agg_states, int n) { - FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - state->N = 0; - state->sumX = 0; + FUNCTION_NAME(state) *states = (FUNCTION_NAME(state) *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].N = 0; + states[i].sumX = 0; #ifdef NEED_SUMX2 - state->sumX2 = 0; + states[i].sumX2 = 0; #endif + } } static void diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c index 0841eb79cc1..518a7491aab 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c @@ -27,11 +27,14 @@ typedef struct } Int24AvgAccumState; static void -int24_avg_accum_init(void *agg_state) +int24_avg_accum_init(void *restrict agg_states, int n) { - Int24AvgAccumState *state = (Int24AvgAccumState *) agg_state; - state->count = 0; - state->sum = 0; + Int24AvgAccumState *states = (Int24AvgAccumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].count = 0; + states[i].sum = 0; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c index 5e87f3c9a32..8b250cc91cc 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c @@ -28,11 +28,14 @@ typedef struct } Int24SumState; static void -int_sum_init(void *agg_state) +int_sum_init(void *restrict agg_states, int n) { - Int24SumState *state = (Int24SumState *) agg_state; - state->result = 0; - state->isnull = true; + Int24SumState *states = (Int24SumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].result = 0; + states[i].isnull = true; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/minmax_templates.c b/tsl/src/nodes/vector_agg/function/minmax_templates.c index be79cc3c1db..0775f6bd1f2 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_templates.c +++ b/tsl/src/nodes/vector_agg/function/minmax_templates.c @@ -26,11 +26,14 @@ typedef struct } MinMaxState; static void -minmax_init(void *agg_state) +minmax_init(void *restrict agg_states, int n) { - MinMaxState *state = (MinMaxState *) agg_state; - state->isvalid = false; - state->value = 0; + MinMaxState *states = (MinMaxState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].isvalid = false; + states[i].value = 0; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/sum_float_templates.c b/tsl/src/nodes/vector_agg/function/sum_float_templates.c index b24e3e3d812..f2b22523b34 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_templates.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_templates.c @@ -23,11 +23,14 @@ typedef struct } FloatSumState; static void -float_sum_init(void *agg_state) +float_sum_init(void *restrict agg_states, int n) { - FloatSumState *state = (FloatSumState *) agg_state; - state->result = 0; - state->isnull = true; + FloatSumState *states = (FloatSumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].result = 0; + states[i].isnull = true; + } } #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index a37747f5166..b60d4f230da 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -77,7 +77,7 @@ gp_batch_reset(GroupingPolicy *obj) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_state = (void *) list_nth(policy->agg_states, i); - agg_def->func->agg_init(agg_state); + agg_def->func->agg_init(agg_state, 1); } const int ngrp = list_length(policy->output_grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index aab2ba2b280..181261a1eeb 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -20,22 +20,35 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include + typedef struct { Datum key; - uint32 status; uint32 agg_state_index; } HashEntry; -static uint64_t -hash64(uint64_t x) +// static pg_attribute_always_inline uint64 +// hash64_1(uint64 x) +//{ +// x ^= x >> 30; +// x *= 0xbf58476d1ce4e5b9U; +// x ^= x >> 27; +// x *= 0x94d049bb133111ebU; +// x ^= x >> 31; +// return x; +// } + +static pg_attribute_always_inline uint64 +hash64_crc(uint64 x) +{ + return _mm_crc32_u64(~0ULL, x); +} + +static pg_attribute_always_inline uint64 +hash64(uint64 x) { - x ^= x >> 30; - x *= 0xbf58476d1ce4e5b9U; - x ^= x >> 27; - x *= 0x94d049bb133111ebU; - x ^= x >> 31; - return x; + return hash64_crc(x); } #define SH_PREFIX h @@ -47,7 +60,8 @@ hash64(uint64_t x) #define SH_SCOPE static inline #define SH_DECLARE #define SH_DEFINE -#include "lib/simplehash.h" +#define SH_ENTRY_EMPTY(entry) (entry->agg_state_index == 0) +#include "import/ts_simplehash.h" struct h_hash; @@ -199,6 +213,7 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; // Assert(gv->decompression_type == 8 /* lolwut */); const uint64 *restrict filter = batch_state->vector_qual_result; + struct h_hash *restrict table = policy->table; for (int row = 0; row < batch_state->total_batch_rows; row++) { bool key_valid = false; @@ -213,7 +228,7 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, if (key_valid) { bool found = false; - HashEntry *entry = h_insert(policy->table, key, &found); + HashEntry *restrict entry = h_insert(table, key, &found); if (!found) { entry->agg_state_index = next_unused_state_index++; @@ -415,12 +430,10 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { - VectorAggDef *def = lfirst(aggdeflc); - for (uint64 i = last_initialized_state_index; i < next_unused_state_index; i++) - { - void *aggstate = def->func->state_bytes * i + (char *) lfirst(aggstatelc); - def->func->agg_init(aggstate); - } + const VectorAggDef *def = lfirst(aggdeflc); + def->func->agg_init(def->func->state_bytes * last_initialized_state_index + + (char *) lfirst(aggstatelc), + next_unused_state_index - last_initialized_state_index); } } @@ -443,6 +456,17 @@ gp_hash_should_emit(GroupingPolicy *gp) // { // return true; // } + /* + * Don't grow the hash table cardinality too much, otherwise we become bound + * by memory reads. In general, when this first stage of grouping doesn't + * significantly reduce the cardinality, it becomes pure overhead and the + * work will be done by the final Postgres aggregation, so we should bail + * out early here. + */ + if (policy->table->members * sizeof(HashEntry) > 128 * 1024) + { + return true; + } return false; } @@ -456,10 +480,12 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); - // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio\n", - // policy->stat_input_valid_rows, policy->table->members + policy->have_null_key, - // policy->stat_input_valid_rows / (float) (policy->table->members + - // policy->have_null_key)); + // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio, %ld aggctx bytes, + //%ld aggstate bytes\n", policy->stat_input_valid_rows, policy->table->members + //+ policy->have_null_key, policy->stat_input_valid_rows / (float) + //(policy->table->members + policy->have_null_key), + // MemoryContextMemAllocated(policy->table->ctx, false), + // MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } HashEntry null_key_entry = { .agg_state_index = 1 }; diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 12ed14e3e84..c25c51c8a6c 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -388,23 +388,20 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; Output: _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) - Group Key: _hyper_1_1_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) - Group Key: _hyper_1_2_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) - Group Key: _hyper_1_3_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -444,7 +441,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; Group Key: _hyper_1_10_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.float_value, _hyper_1_10_chunk.segment_by_value -(63 rows) +(60 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; @@ -457,23 +454,20 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_1_chunk.int_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.int_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) - Group Key: _hyper_1_1_chunk.int_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk.int_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_2_chunk.int_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) - Group Key: _hyper_1_2_chunk.int_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_2_chunk.int_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_3_chunk.int_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) - Group Key: _hyper_1_3_chunk.int_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_3_chunk.int_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -513,7 +507,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Group Key: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value -(63 rows) +(60 rows) -- Vectorization possible with grouping by a segmentby column. :EXPLAIN From 339f91a78222ee4c97f29c5f47f248c1f130f8bb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:59:55 +0200 Subject: [PATCH 008/242] reduce indirections --- tsl/src/nodes/vector_agg/exec.c | 2 +- tsl/src/nodes/vector_agg/exec.h | 2 +- .../nodes/vector_agg/grouping_policy_batch.c | 22 ++++---- .../nodes/vector_agg/grouping_policy_hash.c | 55 ++++++++++--------- 4 files changed, 41 insertions(+), 40 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 548b6ca623f..fa4dc703d42 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -90,7 +90,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) Aggref *aggref = castNode(Aggref, tlentry->expr); VectorAggFunctions *func = get_vector_aggregate(aggref->aggfnoid); Assert(func != NULL); - def->func = func; + def->func = *func; if (list_length(aggref->args) > 0) { diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index d886b927d31..1b38fa81fe7 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -15,7 +15,7 @@ typedef struct { - VectorAggFunctions *func; + VectorAggFunctions func; int input_offset; int output_offset; } VectorAggDef; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index b60d4f230da..23d695cedc1 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -52,8 +52,8 @@ create_grouping_policy_batch(List *agg_defs, List *output_grouping_columns) ListCell *lc; foreach (lc, agg_defs) { - VectorAggDef *def = lfirst(lc); - policy->agg_states = lappend(policy->agg_states, palloc0(def->func->state_bytes)); + VectorAggDef *agg_def = lfirst(lc); + policy->agg_states = lappend(policy->agg_states, palloc0(agg_def->func.state_bytes)); } policy->output_grouping_values = (Datum *) palloc0(MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum)) + @@ -77,7 +77,7 @@ gp_batch_reset(GroupingPolicy *obj) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_state = (void *) list_nth(policy->agg_states, i); - agg_def->func->agg_init(agg_state, 1); + agg_def->func.agg_init(agg_state, 1); } const int ngrp = list_length(policy->output_grouping_columns); @@ -126,10 +126,10 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func->agg_vector(agg_state, - arg_arrow, - batch_state->vector_qual_result, - agg_extra_mctx); + agg_def->func.agg_vector(agg_state, + arg_arrow, + batch_state->vector_qual_result, + agg_extra_mctx); } else { @@ -146,7 +146,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de */ Assert(n > 0); - agg_def->func->agg_const(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + agg_def->func.agg_const(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); } } @@ -211,9 +211,9 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_state = (void *) list_nth(policy->agg_states, i); - agg_def->func->agg_emit(agg_state, - &aggregated_slot->tts_values[agg_def->output_offset], - &aggregated_slot->tts_isnull[agg_def->output_offset]); + agg_def->func.agg_emit(agg_state, + &aggregated_slot->tts_values[agg_def->output_offset], + &aggregated_slot->tts_isnull[agg_def->output_offset]); } const int ngrp = list_length(policy->output_grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 181261a1eeb..d030696288f 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -105,12 +105,12 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) ListCell *lc; foreach (lc, agg_defs) { - VectorAggDef *def = lfirst(lc); - policy->aggstate_bytes_per_key += def->func->state_bytes; + VectorAggDef *agg_def = lfirst(lc); + policy->aggstate_bytes_per_key += agg_def->func.state_bytes; policy->per_agg_states = lappend(policy->per_agg_states, - palloc0(def->func->state_bytes * policy->allocated_aggstate_rows)); + palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); } policy->table = h_create(CurrentMemoryContext, 1000, NULL); @@ -172,7 +172,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func->agg_many(agg_states, offsets, arg_arrow, agg_extra_mctx); + agg_def->func.agg_many(agg_states, offsets, arg_arrow, agg_extra_mctx); } else { @@ -180,14 +180,14 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de * Scalar argument, or count(*). The latter has an optimized * implementation for this case. */ - if (agg_def->func->agg_many_scalar != NULL) + if (agg_def->func.agg_many_scalar != NULL) { - agg_def->func->agg_many_scalar(agg_states, - offsets, - batch_state->total_batch_rows, - arg_datum, - arg_isnull, - agg_extra_mctx); + agg_def->func.agg_many_scalar(agg_states, + offsets, + batch_state->total_batch_rows, + arg_datum, + arg_isnull, + agg_extra_mctx); } else { @@ -198,8 +198,8 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de continue; } - void *state = (offsets[i] * agg_def->func->state_bytes + (char *) agg_states); - agg_def->func->agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); + void *state = (offsets[i] * agg_def->func.state_bytes + (char *) agg_states); + agg_def->func.agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); } } } @@ -421,19 +421,19 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { - VectorAggDef *def = lfirst(aggdeflc); + VectorAggDef *agg_def = lfirst(aggdeflc); lfirst(aggstatelc) = repalloc(lfirst(aggstatelc), - policy->allocated_aggstate_rows * def->func->state_bytes); + policy->allocated_aggstate_rows * agg_def->func.state_bytes); } } forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { - const VectorAggDef *def = lfirst(aggdeflc); - def->func->agg_init(def->func->state_bytes * last_initialized_state_index + - (char *) lfirst(aggstatelc), - next_unused_state_index - last_initialized_state_index); + const VectorAggDef *agg_def = lfirst(aggdeflc); + agg_def->func.agg_init(agg_def->func.state_bytes * last_initialized_state_index + + (char *) lfirst(aggstatelc), + next_unused_state_index - last_initialized_state_index); } } @@ -480,11 +480,12 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); - // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio, %ld aggctx bytes, - //%ld aggstate bytes\n", policy->stat_input_valid_rows, policy->table->members + // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio, %ld aggctx + //bytes, %ld aggstate bytes\n", policy->stat_input_valid_rows, + //policy->table->members //+ policy->have_null_key, policy->stat_input_valid_rows / (float) - //(policy->table->members + policy->have_null_key), - // MemoryContextMemAllocated(policy->table->ctx, false), + //(policy->table->members + + //policy->have_null_key), MemoryContextMemAllocated(policy->table->ctx, false), // MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } @@ -509,10 +510,10 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_states = list_nth(policy->per_agg_states, i); - void *agg_state = entry->agg_state_index * agg_def->func->state_bytes + (char *) agg_states; - agg_def->func->agg_emit(agg_state, - &aggregated_slot->tts_values[agg_def->output_offset], - &aggregated_slot->tts_isnull[agg_def->output_offset]); + void *agg_state = entry->agg_state_index * agg_def->func.state_bytes + (char *) agg_states; + agg_def->func.agg_emit(agg_state, + &aggregated_slot->tts_values[agg_def->output_offset], + &aggregated_slot->tts_isnull[agg_def->output_offset]); } Assert(list_length(policy->output_grouping_columns) == 1); From f075589f68c0b622ca63c0f4f071e3921d82d752 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:33:19 +0200 Subject: [PATCH 009/242] skip null bitmap words --- .../vector_agg/function/agg_many_helper.c | 22 +- tsl/src/nodes/vector_agg/function/functions.c | 29 +-- tsl/src/nodes/vector_agg/function/functions.h | 9 +- .../nodes/vector_agg/grouping_policy_hash.c | 243 +++++++++++------- 4 files changed, 178 insertions(+), 125 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_helper.c index ef8acd28181..f8517c4328a 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_helper.c @@ -5,29 +5,23 @@ */ static void -FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, - MemoryContext agg_extra_mctx) +FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, + const ArrowArray *vector, MemoryContext agg_extra_mctx) { MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); - const int n = vector->length; const CTYPE *values = vector->buffers[1]; const uint64 *valid = vector->buffers[0]; - for (int row = 0; row < n; row++) + for (int row = start_row; row < end_row; row++) { FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); - CTYPE value = values[row]; + const CTYPE value = values[row]; + const bool row_passes = (offsets[row] != 0); + const bool value_notnull = arrow_row_is_valid(valid, row); - if (offsets[row] == 0) + if (row_passes && value_notnull) { - continue; + FUNCTION_NAME(one)(state, value); } - - if (!arrow_row_is_valid(valid, row)) - { - continue; - } - - FUNCTION_NAME(one)(state, value); } MemoryContextSwitchTo(old); } diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 1ebb5b06b22..4dea3c8c90e 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -53,11 +53,12 @@ count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int n, Datum constvalue, - bool constisnull, MemoryContext agg_extra_mctx) +count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) { CountState *states = (CountState *) agg_states; - for (int row = 0; row < n; row++) + for (int row = start_row; row < end_row; row++) { if (offsets[row] == 0) { @@ -131,25 +132,19 @@ count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter } static void -count_any_many(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, - MemoryContext agg_extra_mctx) +count_any_many(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, + const ArrowArray *vector, MemoryContext agg_extra_mctx) { - const int n = vector->length; const uint64 *valid = vector->buffers[0]; - for (int row = 0; row < n; row++) + for (int row = start_row; row < end_row; row++) { - if (offsets[row] == 0) - { - continue; - } - - if (!arrow_row_is_valid(valid, row)) + CountState *state = (offsets[row] + (CountState *) agg_states); + const bool row_passes = (offsets[row] != 0); + const bool value_notnull = arrow_row_is_valid(valid, row); + if (row_passes && value_notnull) { - continue; + state->count++; } - - CountState *state = (offsets[row] + (CountState *) agg_states); - state->count++; } } diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 4d679e14277..9d5539fb244 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -27,11 +27,12 @@ typedef struct void (*agg_const)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, MemoryContext agg_extra_mctx); - void (*agg_many)(void *restrict agg_states, uint32 *restrict offsets, const ArrowArray *vector, - MemoryContext agg_extra_mctx); + void (*agg_many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); - void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int n, - Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx); + void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx); /* Emit a partial result. */ void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d030696288f..eab57f38718 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -87,7 +87,11 @@ typedef struct uint64 allocated_aggstate_rows; List *per_agg_states; + uint64 stat_input_total_rows; + uint64 stat_input_valid_rows; + + uint64 stat_bulk_filtered_rows; } GroupingPolicyHash; static const GroupingPolicy grouping_policy_hash_functions; @@ -134,11 +138,14 @@ gp_hash_reset(GroupingPolicy *obj) policy->have_null_key = false; policy->stat_input_valid_rows = 0; + policy->stat_input_total_rows = 0; + policy->stat_bulk_filtered_rows = 0; } static void -compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_def, void *agg_states, - uint32 *offsets, MemoryContext agg_extra_mctx) +compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int end_row, + VectorAggDef *agg_def, void *agg_states, uint32 *offsets, + MemoryContext agg_extra_mctx) { ArrowArray *arg_arrow = NULL; Datum arg_datum = 0; @@ -172,7 +179,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func.agg_many(agg_states, offsets, arg_arrow, agg_extra_mctx); + agg_def->func.agg_many(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); } else { @@ -184,14 +191,15 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de { agg_def->func.agg_many_scalar(agg_states, offsets, - batch_state->total_batch_rows, + start_row, + end_row, arg_datum, arg_isnull, agg_extra_mctx); } else { - for (int i = 0; i < batch_state->total_batch_rows; i++) + for (int i = start_row; i < end_row; i++) { if (offsets[i] == 0) { @@ -207,14 +215,15 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de static pg_attribute_always_inline uint32 fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, uint32 *restrict offsets, + int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, + uint32 *restrict offsets, void (*get_key)(CompressedColumnValues column, int row, Datum *key, bool *valid)) { CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; // Assert(gv->decompression_type == 8 /* lolwut */); const uint64 *restrict filter = batch_state->vector_qual_result; struct h_hash *restrict table = policy->table; - for (int row = 0; row < batch_state->total_batch_rows; row++) + for (int row = start_row; row < end_row; row++) { bool key_valid = false; Datum key = { 0 }; @@ -242,8 +251,8 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, } } - policy->stat_input_valid_rows += - arrow_num_valid(column.buffers[0], batch_state->total_batch_rows); + policy->stat_input_total_rows += batch_state->total_batch_rows; + policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); return next_unused_state_index; } @@ -300,51 +309,60 @@ get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool static pg_noinline uint32 fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, - uint32 *restrict offsets) + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets) { return fill_offsets_impl(policy, batch_state, key_column_index, next_unused_state_index, + start_row, + end_row, offsets, get_key_arrow_fixed_8); } static pg_noinline uint32 fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, - uint32 *restrict offsets) + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets) { return fill_offsets_impl(policy, batch_state, key_column_index, next_unused_state_index, + start_row, + end_row, offsets, get_key_arrow_fixed_4); } static pg_noinline uint32 fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, - uint32 *restrict offsets) + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets) { return fill_offsets_impl(policy, batch_state, key_column_index, next_unused_state_index, + start_row, + end_row, offsets, get_key_arrow_fixed_2); } static pg_noinline uint32 fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, uint32 *restrict offsets) + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets) { return fill_offsets_impl(policy, batch_state, key_column_index, next_unused_state_index, + start_row, + end_row, offsets, get_key_scalar); } @@ -356,17 +374,6 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(!policy->returning_results); - /* - * State index zero is invalid, and state index one is for null key. We have - * to initialize it at the first run. - */ - const uint32 last_initialized_state_index = - policy->table->members ? policy->table->members + 2 : 1; - uint32 next_unused_state_index = policy->table->members + 2; - - uint32 offsets[1000] = { 0 }; - Assert(batch_state->total_batch_rows <= 1000); - /* * For the partial aggregation node, the grouping columns are always in the * output, so we don't have to separately look at the list of the grouping @@ -375,76 +382,131 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(list_length(policy->output_grouping_columns) == 1); GroupingColumn *g = linitial(policy->output_grouping_columns); CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; + // const uint64_t* restrict key_validity = key_column->buffers[0]; + const uint64_t *restrict filter = batch_state->vector_qual_result; - switch ((int) key_column->decompression_type) - { - case DT_Scalar: - next_unused_state_index = fill_offsets_scalar(policy, - batch_state, - g->input_offset, - next_unused_state_index, - offsets); - break; - case 8: - next_unused_state_index = fill_offsets_arrow_fixed_8(policy, - batch_state, - g->input_offset, - next_unused_state_index, - offsets); - break; - case 4: - next_unused_state_index = fill_offsets_arrow_fixed_4(policy, - batch_state, - g->input_offset, - next_unused_state_index, - offsets); - break; - case 2: - next_unused_state_index = fill_offsets_arrow_fixed_2(policy, - batch_state, - g->input_offset, - next_unused_state_index, - offsets); - break; - default: - Assert(false); - break; - } + uint32 offsets[1000] = { 0 }; - ListCell *aggdeflc; - ListCell *aggstatelc; + const int n = batch_state->total_batch_rows; + int start_row = 0; + int end_row = 0; - if (next_unused_state_index > last_initialized_state_index) + // for (int end_row = MIN(64, n); end_row <= n; end_row += 64) + for (start_row = 0; start_row < n; start_row = end_row) { - if (next_unused_state_index > policy->allocated_aggstate_rows) + if (filter) + { + if (filter[start_row / 64] == 0) + { + end_row = MIN(start_row + 64, n); + policy->stat_bulk_filtered_rows += 64; + continue; + } + + for (end_row = start_row; end_row < n; end_row = MIN(end_row + 64, n)) + { + if (filter[end_row / 64] == 0) + { + break; + } + } + } + else + { + end_row = n; + } + Assert(start_row <= end_row); + Assert(end_row <= n); + /* + * State index zero is invalid, and state index one is for null key. We have + * to initialize it at the first run. + */ + uint32 last_initialized_state_index = + policy->table->members ? policy->table->members + 2 : 1; + uint32 next_unused_state_index = policy->table->members + 2; + + Assert((size_t) end_row <= sizeof(offsets) / sizeof(*offsets)); + + switch ((int) key_column->decompression_type) { - policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + case DT_Scalar: + next_unused_state_index = fill_offsets_scalar(policy, + batch_state, + g->input_offset, + next_unused_state_index, + start_row, + end_row, + offsets); + break; + case 8: + next_unused_state_index = fill_offsets_arrow_fixed_8(policy, + batch_state, + g->input_offset, + next_unused_state_index, + start_row, + end_row, + offsets); + break; + case 4: + next_unused_state_index = fill_offsets_arrow_fixed_4(policy, + batch_state, + g->input_offset, + next_unused_state_index, + start_row, + end_row, + offsets); + break; + case 2: + next_unused_state_index = fill_offsets_arrow_fixed_2(policy, + batch_state, + g->input_offset, + next_unused_state_index, + start_row, + end_row, + offsets); + break; + default: + Assert(false); + break; + } + + ListCell *aggdeflc; + ListCell *aggstatelc; + + if (next_unused_state_index > last_initialized_state_index) + { + if (next_unused_state_index > policy->allocated_aggstate_rows) + { + policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) + { + VectorAggDef *agg_def = lfirst(aggdeflc); + lfirst(aggstatelc) = + repalloc(lfirst(aggstatelc), + policy->allocated_aggstate_rows * agg_def->func.state_bytes); + } + } + forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { - VectorAggDef *agg_def = lfirst(aggdeflc); - lfirst(aggstatelc) = - repalloc(lfirst(aggstatelc), - policy->allocated_aggstate_rows * agg_def->func.state_bytes); + const VectorAggDef *agg_def = lfirst(aggdeflc); + agg_def->func.agg_init(agg_def->func.state_bytes * last_initialized_state_index + + (char *) lfirst(aggstatelc), + next_unused_state_index - last_initialized_state_index); } } forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { - const VectorAggDef *agg_def = lfirst(aggdeflc); - agg_def->func.agg_init(agg_def->func.state_bytes * last_initialized_state_index + - (char *) lfirst(aggstatelc), - next_unused_state_index - last_initialized_state_index); + compute_single_aggregate(batch_state, + start_row, + end_row, + lfirst(aggdeflc), + lfirst(aggstatelc), + offsets, + policy->agg_extra_mctx); } } - - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { - compute_single_aggregate(batch_state, - lfirst(aggdeflc), - lfirst(aggstatelc), - offsets, - policy->agg_extra_mctx); - } } static bool @@ -480,13 +542,14 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); - // fprintf(stderr, "spill after %ld input rows, %d keys, %f ratio, %ld aggctx - //bytes, %ld aggstate bytes\n", policy->stat_input_valid_rows, - //policy->table->members - //+ policy->have_null_key, policy->stat_input_valid_rows / (float) - //(policy->table->members + - //policy->have_null_key), MemoryContextMemAllocated(policy->table->ctx, false), - // MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + // fprintf(stderr, + // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld aggctx + //bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, + //policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, policy->table->members + // + policy->have_null_key, policy->stat_input_valid_rows / + //(float) (policy->table->members + policy->have_null_key), + //MemoryContextMemAllocated(policy->table->ctx, false), + //MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } HashEntry null_key_entry = { .agg_state_index = 1 }; From 88f325dc67840e5f5d07a0b99f701cbcbe2fb4cb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:44:48 +0200 Subject: [PATCH 010/242] cleanup --- tsl/src/import/ts_simplehash.h | 10 ---------- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index 2a630f24017..f4f6db2d30d 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -109,8 +109,6 @@ #define SH_RESET SH_MAKE_NAME(reset) #define SH_INSERT SH_MAKE_NAME(insert) #define SH_INSERT_HASH SH_MAKE_NAME(insert_hash) -#define SH_DELETE_ITEM SH_MAKE_NAME(delete_item) -#define SH_DELETE SH_MAKE_NAME(delete) #define SH_LOOKUP SH_MAKE_NAME(lookup) #define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash) #define SH_GROW SH_MAKE_NAME(grow) @@ -208,12 +206,6 @@ SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE *tb, SH_KEY_TYPE key); /* *_lookup_hash(_hash *tb, key, uint32 hash) */ SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash); -/* void _delete_item(_hash *tb, *entry) */ -SH_SCOPE void SH_DELETE_ITEM(SH_TYPE *tb, SH_ELEMENT_TYPE *entry); - -/* bool _delete(_hash *tb, key) */ -SH_SCOPE bool SH_DELETE(SH_TYPE *tb, SH_KEY_TYPE key); - /* void _start_iterate(_hash *tb, _iterator *iter) */ SH_SCOPE void SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter); @@ -1023,8 +1015,6 @@ SH_STAT(SH_TYPE *tb) #undef SH_RESET #undef SH_INSERT #undef SH_INSERT_HASH -#undef SH_DELETE_ITEM -#undef SH_DELETE #undef SH_LOOKUP #undef SH_LOOKUP_HASH #undef SH_GROW diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index eab57f38718..e542b12bdeb 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -217,7 +217,8 @@ static pg_attribute_always_inline uint32 fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *key, bool *valid)) + void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid)) { CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; // Assert(gv->decompression_type == 8 /* lolwut */); @@ -543,13 +544,14 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); // fprintf(stderr, - // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld aggctx - //bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, - //policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, policy->table->members + // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld + //aggctx bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, + // policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, + // policy->table->members // + policy->have_null_key, policy->stat_input_valid_rows / //(float) (policy->table->members + policy->have_null_key), - //MemoryContextMemAllocated(policy->table->ctx, false), - //MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + // MemoryContextMemAllocated(policy->table->ctx, + // false), MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } HashEntry null_key_entry = { .agg_state_index = 1 }; From 15ab44310866ae12d40b739de749b6ca2540a581 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:51:18 +0200 Subject: [PATCH 011/242] crc32 --- .../nodes/vector_agg/grouping_policy_hash.c | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index e542b12bdeb..3dbd81a3bce 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -28,28 +28,25 @@ typedef struct uint32 agg_state_index; } HashEntry; -// static pg_attribute_always_inline uint64 -// hash64_1(uint64 x) -//{ -// x ^= x >> 30; -// x *= 0xbf58476d1ce4e5b9U; -// x ^= x >> 27; -// x *= 0x94d049bb133111ebU; -// x ^= x >> 31; -// return x; -// } - +#ifdef USE_SSE42_CRC32C static pg_attribute_always_inline uint64 -hash64_crc(uint64 x) +hash64(uint64 x) { return _mm_crc32_u64(~0ULL, x); } +#else static pg_attribute_always_inline uint64 hash64(uint64 x) { - return hash64_crc(x); + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + return x; } +#endif #define SH_PREFIX h #define SH_ELEMENT_TYPE HashEntry @@ -545,7 +542,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) h_start_iterate(policy->table, &policy->iter); // fprintf(stderr, // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld - //aggctx bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, + // aggctx bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, // policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, // policy->table->members // + policy->have_null_key, policy->stat_input_valid_rows / From ff16ec8a0a30dc332706c581bf69958b4cf56d3c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:54:06 +0200 Subject: [PATCH 012/242] license --- tsl/src/import/ts_simplehash.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index f4f6db2d30d..48139ec8138 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -1,3 +1,9 @@ +/* + * This file and its contents are licensed under the Apache License 2.0. + * Please see the included NOTICE for copyright information and + * LICENSE-APACHE for a copy of the license. + */ + /* * simplehash.h * From 4291b173df0824df9b8e42ac154beb32d75677c4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:55:06 +0200 Subject: [PATCH 013/242] benchmark vectorized hash grouping (2024-10-09 no. 10) From 795ef6b189613de38886cb0aa4c4ff332cdf8f1b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:03:45 +0200 Subject: [PATCH 014/242] test deltadelta changes --- .../compression/algorithms/deltadelta_impl.c | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index 6e036a5722b..c1078456b3b 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -12,7 +12,7 @@ #define FUNCTION_NAME_HELPER(X, Y) X##_##Y #define FUNCTION_NAME(X, Y) FUNCTION_NAME_HELPER(X, Y) -static ArrowArray * +static pg_noinline ArrowArray * FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, MemoryContext dest_mctx) { StringInfoData si = { .data = DatumGetPointer(compressed), .len = VARSIZE(compressed) }; @@ -44,12 +44,12 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Pad the number of elements to multiple of 64 bytes if needed, so that we * can work in 64-byte blocks. */ +#define INNER_LOOP_SIZE_LOG2 3 +#define INNER_LOOP_SIZE (1 << INNER_LOOP_SIZE_LOG2) const uint32 n_total = has_nulls ? nulls.num_elements : num_deltas; - const uint32 n_total_padded = - ((n_total * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_total_padded = pad_to_multiple(INNER_LOOP_SIZE, n_total); const uint32 n_notnull = num_deltas; - const uint32 n_notnull_padded = - ((n_notnull * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_notnull_padded = pad_to_multiple(INNER_LOOP_SIZE, n_notnull); Assert(n_total_padded >= n_total); Assert(n_notnull_padded >= n_notnull); Assert(n_total >= n_notnull); @@ -57,7 +57,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory /* * We need additional padding at the end of buffer, because the code that - * converts the elements to postres Datum always reads in 8 bytes. + * converts the elements to postgres Datum always reads in 8 bytes. */ const int buffer_bytes = n_total_padded * sizeof(ELEMENT_TYPE) + 8; ELEMENT_TYPE *restrict decompressed_values = MemoryContextAlloc(dest_mctx, buffer_bytes); @@ -75,17 +75,84 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Also tried zig-zag decoding in a separate loop, seems to be slightly * slower, around the noise threshold. */ -#define INNER_LOOP_SIZE 8 Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { + uint64 x[INNER_LOOP_SIZE]; for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) { - current_delta += zig_zag_decode(deltas_zigzag[outer + inner]); - current_element += current_delta; - decompressed_values[outer + inner] = current_element; + x[inner] = zig_zag_decode(deltas_zigzag[outer + inner]); } + + x[0] += current_delta; + + /* Now deltas of deltas, will make first-order deltas by prefix summation. */ + for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) + { +// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) +// { +// x[i] = x[i] + x[i - (1 << l)]; +// } + uint64 xx[INNER_LOOP_SIZE]; + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; + } + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + x[i] += xx[i]; + } + } + +// const uint64 new_delta = current_delta + x[INNER_LOOP_SIZE - 1]; + const uint64 new_delta = x[INNER_LOOP_SIZE - 1]; + + x[0] += current_element; + + /* Now first-order deltas, will make element values by prefix summation. */ + for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) + { +// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) +// { +// x[i] = x[i] + x[i - (1 << l)]; +// } + +// for (int i = INNER_LOOP_SIZE - 1; i >= 0; i--) +// { +// x[i] = x[i] + ((i >= (1 << l)) ? x[i - (1 << l)] : 0); +// } + + uint64 xx[INNER_LOOP_SIZE]; + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; + } + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + x[i] += xx[i]; + } + } + + /* Now element values. */ +// uint64 xx[INNER_LOOP_SIZE]; +// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) +// { +// xx[inner] = current_element + (1 + inner) * current_delta; +// } +// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) +// { +// x[inner] += xx[inner]; +// } + + for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) + { + decompressed_values[outer + inner] = x[inner]; + } + + current_element = x[INNER_LOOP_SIZE - 1]; + current_delta = new_delta; } +#undef INNER_LOOP_SIZE_LOG2 #undef INNER_LOOP_SIZE uint64 *restrict validity_bitmap = NULL; From 1fabb22cd370087bdefa66026b67039e6f7a2186 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:04:16 +0200 Subject: [PATCH 015/242] some speedups and simplehash simplifications --- tsl/src/import/ts_simplehash.h | 161 +++++++++--------- .../nodes/vector_agg/grouping_policy_hash.c | 79 +++++++-- 2 files changed, 142 insertions(+), 98 deletions(-) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index 48139ec8138..18c3f73bb6a 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -571,14 +571,6 @@ SH_GROW(SH_TYPE *tb, uint64 newsize) static pg_attribute_always_inline SH_ELEMENT_TYPE * SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool *found) { - uint32 startelem; - uint32 curelem; - SH_ELEMENT_TYPE *restrict data; - uint32 insertdist; - -restart: - insertdist = 0; - /* * We do the grow check even if the key is actually present, to avoid * doing the check inside the loop. This also lets us avoid having to @@ -600,15 +592,14 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool /* SH_STAT(tb); */ } + SH_ELEMENT_TYPE *restrict data = tb->data; + /* perform insert, start bucket search at optimal location */ - data = tb->data; - startelem = SH_INITIAL_BUCKET(tb, hash); - curelem = startelem; + const uint32 startelem = SH_INITIAL_BUCKET(tb, hash); + uint32 curelem = startelem; + uint32 insertdist = 0; while (true) { - uint32 curdist; - uint32 curhash; - uint32 curoptimal; SH_ELEMENT_TYPE *entry = &data[curelem]; /* any empty bucket can directly be used */ @@ -638,76 +629,14 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool return entry; } - curhash = SH_ENTRY_HASH(tb, entry); - curoptimal = SH_INITIAL_BUCKET(tb, curhash); - curdist = SH_DISTANCE_FROM_OPTIMAL(tb, curoptimal, curelem); + const uint32 curhash = SH_ENTRY_HASH(tb, entry); + const uint32 curoptimal = SH_INITIAL_BUCKET(tb, curhash); + const uint32 curdist = SH_DISTANCE_FROM_OPTIMAL(tb, curoptimal, curelem); if (insertdist > curdist) { - SH_ELEMENT_TYPE *lastentry = entry; - uint32 emptyelem = curelem; - uint32 moveelem; - int32 emptydist = 0; - - /* find next empty bucket */ - while (true) - { - SH_ELEMENT_TYPE *emptyentry; - - emptyelem = SH_NEXT(tb, emptyelem, startelem); - emptyentry = &data[emptyelem]; - - if (SH_ENTRY_EMPTY(emptyentry)) - { - lastentry = emptyentry; - break; - } - - /* - * To avoid negative consequences from overly imbalanced - * hashtables, grow the hashtable if collisions would require - * us to move a lot of entries. The most likely cause of such - * imbalance is filling a (currently) small table, from a - * currently big one, in hash-table order. Don't grow if the - * hashtable would be too empty, to prevent quick space - * explosion for some weird edge cases. - */ - if (unlikely(++emptydist > SH_GROW_MAX_MOVE) && - ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) - { - tb->grow_threshold = 0; - goto restart; - } - } - - /* shift forward, starting at last occupied element */ - - /* - * TODO: This could be optimized to be one memcpy in many cases, - * excepting wrapping around at the end of ->data. Hasn't shown up - * in profiles so far though. - */ - moveelem = emptyelem; - while (moveelem != curelem) - { - SH_ELEMENT_TYPE *moveentry; - - moveelem = SH_PREV(tb, moveelem, startelem); - moveentry = &data[moveelem]; - - memcpy(lastentry, moveentry, sizeof(SH_ELEMENT_TYPE)); - lastentry = moveentry; - } - - /* and fill the now empty spot */ - tb->members++; - - entry->SH_KEY = key; -#ifdef SH_STORE_HASH - SH_GET_HASH(tb, entry) = hash; -#endif - *found = false; - return entry; + /* We're going to insert at this position. */ + break; } curelem = SH_NEXT(tb, curelem, startelem); @@ -724,10 +653,76 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool if (unlikely(insertdist > SH_GROW_MAX_DIB) && ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) { - tb->grow_threshold = 0; - goto restart; + SH_GROW(tb, tb->size * 2); + return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); } } + + /* Actually insert. */ + SH_ELEMENT_TYPE *entry = &data[curelem]; + SH_ELEMENT_TYPE *lastentry = entry; + uint32 emptyelem = curelem; + int32 emptydist = 0; + + /* find next empty bucket */ + while (true) + { + SH_ELEMENT_TYPE *emptyentry; + + emptyelem = SH_NEXT(tb, emptyelem, startelem); + emptyentry = &data[emptyelem]; + + if (SH_ENTRY_EMPTY(emptyentry)) + { + lastentry = emptyentry; + break; + } + + /* + * To avoid negative consequences from overly imbalanced + * hashtables, grow the hashtable if collisions would require + * us to move a lot of entries. The most likely cause of such + * imbalance is filling a (currently) small table, from a + * currently big one, in hash-table order. Don't grow if the + * hashtable would be too empty, to prevent quick space + * explosion for some weird edge cases. + */ + if (unlikely(++emptydist > SH_GROW_MAX_MOVE) && + ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) + { + SH_GROW(tb, tb->size * 2); + return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); + } + } + + /* shift forward, starting at last occupied element */ + + /* + * TODO: This could be optimized to be one memcpy in many cases, + * excepting wrapping around at the end of ->data. Hasn't shown up + * in profiles so far though. + */ + uint32 moveelem = emptyelem; + while (moveelem != curelem) + { + SH_ELEMENT_TYPE *moveentry; + + moveelem = SH_PREV(tb, moveelem, startelem); + moveentry = &data[moveelem]; + + memcpy(lastentry, moveentry, sizeof(SH_ELEMENT_TYPE)); + lastentry = moveentry; + } + + /* and fill the now empty spot */ + tb->members++; + + entry->SH_KEY = key; +#ifdef SH_STORE_HASH + SH_GET_HASH(tb, entry) = hash; +#endif + *found = false; + return entry; } /* diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 3dbd81a3bce..8bce4e1b2a4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -85,9 +85,7 @@ typedef struct List *per_agg_states; uint64 stat_input_total_rows; - uint64 stat_input_valid_rows; - uint64 stat_bulk_filtered_rows; } GroupingPolicyHash; @@ -114,7 +112,7 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); } - policy->table = h_create(CurrentMemoryContext, 1000, NULL); + policy->table = h_create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); policy->have_null_key = false; policy->returning_results = false; @@ -211,15 +209,13 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } static pg_attribute_always_inline uint32 -fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, - uint32 *restrict offsets, +fill_offsets_impl_for_real(GroupingPolicyHash *policy, + CompressedColumnValues column, const uint64 *restrict filter, + uint32 next_unused_state_index, int start_row, int end_row, + uint32 *restrict offsets, void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid)) { - CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; - // Assert(gv->decompression_type == 8 /* lolwut */); - const uint64 *restrict filter = batch_state->vector_qual_result; struct h_hash *restrict table = policy->table; for (int row = start_row; row < end_row; row++) { @@ -248,6 +244,44 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, offsets[row] = 1; } } + return next_unused_state_index; +} + +static pg_attribute_always_inline uint32 +fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, + uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid)) +{ + CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; + // Assert(gv->decompression_type == 8 /* lolwut */); + const uint64 *restrict filter = batch_state->vector_qual_result; + + if (filter == NULL && column.buffers[0] == NULL) + { + next_unused_state_index = fill_offsets_impl_for_real(policy, column, + filter, next_unused_state_index, start_row, end_row, offsets, get_key); + } + else if (filter != NULL && column.buffers[0] == NULL) + { + next_unused_state_index = fill_offsets_impl_for_real(policy, column, + filter, next_unused_state_index, start_row, end_row, offsets, get_key); + } + else if (filter == NULL && column.buffers[0] != NULL) + { + next_unused_state_index = fill_offsets_impl_for_real(policy, column, + filter, next_unused_state_index, start_row, end_row, offsets, get_key); + } + else if (filter != NULL && column.buffers[0] != NULL) + { + next_unused_state_index = fill_offsets_impl_for_real(policy, column, + filter, next_unused_state_index, start_row, end_row, offsets, get_key); + } + else + { + Assert(false); + } policy->stat_input_total_rows += batch_state->total_batch_rows; policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); @@ -383,8 +417,6 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) // const uint64_t* restrict key_validity = key_column->buffers[0]; const uint64_t *restrict filter = batch_state->vector_qual_result; - uint32 offsets[1000] = { 0 }; - const int n = batch_state->total_batch_rows; int start_row = 0; int end_row = 0; @@ -392,6 +424,10 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) // for (int end_row = MIN(64, n); end_row <= n; end_row += 64) for (start_row = 0; start_row < n; start_row = end_row) { + /* + * If we have a highly selective filter, it's easy to skip the rows for + * which the entire filter bitmap words are zero. + */ if (filter) { if (filter[start_row / 64] == 0) @@ -415,16 +451,22 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } Assert(start_row <= end_row); Assert(end_row <= n); + /* - * State index zero is invalid, and state index one is for null key. We have - * to initialize it at the first run. + * Remember which aggregation states have already existed, and which we + * have to initialize. State index zero is invalid, and state index one + * is for null key. We have to initialize the null key state at the + * first run. */ - uint32 last_initialized_state_index = + const uint32 last_initialized_state_index = policy->table->members ? policy->table->members + 2 : 1; uint32 next_unused_state_index = policy->table->members + 2; + /* + * Match rows to aggregation states using a hash table. + */ + uint32 offsets[1000] = { 0 }; Assert((size_t) end_row <= sizeof(offsets) / sizeof(*offsets)); - switch ((int) key_column->decompression_type) { case DT_Scalar: @@ -471,6 +513,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) ListCell *aggdeflc; ListCell *aggstatelc; + /* + * Initialize the aggregate function states for the newly added keys. + */ if (next_unused_state_index > last_initialized_state_index) { if (next_unused_state_index > policy->allocated_aggstate_rows) @@ -494,6 +539,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } } + /* + * Update the aggregate function states. + */ forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { compute_single_aggregate(batch_state, @@ -505,6 +553,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) policy->agg_extra_mctx); } } + Assert(end_row == n); } static bool From 717abc4ede082bbdc51fe56470ad87a48cfed171 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:04:39 +0200 Subject: [PATCH 016/242] Revert "test deltadelta changes" This reverts commit 795ef6b189613de38886cb0aa4c4ff332cdf8f1b. --- .../compression/algorithms/deltadelta_impl.c | 87 +++---------------- 1 file changed, 10 insertions(+), 77 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index c1078456b3b..6e036a5722b 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -12,7 +12,7 @@ #define FUNCTION_NAME_HELPER(X, Y) X##_##Y #define FUNCTION_NAME(X, Y) FUNCTION_NAME_HELPER(X, Y) -static pg_noinline ArrowArray * +static ArrowArray * FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, MemoryContext dest_mctx) { StringInfoData si = { .data = DatumGetPointer(compressed), .len = VARSIZE(compressed) }; @@ -44,12 +44,12 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Pad the number of elements to multiple of 64 bytes if needed, so that we * can work in 64-byte blocks. */ -#define INNER_LOOP_SIZE_LOG2 3 -#define INNER_LOOP_SIZE (1 << INNER_LOOP_SIZE_LOG2) const uint32 n_total = has_nulls ? nulls.num_elements : num_deltas; - const uint32 n_total_padded = pad_to_multiple(INNER_LOOP_SIZE, n_total); + const uint32 n_total_padded = + ((n_total * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); const uint32 n_notnull = num_deltas; - const uint32 n_notnull_padded = pad_to_multiple(INNER_LOOP_SIZE, n_notnull); + const uint32 n_notnull_padded = + ((n_notnull * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); Assert(n_total_padded >= n_total); Assert(n_notnull_padded >= n_notnull); Assert(n_total >= n_notnull); @@ -57,7 +57,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory /* * We need additional padding at the end of buffer, because the code that - * converts the elements to postgres Datum always reads in 8 bytes. + * converts the elements to postres Datum always reads in 8 bytes. */ const int buffer_bytes = n_total_padded * sizeof(ELEMENT_TYPE) + 8; ELEMENT_TYPE *restrict decompressed_values = MemoryContextAlloc(dest_mctx, buffer_bytes); @@ -75,84 +75,17 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Also tried zig-zag decoding in a separate loop, seems to be slightly * slower, around the noise threshold. */ +#define INNER_LOOP_SIZE 8 Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { - uint64 x[INNER_LOOP_SIZE]; for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) { - x[inner] = zig_zag_decode(deltas_zigzag[outer + inner]); + current_delta += zig_zag_decode(deltas_zigzag[outer + inner]); + current_element += current_delta; + decompressed_values[outer + inner] = current_element; } - - x[0] += current_delta; - - /* Now deltas of deltas, will make first-order deltas by prefix summation. */ - for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) - { -// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) -// { -// x[i] = x[i] + x[i - (1 << l)]; -// } - uint64 xx[INNER_LOOP_SIZE]; - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; - } - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - x[i] += xx[i]; - } - } - -// const uint64 new_delta = current_delta + x[INNER_LOOP_SIZE - 1]; - const uint64 new_delta = x[INNER_LOOP_SIZE - 1]; - - x[0] += current_element; - - /* Now first-order deltas, will make element values by prefix summation. */ - for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) - { -// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) -// { -// x[i] = x[i] + x[i - (1 << l)]; -// } - -// for (int i = INNER_LOOP_SIZE - 1; i >= 0; i--) -// { -// x[i] = x[i] + ((i >= (1 << l)) ? x[i - (1 << l)] : 0); -// } - - uint64 xx[INNER_LOOP_SIZE]; - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; - } - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - x[i] += xx[i]; - } - } - - /* Now element values. */ -// uint64 xx[INNER_LOOP_SIZE]; -// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) -// { -// xx[inner] = current_element + (1 + inner) * current_delta; -// } -// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) -// { -// x[inner] += xx[inner]; -// } - - for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) - { - decompressed_values[outer + inner] = x[inner]; - } - - current_element = x[INNER_LOOP_SIZE - 1]; - current_delta = new_delta; } -#undef INNER_LOOP_SIZE_LOG2 #undef INNER_LOOP_SIZE uint64 *restrict validity_bitmap = NULL; From b03bd6b8456b0950bafc5e6c582a0792a6cf4ace Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:03:45 +0200 Subject: [PATCH 017/242] test deltadelta changes --- .../compression/algorithms/deltadelta_impl.c | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index 6e036a5722b..c1078456b3b 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -12,7 +12,7 @@ #define FUNCTION_NAME_HELPER(X, Y) X##_##Y #define FUNCTION_NAME(X, Y) FUNCTION_NAME_HELPER(X, Y) -static ArrowArray * +static pg_noinline ArrowArray * FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, MemoryContext dest_mctx) { StringInfoData si = { .data = DatumGetPointer(compressed), .len = VARSIZE(compressed) }; @@ -44,12 +44,12 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Pad the number of elements to multiple of 64 bytes if needed, so that we * can work in 64-byte blocks. */ +#define INNER_LOOP_SIZE_LOG2 3 +#define INNER_LOOP_SIZE (1 << INNER_LOOP_SIZE_LOG2) const uint32 n_total = has_nulls ? nulls.num_elements : num_deltas; - const uint32 n_total_padded = - ((n_total * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_total_padded = pad_to_multiple(INNER_LOOP_SIZE, n_total); const uint32 n_notnull = num_deltas; - const uint32 n_notnull_padded = - ((n_notnull * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_notnull_padded = pad_to_multiple(INNER_LOOP_SIZE, n_notnull); Assert(n_total_padded >= n_total); Assert(n_notnull_padded >= n_notnull); Assert(n_total >= n_notnull); @@ -57,7 +57,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory /* * We need additional padding at the end of buffer, because the code that - * converts the elements to postres Datum always reads in 8 bytes. + * converts the elements to postgres Datum always reads in 8 bytes. */ const int buffer_bytes = n_total_padded * sizeof(ELEMENT_TYPE) + 8; ELEMENT_TYPE *restrict decompressed_values = MemoryContextAlloc(dest_mctx, buffer_bytes); @@ -75,17 +75,84 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Also tried zig-zag decoding in a separate loop, seems to be slightly * slower, around the noise threshold. */ -#define INNER_LOOP_SIZE 8 Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { + uint64 x[INNER_LOOP_SIZE]; for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) { - current_delta += zig_zag_decode(deltas_zigzag[outer + inner]); - current_element += current_delta; - decompressed_values[outer + inner] = current_element; + x[inner] = zig_zag_decode(deltas_zigzag[outer + inner]); } + + x[0] += current_delta; + + /* Now deltas of deltas, will make first-order deltas by prefix summation. */ + for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) + { +// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) +// { +// x[i] = x[i] + x[i - (1 << l)]; +// } + uint64 xx[INNER_LOOP_SIZE]; + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; + } + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + x[i] += xx[i]; + } + } + +// const uint64 new_delta = current_delta + x[INNER_LOOP_SIZE - 1]; + const uint64 new_delta = x[INNER_LOOP_SIZE - 1]; + + x[0] += current_element; + + /* Now first-order deltas, will make element values by prefix summation. */ + for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) + { +// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) +// { +// x[i] = x[i] + x[i - (1 << l)]; +// } + +// for (int i = INNER_LOOP_SIZE - 1; i >= 0; i--) +// { +// x[i] = x[i] + ((i >= (1 << l)) ? x[i - (1 << l)] : 0); +// } + + uint64 xx[INNER_LOOP_SIZE]; + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; + } + for (int i = 0; i < INNER_LOOP_SIZE; i++) + { + x[i] += xx[i]; + } + } + + /* Now element values. */ +// uint64 xx[INNER_LOOP_SIZE]; +// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) +// { +// xx[inner] = current_element + (1 + inner) * current_delta; +// } +// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) +// { +// x[inner] += xx[inner]; +// } + + for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) + { + decompressed_values[outer + inner] = x[inner]; + } + + current_element = x[INNER_LOOP_SIZE - 1]; + current_delta = new_delta; } +#undef INNER_LOOP_SIZE_LOG2 #undef INNER_LOOP_SIZE uint64 *restrict validity_bitmap = NULL; From 166d0e83e95f475cab1c302fb66e5eda8266b63b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:21:08 +0100 Subject: [PATCH 018/242] work with signed types --- tsl/src/compression/algorithms/deltadelta.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta.c b/tsl/src/compression/algorithms/deltadelta.c index 48e3b00b893..e768b5c5f59 100644 --- a/tsl/src/compression/algorithms/deltadelta.c +++ b/tsl/src/compression/algorithms/deltadelta.c @@ -27,7 +27,7 @@ #include "simple8b_rle_bitmap.h" static uint64 zig_zag_encode(uint64 value); -static uint64 zig_zag_decode(uint64 value); +static int64 zig_zag_decode(uint64 value); typedef struct DeltaDeltaCompressed { @@ -583,15 +583,15 @@ delta_delta_decompression_iterator_try_next_forward(DecompressionIterator *iter) #undef ELEMENT_TYPE /* Functions for bulk decompression. */ -#define ELEMENT_TYPE uint16 +#define ELEMENT_TYPE int16 #include "deltadelta_impl.c" #undef ELEMENT_TYPE -#define ELEMENT_TYPE uint32 +#define ELEMENT_TYPE int32 #include "deltadelta_impl.c" #undef ELEMENT_TYPE -#define ELEMENT_TYPE uint64 +#define ELEMENT_TYPE int64 #include "deltadelta_impl.c" #undef ELEMENT_TYPE @@ -603,12 +603,12 @@ delta_delta_decompress_all(Datum compressed_data, Oid element_type, MemoryContex case INT8OID: case TIMESTAMPOID: case TIMESTAMPTZOID: - return delta_delta_decompress_all_uint64(compressed_data, dest_mctx); + return delta_delta_decompress_all_int64(compressed_data, dest_mctx); case INT4OID: case DATEOID: - return delta_delta_decompress_all_uint32(compressed_data, dest_mctx); + return delta_delta_decompress_all_int32(compressed_data, dest_mctx); case INT2OID: - return delta_delta_decompress_all_uint16(compressed_data, dest_mctx); + return delta_delta_decompress_all_int16(compressed_data, dest_mctx); default: elog(ERROR, "type '%s' is not supported for deltadelta decompression", @@ -747,7 +747,7 @@ zig_zag_encode(uint64 value) return (value << 1) ^ (((int64) value) < 0 ? 0xFFFFFFFFFFFFFFFFULL : 0); } -static pg_attribute_always_inline uint64 +static pg_attribute_always_inline int64 zig_zag_decode(uint64 value) { /* ZigZag turns negative numbers into odd ones, and positive numbers into even ones*/ From 7f578b4f65274b8ec1b3127a018c08661c9eba98 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:21:15 +0100 Subject: [PATCH 019/242] Revert "work with signed types" This reverts commit 166d0e83e95f475cab1c302fb66e5eda8266b63b. --- tsl/src/compression/algorithms/deltadelta.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta.c b/tsl/src/compression/algorithms/deltadelta.c index e768b5c5f59..48e3b00b893 100644 --- a/tsl/src/compression/algorithms/deltadelta.c +++ b/tsl/src/compression/algorithms/deltadelta.c @@ -27,7 +27,7 @@ #include "simple8b_rle_bitmap.h" static uint64 zig_zag_encode(uint64 value); -static int64 zig_zag_decode(uint64 value); +static uint64 zig_zag_decode(uint64 value); typedef struct DeltaDeltaCompressed { @@ -583,15 +583,15 @@ delta_delta_decompression_iterator_try_next_forward(DecompressionIterator *iter) #undef ELEMENT_TYPE /* Functions for bulk decompression. */ -#define ELEMENT_TYPE int16 +#define ELEMENT_TYPE uint16 #include "deltadelta_impl.c" #undef ELEMENT_TYPE -#define ELEMENT_TYPE int32 +#define ELEMENT_TYPE uint32 #include "deltadelta_impl.c" #undef ELEMENT_TYPE -#define ELEMENT_TYPE int64 +#define ELEMENT_TYPE uint64 #include "deltadelta_impl.c" #undef ELEMENT_TYPE @@ -603,12 +603,12 @@ delta_delta_decompress_all(Datum compressed_data, Oid element_type, MemoryContex case INT8OID: case TIMESTAMPOID: case TIMESTAMPTZOID: - return delta_delta_decompress_all_int64(compressed_data, dest_mctx); + return delta_delta_decompress_all_uint64(compressed_data, dest_mctx); case INT4OID: case DATEOID: - return delta_delta_decompress_all_int32(compressed_data, dest_mctx); + return delta_delta_decompress_all_uint32(compressed_data, dest_mctx); case INT2OID: - return delta_delta_decompress_all_int16(compressed_data, dest_mctx); + return delta_delta_decompress_all_uint16(compressed_data, dest_mctx); default: elog(ERROR, "type '%s' is not supported for deltadelta decompression", @@ -747,7 +747,7 @@ zig_zag_encode(uint64 value) return (value << 1) ^ (((int64) value) < 0 ? 0xFFFFFFFFFFFFFFFFULL : 0); } -static pg_attribute_always_inline int64 +static pg_attribute_always_inline uint64 zig_zag_decode(uint64 value) { /* ZigZag turns negative numbers into odd ones, and positive numbers into even ones*/ From e70cb0ba83ae0a9602578a7eaa801d688801a91c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:39:04 +0100 Subject: [PATCH 020/242] bulk stuff specialized to element type --- .../compression/algorithms/deltadelta_impl.c | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index c1078456b3b..ac9d374f4c8 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -78,7 +78,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { - uint64 x[INNER_LOOP_SIZE]; + ELEMENT_TYPE x[INNER_LOOP_SIZE]; for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) { x[inner] = zig_zag_decode(deltas_zigzag[outer + inner]); @@ -89,48 +89,48 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory /* Now deltas of deltas, will make first-order deltas by prefix summation. */ for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) { -// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) -// { -// x[i] = x[i] + x[i - (1 << l)]; -// } - uint64 xx[INNER_LOOP_SIZE]; - for (int i = 0; i < INNER_LOOP_SIZE; i++) + for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) { - xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; - } - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - x[i] += xx[i]; + x[i] = x[i] + x[i - (1 << l)]; } +// ELEMENT_TYPE xx[INNER_LOOP_SIZE]; +// for (int i = 0; i < INNER_LOOP_SIZE; i++) +// { +// xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; +// } +// for (int i = 0; i < INNER_LOOP_SIZE; i++) +// { +// x[i] += xx[i]; +// } } // const uint64 new_delta = current_delta + x[INNER_LOOP_SIZE - 1]; - const uint64 new_delta = x[INNER_LOOP_SIZE - 1]; + const ELEMENT_TYPE new_delta = x[INNER_LOOP_SIZE - 1]; x[0] += current_element; /* Now first-order deltas, will make element values by prefix summation. */ for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) { -// for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) -// { -// x[i] = x[i] + x[i - (1 << l)]; -// } + for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) + { + x[i] = x[i] + x[i - (1 << l)]; + } // for (int i = INNER_LOOP_SIZE - 1; i >= 0; i--) // { // x[i] = x[i] + ((i >= (1 << l)) ? x[i - (1 << l)] : 0); // } - uint64 xx[INNER_LOOP_SIZE]; - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; - } - for (int i = 0; i < INNER_LOOP_SIZE; i++) - { - x[i] += xx[i]; - } +// ELEMENT_TYPE xx[INNER_LOOP_SIZE]; +// for (int i = 0; i < INNER_LOOP_SIZE; i++) +// { +// xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; +// } +// for (int i = 0; i < INNER_LOOP_SIZE; i++) +// { +// x[i] += xx[i]; +// } } /* Now element values. */ From 00408446976ead1f74c2239863cf676e3d8f1cf2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:05:47 +0100 Subject: [PATCH 021/242] roll back the delta delta stuff --- .../compression/algorithms/deltadelta_impl.c | 75 +------------------ 1 file changed, 4 insertions(+), 71 deletions(-) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index ac9d374f4c8..3100c8a8822 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -12,7 +12,7 @@ #define FUNCTION_NAME_HELPER(X, Y) X##_##Y #define FUNCTION_NAME(X, Y) FUNCTION_NAME_HELPER(X, Y) -static pg_noinline ArrowArray * +static ArrowArray * FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, MemoryContext dest_mctx) { StringInfoData si = { .data = DatumGetPointer(compressed), .len = VARSIZE(compressed) }; @@ -78,79 +78,12 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { - ELEMENT_TYPE x[INNER_LOOP_SIZE]; for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) { - x[inner] = zig_zag_decode(deltas_zigzag[outer + inner]); + current_delta += zig_zag_decode(deltas_zigzag[outer + inner]); + current_element += current_delta; + decompressed_values[outer + inner] = current_element; } - - x[0] += current_delta; - - /* Now deltas of deltas, will make first-order deltas by prefix summation. */ - for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) - { - for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) - { - x[i] = x[i] + x[i - (1 << l)]; - } -// ELEMENT_TYPE xx[INNER_LOOP_SIZE]; -// for (int i = 0; i < INNER_LOOP_SIZE; i++) -// { -// xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; -// } -// for (int i = 0; i < INNER_LOOP_SIZE; i++) -// { -// x[i] += xx[i]; -// } - } - -// const uint64 new_delta = current_delta + x[INNER_LOOP_SIZE - 1]; - const ELEMENT_TYPE new_delta = x[INNER_LOOP_SIZE - 1]; - - x[0] += current_element; - - /* Now first-order deltas, will make element values by prefix summation. */ - for (int l = 0; l < INNER_LOOP_SIZE_LOG2; l++) - { - for (int i = INNER_LOOP_SIZE - 1; i >= (1 << l); i--) - { - x[i] = x[i] + x[i - (1 << l)]; - } - -// for (int i = INNER_LOOP_SIZE - 1; i >= 0; i--) -// { -// x[i] = x[i] + ((i >= (1 << l)) ? x[i - (1 << l)] : 0); -// } - -// ELEMENT_TYPE xx[INNER_LOOP_SIZE]; -// for (int i = 0; i < INNER_LOOP_SIZE; i++) -// { -// xx[i] = (i >= (1 << l)) ? x[i - (1 << l)] : 0; -// } -// for (int i = 0; i < INNER_LOOP_SIZE; i++) -// { -// x[i] += xx[i]; -// } - } - - /* Now element values. */ -// uint64 xx[INNER_LOOP_SIZE]; -// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) -// { -// xx[inner] = current_element + (1 + inner) * current_delta; -// } -// for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) -// { -// x[inner] += xx[inner]; -// } - - for (uint32 inner = 0; inner < INNER_LOOP_SIZE; inner++) - { - decompressed_values[outer + inner] = x[inner]; - } - - current_element = x[INNER_LOOP_SIZE - 1]; - current_delta = new_delta; } #undef INNER_LOOP_SIZE_LOG2 #undef INNER_LOOP_SIZE From 7a9c3200e8534f60c3adcaafffc71fa8f7ac415a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:05:55 +0100 Subject: [PATCH 022/242] more generic -- started to make some changes --- tsl/src/nodes/vector_agg/exec.c | 8 ++ tsl/src/nodes/vector_agg/exec.h | 4 + .../nodes/vector_agg/grouping_policy_hash.c | 107 ++++++++++++++---- 3 files changed, 98 insertions(+), 21 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index fa4dc703d42..13ad379bf8b 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -119,6 +119,14 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) Var *var = castNode(Var, tlentry->expr); col->input_offset = get_input_offset(decompress_state, var); + + DecompressContext *dcontext = &decompress_state->decompress_context; + CompressionColumnDescription *desc = + &dcontext->compressed_chunk_columns[col->input_offset]; + + col->typid = desc->typid; + col->value_bytes = desc->value_bytes; + col->by_value = desc->by_value; } } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 1b38fa81fe7..f991729125f 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -24,6 +24,10 @@ typedef struct { int input_offset; int output_offset; + + Oid typid; + int16 value_bytes; + bool by_value; } GroupingColumn; typedef struct diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 8bce4e1b2a4..d0829cf0404 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -62,13 +62,36 @@ hash64(uint64 x) struct h_hash; +typedef struct +{ + void *(*create)(MemoryContext context, uint32 initial_rows, void *data); + void (*reset)(void *table); + uint32 (*get_num_keys)(void *table); + uint64 (*get_size_bytes)(void *table); +} HashTableFunctions; + +static uint32 +get_num_keys(void *table) +{ + struct h_hash *hash = (struct h_hash *) table; + return hash->members; +} + +static uint64 +get_size_bytes(void *table) +{ + struct h_hash *hash = (struct h_hash *) table; + return hash->members * sizeof(HashEntry); +} + typedef struct { GroupingPolicy funcs; List *agg_defs; List *output_grouping_columns; bool partial_per_batch; - struct h_hash *table; + void *table; + HashTableFunctions functions; bool have_null_key; struct h_iterator iter; bool returning_results; @@ -84,6 +107,10 @@ typedef struct uint64 allocated_aggstate_rows; List *per_agg_states; + uint64 key_bytes; + uint64 allocated_key_rows; + void *keys; + uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; @@ -112,7 +139,22 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); } - policy->table = h_create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); + Assert(list_length(policy->output_grouping_columns) == 1); + GroupingColumn *g = linitial(policy->output_grouping_columns); + policy->key_bytes = g->value_bytes; + Assert(policy->key_bytes > 0); + policy->allocated_key_rows = policy->allocated_aggstate_rows; + policy->keys = palloc0(policy->allocated_key_rows * policy->key_bytes); + + policy->functions = (HashTableFunctions){ + .create = (void *(*) (MemoryContext, uint32, void *) ) h_create, + .reset = (void (*)(void *)) h_reset, + .get_num_keys = get_num_keys, + .get_size_bytes = get_size_bytes, + }; + + policy->table = + policy->functions.create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); policy->have_null_key = false; policy->returning_results = false; @@ -129,7 +171,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; - h_reset(policy->table); + policy->functions.reset(policy->table); policy->have_null_key = false; policy->stat_input_valid_rows = 0; @@ -209,12 +251,11 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } static pg_attribute_always_inline uint32 -fill_offsets_impl_for_real(GroupingPolicyHash *policy, - CompressedColumnValues column, const uint64 *restrict filter, - uint32 next_unused_state_index, int start_row, int end_row, - uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) +fill_offsets_impl_for_real(GroupingPolicyHash *policy, CompressedColumnValues column, + const uint64 *restrict filter, uint32 next_unused_state_index, + int start_row, int end_row, uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, + Datum *restrict key, bool *restrict valid)) { struct h_hash *restrict table = policy->table; for (int row = start_row; row < end_row; row++) @@ -260,23 +301,47 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, if (filter == NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl_for_real(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl_for_real(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter == NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl_for_real(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl_for_real(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else { @@ -458,9 +523,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * is for null key. We have to initialize the null key state at the * first run. */ - const uint32 last_initialized_state_index = - policy->table->members ? policy->table->members + 2 : 1; - uint32 next_unused_state_index = policy->table->members + 2; + const uint32 hash_keys = policy->functions.get_num_keys(policy->table); + const uint32 last_initialized_state_index = hash_keys ? hash_keys + 2 : 1; + uint32 next_unused_state_index = hash_keys + 2; /* * Match rows to aggregation states using a hash table. @@ -572,7 +637,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - if (policy->table->members * sizeof(HashEntry) > 128 * 1024) + if (policy->functions.get_size_bytes(policy->table) > 128 * 1024) { return true; } From 694faf68889ff0dccf2a0dd17d36288746d84e5e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:09:59 +0100 Subject: [PATCH 023/242] use simplehash --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 8bce4e1b2a4..9bac208b090 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -25,6 +25,7 @@ typedef struct { Datum key; + uint32 status; uint32 agg_state_index; } HashEntry; @@ -58,7 +59,7 @@ hash64(uint64 x) #define SH_DECLARE #define SH_DEFINE #define SH_ENTRY_EMPTY(entry) (entry->agg_state_index == 0) -#include "import/ts_simplehash.h" +#include struct h_hash; From 3d056744e3e694b3a81f9e37d373a49b904a6373 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:31:06 +0100 Subject: [PATCH 024/242] cleanup --- .../nodes/vector_agg/grouping_policy_hash.c | 221 ++++++++++-------- 1 file changed, 127 insertions(+), 94 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 9bac208b090..d2aa6870335 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -20,16 +20,13 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" -#include - -typedef struct -{ - Datum key; - uint32 status; - uint32 agg_state_index; -} HashEntry; - +/* + * We can use crc32 as a hash function, it has bad properties but takes only one + * cycle, which is why it is sometimes used in the existing hash table + * implementations. + */ #ifdef USE_SSE42_CRC32C +#include static pg_attribute_always_inline uint64 hash64(uint64 x) { @@ -37,6 +34,9 @@ hash64(uint64 x) } #else +/* + * When we don't have the crc32 instruction, use the SplitMix64 finalizer. + */ static pg_attribute_always_inline uint64 hash64(uint64 x) { @@ -49,6 +49,17 @@ hash64(uint64 x) } #endif +/* + * For the hash table, use the generic Datum key that is mapped to the aggregate + * state index. + */ +typedef struct +{ + Datum key; + uint32 status; + uint32 agg_state_index; +} HashEntry; + #define SH_PREFIX h #define SH_ELEMENT_TYPE HashEntry #define SH_KEY_TYPE Datum @@ -209,11 +220,13 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } } +/* + * Fill the aggregation state offsets for all rows using a hash table. + */ static pg_attribute_always_inline uint32 -fill_offsets_impl_for_real(GroupingPolicyHash *policy, - CompressedColumnValues column, const uint64 *restrict filter, - uint32 next_unused_state_index, int start_row, int end_row, - uint32 *restrict offsets, +fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, + const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets, void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid)) { @@ -248,36 +261,64 @@ fill_offsets_impl_for_real(GroupingPolicyHash *policy, return next_unused_state_index; } +/* + * This function exists just to nudge the compiler to generate simplified + * implementation for the important case where the entire batch matches and the + * key has no null values. + */ static pg_attribute_always_inline uint32 -fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, - uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) +fill_offsets_dispatch(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid)) { CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; - // Assert(gv->decompression_type == 8 /* lolwut */); const uint64 *restrict filter = batch_state->vector_qual_result; if (filter == NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter == NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, column, - filter, next_unused_state_index, start_row, end_row, offsets, get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else { @@ -289,15 +330,17 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, return next_unused_state_index; } -// static pg_attribute_always_inline -// void get_key_generic(CompressedColumnValues *column, int row, Datum *key, bool *valid) -//{ -// Assert(column->decompression_type > 0); -// const void *values = column->arrow->buffers[1]; -// const uint64 *key_validity = column->arrow->buffers[0]; -// *valid = arrow_row_is_valid(key_validity, row); -// memcpy(key, column->decompression_type * row + (char *) values, column->decompression_type); -// } +/* + * Functions to get the key value from the decompressed column, depending on its + * width and whether it's a scalar column. + */ +static pg_attribute_always_inline void +get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) +{ + Assert(column.decompression_type == DT_Scalar); + *key = *column.output_value; + *valid = !*column.output_isnull; +} static pg_attribute_always_inline void get_key_arrow_fixed(CompressedColumnValues column, int row, int key_bytes, Datum *restrict key, @@ -328,31 +371,33 @@ static pg_attribute_always_inline void get_key_arrow_fixed_8(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) { - /* FIXME for float8 not by value */ - get_key_arrow_fixed(column, row, 8, key, valid); -} +#ifndef USE_FLOAT8_BYVAL + /* + * Shouldn't be called for this configuration, because we only use this + * grouping strategy for by-value types. + */ + Assert(false); +#endif -static pg_attribute_always_inline void -get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) -{ - Assert(column.decompression_type == DT_Scalar); - *key = *column.output_value; - *valid = !*column.output_isnull; + get_key_arrow_fixed(column, row, 8, key, valid); } +/* + * Implementation of bulk hashing specialized for a given key width. + */ static pg_noinline uint32 fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_8); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_8); } static pg_noinline uint32 @@ -360,14 +405,14 @@ fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *bat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_4); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_4); } static pg_noinline uint32 @@ -375,14 +420,14 @@ fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *bat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_2); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_2); } static pg_noinline uint32 @@ -390,14 +435,14 @@ fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_stat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_scalar); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_scalar); } static void @@ -407,6 +452,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(!policy->returning_results); + const uint64_t *restrict filter = batch_state->vector_qual_result; + const int n = batch_state->total_batch_rows; + /* * For the partial aggregation node, the grouping columns are always in the * output, so we don't have to separately look at the list of the grouping @@ -415,14 +463,8 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(list_length(policy->output_grouping_columns) == 1); GroupingColumn *g = linitial(policy->output_grouping_columns); CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; - // const uint64_t* restrict key_validity = key_column->buffers[0]; - const uint64_t *restrict filter = batch_state->vector_qual_result; - - const int n = batch_state->total_batch_rows; int start_row = 0; int end_row = 0; - - // for (int end_row = MIN(64, n); end_row <= n; end_row += 64) for (start_row = 0; start_row < n; start_row = end_row) { /* @@ -561,11 +603,7 @@ static bool gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - (void) policy; - // if (policy->table->members + policy->have_null_key > 0) - // { - // return true; - // } + /* * Don't grow the hash table cardinality too much, otherwise we become bound * by memory reads. In general, when this first stage of grouping doesn't @@ -573,11 +611,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - if (policy->table->members * sizeof(HashEntry) > 128 * 1024) - { - return true; - } - return false; + return policy->table->members * sizeof(HashEntry) > 128 * 1024; } static bool @@ -587,7 +621,6 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) if (!policy->returning_results) { - /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); // fprintf(stderr, From d90a90f24c9f5bfa3089d9233f836d541ce5ecb5 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:31:18 +0100 Subject: [PATCH 025/242] benchmark vectorized hash grouping (simple) (2024-10-14 no. 11) From 4a9354964fcecd533e770f7e2f1d64b9d1c7e660 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:26:30 +0100 Subject: [PATCH 026/242] add more tests --- tsl/test/expected/vector_agg_functions.out | 2145 ++++++++++++-------- tsl/test/sql/vector_agg_functions.sql | 49 +- 2 files changed, 1293 insertions(+), 901 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 9e9f8115e57..c79c667d15a 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -9,7 +9,7 @@ $$ LANGUAGE SQL; \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, cfloat4 float4, cfloat8 float8, cts timestamp, ctstz timestamptz, @@ -22,27 +22,47 @@ NOTICE: adding not-null constraint to column "s" (1,public,aggfns,t) (1 row) -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000::int + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, + (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, + (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t + 4) * 100)::float4 end as cfloat4, + (mix(s + t + 5) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('aggfns') x; + count +------- + 1 +(1 row) + +alter table aggfns add column ss int default 11; +insert into aggfns +select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1; select count(compress_chunk(x)) from show_chunks('aggfns') x; count ------- @@ -75,7 +95,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -102,13 +123,50 @@ where end and case + when variable = '*' then function = 'count' when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') + when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') else true end order by explain, condition.n, variable, function, grouping.n \gexec +select count(*) from aggfns order by 1; + count +-------- + 200000 +(1 row) + +select s, count(*) from aggfns group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(*) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 19 +(10 rows) + select max(cdate) from aggfns order by 1; max ------------ @@ -134,8 +192,6 @@ select ss, max(cdate) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-11-2185 5 | 08-28-2212 @@ -143,6 +199,8 @@ select ss, max(cdate) from aggfns group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-05-2322 + 11 | 01-24-2183 + | 07-03-2156 (10 rows) select min(cdate) from aggfns order by 1; @@ -170,8 +228,6 @@ select ss, min(cdate) from aggfns group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -179,6 +235,8 @@ select ss, min(cdate) from aggfns group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns order by 1; @@ -206,15 +264,15 @@ select ss, avg(cfloat4) from aggfns group by ss order by 1; ss | avg ----+-------------------- 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -0.13252146150968 + 4 | -0.124977103379316 5 | -0.130611110996222 6 | -0.131984978889441 7 | -0.131050092529273 8 | -0.131313872741675 9 | -0.132765194868064 + 11 | NaN + | -5.91588952823689 (10 rows) select count(cfloat4) from aggfns order by 1; @@ -242,15 +300,15 @@ select ss, count(cfloat4) from aggfns group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cfloat4) from aggfns order by 1; @@ -275,18 +333,18 @@ select s, max(cfloat4) from aggfns group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns order by 1; @@ -314,8 +372,6 @@ select ss, min(cfloat4) from aggfns group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -Infinity 4 | -49.9756 5 | -49.9756 @@ -323,6 +379,8 @@ select ss, min(cfloat4) from aggfns group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns order by 1; @@ -350,15 +408,15 @@ select ss, stddev(cfloat4) from aggfns group by ss order by 1; ss | stddev ----+------------------ 0 | 28.8941380063427 - 1 | NaN - 2 | NaN 3 | NaN - 4 | 28.8948189281654 + 4 | 28.89302954083 5 | 28.8951827753267 6 | 28.8960531969495 7 | 28.8959678301628 8 | 28.8963276918371 9 | 28.8968307405966 + 11 | NaN + | 27.2867943876683 (10 rows) select sum(cfloat4) from aggfns order by 1; @@ -386,15 +444,15 @@ select ss, sum(cfloat4) from aggfns group by ss order by 1; ss | sum ----+----------- 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 + 4 | -2497.17 5 | -2612.22 6 | -2639.7 7 | -2621 8 | -2626.28 9 | -2655.3 + 11 | NaN + | -112.402 (10 rows) select avg(cfloat8) from aggfns order by 1; @@ -422,15 +480,15 @@ select ss, avg(cfloat8) from aggfns group by ss order by 1; ss | avg ----+-------------------- 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 + 3 | -0.128550004763072 + 4 | -0.129264304572168 5 | -0.131984980024863 6 | -0.131050093692029 7 | -0.13131387403002 8 | -0.132765196124092 9 | -0.134423591727391 + 11 | -0.131587538323368 + | -4.30903203025656 (10 rows) select max(cfloat8) from aggfns order by 1; @@ -455,18 +513,18 @@ select s, max(cfloat8) from aggfns group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns order by 1; @@ -494,8 +552,6 @@ select ss, min(cfloat8) from aggfns group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -503,6 +559,8 @@ select ss, min(cfloat8) from aggfns group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns order by 1; @@ -530,15 +588,15 @@ select ss, stddev(cfloat8) from aggfns group by ss order by 1; ss | stddev ----+------------------ 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 + 3 | 28.8988694216911 + 4 | 28.8937408619903 5 | 28.8960532056265 6 | 28.8959678388464 7 | 28.8963277006942 8 | 28.8968307494196 9 | 28.8953209642426 + 11 | 28.8954978116663 + | 24.556507133269 (10 rows) select sum(cfloat8) from aggfns order by 1; @@ -566,15 +624,15 @@ select ss, sum(cfloat8) from aggfns group by ss order by 1; ss | sum ----+------------------- 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 + 3 | -2568.55764517095 + 4 | -2582.83006965648 5 | -2639.69960049726 6 | -2621.00187384058 7 | -2626.2774806004 8 | -2655.30392248183 9 | -2688.47183454782 + 11 | -5266.00169616286 + | -81.8716085748747 (10 rows) select avg(cint2) from aggfns order by 1; @@ -599,18 +657,18 @@ select s, avg(cint2) from aggfns group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 + ss | avg +----+----------------------- + 0 | -42.2972824182973825 + 3 | -42.6071034966436229 + 4 | -40.0837090471896604 + 5 | -43.5287022671537961 + 6 | -41.7711325759471498 + 7 | -41.3288123717531655 + 8 | -40.6353035383614434 + 9 | -43.1119563585406136 + 11 | -42.9734623946374528 + | -335.0000000000000000 (10 rows) select max(cint2) from aggfns order by 1; @@ -638,8 +696,6 @@ select ss, max(cint2) from aggfns group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -647,6 +703,8 @@ select ss, max(cint2) from aggfns group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 13720 (10 rows) select min(cint2) from aggfns order by 1; @@ -674,8 +732,6 @@ select ss, min(cint2) from aggfns group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -683,6 +739,8 @@ select ss, min(cint2) from aggfns group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns order by 1; @@ -710,15 +768,15 @@ select ss, stddev(cint2) from aggfns group by ss order by 1; ss | stddev ----+------------------- 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 + 3 | 9466.351508971864 + 4 | 9469.021659499615 5 | 9467.599133444078 6 | 9468.362090451302 7 | 9467.745653535755 8 | 9466.743345080951 9 | 9468.145452253715 + 11 | 9467.946206136906 + | 9796.780548277639 (10 rows) select sum(cint2) from aggfns order by 1; @@ -743,18 +801,18 @@ select s, sum(cint2) from aggfns group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 + ss | sum +----+---------- + 0 | -845142 + 3 | -850523 + 4 | -800151 + 5 | -869747 + 6 | -834629 + 7 | -825791 + 8 | -811934 + 9 | -861420 + 11 | -1718122 + | -6365 (10 rows) select avg(cint4) from aggfns order by 1; @@ -782,15 +840,15 @@ select ss, avg(cint4) from aggfns group by ss order by 1; ss | avg ----+----------------------- 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 + 3 | -2682566.613082428307 + 4 | -2753845.761523447275 5 | -2850351.637450000000 6 | -2845789.891100000000 7 | -2804766.678700000000 8 | -2834269.365200000000 9 | -2814193.446750000000 + 11 | -2846001.238586671331 + | -146005017.57894737 (10 rows) select max(cint4) from aggfns order by 1; @@ -818,8 +876,6 @@ select ss, max(cint4) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -827,6 +883,8 @@ select ss, max(cint4) from aggfns group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 978482473 (10 rows) select min(cint4) from aggfns order by 1; @@ -854,8 +912,6 @@ select ss, min(cint4) from aggfns group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -863,6 +919,8 @@ select ss, min(cint4) from aggfns group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -960881516 (10 rows) select stddev(cint4) from aggfns order by 1; @@ -890,15 +948,15 @@ select ss, stddev(cint4) from aggfns group by ss order by 1; ss | stddev ----+----------- 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 + 3 | 620502162 + 4 | 620460588 5 | 620498014 6 | 620492575 7 | 620500389 8 | 620519080 9 | 620517247 + 11 | 620490348 + | 569369090 (10 rows) select sum(cint4) from aggfns order by 1; @@ -923,18 +981,18 @@ select s, sum(cint4) from aggfns group by s order by 1; (10 rows) select ss, sum(cint4) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 + ss | sum +----+--------------- + 0 | -58384962420 + 3 | -53600363496 + 4 | -55024592161 + 5 | -57007032749 + 6 | -56915797822 + 7 | -56095333574 + 8 | -56685387304 + 9 | -56283868935 + 11 | -113894123567 + | -2774095334 (10 rows) select avg(cint8) from aggfns order by 1; @@ -962,15 +1020,15 @@ select ss, avg(cint8) from aggfns group by ss order by 1; ss | avg ----+----------------------- 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 + 3 | -2653999.743206045743 + 4 | -3009394.583854661929 5 | -2845789.891100000000 6 | -2804766.678700000000 7 | -2834269.365200000000 8 | -2814193.446750000000 9 | -2819857.913500000000 + 11 | -2748620.862390364577 + | -127121035.31578947 (10 rows) select max(cint8) from aggfns order by 1; @@ -998,8 +1056,6 @@ select ss, max(cint8) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -1007,6 +1063,8 @@ select ss, max(cint8) from aggfns group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns order by 1; @@ -1034,8 +1092,6 @@ select ss, min(cint8) from aggfns group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -1043,6 +1099,8 @@ select ss, min(cint8) from aggfns group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -796158533 (10 rows) select stddev(cint8) from aggfns order by 1; @@ -1070,15 +1128,15 @@ select ss, stddev(cint8) from aggfns group by ss order by 1; ss | stddev ----+----------- 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 + 3 | 620514804 + 4 | 620462299 5 | 620492575 6 | 620500389 7 | 620519080 8 | 620517247 9 | 620524975 + 11 | 620478168 + | 609007799 (10 rows) select sum(cint8) from aggfns order by 1; @@ -1103,18 +1161,18 @@ select s, sum(cint8) from aggfns group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 + ss | sum +----+--------------- + 0 | -56727567295 + 3 | -53029568869 + 4 | -60130713180 + 5 | -56915797822 + 6 | -56095333574 + 7 | -56685387304 + 8 | -56283868935 + 9 | -56397158270 + 11 | -109997058292 + | -2415299671 (10 rows) select max(cts) from aggfns order by 1; @@ -1142,8 +1200,6 @@ select ss, max(cts) from aggfns group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:41 2021 @@ -1151,6 +1207,8 @@ select ss, max(cts) from aggfns group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns order by 1; @@ -1178,8 +1236,6 @@ select ss, min(cts) from aggfns group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -1187,6 +1243,8 @@ select ss, min(cts) from aggfns group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns order by 1; @@ -1214,8 +1272,6 @@ select ss, max(ctstz) from aggfns group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -1223,6 +1279,8 @@ select ss, max(ctstz) from aggfns group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns order by 1; @@ -1250,8 +1308,6 @@ select ss, min(ctstz) from aggfns group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -1259,6 +1315,8 @@ select ss, min(ctstz) from aggfns group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns order by 1; @@ -1286,8 +1344,6 @@ select ss, avg(s) from aggfns group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -1295,6 +1351,8 @@ select ss, avg(s) from aggfns group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5011869362053025 + | 3.0000000000000000 (10 rows) select count(s) from aggfns order by 1; @@ -1322,15 +1380,15 @@ select ss, count(s) from aggfns group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(s) from aggfns order by 1; @@ -1358,8 +1416,6 @@ select ss, max(s) from aggfns group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1367,6 +1423,8 @@ select ss, max(s) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns order by 1; @@ -1394,8 +1452,6 @@ select ss, min(s) from aggfns group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1403,6 +1459,8 @@ select ss, min(s) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns order by 1; @@ -1427,18 +1485,18 @@ select s, stddev(s) from aggfns group by s order by 1; (10 rows) select ss, stddev(s) from aggfns group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50284545977155885187 + | 0 (10 rows) select sum(s) from aggfns order by 1; @@ -1466,31 +1524,31 @@ select ss, sum(s) from aggfns group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 60076 + | 57 (10 rows) select avg(ss) from aggfns order by 1; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) select s, avg(ss) from aggfns group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -1502,8 +1560,6 @@ select ss, avg(ss) from aggfns group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -1511,22 +1567,60 @@ select ss, avg(ss) from aggfns group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns order by 1; + count +-------- + 199981 +(1 row) + +select s, count(ss) from aggfns group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 19981 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(ss) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 0 (10 rows) select max(ss) from aggfns order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -1538,8 +1632,6 @@ select ss, max(ss) from aggfns group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1547,6 +1639,8 @@ select ss, max(ss) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns order by 1; @@ -1559,8 +1653,8 @@ select s, min(ss) from aggfns group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -1574,8 +1668,6 @@ select ss, min(ss) from aggfns group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1583,35 +1675,35 @@ select ss, min(ss) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns order by 1; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) select s, stddev(ss) from aggfns group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.21565737387148452722 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -1619,22 +1711,24 @@ select ss, stddev(ss) from aggfns group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns order by 1; - sum --------- - 900000 + sum +--------- + 1280076 (1 row) select s, sum(ss) from aggfns group by s order by 1; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 1 | 220000 + 2 | 220000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 @@ -1646,15 +1740,15 @@ select ss, sum(ss) from aggfns group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 440209 + | (10 rows) select max(t) from aggfns order by 1; @@ -1682,8 +1776,6 @@ select ss, max(t) from aggfns group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 30000 - 2 | 40000 3 | 50000 4 | 60000 5 | 70000 @@ -1691,6 +1783,8 @@ select ss, max(t) from aggfns group by ss order by 1; 7 | 90000 8 | 100000 9 | 110000 + 11 | 59192 + | 49491 (10 rows) select min(t) from aggfns order by 1; @@ -1718,8 +1812,6 @@ select ss, min(t) from aggfns group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -1727,6 +1819,44 @@ select ss, min(t) from aggfns group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 30537 +(10 rows) + +select count(*) from aggfns where cfloat8 > 0 order by 1; + count +------- + 99430 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 9943 + 1 | 9943 + 2 | 9942 + 3 | 9942 + 4 | 9943 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 9943 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(cdate) from aggfns where cfloat8 > 0 order by 1; @@ -1754,8 +1884,6 @@ select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 10-04-2075 - 1 | 02-21-2103 - 2 | 07-08-2130 3 | 11-22-2157 4 | 04-11-2185 5 | 08-27-2212 @@ -1763,6 +1891,8 @@ select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 05-31-2267 8 | 10-15-2294 9 | 03-05-2322 + 11 | 03-03-2180 + | 07-03-2156 (10 rows) select min(cdate) from aggfns where cfloat8 > 0 order by 1; @@ -1790,8 +1920,6 @@ select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-11-2075 3 | 02-26-2103 4 | 07-13-2130 5 | 11-27-2157 @@ -1799,6 +1927,8 @@ select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 05-18-2110 (10 rows) select avg(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1826,15 +1956,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.542617154225893 - 1 | -0.540875748760701 - 2 | -0.541406464808325 3 | -Infinity - 4 | -0.544616367218129 + 4 | -0.545104747625541 5 | -0.544616367218129 6 | -0.547797322998719 7 | -0.547797322998719 8 | -0.544139963208192 9 | -0.547059247380753 + 11 | -0.540899217374597 + | -1.46971142292023 (10 rows) select count(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1862,15 +1992,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 + 3 | 9934 + 4 | 9932 5 | 9943 6 | 9944 7 | 9944 8 | 9943 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1898,8 +2028,6 @@ select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+--------- 0 | 49.9734 - 1 | 49.9734 - 2 | 49.9734 3 | 49.9734 4 | 49.9734 5 | 49.9734 @@ -1907,6 +2035,8 @@ select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 49.9734 8 | 49.9734 9 | 49.9734 + 11 | 49.9734 + | 24.3202 (10 rows) select min(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1934,8 +2064,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----------- 0 | -49.9722 - 1 | -49.9722 - 2 | -49.9722 3 | -Infinity 4 | -49.9722 5 | -49.9722 @@ -1943,6 +2071,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -49.9722 8 | -49.9722 9 | -49.9722 + 11 | -49.9722 + | -45.111 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1970,15 +2100,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------ 0 | 28.889048755135 - 1 | 28.8872257367626 - 2 | 28.8886301576555 3 | NaN - 4 | 28.8889504423898 + 4 | 28.8896204728232 5 | 28.8889504423898 6 | 28.8892391773513 7 | 28.8892391773513 8 | 28.8883896891408 9 | 28.8893600799806 + 11 | 28.886867950284 + | 23.0946953685783 (10 rows) select sum(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -2006,15 +2136,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+----------- 0 | -5395.24 - 1 | -5377.93 - 2 | -5382.66 3 | -Infinity - 4 | -5415.12 + 4 | -5413.98 5 | -5415.12 6 | -5447.3 7 | -5447.3 8 | -5410.38 9 | -5439.41 + 11 | -10761.7 + | -11.7577 (10 rows) select avg(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2042,15 +2172,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------ 0 | 25.0253254492148 - 1 | 25.0296791394684 - 2 | 25.0284447917954 - 3 | 25.0284447917954 - 4 | 25.0283891332554 + 3 | 25.0326248798677 + 4 | 25.0314280577154 5 | 25.0283891332554 6 | 25.0265337956144 7 | 25.0265337956144 8 | 25.0286117211772 9 | 25.0252759158804 + 11 | 25.0275446062773 + | 19.8378204280743 (10 rows) select max(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2075,18 +2205,18 @@ select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2114,8 +2244,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+--------------------- 0 | 0.00456937123090029 - 1 | 0.00456937123090029 - 2 | 0.00456937123090029 3 | 0.00456937123090029 4 | 0.00456937123090029 5 | 0.00456937123090029 @@ -2123,6 +2251,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 0.00456937123090029 8 | 0.00456937123090029 9 | 0.00456937123090029 + 11 | 0.00456937123090029 + | 0.0712367007508874 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2150,15 +2280,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------ 0 | 14.4393152148108 - 1 | 14.4397230124184 - 2 | 14.4399246592273 - 3 | 14.4399246592273 - 4 | 14.4391994993402 + 3 | 14.4385675470181 + 4 | 14.4418957208478 5 | 14.4391994993402 6 | 14.4396587086659 7 | 14.4396587086659 8 | 14.4388979969066 9 | 14.4386334818319 + 11 | 14.4381143863288 + | 16.2202029568666 (10 rows) select sum(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2186,15 +2316,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+------------------ 0 | 248826.810941542 - 1 | 248870.099683735 - 2 | 248832.79812003 - 3 | 248832.79812003 - 4 | 248857.273151958 + 3 | 248674.095556606 + 4 | 248612.143469229 5 | 248857.273151958 6 | 248863.85206359 7 | 248863.85206359 8 | 248859.486343665 9 | 248826.318431599 + 11 | 497948.027486494 + | 158.702563424595 (10 rows) select avg(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2219,18 +2349,18 @@ select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+--------------------- - 0 | 62.5336219045701631 - 1 | 61.1402396053558844 - 2 | 64.7349239907379442 - 3 | 60.4202577527184857 - 4 | 58.4389090177133655 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 + ss | avg +----+----------------------- + 0 | 62.5336219045701631 + 3 | 59.2794236195082628 + 4 | 60.5569773299748111 + 5 | 53.6134098459679855 + 6 | 59.4139909411172622 + 7 | 62.9917446894191080 + 8 | 57.2486665995773372 + 9 | 59.3958123615864707 + 11 | 61.8774966041153092 + | 1475.6250000000000000 (10 rows) select max(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2258,8 +2388,6 @@ select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------- 0 | 16377 - 1 | 16377 - 2 | 16377 3 | 16377 4 | 16377 5 | 16377 @@ -2267,6 +2395,8 @@ select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 16377 8 | 16377 9 | 16377 + 11 | 16377 + | 13720 (10 rows) select min(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2294,8 +2424,6 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+-------- 0 | -16374 - 1 | -16374 - 2 | -16374 3 | -16374 4 | -16374 5 | -16374 @@ -2303,6 +2431,8 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -16374 8 | -16374 9 | -16374 + 11 | -16374 + | -12426 (10 rows) select stddev(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2330,15 +2460,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------- 0 | 9396.868628954375 - 1 | 9397.478004684803 - 2 | 9396.003979674052 - 3 | 9395.588131506675 - 4 | 9395.667525723886 + 3 | 9395.145600532270 + 4 | 9398.818234815872 5 | 9394.622668940645 6 | 9397.336273737402 7 | 9394.449892433625 8 | 9394.534603851403 9 | 9396.374239570388 + 11 | 9394.931149048751 + | 10506.43193392 (10 rows) select sum(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2363,18 +2493,18 @@ select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------- - 0 | 621209 - 1 | 607306 - 2 | 643012 - 3 | 600094 - 4 | 580649 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 + ss | sum +----+--------- + 0 | 621209 + 3 | 588289 + 4 | 601028 + 5 | 532542 + 6 | 590278 + 7 | 625697 + 8 | 568880 + 9 | 590038 + 11 | 1229939 + | 11805 (10 rows) select avg(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2399,18 +2529,18 @@ select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -3230391.667404203963 - 1 | -3063702.023936437695 - 2 | -3067528.135686984510 - 3 | -3067528.135686984510 - 4 | -2963500.289651010761 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 + ss | avg +----+------------------------ + 0 | -3230391.667404203963 + 3 | -2996690.484799677874 + 4 | -3090966.561316955296 + 5 | -2963500.289651010761 + 6 | -3033294.541331456154 + 7 | -3033294.541331456154 + 8 | -3023451.730664789299 + 9 | -2983069.716282812029 + 11 | -3001927.897165259349 + | -91030181.125000000000 (10 rows) select max(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2438,8 +2568,6 @@ select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 1073213373 - 1 | 1073213373 - 2 | 1073213373 3 | 1073213373 4 | 1073213373 5 | 1073213373 @@ -2447,6 +2575,8 @@ select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 1073213373 8 | 1073213373 9 | 1073213373 + 11 | 1073213373 + | 978482473 (10 rows) select min(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2474,8 +2604,6 @@ select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------- 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 3 | -1073053412 4 | -1073053412 5 | -1073053412 @@ -2483,6 +2611,8 @@ select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -1073053412 8 | -1073053412 9 | -1073053412 + 11 | -1073053412 + | -960881516 (10 rows) select stddev(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2510,15 +2640,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+----------- 0 | 622275017 - 1 | 622236051 - 2 | 622267230 - 3 | 622267230 - 4 | 622322391 + 3 | 622183925 + 4 | 622245451 5 | 622322391 6 | 622330015 7 | 622330015 8 | 622360538 9 | 622356873 + 11 | 622274449 + | 762095534 (10 rows) select sum(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2546,15 +2676,15 @@ select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+-------------- 0 | -32119784349 - 1 | -30462389224 - 2 | -30497364725 - 3 | -30497364725 - 4 | -29466083380 + 3 | -29769123276 + 4 | -30699479887 5 | -29466083380 6 | -30163080919 7 | -30163080919 8 | -30062180558 9 | -29660662189 + 11 | -59726357442 + | -728241449 (10 rows) select avg(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2582,15 +2712,15 @@ select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+----------------------- 0 | -7332793.526098762949 - 1 | -7334675.513225384693 - 2 | -7250229.067592033796 - 3 | -7250229.067592033796 - 4 | -7326050.594790304737 + 3 | -7271023.008153815180 + 4 | -7498519.579943616593 5 | -7326050.594790304737 6 | -7272459.754123089300 7 | -7272459.754123089300 8 | -7247017.818163532133 9 | -7258411.696771598109 + 11 | -7206377.192098914355 + | 18570646.625000000000 (10 rows) select max(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2618,8 +2748,6 @@ select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 1073659785 - 1 | 1073659785 - 2 | 1073659785 3 | 1073659785 4 | 1073659785 5 | 1073659785 @@ -2627,6 +2755,8 @@ select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 1073659785 8 | 1073659785 9 | 1073659785 + 11 | 1073659785 + | 969157980 (10 rows) select min(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2654,8 +2784,6 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -2663,6 +2791,8 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -672677796 (10 rows) select stddev(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2690,15 +2820,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+----------- 0 | 623613696 - 1 | 623613596 - 2 | 623588105 - 3 | 623588105 - 4 | 623602577 + 3 | 623600813 + 4 | 623575078 5 | 623602577 6 | 623594116 7 | 623594116 8 | 623620316 9 | 623635702 + 11 | 623598886 + | 648969761 (10 rows) select sum(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2723,18 +2853,18 @@ select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -72909966030 - 1 | -72928678628 - 2 | -72081777390 - 3 | -72081777390 - 4 | -72842921064 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 + ss | sum +----+--------------- + 0 | -72909966030 + 3 | -72230342563 + 4 | -74475296468 + 5 | -72842921064 + 6 | -72317339795 + 7 | -72317339795 + 8 | -72057098166 + 9 | -72170387501 + 11 | -143378080614 + | 148565173 (10 rows) select max(cts) from aggfns where cfloat8 > 0 order by 1; @@ -2762,8 +2892,6 @@ select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:20 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:40 2021 3 | Fri Jan 01 14:54:19 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:40 2021 @@ -2771,6 +2899,8 @@ select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Sat Jan 02 02:01:00 2021 8 | Sat Jan 02 04:47:39 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:09:56 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns where cfloat8 > 0 order by 1; @@ -2798,8 +2928,6 @@ select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:27 2021 3 | Fri Jan 01 09:21:06 2021 4 | Fri Jan 01 12:07:45 2021 5 | Fri Jan 01 14:54:24 2021 @@ -2807,6 +2935,8 @@ select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 10:05:04 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 > 0 order by 1; @@ -2834,8 +2964,6 @@ select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:20 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:40 2021 PST 3 | Fri Jan 01 14:54:19 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:40 2021 PST @@ -2843,6 +2971,8 @@ select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Sat Jan 02 02:01:00 2021 PST 8 | Sat Jan 02 04:47:39 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:09:56 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 > 0 order by 1; @@ -2870,8 +3000,6 @@ select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:27 2021 PST 3 | Fri Jan 01 09:21:06 2021 PST 4 | Fri Jan 01 12:07:45 2021 PST 5 | Fri Jan 01 14:54:24 2021 PST @@ -2879,6 +3007,8 @@ select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 10:05:04 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 > 0 order by 1; @@ -2906,8 +3036,6 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -2915,6 +3043,8 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5013570566948130 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 > 0 order by 1; @@ -2942,15 +3072,15 @@ select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 + 3 | 9934 + 4 | 9932 5 | 9943 6 | 9944 7 | 9944 8 | 9943 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(s) from aggfns where cfloat8 > 0 order by 1; @@ -2978,8 +3108,6 @@ select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -2987,6 +3115,8 @@ select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 > 0 order by 1; @@ -3014,8 +3144,6 @@ select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3023,6 +3151,8 @@ select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 > 0 order by 1; @@ -3047,18 +3177,18 @@ select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50331713731225271878 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 > 0 order by 1; @@ -3086,31 +3216,31 @@ select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+------- 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 + 3 | 29802 + 4 | 39728 5 | 49715 6 | 59664 7 | 69608 8 | 79544 9 | 89487 + 11 | 29871 + | 24 (10 rows) select avg(ss) from aggfns where cfloat8 > 0 order by 1; avg -------------------- - 4.5000804586141004 + 6.4010379996379071 (1 row) select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | avg ---+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0077441416071608 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -3122,8 +3252,6 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -3131,22 +3259,60 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 > 0 order by 1; + count +------- + 99422 +(1 row) + +select s, count(ss) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 9943 + 1 | 9943 + 2 | 9942 + 3 | 9934 + 4 | 9943 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 9943 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + 11 | 19896 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 > 0 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -3158,8 +3324,6 @@ select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3167,6 +3331,8 @@ select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 > 0 order by 1; @@ -3179,8 +3345,8 @@ select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -3194,8 +3360,6 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3203,35 +3367,35 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 > 0 order by 1; stddev -------------------- - 2.8722957659869625 + 3.3528295838273201 (1 row) select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.23271112137690657933 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -3239,42 +3403,44 @@ select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 > 0 order by 1; sum -------- - 447443 + 636404 (1 row) select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 + s | sum +---+-------- + 0 | 0 + 1 | 109373 + 2 | 109362 + 3 | 29802 + 4 | 39849 + 5 | 49715 + 6 | 59664 + 7 | 69608 + 8 | 79544 + 9 | 89487 (10 rows) select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 + ss | sum +----+-------- + 0 | 0 + 3 | 29802 + 4 | 39728 + 5 | 49715 + 6 | 59664 + 7 | 69608 + 8 | 79544 + 9 | 89487 + 11 | 218856 + | (10 rows) select max(t) from aggfns where cfloat8 > 0 order by 1; @@ -3302,8 +3468,6 @@ select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+-------- 0 | 19999 - 1 | 30000 - 2 | 39999 3 | 49998 4 | 60000 5 | 69999 @@ -3311,6 +3475,8 @@ select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 89999 8 | 99998 9 | 110000 + 11 | 58135 + | 49491 (10 rows) select min(t) from aggfns where cfloat8 > 0 order by 1; @@ -3338,8 +3504,6 @@ select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20006 3 | 30005 4 | 40004 5 | 50003 @@ -3347,6 +3511,44 @@ select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 32643 +(10 rows) + +select count(*) from aggfns where cfloat8 <= 0 order by 1; + count +-------- + 100570 +(1 row) + +select s, count(*) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 10057 + 1 | 10057 + 2 | 10058 + 3 | 10058 + 4 | 10057 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 10057 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(cdate) from aggfns where cfloat8 <= 0 order by 1; @@ -3374,8 +3576,6 @@ select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-20-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-10-2185 5 | 08-28-2212 @@ -3383,6 +3583,8 @@ select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-04-2322 + 11 | 01-24-2183 + | 08-15-2153 (10 rows) select min(cdate) from aggfns where cfloat8 <= 0 order by 1; @@ -3410,8 +3612,6 @@ select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------ 0 | 01-04-2021 - 1 | 05-21-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -3419,6 +3619,8 @@ select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 09-01-2212 8 | 01-17-2240 9 | 06-03-2267 + 11 | 05-21-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3446,15 +3648,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+------------------- 0 | 0.273710566446533 - 1 | NaN - 2 | Infinity - 3 | 0.271225418012403 - 4 | 0.274902188431565 + 3 | 0.281539709766287 + 4 | 0.290259015901558 5 | 0.278701234893647 6 | 0.279196201482741 7 | 0.281055561785383 8 | 0.276832673694496 9 | 0.276832673694496 + 11 | NaN + | -9.14947360483083 (10 rows) select count(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3482,15 +3684,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 + 3 | 10047 + 4 | 10049 5 | 10057 6 | 10056 7 | 10056 8 | 10057 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3515,18 +3717,18 @@ select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3554,8 +3756,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+---------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -49.9756 4 | -49.9756 5 | -49.9756 @@ -3563,6 +3763,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3590,15 +3792,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1 ss | stddev ----+------------------ 0 | 28.8948722701767 - 1 | NaN - 2 | NaN - 3 | 28.8971947735822 - 4 | 28.8962786797298 + 3 | 28.8951497341689 + 4 | 28.8918331282339 5 | 28.8969485514879 6 | 28.898342825597 7 | 28.8981465590944 8 | 28.8998126918449 9 | 28.8998126918449 + 11 | NaN + | 30.6521210689863 (10 rows) select sum(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3626,15 +3828,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- 0 | 2752.71 - 1 | NaN - 2 | Infinity - 3 | 2727.99 - 4 | 2764.69 + 3 | 2828.63 + 4 | 2916.81 5 | 2802.9 6 | 2807.6 7 | 2826.29 8 | 2784.11 9 | 2784.11 + 11 | NaN + | -100.644 (10 rows) select avg(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3662,15 +3864,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+------------------- 0 | -25.0026878159296 - 1 | -25.0026878159296 - 2 | -25.0037259853644 - 3 | -25.0033035766331 - 4 | -25.0044243209649 + 3 | -25.0067336719196 + 4 | -24.9970119951125 5 | -25.0071564832908 6 | -25.0084381401581 7 | -25.0089627629465 8 | -25.0089281362381 9 | -25.0089281362381 + 11 | -25.0069089689736 + | -21.870379272679 (10 rows) select max(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3698,8 +3900,6 @@ select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----------------------- 0 | -0.000542588531970978 - 1 | -0.000542588531970978 - 2 | -0.000542588531970978 3 | -0.000542588531970978 4 | -0.000542588531970978 5 | -0.000542588531970978 @@ -3707,6 +3907,8 @@ select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -0.000542588531970978 8 | -0.000542588531970978 9 | -0.000542588531970978 + 11 | -0.000542588531970978 + | -4.53631093259901 (10 rows) select min(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3734,8 +3936,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -3743,6 +3943,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3770,15 +3972,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1 ss | stddev ----+------------------ 0 | 14.4821730365752 - 1 | 14.4821730365752 - 2 | 14.4818272972739 - 3 | 14.4815478866618 - 4 | 14.48183169158 + 3 | 14.485819356309 + 4 | 14.4810339821535 5 | 14.4805923063393 6 | 14.4807418968606 7 | 14.4812687827813 8 | 14.4805491499824 9 | 14.4805491499824 + 11 | 14.4820374611522 + | 9.77628724519737 (10 rows) select sum(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3806,15 +4008,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------------------- 0 | -251452.031364804 - 1 | -251452.031364804 - 2 | -251487.475960795 - 3 | -251483.227373776 - 4 | -251469.495395944 + 3 | -251242.653201777 + 4 | -251194.973538886 5 | -251496.972752456 6 | -251484.85393743 7 | -251490.12954419 8 | -251514.790266147 9 | -251514.790266147 + 11 | -503214.029182657 + | -240.574171999469 (10 rows) select avg(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3839,18 +4041,18 @@ select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -145.9491390464815368 - 1 | -146.0055732484076433 - 2 | -145.5036823248407643 - 3 | -144.9877599761170266 - 4 | -141.3792931806869089 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 + ss | avg +----+------------------------ + 0 | -145.9491390464815368 + 3 | -143.3365212193664077 + 4 | -139.6013749128225565 + 5 | -139.5590167197452229 + 6 | -141.8382440772446745 + 7 | -144.4554140127388535 + 8 | -137.4765033851055356 + 9 | -144.4668060117447994 + 11 | -146.6405192996418623 + | -1651.8181818181818182 (10 rows) select max(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3878,8 +4080,6 @@ select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -3887,6 +4087,8 @@ select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 10616 (10 rows) select min(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3914,8 +4116,6 @@ select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -3923,6 +4123,8 @@ select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3950,15 +4152,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+------------------- 0 | 9538.832178541630 - 1 | 9537.717255354464 - 2 | 9540.157933140146 - 3 | 9535.281475740805 - 4 | 9537.335027198989 + 3 | 9535.623908566148 + 4 | 9537.357537825379 5 | 9538.686769657499 6 | 9537.494931550558 7 | 9538.995155888144 8 | 9537.123911034158 9 | 9537.962959664725 + 11 | 9538.688016316899 + | 9537.230025727405 (10 rows) select sum(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3986,15 +4188,15 @@ select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- 0 | -1466351 - 1 | -1467064 - 2 | -1462021 - 3 | -1456982 - 4 | -1420155 + 3 | -1438812 + 4 | -1401179 5 | -1402289 6 | -1424907 7 | -1451488 8 | -1380814 9 | -1451458 + 11 | -2948061 + | -18170 (10 rows) select avg(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4022,15 +4224,15 @@ select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+----------------------- 0 | -2611631.507507208909 - 1 | -2611631.507507208909 - 2 | -2609754.938158679658 - 3 | -2572787.244482004375 - 4 | -2583154.535149647012 + 3 | -2371975.736040609137 + 4 | -2420650.042193253060 5 | -2738485.569155811872 6 | -2660373.598150357995 7 | -2578784.074681782021 8 | -2647231.455304762852 9 | -2647231.455304762852 + 11 | -2691833.530040252447 + | -185986716.81818182 (10 rows) select max(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4058,8 +4260,6 @@ select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -4067,6 +4267,8 @@ select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 556763469 (10 rows) select min(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4094,8 +4296,6 @@ select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -4103,6 +4303,8 @@ select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -888962001 (10 rows) select stddev(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4130,15 +4332,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+----------- 0 | 618765816 - 1 | 618765816 - 2 | 618735080 - 3 | 618695738 - 4 | 618725626 + 3 | 618865631 + 4 | 618722231 5 | 618719952 6 | 618701125 7 | 618716683 8 | 618723996 9 | 618723996 + 11 | 618736738 + | 415688814 (10 rows) select sum(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4166,15 +4368,15 @@ select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+-------------- 0 | -26265178071 - 1 | -26265178071 - 2 | -26248915168 - 3 | -25877094105 - 4 | -25978785160 + 3 | -23831240220 + 4 | -24325112274 5 | -27540949369 6 | -26752716903 7 | -25932252655 8 | -26623206746 9 | -26623206746 + 11 | -54167766125 + | -2045853885 (10 rows) select avg(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4202,15 +4404,15 @@ select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------- 0 | 1609068.184846375659 - 1 | 1609068.184846375659 - 2 | 1561674.145953469875 - 3 | 1654097.121694173792 - 4 | 1574613.534354181167 + 3 | 1911095.221857270827 + 4 | 1427463.756393671012 5 | 1583685.317888038182 6 | 1613166.887529832936 7 | 1554490.104514717582 8 | 1568383.139206522820 9 | 1568383.139206522820 + 11 | 1658849.193559608408 + | -233078622.18181818 (10 rows) select max(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4238,8 +4440,6 @@ select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -4247,6 +4447,8 @@ select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4274,8 +4476,6 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------- 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 3 | -1073053412 4 | -1073053412 5 | -1073053412 @@ -4283,6 +4483,8 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -1073053412 8 | -1073053412 9 | -1073053412 + 11 | -1073053412 + | -796158533 (10 rows) select stddev(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4310,15 +4512,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+----------- 0 | 617360997 - 1 | 617360997 - 2 | 617348601 - 3 | 617433171 - 4 | 617412408 + 3 | 617445433 + 4 | 617369297 5 | 617401473 6 | 617425094 7 | 617462874 8 | 617433744 9 | 617433744 + 11 | 617360997 + | 586053845 (10 rows) select sum(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4346,15 +4548,15 @@ select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------------- 0 | 16182398735 - 1 | 16182398735 - 2 | 15707318560 - 3 | 16636908850 - 4 | 15835888315 + 3 | 19200773694 + 4 | 14344583288 5 | 15927123242 6 | 16222006221 7 | 15631952491 8 | 15773229231 9 | 15773229231 + 11 | 33381022322 + | -2563864844 (10 rows) select max(cts) from aggfns where cfloat8 <= 0 order by 1; @@ -4382,8 +4584,6 @@ select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:00 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:00 2021 5 | Fri Jan 01 20:27:41 2021 @@ -4391,6 +4591,8 @@ select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:20 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:28:19 2021 (10 rows) select min(cts) from aggfns where cfloat8 <= 0 order by 1; @@ -4418,8 +4620,6 @@ select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:04 2021 - 1 | Fri Jan 01 03:47:43 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -4427,6 +4627,8 @@ select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Fri Jan 01 20:27:45 2021 8 | Fri Jan 01 23:14:24 2021 9 | Sat Jan 02 02:01:03 2021 + 11 | Fri Jan 01 03:47:43 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 <= 0 order by 1; @@ -4454,8 +4656,6 @@ select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:00 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:00 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -4463,6 +4663,8 @@ select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:20 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:28:19 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 <= 0 order by 1; @@ -4490,8 +4692,6 @@ select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:04 2021 PST - 1 | Fri Jan 01 03:47:43 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -4499,6 +4699,8 @@ select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Fri Jan 01 20:27:45 2021 PST 8 | Fri Jan 01 23:14:24 2021 PST 9 | Sat Jan 02 02:01:03 2021 PST + 11 | Fri Jan 01 03:47:43 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4526,8 +4728,6 @@ select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -4535,6 +4735,8 @@ select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5010187347810963 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4562,15 +4764,15 @@ select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 + 3 | 10047 + 4 | 10049 5 | 10057 6 | 10056 7 | 10056 8 | 10057 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4598,8 +4800,6 @@ select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4607,6 +4807,8 @@ select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4634,8 +4836,6 @@ select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4643,6 +4843,8 @@ select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4667,18 +4869,18 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50239111765906328317 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4706,31 +4908,31 @@ select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------- 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 + 3 | 30141 + 4 | 40196 5 | 50285 6 | 60336 7 | 70392 8 | 80456 9 | 90513 + 11 | 30205 + | 33 (10 rows) select avg(ss) from aggfns where cfloat8 <= 0 order by 1; avg -------------------- - 4.4999204534155315 + 6.4009387523742281 (1 row) select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0055682609127971 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -4742,8 +4944,6 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -4751,22 +4951,60 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 <= 0 order by 1; + count +-------- + 100559 +(1 row) + +select s, count(ss) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 10057 + 1 | 10057 + 2 | 10058 + 3 | 10047 + 4 | 10057 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 10057 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + 11 | 20123 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 <= 0 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -4778,8 +5016,6 @@ select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4787,6 +5023,8 @@ select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 <= 0 order by 1; @@ -4799,8 +5037,8 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -4814,8 +5052,6 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4823,35 +5059,35 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 <= 0 order by 1; stddev -------------------- - 2.8722956022845549 + 3.3528527058531930 (1 row) select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.19735930141067535100 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -4859,42 +5095,44 @@ select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 <= 0 order by 1; sum -------- - 452557 + 643672 (1 row) select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 + s | sum +---+-------- + 0 | 0 + 1 | 110627 + 2 | 110638 + 3 | 30141 + 4 | 40284 + 5 | 50285 + 6 | 60336 + 7 | 70392 + 8 | 80456 + 9 | 90513 (10 rows) select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 + ss | sum +----+-------- + 0 | 0 + 3 | 30141 + 4 | 40196 + 5 | 50285 + 6 | 60336 + 7 | 70392 + 8 | 80456 + 9 | 90513 + 11 | 221353 + | (10 rows) select max(t) from aggfns where cfloat8 <= 0 order by 1; @@ -4922,8 +5160,6 @@ select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 29999 - 2 | 40000 3 | 50000 4 | 59999 5 | 70000 @@ -4931,6 +5167,8 @@ select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 90000 8 | 100000 9 | 109999 + 11 | 59192 + | 48438 (10 rows) select min(t) from aggfns where cfloat8 <= 0 order by 1; @@ -4958,8 +5196,6 @@ select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------- 0 | 3 - 1 | 10002 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -4967,6 +5203,44 @@ select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 70004 8 | 80003 9 | 90002 + 11 | 10002 + | 30537 +(10 rows) + +select count(*) from aggfns where cfloat8 < 1000 order by 1; + count +-------- + 200000 +(1 row) + +select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cdate) from aggfns where cfloat8 < 1000 order by 1; @@ -4994,8 +5268,6 @@ select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-11-2185 5 | 08-28-2212 @@ -5003,6 +5275,8 @@ select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-05-2322 + 11 | 01-24-2183 + | 07-03-2156 (10 rows) select min(cdate) from aggfns where cfloat8 < 1000 order by 1; @@ -5030,8 +5304,6 @@ select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -5039,6 +5311,8 @@ select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5066,15 +5340,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -0.13252146150968 + 4 | -0.124977103379316 5 | -0.130611110996222 6 | -0.131984978889441 7 | -0.131050092529273 8 | -0.131313872741675 9 | -0.132765194868064 + 11 | NaN + | -5.91588952823689 (10 rows) select count(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5102,15 +5376,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5135,18 +5409,18 @@ select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5174,8 +5448,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -Infinity 4 | -49.9756 5 | -49.9756 @@ -5183,6 +5455,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5210,15 +5484,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by ss | stddev ----+------------------ 0 | 28.8941380063427 - 1 | NaN - 2 | NaN 3 | NaN - 4 | 28.8948189281654 + 4 | 28.89302954083 5 | 28.8951827753267 6 | 28.8960531969495 7 | 28.8959678301628 8 | 28.8963276918371 9 | 28.8968307405966 + 11 | NaN + | 27.2867943876683 (10 rows) select sum(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5246,15 +5520,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+----------- 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 + 4 | -2497.17 5 | -2612.22 6 | -2639.7 7 | -2621 8 | -2626.28 9 | -2655.3 + 11 | NaN + | -112.402 (10 rows) select avg(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5282,15 +5556,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 + 3 | -0.128550004763072 + 4 | -0.129264304572168 5 | -0.131984980024863 6 | -0.131050093692029 7 | -0.13131387403002 8 | -0.132765196124092 9 | -0.134423591727391 + 11 | -0.131587538323368 + | -4.30903203025656 (10 rows) select max(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5315,18 +5589,18 @@ select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5354,8 +5628,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -5363,6 +5635,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5390,15 +5664,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by ss | stddev ----+------------------ 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 + 3 | 28.8988694216911 + 4 | 28.8937408619903 5 | 28.8960532056265 6 | 28.8959678388464 7 | 28.8963277006942 8 | 28.8968307494196 9 | 28.8953209642426 + 11 | 28.8954978116663 + | 24.556507133269 (10 rows) select sum(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5426,15 +5700,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+------------------- 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 + 3 | -2568.55764517095 + 4 | -2582.83006965648 5 | -2639.69960049726 6 | -2621.00187384058 7 | -2626.2774806004 8 | -2655.30392248183 9 | -2688.47183454782 + 11 | -5266.00169616286 + | -81.8716085748747 (10 rows) select avg(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5459,18 +5733,18 @@ select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 + ss | avg +----+----------------------- + 0 | -42.2972824182973825 + 3 | -42.6071034966436229 + 4 | -40.0837090471896604 + 5 | -43.5287022671537961 + 6 | -41.7711325759471498 + 7 | -41.3288123717531655 + 8 | -40.6353035383614434 + 9 | -43.1119563585406136 + 11 | -42.9734623946374528 + | -335.0000000000000000 (10 rows) select max(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5498,8 +5772,6 @@ select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -5507,6 +5779,8 @@ select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 13720 (10 rows) select min(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5534,8 +5808,6 @@ select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -5543,6 +5815,8 @@ select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5570,15 +5844,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+------------------- 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 + 3 | 9466.351508971864 + 4 | 9469.021659499615 5 | 9467.599133444078 6 | 9468.362090451302 7 | 9467.745653535755 8 | 9466.743345080951 9 | 9468.145452253715 + 11 | 9467.946206136906 + | 9796.780548277639 (10 rows) select sum(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5603,18 +5877,18 @@ select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 + ss | sum +----+---------- + 0 | -845142 + 3 | -850523 + 4 | -800151 + 5 | -869747 + 6 | -834629 + 7 | -825791 + 8 | -811934 + 9 | -861420 + 11 | -1718122 + | -6365 (10 rows) select avg(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5642,15 +5916,15 @@ select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+----------------------- 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 + 3 | -2682566.613082428307 + 4 | -2753845.761523447275 5 | -2850351.637450000000 6 | -2845789.891100000000 7 | -2804766.678700000000 8 | -2834269.365200000000 9 | -2814193.446750000000 + 11 | -2846001.238586671331 + | -146005017.57894737 (10 rows) select max(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5678,8 +5952,6 @@ select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -5687,6 +5959,8 @@ select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 978482473 (10 rows) select min(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5714,8 +5988,6 @@ select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -5723,6 +5995,8 @@ select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -960881516 (10 rows) select stddev(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5750,15 +6024,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+----------- 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 + 3 | 620502162 + 4 | 620460588 5 | 620498014 6 | 620492575 7 | 620500389 8 | 620519080 9 | 620517247 + 11 | 620490348 + | 569369090 (10 rows) select sum(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5783,18 +6057,18 @@ select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 + ss | sum +----+--------------- + 0 | -58384962420 + 3 | -53600363496 + 4 | -55024592161 + 5 | -57007032749 + 6 | -56915797822 + 7 | -56095333574 + 8 | -56685387304 + 9 | -56283868935 + 11 | -113894123567 + | -2774095334 (10 rows) select avg(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5822,15 +6096,15 @@ select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+----------------------- 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 + 3 | -2653999.743206045743 + 4 | -3009394.583854661929 5 | -2845789.891100000000 6 | -2804766.678700000000 7 | -2834269.365200000000 8 | -2814193.446750000000 9 | -2819857.913500000000 + 11 | -2748620.862390364577 + | -127121035.31578947 (10 rows) select max(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5858,8 +6132,6 @@ select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -5867,6 +6139,8 @@ select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5894,8 +6168,6 @@ select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -5903,6 +6175,8 @@ select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -796158533 (10 rows) select stddev(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5930,15 +6204,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+----------- 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 + 3 | 620514804 + 4 | 620462299 5 | 620492575 6 | 620500389 7 | 620519080 8 | 620517247 9 | 620524975 + 11 | 620478168 + | 609007799 (10 rows) select sum(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5963,18 +6237,18 @@ select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 + ss | sum +----+--------------- + 0 | -56727567295 + 3 | -53029568869 + 4 | -60130713180 + 5 | -56915797822 + 6 | -56095333574 + 7 | -56685387304 + 8 | -56283868935 + 9 | -56397158270 + 11 | -109997058292 + | -2415299671 (10 rows) select max(cts) from aggfns where cfloat8 < 1000 order by 1; @@ -6002,8 +6276,6 @@ select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:41 2021 @@ -6011,6 +6283,8 @@ select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns where cfloat8 < 1000 order by 1; @@ -6038,8 +6312,6 @@ select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -6047,6 +6319,8 @@ select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 < 1000 order by 1; @@ -6074,8 +6348,6 @@ select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -6083,6 +6355,8 @@ select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 < 1000 order by 1; @@ -6110,8 +6384,6 @@ select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -6119,6 +6391,8 @@ select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6146,8 +6420,6 @@ select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -6155,6 +6427,8 @@ select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5011869362053025 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6182,15 +6456,15 @@ select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6218,8 +6492,6 @@ select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6227,6 +6499,8 @@ select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6254,8 +6528,6 @@ select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6263,6 +6535,8 @@ select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6287,18 +6561,18 @@ select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50284545977155885187 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6326,31 +6600,31 @@ select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 60076 + | 57 (10 rows) select avg(ss) from aggfns where cfloat8 < 1000 order by 1; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -6362,8 +6636,6 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -6371,22 +6643,60 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 < 1000 order by 1; + count +-------- + 199981 +(1 row) + +select s, count(ss) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 19981 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 < 1000 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -6398,8 +6708,6 @@ select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6407,6 +6715,8 @@ select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 < 1000 order by 1; @@ -6419,8 +6729,8 @@ select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -6434,8 +6744,6 @@ select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6443,35 +6751,35 @@ select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 < 1000 order by 1; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.21565737387148452722 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -6479,22 +6787,24 @@ select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 < 1000 order by 1; - sum --------- - 900000 + sum +--------- + 1280076 (1 row) select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 1 | 220000 + 2 | 220000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 @@ -6506,15 +6816,15 @@ select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 440209 + | (10 rows) select max(t) from aggfns where cfloat8 < 1000 order by 1; @@ -6542,8 +6852,6 @@ select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 30000 - 2 | 40000 3 | 50000 4 | 60000 5 | 70000 @@ -6551,6 +6859,8 @@ select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 90000 8 | 100000 9 | 110000 + 11 | 59192 + | 49491 (10 rows) select min(t) from aggfns where cfloat8 < 1000 order by 1; @@ -6578,8 +6888,6 @@ select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -6587,8 +6895,26 @@ select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 30537 (10 rows) +select count(*) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select max(cdate) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7207,6 +7533,22 @@ select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) +select count(ss) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select s, count(ss) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select ss, count(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select max(ss) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7302,6 +7644,41 @@ select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) +select count(*) from aggfns where cint2 is null order by 1; + count +------- + 190 +(1 row) + +select s, count(*) from aggfns where cint2 is null group by s order by 1; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select ss, count(*) from aggfns where cint2 is null group by ss order by 1; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select avg(cint2) from aggfns where cint2 is null order by 1; avg ----- @@ -7327,8 +7704,6 @@ select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; ss | avg ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7336,7 +7711,8 @@ select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select count(cint2) from aggfns where cint2 is null order by 1; count @@ -7363,8 +7739,6 @@ select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; ss | count ----+------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -7372,7 +7746,8 @@ select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 0 8 | 0 9 | 0 -(10 rows) + 11 | 0 +(9 rows) select max(cint2) from aggfns where cint2 is null order by 1; max @@ -7399,8 +7774,6 @@ select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; ss | max ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7408,7 +7781,8 @@ select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select min(cint2) from aggfns where cint2 is null order by 1; min @@ -7435,8 +7809,6 @@ select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; ss | min ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7444,7 +7816,8 @@ select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select stddev(cint2) from aggfns where cint2 is null order by 1; stddev @@ -7471,8 +7844,6 @@ select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; ss | stddev ----+-------- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7480,7 +7851,8 @@ select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select sum(cint2) from aggfns where cint2 is null order by 1; sum @@ -7507,8 +7879,6 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; ss | sum ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7516,5 +7886,6 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 35ec690bf07..b3bad3f812f 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -12,38 +12,57 @@ $$ LANGUAGE SQL; \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, cfloat4 float4, cfloat8 float8, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000::int + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, + (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, + (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t + 4) * 100)::float4 end as cfloat4, + (mix(s + t + 5) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; + alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); select count(compress_chunk(x)) from show_chunks('aggfns') x; +alter table aggfns add column ss int default 11; + +insert into aggfns +select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1; + +select count(compress_chunk(x)) from show_chunks('aggfns') x; + analyze aggfns; ---- Uncomment to generate reference. Note that there are minor discrepancies @@ -72,7 +91,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -99,8 +119,9 @@ where end and case + when variable = '*' then function = 'count' when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') + when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') else true end From 3e06b9224643f3b14f88e284bb019c6c96959016 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:26:57 +0100 Subject: [PATCH 027/242] remove modified simplehash --- tsl/src/import/ts_simplehash.h | 1038 -------------------------------- 1 file changed, 1038 deletions(-) delete mode 100644 tsl/src/import/ts_simplehash.h diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h deleted file mode 100644 index 18c3f73bb6a..00000000000 --- a/tsl/src/import/ts_simplehash.h +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * This file and its contents are licensed under the Apache License 2.0. - * Please see the included NOTICE for copyright information and - * LICENSE-APACHE for a copy of the license. - */ - -/* - * simplehash.h - * - * When included this file generates a "templated" (by way of macros) - * open-addressing hash table implementation specialized to user-defined - * types. - * - * It's probably not worthwhile to generate such a specialized implementation - * for hash tables that aren't performance or space sensitive. - * - * Compared to dynahash, simplehash has the following benefits: - * - * - Due to the "templated" code generation has known structure sizes and no - * indirect function calls (which show up substantially in dynahash - * profiles). These features considerably increase speed for small - * entries. - * - Open addressing has better CPU cache behavior than dynahash's chained - * hashtables. - * - The generated interface is type-safe and easier to use than dynahash, - * though at the cost of more complex setup. - * - Allocates memory in a MemoryContext or another allocator with a - * malloc/free style interface (which isn't easily usable in a shared - * memory context) - * - Does not require the overhead of a separate memory context. - * - * Usage notes: - * - * To generate a hash-table and associated functions for a use case several - * macros have to be #define'ed before this file is included. Including - * the file #undef's all those, so a new hash table can be generated - * afterwards. - * The relevant parameters are: - * - SH_PREFIX - prefix for all symbol names generated. A prefix of 'foo' - * will result in hash table type 'foo_hash' and functions like - * 'foo_insert'/'foo_lookup' and so forth. - * - SH_ELEMENT_TYPE - type of the contained elements - * - SH_KEY_TYPE - type of the hashtable's key - * - SH_DECLARE - if defined function prototypes and type declarations are - * generated - * - SH_DEFINE - if defined function definitions are generated - * - SH_SCOPE - in which scope (e.g. extern, static inline) do function - * declarations reside - * - SH_RAW_ALLOCATOR - if defined, memory contexts are not used; instead, - * use this to allocate bytes. The allocator must zero the returned space. - * - SH_USE_NONDEFAULT_ALLOCATOR - if defined no element allocator functions - * are defined, so you can supply your own - * The following parameters are only relevant when SH_DEFINE is defined: - * - SH_KEY - name of the element in SH_ELEMENT_TYPE containing the hash key - * - SH_EQUAL(table, a, b) - compare two table keys - * - SH_HASH_KEY(table, key) - generate hash for the key - * - SH_STORE_HASH - if defined the hash is stored in the elements - * - SH_GET_HASH(tb, a) - return the field to store the hash in - * - * While SH_STORE_HASH (and subsequently SH_GET_HASH) are optional, because - * the hash table implementation needs to compare hashes to move elements - * (particularly when growing the hash), it's preferable, if possible, to - * store the element's hash in the element's data type. If the hash is so - * stored, the hash table will also compare hashes before calling SH_EQUAL - * when comparing two keys. - * - * For convenience the hash table create functions accept a void pointer - * that will be stored in the hash table type's member private_data. This - * allows callbacks to reference caller provided data. - * - * For examples of usage look at tidbitmap.c (file local definition) and - * execnodes.h/execGrouping.c (exposed declaration, file local - * implementation). - * - * Hash table design: - * - * The hash table design chosen is a variant of linear open-addressing. The - * reason for doing so is that linear addressing is CPU cache & pipeline - * friendly. The biggest disadvantage of simple linear addressing schemes - * are highly variable lookup times due to clustering, and deletions - * leaving a lot of tombstones around. To address these issues a variant - * of "robin hood" hashing is employed. Robin hood hashing optimizes - * chaining lengths by moving elements close to their optimal bucket - * ("rich" elements), out of the way if a to-be-inserted element is further - * away from its optimal position (i.e. it's "poor"). While that can make - * insertions slower, the average lookup performance is a lot better, and - * higher fill factors can be used in a still performant manner. To avoid - * tombstones - which normally solve the issue that a deleted node's - * presence is relevant to determine whether a lookup needs to continue - * looking or is done - buckets following a deleted element are shifted - * backwards, unless they're empty or already at their optimal position. - * - * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * src/include/lib/simplehash.h - */ - -#include "port/pg_bitutils.h" - -/* helpers */ -#define SH_MAKE_PREFIX(a) CppConcat(a, _) -#define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX), name) -#define SH_MAKE_NAME_(a, b) CppConcat(a, b) - -/* name macros for: */ - -/* type declarations */ -#define SH_TYPE SH_MAKE_NAME(hash) -#define SH_ITERATOR SH_MAKE_NAME(iterator) - -/* function declarations */ -#define SH_CREATE SH_MAKE_NAME(create) -#define SH_DESTROY SH_MAKE_NAME(destroy) -#define SH_RESET SH_MAKE_NAME(reset) -#define SH_INSERT SH_MAKE_NAME(insert) -#define SH_INSERT_HASH SH_MAKE_NAME(insert_hash) -#define SH_LOOKUP SH_MAKE_NAME(lookup) -#define SH_LOOKUP_HASH SH_MAKE_NAME(lookup_hash) -#define SH_GROW SH_MAKE_NAME(grow) -#define SH_START_ITERATE SH_MAKE_NAME(start_iterate) -#define SH_START_ITERATE_AT SH_MAKE_NAME(start_iterate_at) -#define SH_ITERATE SH_MAKE_NAME(iterate) -#define SH_ALLOCATE SH_MAKE_NAME(allocate) -#define SH_FREE SH_MAKE_NAME(free) -#define SH_STAT SH_MAKE_NAME(stat) - -/* internal helper functions (no externally visible prototypes) */ -#define SH_COMPUTE_PARAMETERS SH_MAKE_NAME(compute_parameters) -#define SH_NEXT SH_MAKE_NAME(next) -#define SH_PREV SH_MAKE_NAME(prev) -#define SH_DISTANCE_FROM_OPTIMAL SH_MAKE_NAME(distance) -#define SH_INITIAL_BUCKET SH_MAKE_NAME(initial_bucket) -#define SH_ENTRY_HASH SH_MAKE_NAME(entry_hash) -#define SH_INSERT_HASH_INTERNAL SH_MAKE_NAME(insert_hash_internal) -#define SH_LOOKUP_HASH_INTERNAL SH_MAKE_NAME(lookup_hash_internal) - -/* generate forward declarations necessary to use the hash table */ -#ifdef SH_DECLARE - -/* type definitions */ -typedef struct SH_TYPE -{ - /* - * Size of data / bucket array, 64 bits to handle UINT32_MAX sized hash - * tables. Note that the maximum number of elements is lower - * (SH_MAX_FILLFACTOR) - */ - uint64 size; - - /* how many elements have valid contents */ - uint32 members; - - /* mask for bucket and size calculations, based on size */ - uint32 sizemask; - - /* boundary after which to grow hashtable */ - uint32 grow_threshold; - - /* hash buckets */ - SH_ELEMENT_TYPE *restrict data; - -#ifndef SH_RAW_ALLOCATOR - /* memory context to use for allocations */ - MemoryContext ctx; -#endif - - /* user defined data, useful for callbacks */ - void *private_data; -} SH_TYPE; - -typedef struct SH_ITERATOR -{ - uint32 cur; /* current element */ - uint32 end; - bool done; /* iterator exhausted? */ -} SH_ITERATOR; - -/* externally visible function prototypes */ -#ifdef SH_RAW_ALLOCATOR -/* _hash _create(uint32 nelements, void *private_data) */ -SH_SCOPE SH_TYPE *SH_CREATE(uint32 nelements, void *private_data); -#else -/* - * _hash _create(MemoryContext ctx, uint32 nelements, - * void *private_data) - */ -SH_SCOPE SH_TYPE *SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data); -#endif - -/* void _destroy(_hash *tb) */ -SH_SCOPE void SH_DESTROY(SH_TYPE *tb); - -/* void _reset(_hash *tb) */ -SH_SCOPE void SH_RESET(SH_TYPE *tb); - -/* void _grow(_hash *tb, uint64 newsize) */ -SH_SCOPE void SH_GROW(SH_TYPE *tb, uint64 newsize); - -/* *_insert(_hash *tb, key, bool *found) */ -SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found); - -/* - * *_insert_hash(_hash *tb, key, uint32 hash, - * bool *found) - */ -SH_SCOPE SH_ELEMENT_TYPE *SH_INSERT_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash, bool *found); - -/* *_lookup(_hash *tb, key) */ -SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP(SH_TYPE *tb, SH_KEY_TYPE key); - -/* *_lookup_hash(_hash *tb, key, uint32 hash) */ -SH_SCOPE SH_ELEMENT_TYPE *SH_LOOKUP_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash); - -/* void _start_iterate(_hash *tb, _iterator *iter) */ -SH_SCOPE void SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter); - -/* - * void _start_iterate_at(_hash *tb, _iterator *iter, - * uint32 at) - */ -SH_SCOPE void SH_START_ITERATE_AT(SH_TYPE *tb, SH_ITERATOR *iter, uint32 at); - -/* *_iterate(_hash *tb, _iterator *iter) */ -SH_SCOPE SH_ELEMENT_TYPE *SH_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter); - -/* void _stat(_hash *tb */ -SH_SCOPE void SH_STAT(SH_TYPE *tb); - -#endif /* SH_DECLARE */ - -/* generate implementation of the hash table */ -#ifdef SH_DEFINE - -#ifndef SH_RAW_ALLOCATOR -#include "utils/memutils.h" -#endif - -/* max data array size,we allow up to PG_UINT32_MAX buckets, including 0 */ -#define SH_MAX_SIZE (((uint64) PG_UINT32_MAX) + 1) - -/* normal fillfactor, unless already close to maximum */ -#ifndef SH_FILLFACTOR -#define SH_FILLFACTOR (0.9) -#endif -/* increase fillfactor if we otherwise would error out */ -#define SH_MAX_FILLFACTOR (0.98) -/* grow if actual and optimal location bigger than */ -#ifndef SH_GROW_MAX_DIB -#define SH_GROW_MAX_DIB 25 -#endif -/* grow if more than elements to move when inserting */ -#ifndef SH_GROW_MAX_MOVE -#define SH_GROW_MAX_MOVE 150 -#endif -#ifndef SH_GROW_MIN_FILLFACTOR -/* but do not grow due to SH_GROW_MAX_* if below */ -#define SH_GROW_MIN_FILLFACTOR 0.1 -#endif - -#ifdef SH_STORE_HASH -#define SH_COMPARE_KEYS(tb, ahash, akey, b) \ - (ahash == SH_GET_HASH(tb, b) && SH_EQUAL(tb, b->SH_KEY, akey)) -#else -#define SH_COMPARE_KEYS(tb, ahash, akey, b) (SH_EQUAL(tb, b->SH_KEY, akey)) -#endif - -/* - * Wrap the following definitions in include guards, to avoid multiple - * definition errors if this header is included more than once. The rest of - * the file deliberately has no include guards, because it can be included - * with different parameters to define functions and types with non-colliding - * names. - */ -#ifndef SIMPLEHASH_H -#define SIMPLEHASH_H - -#ifdef FRONTEND -#define sh_error(...) pg_fatal(__VA_ARGS__) -#define sh_log(...) pg_log_info(__VA_ARGS__) -#else -#define sh_error(...) elog(ERROR, __VA_ARGS__) -#define sh_log(...) elog(LOG, __VA_ARGS__) -#endif - -#endif - -/* - * Compute sizing parameters for hashtable. Called when creating and growing - * the hashtable. - */ -static inline void -SH_COMPUTE_PARAMETERS(SH_TYPE *tb, uint64 newsize) -{ - uint64 size; - - /* supporting zero sized hashes would complicate matters */ - size = Max(newsize, 2); - - /* round up size to the next power of 2, that's how bucketing works */ - size = pg_nextpower2_64(size); - Assert(size <= SH_MAX_SIZE); - - /* - * Verify that allocation of ->data is possible on this platform, without - * overflowing Size. - */ - if (unlikely((((uint64) sizeof(SH_ELEMENT_TYPE)) * size) >= SIZE_MAX / 2)) - sh_error("hash table too large"); - - /* now set size */ - tb->size = size; - tb->sizemask = (uint32) (size - 1); - - /* - * Compute the next threshold at which we need to grow the hash table - * again. - */ - if (tb->size == SH_MAX_SIZE) - tb->grow_threshold = ((double) tb->size) * SH_MAX_FILLFACTOR; - else - tb->grow_threshold = ((double) tb->size) * SH_FILLFACTOR; -} - -/* return the optimal bucket for the hash */ -static pg_attribute_always_inline uint32 -SH_INITIAL_BUCKET(SH_TYPE *tb, uint32 hash) -{ - return hash & tb->sizemask; -} - -/* return next bucket after the current, handling wraparound */ -static inline uint32 -SH_NEXT(SH_TYPE *tb, uint32 curelem, uint32 startelem) -{ - curelem = (curelem + 1) & tb->sizemask; - - Assert(curelem != startelem); - - return curelem; -} - -/* return bucket before the current, handling wraparound */ -static inline uint32 -SH_PREV(SH_TYPE *tb, uint32 curelem, uint32 startelem) -{ - curelem = (curelem - 1) & tb->sizemask; - - Assert(curelem != startelem); - - return curelem; -} - -/* return distance between bucket and its optimal position */ -static inline uint32 -SH_DISTANCE_FROM_OPTIMAL(SH_TYPE *tb, uint32 optimal, uint32 bucket) -{ - if (optimal <= bucket) - return bucket - optimal; - else - return (tb->size + bucket) - optimal; -} - -static inline uint32 -SH_ENTRY_HASH(SH_TYPE *tb, SH_ELEMENT_TYPE *entry) -{ -#ifdef SH_STORE_HASH - return SH_GET_HASH(tb, entry); -#else - return SH_HASH_KEY(tb, entry->SH_KEY); -#endif -} - -/* default memory allocator function */ -static inline void *SH_ALLOCATE(SH_TYPE *type, Size size); -static inline void SH_FREE(SH_TYPE *type, void *pointer); - -#ifndef SH_USE_NONDEFAULT_ALLOCATOR - -/* default memory allocator function */ -static inline void * -SH_ALLOCATE(SH_TYPE *type, Size size) -{ -#ifdef SH_RAW_ALLOCATOR - return SH_RAW_ALLOCATOR(size); -#else - return MemoryContextAllocExtended(type->ctx, size, MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); -#endif -} - -/* default memory free function */ -static inline void -SH_FREE(SH_TYPE *type, void *pointer) -{ - pfree(pointer); -} - -#endif - -/* - * Create a hash table with enough space for `nelements` distinct members. - * Memory for the hash table is allocated from the passed-in context. If - * desired, the array of elements can be allocated using a passed-in allocator; - * this could be useful in order to place the array of elements in a shared - * memory, or in a context that will outlive the rest of the hash table. - * Memory other than for the array of elements will still be allocated from - * the passed-in context. - */ -#ifdef SH_RAW_ALLOCATOR -SH_SCOPE SH_TYPE * -SH_CREATE(uint32 nelements, void *private_data) -#else -SH_SCOPE SH_TYPE * -SH_CREATE(MemoryContext ctx, uint32 nelements, void *private_data) -#endif -{ - SH_TYPE *tb; - uint64 size; - -#ifdef SH_RAW_ALLOCATOR - tb = (SH_TYPE *) SH_RAW_ALLOCATOR(sizeof(SH_TYPE)); -#else - tb = (SH_TYPE *) MemoryContextAllocZero(ctx, sizeof(SH_TYPE)); - tb->ctx = ctx; -#endif - tb->private_data = private_data; - - /* increase nelements by fillfactor, want to store nelements elements */ - size = Min((double) SH_MAX_SIZE, ((double) nelements) / SH_FILLFACTOR); - - SH_COMPUTE_PARAMETERS(tb, size); - - tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size); - - return tb; -} - -/* destroy a previously created hash table */ -SH_SCOPE void -SH_DESTROY(SH_TYPE *tb) -{ - SH_FREE(tb, tb->data); - pfree(tb); -} - -/* reset the contents of a previously created hash table */ -SH_SCOPE void -SH_RESET(SH_TYPE *tb) -{ - memset(tb->data, 0, sizeof(SH_ELEMENT_TYPE) * tb->size); - tb->members = 0; -} - -/* - * Grow a hash table to at least `newsize` buckets. - * - * Usually this will automatically be called by insertions/deletions, when - * necessary. But resizing to the exact input size can be advantageous - * performance-wise, when known at some point. - */ -SH_SCOPE void -SH_GROW(SH_TYPE *tb, uint64 newsize) -{ - uint64 oldsize = tb->size; - SH_ELEMENT_TYPE *olddata = tb->data; - SH_ELEMENT_TYPE *newdata; - uint32 i; - uint32 startelem = 0; - uint32 copyelem; - - Assert(oldsize == pg_nextpower2_64(oldsize)); - Assert(oldsize != SH_MAX_SIZE); - Assert(oldsize < newsize); - - /* compute parameters for new table */ - SH_COMPUTE_PARAMETERS(tb, newsize); - - tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, sizeof(SH_ELEMENT_TYPE) * tb->size); - - newdata = tb->data; - - /* - * Copy entries from the old data to newdata. We theoretically could use - * SH_INSERT here, to avoid code duplication, but that's more general than - * we need. We neither want tb->members increased, nor do we need to do - * deal with deleted elements, nor do we need to compare keys. So a - * special-cased implementation is lot faster. As resizing can be time - * consuming and frequent, that's worthwhile to optimize. - * - * To be able to simply move entries over, we have to start not at the - * first bucket (i.e olddata[0]), but find the first bucket that's either - * empty, or is occupied by an entry at its optimal position. Such a - * bucket has to exist in any table with a load factor under 1, as not all - * buckets are occupied, i.e. there always has to be an empty bucket. By - * starting at such a bucket we can move the entries to the larger table, - * without having to deal with conflicts. - */ - - /* search for the first element in the hash that's not wrapped around */ - for (i = 0; i < oldsize; i++) - { - SH_ELEMENT_TYPE *oldentry = &olddata[i]; - uint32 hash; - uint32 optimal; - - if (SH_ENTRY_EMPTY(oldentry)) - { - startelem = i; - break; - } - - hash = SH_ENTRY_HASH(tb, oldentry); - optimal = SH_INITIAL_BUCKET(tb, hash); - - if (optimal == i) - { - startelem = i; - break; - } - } - - /* and copy all elements in the old table */ - copyelem = startelem; - for (i = 0; i < oldsize; i++) - { - SH_ELEMENT_TYPE *oldentry = &olddata[copyelem]; - - if (!SH_ENTRY_EMPTY(oldentry)) - { - uint32 hash; - uint32 startelem; - uint32 curelem; - SH_ELEMENT_TYPE *newentry; - - hash = SH_ENTRY_HASH(tb, oldentry); - startelem = SH_INITIAL_BUCKET(tb, hash); - curelem = startelem; - - /* find empty element to put data into */ - while (true) - { - newentry = &newdata[curelem]; - - if (SH_ENTRY_EMPTY(newentry)) - { - break; - } - - curelem = SH_NEXT(tb, curelem, startelem); - } - - /* copy entry to new slot */ - memcpy(newentry, oldentry, sizeof(SH_ELEMENT_TYPE)); - } - - /* can't use SH_NEXT here, would use new size */ - copyelem++; - if (copyelem >= oldsize) - { - copyelem = 0; - } - } - - SH_FREE(tb, olddata); -} - -/* - * This is a separate static inline function, so it can be reliably be inlined - * into its wrapper functions even if SH_SCOPE is extern. - */ -static pg_attribute_always_inline SH_ELEMENT_TYPE * -SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool *found) -{ - /* - * We do the grow check even if the key is actually present, to avoid - * doing the check inside the loop. This also lets us avoid having to - * re-find our position in the hashtable after resizing. - * - * Note that this also reached when resizing the table due to - * SH_GROW_MAX_DIB / SH_GROW_MAX_MOVE. - */ - if (unlikely(tb->members >= tb->grow_threshold)) - { - if (unlikely(tb->size == SH_MAX_SIZE)) - sh_error("hash table size exceeded"); - - /* - * When optimizing, it can be very useful to print these out. - */ - /* SH_STAT(tb); */ - SH_GROW(tb, tb->size * 2); - /* SH_STAT(tb); */ - } - - SH_ELEMENT_TYPE *restrict data = tb->data; - - /* perform insert, start bucket search at optimal location */ - const uint32 startelem = SH_INITIAL_BUCKET(tb, hash); - uint32 curelem = startelem; - uint32 insertdist = 0; - while (true) - { - SH_ELEMENT_TYPE *entry = &data[curelem]; - - /* any empty bucket can directly be used */ - if (SH_ENTRY_EMPTY(entry)) - { - tb->members++; - entry->SH_KEY = key; -#ifdef SH_STORE_HASH - SH_GET_HASH(tb, entry) = hash; -#endif - *found = false; - return entry; - } - - /* - * If the bucket is not empty, we either found a match (in which case - * we're done), or we have to decide whether to skip over or move the - * colliding entry. When the colliding element's distance to its - * optimal position is smaller than the to-be-inserted entry's, we - * shift the colliding entry (and its followers) forward by one. - */ - - if (SH_COMPARE_KEYS(tb, hash, key, entry)) - { - Assert(!SH_ENTRY_EMPTY(entry)); - *found = true; - return entry; - } - - const uint32 curhash = SH_ENTRY_HASH(tb, entry); - const uint32 curoptimal = SH_INITIAL_BUCKET(tb, curhash); - const uint32 curdist = SH_DISTANCE_FROM_OPTIMAL(tb, curoptimal, curelem); - - if (insertdist > curdist) - { - /* We're going to insert at this position. */ - break; - } - - curelem = SH_NEXT(tb, curelem, startelem); - insertdist++; - - /* - * To avoid negative consequences from overly imbalanced hashtables, - * grow the hashtable if collisions lead to large runs. The most - * likely cause of such imbalance is filling a (currently) small - * table, from a currently big one, in hash-table order. Don't grow - * if the hashtable would be too empty, to prevent quick space - * explosion for some weird edge cases. - */ - if (unlikely(insertdist > SH_GROW_MAX_DIB) && - ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) - { - SH_GROW(tb, tb->size * 2); - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); - } - } - - /* Actually insert. */ - SH_ELEMENT_TYPE *entry = &data[curelem]; - SH_ELEMENT_TYPE *lastentry = entry; - uint32 emptyelem = curelem; - int32 emptydist = 0; - - /* find next empty bucket */ - while (true) - { - SH_ELEMENT_TYPE *emptyentry; - - emptyelem = SH_NEXT(tb, emptyelem, startelem); - emptyentry = &data[emptyelem]; - - if (SH_ENTRY_EMPTY(emptyentry)) - { - lastentry = emptyentry; - break; - } - - /* - * To avoid negative consequences from overly imbalanced - * hashtables, grow the hashtable if collisions would require - * us to move a lot of entries. The most likely cause of such - * imbalance is filling a (currently) small table, from a - * currently big one, in hash-table order. Don't grow if the - * hashtable would be too empty, to prevent quick space - * explosion for some weird edge cases. - */ - if (unlikely(++emptydist > SH_GROW_MAX_MOVE) && - ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) - { - SH_GROW(tb, tb->size * 2); - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); - } - } - - /* shift forward, starting at last occupied element */ - - /* - * TODO: This could be optimized to be one memcpy in many cases, - * excepting wrapping around at the end of ->data. Hasn't shown up - * in profiles so far though. - */ - uint32 moveelem = emptyelem; - while (moveelem != curelem) - { - SH_ELEMENT_TYPE *moveentry; - - moveelem = SH_PREV(tb, moveelem, startelem); - moveentry = &data[moveelem]; - - memcpy(lastentry, moveentry, sizeof(SH_ELEMENT_TYPE)); - lastentry = moveentry; - } - - /* and fill the now empty spot */ - tb->members++; - - entry->SH_KEY = key; -#ifdef SH_STORE_HASH - SH_GET_HASH(tb, entry) = hash; -#endif - *found = false; - return entry; -} - -/* - * Insert the key key into the hash-table, set *found to true if the key - * already exists, false otherwise. Returns the hash-table entry in either - * case. - */ -static pg_attribute_always_inline SH_ELEMENT_TYPE * -SH_INSERT(SH_TYPE *tb, SH_KEY_TYPE key, bool *found) -{ - uint32 hash = SH_HASH_KEY(tb, key); - - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); -} - -/* - * Insert the key key into the hash-table using an already-calculated - * hash. Set *found to true if the key already exists, false - * otherwise. Returns the hash-table entry in either case. - */ -SH_SCOPE SH_ELEMENT_TYPE * -SH_INSERT_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash, bool *found) -{ - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); -} - -/* - * This is a separate static inline function, so it can be reliably be inlined - * into its wrapper functions even if SH_SCOPE is extern. - */ -static inline SH_ELEMENT_TYPE * -SH_LOOKUP_HASH_INTERNAL(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash) -{ - const uint32 startelem = SH_INITIAL_BUCKET(tb, hash); - uint32 curelem = startelem; - - while (true) - { - SH_ELEMENT_TYPE *entry = &tb->data[curelem]; - - if (SH_ENTRY_EMPTY(entry)) - { - return NULL; - } - - Assert(!SH_ENTRY_EMPTY(entry)); - - if (SH_COMPARE_KEYS(tb, hash, key, entry)) - return entry; - - /* - * TODO: we could stop search based on distance. If the current - * buckets's distance-from-optimal is smaller than what we've skipped - * already, the entry doesn't exist. Probably only do so if - * SH_STORE_HASH is defined, to avoid re-computing hashes? - */ - - curelem = SH_NEXT(tb, curelem, startelem); - } -} - -/* - * Lookup up entry in hash table. Returns NULL if key not present. - */ -SH_SCOPE SH_ELEMENT_TYPE * -SH_LOOKUP(SH_TYPE *tb, SH_KEY_TYPE key) -{ - uint32 hash = SH_HASH_KEY(tb, key); - - return SH_LOOKUP_HASH_INTERNAL(tb, key, hash); -} - -/* - * Lookup up entry in hash table using an already-calculated hash. - * - * Returns NULL if key not present. - */ -SH_SCOPE SH_ELEMENT_TYPE * -SH_LOOKUP_HASH(SH_TYPE *tb, SH_KEY_TYPE key, uint32 hash) -{ - return SH_LOOKUP_HASH_INTERNAL(tb, key, hash); -} - -/* - * Initialize iterator. - */ -SH_SCOPE void -SH_START_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter) -{ - uint64 startelem = PG_UINT64_MAX; - - /* - * Search for the first empty element. As deletions during iterations are - * supported, we want to start/end at an element that cannot be affected - * by elements being shifted. - */ - for (uint32 i = 0; i < tb->size; i++) - { - SH_ELEMENT_TYPE *entry = &tb->data[i]; - - if (SH_ENTRY_EMPTY(entry)) - { - startelem = i; - break; - } - } - - /* we should have found an empty element */ - Assert(startelem < SH_MAX_SIZE); - - /* - * Iterate backwards, that allows the current element to be deleted, even - * if there are backward shifts - */ - iter->cur = startelem; - iter->end = iter->cur; - iter->done = false; -} - -/* - * Initialize iterator to a specific bucket. That's really only useful for - * cases where callers are partially iterating over the hashspace, and that - * iteration deletes and inserts elements based on visited entries. Doing that - * repeatedly could lead to an unbalanced keyspace when always starting at the - * same position. - */ -SH_SCOPE void -SH_START_ITERATE_AT(SH_TYPE *tb, SH_ITERATOR *iter, uint32 at) -{ - /* - * Iterate backwards, that allows the current element to be deleted, even - * if there are backward shifts. - */ - iter->cur = at & tb->sizemask; /* ensure at is within a valid range */ - iter->end = iter->cur; - iter->done = false; -} - -/* - * Iterate over all entries in the hash-table. Return the next occupied entry, - * or NULL if done. - * - * During iteration the current entry in the hash table may be deleted, - * without leading to elements being skipped or returned twice. Additionally - * the rest of the table may be modified (i.e. there can be insertions or - * deletions), but if so, there's neither a guarantee that all nodes are - * visited at least once, nor a guarantee that a node is visited at most once. - */ -SH_SCOPE SH_ELEMENT_TYPE * -SH_ITERATE(SH_TYPE *tb, SH_ITERATOR *iter) -{ - while (!iter->done) - { - SH_ELEMENT_TYPE *elem; - - elem = &tb->data[iter->cur]; - - /* next element in backward direction */ - iter->cur = (iter->cur - 1) & tb->sizemask; - - if ((iter->cur & tb->sizemask) == (iter->end & tb->sizemask)) - iter->done = true; - if (!SH_ENTRY_EMPTY(elem)) - { - return elem; - } - } - - return NULL; -} - -/* - * Report some statistics about the state of the hashtable. For - * debugging/profiling purposes only. - */ -SH_SCOPE void -SH_STAT(SH_TYPE *tb) -{ - uint32 max_chain_length = 0; - uint32 total_chain_length = 0; - double avg_chain_length; - double fillfactor; - uint32 i; - - uint32 *collisions = (uint32 *) palloc0(tb->size * sizeof(uint32)); - uint32 total_collisions = 0; - uint32 max_collisions = 0; - double avg_collisions; - - for (i = 0; i < tb->size; i++) - { - uint32 hash; - uint32 optimal; - uint32 dist; - SH_ELEMENT_TYPE *elem; - - elem = &tb->data[i]; - - if (SH_ENTRY_EMPTY(elem)) - continue; - - hash = SH_ENTRY_HASH(tb, elem); - optimal = SH_INITIAL_BUCKET(tb, hash); - dist = SH_DISTANCE_FROM_OPTIMAL(tb, optimal, i); - - if (dist > max_chain_length) - max_chain_length = dist; - total_chain_length += dist; - - collisions[optimal]++; - } - - for (i = 0; i < tb->size; i++) - { - uint32 curcoll = collisions[i]; - - if (curcoll == 0) - continue; - - /* single contained element is not a collision */ - curcoll--; - total_collisions += curcoll; - if (curcoll > max_collisions) - max_collisions = curcoll; - } - - /* large enough to be worth freeing, even if just used for debugging */ - pfree(collisions); - - if (tb->members > 0) - { - fillfactor = tb->members / ((double) tb->size); - avg_chain_length = ((double) total_chain_length) / tb->members; - avg_collisions = ((double) total_collisions) / tb->members; - } - else - { - fillfactor = 0; - avg_chain_length = 0; - avg_collisions = 0; - } - - sh_log("size: " UINT64_FORMAT - ", members: %u, filled: %f, total chain: %u, max chain: %u, avg chain: %f, " - "total_collisions: %u, max_collisions: %u, avg_collisions: %f", - tb->size, - tb->members, - fillfactor, - total_chain_length, - max_chain_length, - avg_chain_length, - total_collisions, - max_collisions, - avg_collisions); -} - -#endif /* SH_DEFINE */ - -/* undefine external parameters, so next hash table can be defined */ -#undef SH_PREFIX -#undef SH_KEY_TYPE -#undef SH_KEY -#undef SH_ELEMENT_TYPE -#undef SH_HASH_KEY -#undef SH_SCOPE -#undef SH_DECLARE -#undef SH_DEFINE -#undef SH_GET_HASH -#undef SH_STORE_HASH -#undef SH_USE_NONDEFAULT_ALLOCATOR -#undef SH_EQUAL - -/* undefine locally declared macros */ -#undef SH_MAKE_PREFIX -#undef SH_MAKE_NAME -#undef SH_MAKE_NAME_ -#undef SH_FILLFACTOR -#undef SH_MAX_FILLFACTOR -#undef SH_GROW_MAX_DIB -#undef SH_GROW_MAX_MOVE -#undef SH_GROW_MIN_FILLFACTOR -#undef SH_MAX_SIZE - -/* types */ -#undef SH_TYPE -#undef SH_ITERATOR - -/* external function names */ -#undef SH_CREATE -#undef SH_DESTROY -#undef SH_RESET -#undef SH_INSERT -#undef SH_INSERT_HASH -#undef SH_LOOKUP -#undef SH_LOOKUP_HASH -#undef SH_GROW -#undef SH_START_ITERATE -#undef SH_START_ITERATE_AT -#undef SH_ITERATE -#undef SH_ALLOCATE -#undef SH_FREE -#undef SH_STAT - -/* internal function names */ -#undef SH_COMPUTE_PARAMETERS -#undef SH_COMPARE_KEYS -#undef SH_INITIAL_BUCKET -#undef SH_NEXT -#undef SH_PREV -#undef SH_DISTANCE_FROM_OPTIMAL -#undef SH_ENTRY_HASH -#undef SH_INSERT_HASH_INTERNAL -#undef SH_LOOKUP_HASH_INTERNAL From a7942ed5b2636920b1bb2decfcd80d41ba2b2b65 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:59:02 +0100 Subject: [PATCH 028/242] offsets --- .../nodes/vector_agg/grouping_policy_hash.c | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d2aa6870335..693ec753f79 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -69,7 +69,6 @@ typedef struct #define SH_SCOPE static inline #define SH_DECLARE #define SH_DEFINE -#define SH_ENTRY_EMPTY(entry) (entry->agg_state_index == 0) #include struct h_hash; @@ -92,9 +91,20 @@ typedef struct */ MemoryContext agg_extra_mctx; - uint64 aggstate_bytes_per_key; - uint64 allocated_aggstate_rows; + /* + * Temporary storage of aggregate state offsets for a given batch. We keep + * it in the policy because it is too big to keep on stack, and we don't + * want to reallocate it each batch. + */ + uint32 *offsets; + uint64 num_allocated_offsets; + + /* + * Storage of aggregate function states, each List entry is the array of + * states for the respective function from agg_defs. + */ List *per_agg_states; + uint64 allocated_aggstate_rows; uint64 stat_input_total_rows; uint64 stat_input_valid_rows; @@ -112,13 +122,11 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->agg_defs = agg_defs; policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - policy->allocated_aggstate_rows = 1000; + policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; ListCell *lc; foreach (lc, agg_defs) { VectorAggDef *agg_def = lfirst(lc); - policy->aggstate_bytes_per_key += agg_def->func.state_bytes; - policy->per_agg_states = lappend(policy->per_agg_states, palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); @@ -455,6 +463,17 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) const uint64_t *restrict filter = batch_state->vector_qual_result; const int n = batch_state->total_batch_rows; + /* + * Initialize the array for storing the aggregate state offsets corresponding + * to a given batch row. + */ + if ((size_t) n > policy->num_allocated_offsets) + { + policy->num_allocated_offsets = n; + policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + } + memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); + /* * For the partial aggregation node, the grouping columns are always in the * output, so we don't have to separately look at the list of the grouping @@ -508,8 +527,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Match rows to aggregation states using a hash table. */ - uint32 offsets[1000] = { 0 }; - Assert((size_t) end_row <= sizeof(offsets) / sizeof(*offsets)); + Assert((size_t) end_row <= policy->num_allocated_offsets); switch ((int) key_column->decompression_type) { case DT_Scalar: @@ -519,7 +537,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 8: next_unused_state_index = fill_offsets_arrow_fixed_8(policy, @@ -528,7 +546,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 4: next_unused_state_index = fill_offsets_arrow_fixed_4(policy, @@ -537,7 +555,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 2: next_unused_state_index = fill_offsets_arrow_fixed_2(policy, @@ -546,7 +564,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; default: Assert(false); @@ -592,7 +610,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) end_row, lfirst(aggdeflc), lfirst(aggstatelc), - offsets, + policy->offsets, policy->agg_extra_mctx); } } From 6fb517f01a9d1bd6591d422f6415d6fbc3359433 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:02:45 +0100 Subject: [PATCH 029/242] cleanup --- .../workflows/linux-32bit-build-and-test.yaml | 4 +- tsl/src/nodes/vector_agg/exec.c | 7 +- .../nodes/vector_agg/grouping_policy_hash.c | 70 +++++++++++++------ tsl/src/nodes/vector_agg/plan.c | 15 +++- 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index 7a261a1445d..ed3afc0be1e 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -47,7 +47,9 @@ jobs: CC: clang-14 CXX: clang++-14 DEBIAN_FRONTEND: noninteractive - IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler*" + # vectorized_aggregation has different output on i386 because int8 is by + # reference and currently it cannot be used for vectorized hash grouping. + IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* vectorized_aggregation" SKIPS: chunk_adaptive histogram_test-* EXTENSIONS: "postgres_fdw test_decoding" strategy: diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index fa4dc703d42..a6ebae5de51 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -122,7 +122,6 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } } - /// List *grouping_child_output_offsets = linitial(cscan->custom_private); if (list_length(vector_agg_state->output_grouping_columns) == 1) { GroupingColumn *col = @@ -132,6 +131,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && (size_t) desc->value_bytes <= sizeof(Datum)) { + /* + * Hash grouping by a single fixed-size by-value compressed column. + */ vector_agg_state->grouping = create_grouping_policy_hash(vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); @@ -140,6 +142,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) if (vector_agg_state->grouping == NULL) { + /* + * Per-batch grouping. + */ vector_agg_state->grouping = create_grouping_policy_batch(vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 693ec753f79..1381755b932 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -5,9 +5,8 @@ */ /* - * This grouping policy aggregates entire compressed batches. It can be used to - * aggregate with no grouping, or to produce partial aggregates per each batch - * to group by segmentby columns. + * This grouping policy groups the rows using a hash table. Currently it only + * supports a single fixed-size by-value compressed column that fits into a Datum. */ #include @@ -20,6 +19,8 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#define DEBUG_LOG(MSG, ...) elog(DEBUG3, MSG, __VA_ARGS__) + /* * We can use crc32 as a hash function, it has bad properties but takes only one * cycle, which is why it is sometimes used in the existing hash table @@ -75,14 +76,33 @@ struct h_hash; typedef struct { + /* + * We're using data inheritance from the GroupingPolicy. + */ GroupingPolicy funcs; + List *agg_defs; List *output_grouping_columns; - bool partial_per_batch; + + /* + * The hash table we use for grouping. + */ struct h_hash *table; - bool have_null_key; - struct h_iterator iter; + + /* + * We have to track whether we are in the mode of returning the partial + * aggregation results, and also use a hash table iterator to track our + * progress between emit() calls. + */ bool returning_results; + struct h_iterator iter; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and it has a reserved aggregate state index 1. We also reset this + * flag after we output the null key during iteration. + */ + bool have_null_key; /* * A memory context for aggregate functions to allocate additional data, @@ -93,19 +113,23 @@ typedef struct /* * Temporary storage of aggregate state offsets for a given batch. We keep - * it in the policy because it is too big to keep on stack, and we don't - * want to reallocate it each batch. + * it in the policy because it is potentially too big to keep on stack, and + * we don't want to reallocate it each batch. */ uint32 *offsets; uint64 num_allocated_offsets; /* * Storage of aggregate function states, each List entry is the array of - * states for the respective function from agg_defs. + * states for the respective function from agg_defs. The state index 0 is + * invalid, and the state index 1 is reserved for a null key. */ List *per_agg_states; uint64 allocated_aggstate_rows; + /* + * Some statistics for debugging. + */ uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; @@ -200,7 +224,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e { /* * Scalar argument, or count(*). The latter has an optimized - * implementation for this case. + * implementation. */ if (agg_def->func.agg_many_scalar != NULL) { @@ -266,6 +290,7 @@ fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, offsets[row] = 1; } } + return next_unused_state_index; } @@ -488,7 +513,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) { /* * If we have a highly selective filter, it's easy to skip the rows for - * which the entire filter bitmap words are zero. + * which the entire words of the filter bitmap are zero. */ if (filter) { @@ -641,15 +666,20 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) { policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); - // fprintf(stderr, - // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld - // aggctx bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, - // policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, - // policy->table->members - // + policy->have_null_key, policy->stat_input_valid_rows / - //(float) (policy->table->members + policy->have_null_key), - // MemoryContextMemAllocated(policy->table->ctx, - // false), MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + + const float keys = policy->table->members + policy->have_null_key; + if (keys > 0) + { + DEBUG_LOG("spill after %ld input %ld valid %ld bulk filtered %.0f keys %f ratio %ld " + "aggctx bytes %ld aggstate bytes", + policy->stat_input_total_rows, + policy->stat_input_valid_rows, + policy->stat_bulk_filtered_rows, + keys, + policy->stat_input_valid_rows / keys, + MemoryContextMemAllocated(policy->table->ctx, false), + MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + } } HashEntry null_key_entry = { .agg_state_index = 1 }; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index f358d7a5a28..8c42cb43906 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -313,17 +313,25 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) /* * Whether we can perform vectorized aggregation with a given grouping. - * Currently supports either no grouping or grouping by segmentby columns. */ static bool can_vectorize_grouping(Agg *agg, CustomScan *custom) { + /* + * We support vectorized aggregation without grouping. + */ if (agg->numCols == 0) { return true; } - if (agg->numCols == 1) + /* + * We support hashed vectorized grouping by one fixed-size by-value + * compressed column. + * We cannot use it when the plan has GroupAggregate because the + * latter requires sorted output. + */ + if (agg->numCols == 1 && agg->aggstrategy == AGG_HASHED) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); TargetEntry *entry = list_nth(agg->plan.targetlist, offset); @@ -342,6 +350,9 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) } } + /* + * We support grouping by any number of columns if all of them are segmentby. + */ for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); From ffb28cf7143530a0089c762696daa7c7dbb3459b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:05:04 +0100 Subject: [PATCH 030/242] changelog --- .unreleased/vectorized-grouping-one-fixed | 1 + 1 file changed, 1 insertion(+) create mode 100644 .unreleased/vectorized-grouping-one-fixed diff --git a/.unreleased/vectorized-grouping-one-fixed b/.unreleased/vectorized-grouping-one-fixed new file mode 100644 index 00000000000..47f74a45210 --- /dev/null +++ b/.unreleased/vectorized-grouping-one-fixed @@ -0,0 +1 @@ +Implements: #7341 Vectorized aggregation with grouping by one fixed-size by-value compressed column (such as arithmetic types). From 778ca97d906341304ef0934b73c8f2f8537167f5 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:18:10 +0100 Subject: [PATCH 031/242] cleanup --- .../nodes/vector_agg/function/agg_const_helper.c | 16 +++++++++++----- .../nodes/vector_agg/function/agg_many_helper.c | 6 ++++++ .../vector_agg/function/float48_accum_single.c | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_const_helper.c b/tsl/src/nodes/vector_agg/function/agg_const_helper.c index c83d38526be..4823a789096 100644 --- a/tsl/src/nodes/vector_agg/function/agg_const_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_const_helper.c @@ -11,14 +11,20 @@ * implementation otherwise. */ static void -FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int nn, +FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int n, MemoryContext agg_extra_mctx) { - const uint64 valid = constisnull ? 0 : 1; - const CTYPE value = valid ? DATUM_TO_CTYPE(constvalue) : 0; + if (constisnull) + { + return; + } + + const CTYPE value = DATUM_TO_CTYPE(constvalue); - for (int i = 0; i < nn; i++) + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); + for (int i = 0; i < n; i++) { - FUNCTION_NAME(vector_impl)(agg_state, 1, &value, &valid, NULL, agg_extra_mctx); + FUNCTION_NAME(one)(agg_state, value); } + MemoryContextSwitchTo(old); } diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_helper.c index f8517c4328a..dcf75622e4a 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_helper.c @@ -4,6 +4,12 @@ * LICENSE-TIMESCALE for a copy of the license. */ +/* + * A generic implementation of adding the given batch to many aggregate function + * states with given offsets. Used for hash aggregation, and builds on the + * FUNCTION_NAME(one) function, which adds one passing non-null row to the given + * aggregate function state. + */ static void FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index 6a07c28e238..bb411d9d5c2 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -203,7 +203,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const /* * Vector registers can be up to 512 bits wide. */ -#define UNROLL_SIZE ((int) ((512 / 8) / sizeof(CTYPE))) +#define UNROLL_SIZE ((int) (512 / 8 / sizeof(CTYPE))) /* * Each inner iteration works with its own accumulators to avoid data From ef3847af40c15998eb595223c751ec69288a4789 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:18:23 +0100 Subject: [PATCH 032/242] benchmark vectorized hash grouping (simple) (2024-10-15 no. 12) From 1409c741d8c28fd2aaa94778b798ff50d4ffbc83 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 18:27:47 +0100 Subject: [PATCH 033/242] 32-bit --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 1381755b932..8b387e2e900 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -19,7 +19,15 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#ifdef USE_FLOAT8_BYVAL #define DEBUG_LOG(MSG, ...) elog(DEBUG3, MSG, __VA_ARGS__) +#else +/* + * On 32-bit platforms we'd have to use the cross-platform int width printf + * specifiers which are really unreadable. + */ +#define DEBUG_LOG(...) +#endif /* * We can use crc32 as a hash function, it has bad properties but takes only one From 514ae96b12709a0d3a702257cb5f6c2bb4b5097f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:30:22 +0100 Subject: [PATCH 034/242] some renames --- ...many_helper.c => agg_many_vector_helper.c} | 4 ++-- ...agg_const_helper.c => agg_scalar_helper.c} | 4 ++-- .../function/float48_accum_single.c | 8 +++---- tsl/src/nodes/vector_agg/function/functions.c | 6 ++--- tsl/src/nodes/vector_agg/function/functions.h | 22 +++++++++++++------ .../vector_agg/function/int128_accum_single.c | 8 +++---- .../function/int24_avg_accum_single.c | 8 +++---- .../vector_agg/function/int24_sum_single.c | 8 +++---- .../function/minmax_arithmetic_single.c | 8 +++---- .../vector_agg/function/sum_float_single.c | 8 +++---- .../nodes/vector_agg/grouping_policy_batch.c | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 5 +++-- 12 files changed, 50 insertions(+), 41 deletions(-) rename tsl/src/nodes/vector_agg/function/{agg_many_helper.c => agg_many_vector_helper.c} (85%) rename tsl/src/nodes/vector_agg/function/{agg_const_helper.c => agg_scalar_helper.c} (85%) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c similarity index 85% rename from tsl/src/nodes/vector_agg/function/agg_many_helper.c rename to tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index dcf75622e4a..47916e29131 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -11,8 +11,8 @@ * aggregate function state. */ static void -FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, - const ArrowArray *vector, MemoryContext agg_extra_mctx) +FUNCTION_NAME(many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) { MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); const CTYPE *values = vector->buffers[1]; diff --git a/tsl/src/nodes/vector_agg/function/agg_const_helper.c b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c similarity index 85% rename from tsl/src/nodes/vector_agg/function/agg_const_helper.c rename to tsl/src/nodes/vector_agg/function/agg_scalar_helper.c index 4823a789096..0d81abfcf65 100644 --- a/tsl/src/nodes/vector_agg/function/agg_const_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c @@ -11,8 +11,8 @@ * implementation otherwise. */ static void -FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +FUNCTION_NAME(scalar)(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { if (constisnull) { diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index bb411d9d5c2..73743c5aa1a 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -319,17 +319,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->Sx = newSx; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), .agg_init = FUNCTION_NAME(init), .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #undef UPDATE #undef COMBINE diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 4dea3c8c90e..826dd02bfa9 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -72,7 +72,7 @@ count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, - .agg_const = count_star_const, + .agg_scalar = count_star_const, .agg_emit = count_emit, .agg_many_scalar = count_star_many_scalar, }; @@ -152,9 +152,9 @@ VectorAggFunctions count_any_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_emit = count_emit, - .agg_const = count_any_const, + .agg_scalar = count_any_const, .agg_vector = count_any_vector, - .agg_many = count_any_many, + .agg_many_vector = count_any_many, }; /* diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 9d5539fb244..70785a5d802 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -23,18 +23,26 @@ typedef struct void (*agg_vector)(void *restrict agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx); - /* Aggregate a constant (like segmentby or column with default value). */ - void (*agg_const)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx); - - void (*agg_many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); + /* Aggregate a scalar value, like segmentby or column with default value. */ + void (*agg_scalar)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx); + /* + * Add the rows of the given arrow array to aggregate function states given + * by the respecitve offsets. + */ + void (*agg_many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); + + /* + * Same as above, but for a scalar argument. This is mostly important for + * count(*) and can be NULL. + */ void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx); - /* Emit a partial result. */ + /* Emit a partial aggregation result. */ void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index bf0f90e5044..bf60e64cd12 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -110,17 +110,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) #endif } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), .agg_init = FUNCTION_NAME(init), .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 2051fe006d5..62ebb5ad52b 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -38,17 +38,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->sum += value; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24AvgAccumState), .agg_init = int24_avg_accum_init, .agg_emit = int24_avg_accum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index c96a45fc96f..8bfb15676ae 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -61,17 +61,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) typedef Int24SumState FUNCTION_NAME(state); -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24SumState), .agg_init = int_sum_init, .agg_emit = int_sum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index 127b5176291..6d110fcdc34 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -58,17 +58,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) } } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(MinMaxState), .agg_init = minmax_init, .agg_emit = minmax_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 41565feabfc..6b56b433c89 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -90,17 +90,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->result += value; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FloatSumState), .agg_init = float_sum_init, .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 23d695cedc1..f7c7db9ee46 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -146,7 +146,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de */ Assert(n > 0); - agg_def->func.agg_const(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 8b387e2e900..fdcf50e41cd 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -226,7 +226,8 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func.agg_many(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); + agg_def->func + .agg_many_vector(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); } else { @@ -254,7 +255,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } void *state = (offsets[i] * agg_def->func.state_bytes + (char *) agg_states); - agg_def->func.agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); + agg_def->func.agg_scalar(state, arg_datum, arg_isnull, 1, agg_extra_mctx); } } } From 22d23b344c185b2ffb3950b80419efa0f443cbec Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:47:25 +0100 Subject: [PATCH 035/242] cleanup --- tsl/src/nodes/vector_agg/function/functions.c | 18 +++++++++--------- .../nodes/vector_agg/grouping_policy_hash.c | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 826dd02bfa9..fc141762497 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -45,8 +45,8 @@ count_emit(void *agg_state, Datum *out_result, bool *out_isnull) } static void -count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; state->count += n; @@ -72,7 +72,7 @@ count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, - .agg_scalar = count_star_const, + .agg_scalar = count_star_scalar, .agg_emit = count_emit, .agg_many_scalar = count_star_many_scalar, }; @@ -81,8 +81,8 @@ VectorAggFunctions count_star_agg = { * Aggregate function count(x). */ static void -count_any_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_any_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { if (constisnull) { @@ -94,8 +94,8 @@ count_any_const(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, - MemoryContext agg_extra_mctx) +count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; const int n = vector->length; @@ -152,8 +152,8 @@ VectorAggFunctions count_any_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_emit = count_emit, - .agg_scalar = count_any_const, - .agg_vector = count_any_vector, + .agg_scalar = count_any_scalar, + .agg_vector = count_any_many_vector, .agg_many_vector = count_any_many, }; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index fdcf50e41cd..0a8258efcb2 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -80,8 +80,9 @@ typedef struct #define SH_DEFINE #include -struct h_hash; - +/* + * Hash grouping policy. + */ typedef struct { /* From 5756319ab0dc87006c0d94fdd43dfadfd96c5677 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:52:19 +0100 Subject: [PATCH 036/242] renames --- .../function/{agg_many_helper.c => agg_many_vector_helper.c} | 0 .../function/{agg_const_helper.c => agg_scalar_helper.c} | 0 tsl/src/nodes/vector_agg/function/float48_accum_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/int128_accum_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/int24_sum_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/sum_float_single.c | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) rename tsl/src/nodes/vector_agg/function/{agg_many_helper.c => agg_many_vector_helper.c} (100%) rename tsl/src/nodes/vector_agg/function/{agg_const_helper.c => agg_scalar_helper.c} (100%) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c similarity index 100% rename from tsl/src/nodes/vector_agg/function/agg_many_helper.c rename to tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c diff --git a/tsl/src/nodes/vector_agg/function/agg_const_helper.c b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c similarity index 100% rename from tsl/src/nodes/vector_agg/function/agg_const_helper.c rename to tsl/src/nodes/vector_agg/function/agg_scalar_helper.c diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index 6a07c28e238..bcee157a560 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -319,8 +319,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->Sx = newSx; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index bf0f90e5044..e4e8a1bc181 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -110,8 +110,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) #endif } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 2051fe006d5..e7973f13091 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -38,8 +38,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->sum += value; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index c96a45fc96f..f92b865814c 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -61,8 +61,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) typedef Int24SumState FUNCTION_NAME(state); -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index 127b5176291..28f84f725b0 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -58,8 +58,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) } } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 41565feabfc..bab33a59983 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -90,8 +90,8 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->result += value; } -#include "agg_const_helper.c" -#include "agg_many_helper.c" +#include "agg_scalar_helper.c" +#include "agg_many_vector_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { From 2361e136b31303eddb2edc4f724016c0d93f58fb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:02:59 +0100 Subject: [PATCH 037/242] merge --- .../workflows/linux-32bit-build-and-test.yaml | 4 +- tsl/src/nodes/vector_agg/exec.c | 7 +- .../function/agg_many_vector_helper.c | 10 +- .../vector_agg/function/agg_scalar_helper.c | 18 +- .../function/float48_accum_single.c | 8 +- tsl/src/nodes/vector_agg/function/functions.c | 20 +- tsl/src/nodes/vector_agg/function/functions.h | 22 +- .../vector_agg/function/int128_accum_single.c | 6 +- .../function/int24_avg_accum_single.c | 6 +- .../vector_agg/function/int24_sum_single.c | 6 +- .../function/minmax_arithmetic_single.c | 6 +- .../vector_agg/function/sum_float_single.c | 6 +- .../nodes/vector_agg/grouping_policy_batch.c | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 368 +-- tsl/src/nodes/vector_agg/plan.c | 15 +- tsl/test/expected/vector_agg_functions.out | 2145 ++++++++++------- tsl/test/sql/vector_agg_functions.sql | 49 +- 17 files changed, 1600 insertions(+), 1098 deletions(-) diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index 7a261a1445d..ed3afc0be1e 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -47,7 +47,9 @@ jobs: CC: clang-14 CXX: clang++-14 DEBIAN_FRONTEND: noninteractive - IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler*" + # vectorized_aggregation has different output on i386 because int8 is by + # reference and currently it cannot be used for vectorized hash grouping. + IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* vectorized_aggregation" SKIPS: chunk_adaptive histogram_test-* EXTENSIONS: "postgres_fdw test_decoding" strategy: diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 13ad379bf8b..60aef1dea9b 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -130,7 +130,6 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } } - /// List *grouping_child_output_offsets = linitial(cscan->custom_private); if (list_length(vector_agg_state->output_grouping_columns) == 1) { GroupingColumn *col = @@ -140,6 +139,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && (size_t) desc->value_bytes <= sizeof(Datum)) { + /* + * Hash grouping by a single fixed-size by-value compressed column. + */ vector_agg_state->grouping = create_grouping_policy_hash(vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); @@ -148,6 +150,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) if (vector_agg_state->grouping == NULL) { + /* + * Per-batch grouping. + */ vector_agg_state->grouping = create_grouping_policy_batch(vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index f8517c4328a..47916e29131 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -4,9 +4,15 @@ * LICENSE-TIMESCALE for a copy of the license. */ +/* + * A generic implementation of adding the given batch to many aggregate function + * states with given offsets. Used for hash aggregation, and builds on the + * FUNCTION_NAME(one) function, which adds one passing non-null row to the given + * aggregate function state. + */ static void -FUNCTION_NAME(many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, - const ArrowArray *vector, MemoryContext agg_extra_mctx) +FUNCTION_NAME(many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) { MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); const CTYPE *values = vector->buffers[1]; diff --git a/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c index c83d38526be..0d81abfcf65 100644 --- a/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c @@ -11,14 +11,20 @@ * implementation otherwise. */ static void -FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int nn, - MemoryContext agg_extra_mctx) +FUNCTION_NAME(scalar)(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { - const uint64 valid = constisnull ? 0 : 1; - const CTYPE value = valid ? DATUM_TO_CTYPE(constvalue) : 0; + if (constisnull) + { + return; + } + + const CTYPE value = DATUM_TO_CTYPE(constvalue); - for (int i = 0; i < nn; i++) + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); + for (int i = 0; i < n; i++) { - FUNCTION_NAME(vector_impl)(agg_state, 1, &value, &valid, NULL, agg_extra_mctx); + FUNCTION_NAME(one)(agg_state, value); } + MemoryContextSwitchTo(old); } diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index bcee157a560..73743c5aa1a 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -203,7 +203,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const /* * Vector registers can be up to 512 bits wide. */ -#define UNROLL_SIZE ((int) ((512 / 8) / sizeof(CTYPE))) +#define UNROLL_SIZE ((int) (512 / 8 / sizeof(CTYPE))) /* * Each inner iteration works with its own accumulators to avoid data @@ -319,17 +319,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->Sx = newSx; } -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), .agg_init = FUNCTION_NAME(init), .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #undef UPDATE #undef COMBINE diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 4dea3c8c90e..fc141762497 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -45,8 +45,8 @@ count_emit(void *agg_state, Datum *out_result, bool *out_isnull) } static void -count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; state->count += n; @@ -72,7 +72,7 @@ count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, - .agg_const = count_star_const, + .agg_scalar = count_star_scalar, .agg_emit = count_emit, .agg_many_scalar = count_star_many_scalar, }; @@ -81,8 +81,8 @@ VectorAggFunctions count_star_agg = { * Aggregate function count(x). */ static void -count_any_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_any_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { if (constisnull) { @@ -94,8 +94,8 @@ count_any_const(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, - MemoryContext agg_extra_mctx) +count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; const int n = vector->length; @@ -152,9 +152,9 @@ VectorAggFunctions count_any_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_emit = count_emit, - .agg_const = count_any_const, - .agg_vector = count_any_vector, - .agg_many = count_any_many, + .agg_scalar = count_any_scalar, + .agg_vector = count_any_many_vector, + .agg_many_vector = count_any_many, }; /* diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 9d5539fb244..70785a5d802 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -23,18 +23,26 @@ typedef struct void (*agg_vector)(void *restrict agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx); - /* Aggregate a constant (like segmentby or column with default value). */ - void (*agg_const)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx); - - void (*agg_many)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); + /* Aggregate a scalar value, like segmentby or column with default value. */ + void (*agg_scalar)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx); + /* + * Add the rows of the given arrow array to aggregate function states given + * by the respecitve offsets. + */ + void (*agg_many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, + int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); + + /* + * Same as above, but for a scalar argument. This is mostly important for + * count(*) and can be NULL. + */ void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx); - /* Emit a partial result. */ + /* Emit a partial aggregation result. */ void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index e4e8a1bc181..bf60e64cd12 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -110,17 +110,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) #endif } -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), .agg_init = FUNCTION_NAME(init), .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index e7973f13091..62ebb5ad52b 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -38,17 +38,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->sum += value; } -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24AvgAccumState), .agg_init = int24_avg_accum_init, .agg_emit = int24_avg_accum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index f92b865814c..8bfb15676ae 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -61,17 +61,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) typedef Int24SumState FUNCTION_NAME(state); -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24SumState), .agg_init = int_sum_init, .agg_emit = int_sum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index 28f84f725b0..6d110fcdc34 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -58,17 +58,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) } } -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(MinMaxState), .agg_init = minmax_init, .agg_emit = minmax_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index bab33a59983..6b56b433c89 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -90,17 +90,17 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->result += value; } -#include "agg_scalar_helper.c" #include "agg_many_vector_helper.c" +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FloatSumState), .agg_init = float_sum_init, .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), - .agg_many = FUNCTION_NAME(many), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 23d695cedc1..f7c7db9ee46 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -146,7 +146,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de */ Assert(n > 0); - agg_def->func.agg_const(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d0829cf0404..8787e8dcb8a 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -5,9 +5,8 @@ */ /* - * This grouping policy aggregates entire compressed batches. It can be used to - * aggregate with no grouping, or to produce partial aggregates per each batch - * to group by segmentby columns. + * This grouping policy groups the rows using a hash table. Currently it only + * supports a single fixed-size by-value compressed column that fits into a Datum. */ #include @@ -20,15 +19,23 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" -#include - -typedef struct -{ - Datum key; - uint32 agg_state_index; -} HashEntry; +#ifdef USE_FLOAT8_BYVAL +#define DEBUG_LOG(MSG, ...) elog(DEBUG3, MSG, __VA_ARGS__) +#else +/* + * On 32-bit platforms we'd have to use the cross-platform int width printf + * specifiers which are really unreadable. + */ +#define DEBUG_LOG(...) +#endif +/* + * We can use crc32 as a hash function, it has bad properties but takes only one + * cycle, which is why it is sometimes used in the existing hash table + * implementations. + */ #ifdef USE_SSE42_CRC32C +#include static pg_attribute_always_inline uint64 hash64(uint64 x) { @@ -36,6 +43,9 @@ hash64(uint64 x) } #else +/* + * When we don't have the crc32 instruction, use the SplitMix64 finalizer. + */ static pg_attribute_always_inline uint64 hash64(uint64 x) { @@ -48,6 +58,17 @@ hash64(uint64 x) } #endif +/* + * For the hash table, use the generic Datum key that is mapped to the aggregate + * state index. + */ +typedef struct +{ + Datum key; + uint32 status; + uint32 agg_state_index; +} HashEntry; + #define SH_PREFIX h #define SH_ELEMENT_TYPE HashEntry #define SH_KEY_TYPE Datum @@ -84,17 +105,39 @@ get_size_bytes(void *table) return hash->members * sizeof(HashEntry); } +/* + * Hash grouping policy. + */ typedef struct { + /* + * We're using data inheritance from the GroupingPolicy. + */ GroupingPolicy funcs; + List *agg_defs; List *output_grouping_columns; - bool partial_per_batch; + + /* + * The hash table we use for grouping. + */ void *table; HashTableFunctions functions; - bool have_null_key; - struct h_iterator iter; + + /* + * We have to track whether we are in the mode of returning the partial + * aggregation results, and also use a hash table iterator to track our + * progress between emit() calls. + */ bool returning_results; + struct h_iterator iter; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and it has a reserved aggregate state index 1. We also reset this + * flag after we output the null key during iteration. + */ + bool have_null_key; /* * A memory context for aggregate functions to allocate additional data, @@ -103,14 +146,29 @@ typedef struct */ MemoryContext agg_extra_mctx; - uint64 aggstate_bytes_per_key; - uint64 allocated_aggstate_rows; + /* + * Temporary storage of aggregate state offsets for a given batch. We keep + * it in the policy because it is potentially too big to keep on stack, and + * we don't want to reallocate it each batch. + */ + uint32 *offsets; + uint64 num_allocated_offsets; + + /* + * Storage of aggregate function states, each List entry is the array of + * states for the respective function from agg_defs. The state index 0 is + * invalid, and the state index 1 is reserved for a null key. + */ List *per_agg_states; + uint64 allocated_aggstate_rows; uint64 key_bytes; uint64 allocated_key_rows; void *keys; + /* + * Some statistics for debugging. + */ uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; @@ -127,13 +185,11 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->agg_defs = agg_defs; policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - policy->allocated_aggstate_rows = 1000; + policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; ListCell *lc; foreach (lc, agg_defs) { VectorAggDef *agg_def = lfirst(lc); - policy->aggstate_bytes_per_key += agg_def->func.state_bytes; - policy->per_agg_states = lappend(policy->per_agg_states, palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); @@ -216,13 +272,14 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func.agg_many(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); + agg_def->func + .agg_many_vector(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); } else { /* * Scalar argument, or count(*). The latter has an optimized - * implementation for this case. + * implementation. */ if (agg_def->func.agg_many_scalar != NULL) { @@ -244,18 +301,21 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } void *state = (offsets[i] * agg_def->func.state_bytes + (char *) agg_states); - agg_def->func.agg_const(state, arg_datum, arg_isnull, 1, agg_extra_mctx); + agg_def->func.agg_scalar(state, arg_datum, arg_isnull, 1, agg_extra_mctx); } } } } +/* + * Fill the aggregation state offsets for all rows using a hash table. + */ static pg_attribute_always_inline uint32 -fill_offsets_impl_for_real(GroupingPolicyHash *policy, CompressedColumnValues column, - const uint64 *restrict filter, uint32 next_unused_state_index, - int start_row, int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, - Datum *restrict key, bool *restrict valid)) +fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, + const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid)) { struct h_hash *restrict table = policy->table; for (int row = start_row; row < end_row; row++) @@ -285,63 +345,68 @@ fill_offsets_impl_for_real(GroupingPolicyHash *policy, CompressedColumnValues co offsets[row] = 1; } } + return next_unused_state_index; } +/* + * This function exists just to nudge the compiler to generate simplified + * implementation for the important case where the entire batch matches and the + * key has no null values. + */ static pg_attribute_always_inline uint32 -fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, - uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) +fill_offsets_dispatch(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int key_column_index, uint32 next_unused_state_index, int start_row, + int end_row, uint32 *restrict offsets, + void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, + bool *restrict valid)) { CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; - // Assert(gv->decompression_type == 8 /* lolwut */); const uint64 *restrict filter = batch_state->vector_qual_result; if (filter == NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] == NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter == NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else if (filter != NULL && column.buffers[0] != NULL) { - next_unused_state_index = fill_offsets_impl_for_real(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); + next_unused_state_index = fill_offsets_impl(policy, + column, + filter, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key); } else { @@ -353,15 +418,17 @@ fill_offsets_impl(GroupingPolicyHash *policy, DecompressBatchState *batch_state, return next_unused_state_index; } -// static pg_attribute_always_inline -// void get_key_generic(CompressedColumnValues *column, int row, Datum *key, bool *valid) -//{ -// Assert(column->decompression_type > 0); -// const void *values = column->arrow->buffers[1]; -// const uint64 *key_validity = column->arrow->buffers[0]; -// *valid = arrow_row_is_valid(key_validity, row); -// memcpy(key, column->decompression_type * row + (char *) values, column->decompression_type); -// } +/* + * Functions to get the key value from the decompressed column, depending on its + * width and whether it's a scalar column. + */ +static pg_attribute_always_inline void +get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) +{ + Assert(column.decompression_type == DT_Scalar); + *key = *column.output_value; + *valid = !*column.output_isnull; +} static pg_attribute_always_inline void get_key_arrow_fixed(CompressedColumnValues column, int row, int key_bytes, Datum *restrict key, @@ -392,31 +459,33 @@ static pg_attribute_always_inline void get_key_arrow_fixed_8(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) { - /* FIXME for float8 not by value */ - get_key_arrow_fixed(column, row, 8, key, valid); -} +#ifndef USE_FLOAT8_BYVAL + /* + * Shouldn't be called for this configuration, because we only use this + * grouping strategy for by-value types. + */ + Assert(false); +#endif -static pg_attribute_always_inline void -get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) -{ - Assert(column.decompression_type == DT_Scalar); - *key = *column.output_value; - *valid = !*column.output_isnull; + get_key_arrow_fixed(column, row, 8, key, valid); } +/* + * Implementation of bulk hashing specialized for a given key width. + */ static pg_noinline uint32 fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_8); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_8); } static pg_noinline uint32 @@ -424,14 +493,14 @@ fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *bat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_4); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_4); } static pg_noinline uint32 @@ -439,14 +508,14 @@ fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *bat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_2); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_arrow_fixed_2); } static pg_noinline uint32 @@ -454,14 +523,14 @@ fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_stat int key_column_index, uint32 next_unused_state_index, int start_row, int end_row, uint32 *restrict offsets) { - return fill_offsets_impl(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_scalar); + return fill_offsets_dispatch(policy, + batch_state, + key_column_index, + next_unused_state_index, + start_row, + end_row, + offsets, + get_key_scalar); } static void @@ -471,6 +540,20 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(!policy->returning_results); + const uint64_t *restrict filter = batch_state->vector_qual_result; + const int n = batch_state->total_batch_rows; + + /* + * Initialize the array for storing the aggregate state offsets corresponding + * to a given batch row. + */ + if ((size_t) n > policy->num_allocated_offsets) + { + policy->num_allocated_offsets = n; + policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + } + memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); + /* * For the partial aggregation node, the grouping columns are always in the * output, so we don't have to separately look at the list of the grouping @@ -479,19 +562,13 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(list_length(policy->output_grouping_columns) == 1); GroupingColumn *g = linitial(policy->output_grouping_columns); CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; - // const uint64_t* restrict key_validity = key_column->buffers[0]; - const uint64_t *restrict filter = batch_state->vector_qual_result; - - const int n = batch_state->total_batch_rows; int start_row = 0; int end_row = 0; - - // for (int end_row = MIN(64, n); end_row <= n; end_row += 64) for (start_row = 0; start_row < n; start_row = end_row) { /* * If we have a highly selective filter, it's easy to skip the rows for - * which the entire filter bitmap words are zero. + * which the entire words of the filter bitmap are zero. */ if (filter) { @@ -530,8 +607,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Match rows to aggregation states using a hash table. */ - uint32 offsets[1000] = { 0 }; - Assert((size_t) end_row <= sizeof(offsets) / sizeof(*offsets)); + Assert((size_t) end_row <= policy->num_allocated_offsets); switch ((int) key_column->decompression_type) { case DT_Scalar: @@ -541,7 +617,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 8: next_unused_state_index = fill_offsets_arrow_fixed_8(policy, @@ -550,7 +626,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 4: next_unused_state_index = fill_offsets_arrow_fixed_4(policy, @@ -559,7 +635,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; case 2: next_unused_state_index = fill_offsets_arrow_fixed_2(policy, @@ -568,7 +644,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) next_unused_state_index, start_row, end_row, - offsets); + policy->offsets); break; default: Assert(false); @@ -614,7 +690,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) end_row, lfirst(aggdeflc), lfirst(aggstatelc), - offsets, + policy->offsets, policy->agg_extra_mctx); } } @@ -625,11 +701,7 @@ static bool gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - (void) policy; - // if (policy->table->members + policy->have_null_key > 0) - // { - // return true; - // } + /* * Don't grow the hash table cardinality too much, otherwise we become bound * by memory reads. In general, when this first stage of grouping doesn't @@ -637,11 +709,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - if (policy->functions.get_size_bytes(policy->table) > 128 * 1024) - { - return true; - } - return false; + return policy->functions.get_size_bytes(policy->table) > 128 * 1024; } static bool @@ -651,18 +719,22 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) if (!policy->returning_results) { - /* FIXME doesn't work on final result emission w/o should_emit. */ policy->returning_results = true; h_start_iterate(policy->table, &policy->iter); - // fprintf(stderr, - // "spill after %ld input %ld valid %ld bulk filtered, %d keys, %f ratio, %ld - // aggctx bytes, %ld aggstate bytes\n", policy->stat_input_total_rows, - // policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, - // policy->table->members - // + policy->have_null_key, policy->stat_input_valid_rows / - //(float) (policy->table->members + policy->have_null_key), - // MemoryContextMemAllocated(policy->table->ctx, - // false), MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + + const float keys = policy->functions.get_num_keys(policy->table) + policy->have_null_key; + if (keys > 0) + { + DEBUG_LOG("spill after %ld input %ld valid %ld bulk filtered %.0f keys %f ratio %ld " + "curctx bytes %ld aggstate bytes", + policy->stat_input_total_rows, + policy->stat_input_valid_rows, + policy->stat_bulk_filtered_rows, + keys, + policy->stat_input_valid_rows / keys, + MemoryContextMemAllocated(CurrentMemoryContext, false), + MemoryContextMemAllocated(policy->agg_extra_mctx, false)); + } } HashEntry null_key_entry = { .agg_state_index = 1 }; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index f358d7a5a28..8c42cb43906 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -313,17 +313,25 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) /* * Whether we can perform vectorized aggregation with a given grouping. - * Currently supports either no grouping or grouping by segmentby columns. */ static bool can_vectorize_grouping(Agg *agg, CustomScan *custom) { + /* + * We support vectorized aggregation without grouping. + */ if (agg->numCols == 0) { return true; } - if (agg->numCols == 1) + /* + * We support hashed vectorized grouping by one fixed-size by-value + * compressed column. + * We cannot use it when the plan has GroupAggregate because the + * latter requires sorted output. + */ + if (agg->numCols == 1 && agg->aggstrategy == AGG_HASHED) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); TargetEntry *entry = list_nth(agg->plan.targetlist, offset); @@ -342,6 +350,9 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) } } + /* + * We support grouping by any number of columns if all of them are segmentby. + */ for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 9e9f8115e57..c79c667d15a 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -9,7 +9,7 @@ $$ LANGUAGE SQL; \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, cfloat4 float4, cfloat8 float8, cts timestamp, ctstz timestamptz, @@ -22,27 +22,47 @@ NOTICE: adding not-null constraint to column "s" (1,public,aggfns,t) (1 row) -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000::int + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, + (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, + (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t + 4) * 100)::float4 end as cfloat4, + (mix(s + t + 5) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('aggfns') x; + count +------- + 1 +(1 row) + +alter table aggfns add column ss int default 11; +insert into aggfns +select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1; select count(compress_chunk(x)) from show_chunks('aggfns') x; count ------- @@ -75,7 +95,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -102,13 +123,50 @@ where end and case + when variable = '*' then function = 'count' when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') + when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') else true end order by explain, condition.n, variable, function, grouping.n \gexec +select count(*) from aggfns order by 1; + count +-------- + 200000 +(1 row) + +select s, count(*) from aggfns group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(*) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 19 +(10 rows) + select max(cdate) from aggfns order by 1; max ------------ @@ -134,8 +192,6 @@ select ss, max(cdate) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-11-2185 5 | 08-28-2212 @@ -143,6 +199,8 @@ select ss, max(cdate) from aggfns group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-05-2322 + 11 | 01-24-2183 + | 07-03-2156 (10 rows) select min(cdate) from aggfns order by 1; @@ -170,8 +228,6 @@ select ss, min(cdate) from aggfns group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -179,6 +235,8 @@ select ss, min(cdate) from aggfns group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns order by 1; @@ -206,15 +264,15 @@ select ss, avg(cfloat4) from aggfns group by ss order by 1; ss | avg ----+-------------------- 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -0.13252146150968 + 4 | -0.124977103379316 5 | -0.130611110996222 6 | -0.131984978889441 7 | -0.131050092529273 8 | -0.131313872741675 9 | -0.132765194868064 + 11 | NaN + | -5.91588952823689 (10 rows) select count(cfloat4) from aggfns order by 1; @@ -242,15 +300,15 @@ select ss, count(cfloat4) from aggfns group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cfloat4) from aggfns order by 1; @@ -275,18 +333,18 @@ select s, max(cfloat4) from aggfns group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns order by 1; @@ -314,8 +372,6 @@ select ss, min(cfloat4) from aggfns group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -Infinity 4 | -49.9756 5 | -49.9756 @@ -323,6 +379,8 @@ select ss, min(cfloat4) from aggfns group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns order by 1; @@ -350,15 +408,15 @@ select ss, stddev(cfloat4) from aggfns group by ss order by 1; ss | stddev ----+------------------ 0 | 28.8941380063427 - 1 | NaN - 2 | NaN 3 | NaN - 4 | 28.8948189281654 + 4 | 28.89302954083 5 | 28.8951827753267 6 | 28.8960531969495 7 | 28.8959678301628 8 | 28.8963276918371 9 | 28.8968307405966 + 11 | NaN + | 27.2867943876683 (10 rows) select sum(cfloat4) from aggfns order by 1; @@ -386,15 +444,15 @@ select ss, sum(cfloat4) from aggfns group by ss order by 1; ss | sum ----+----------- 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 + 4 | -2497.17 5 | -2612.22 6 | -2639.7 7 | -2621 8 | -2626.28 9 | -2655.3 + 11 | NaN + | -112.402 (10 rows) select avg(cfloat8) from aggfns order by 1; @@ -422,15 +480,15 @@ select ss, avg(cfloat8) from aggfns group by ss order by 1; ss | avg ----+-------------------- 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 + 3 | -0.128550004763072 + 4 | -0.129264304572168 5 | -0.131984980024863 6 | -0.131050093692029 7 | -0.13131387403002 8 | -0.132765196124092 9 | -0.134423591727391 + 11 | -0.131587538323368 + | -4.30903203025656 (10 rows) select max(cfloat8) from aggfns order by 1; @@ -455,18 +513,18 @@ select s, max(cfloat8) from aggfns group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns order by 1; @@ -494,8 +552,6 @@ select ss, min(cfloat8) from aggfns group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -503,6 +559,8 @@ select ss, min(cfloat8) from aggfns group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns order by 1; @@ -530,15 +588,15 @@ select ss, stddev(cfloat8) from aggfns group by ss order by 1; ss | stddev ----+------------------ 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 + 3 | 28.8988694216911 + 4 | 28.8937408619903 5 | 28.8960532056265 6 | 28.8959678388464 7 | 28.8963277006942 8 | 28.8968307494196 9 | 28.8953209642426 + 11 | 28.8954978116663 + | 24.556507133269 (10 rows) select sum(cfloat8) from aggfns order by 1; @@ -566,15 +624,15 @@ select ss, sum(cfloat8) from aggfns group by ss order by 1; ss | sum ----+------------------- 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 + 3 | -2568.55764517095 + 4 | -2582.83006965648 5 | -2639.69960049726 6 | -2621.00187384058 7 | -2626.2774806004 8 | -2655.30392248183 9 | -2688.47183454782 + 11 | -5266.00169616286 + | -81.8716085748747 (10 rows) select avg(cint2) from aggfns order by 1; @@ -599,18 +657,18 @@ select s, avg(cint2) from aggfns group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 + ss | avg +----+----------------------- + 0 | -42.2972824182973825 + 3 | -42.6071034966436229 + 4 | -40.0837090471896604 + 5 | -43.5287022671537961 + 6 | -41.7711325759471498 + 7 | -41.3288123717531655 + 8 | -40.6353035383614434 + 9 | -43.1119563585406136 + 11 | -42.9734623946374528 + | -335.0000000000000000 (10 rows) select max(cint2) from aggfns order by 1; @@ -638,8 +696,6 @@ select ss, max(cint2) from aggfns group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -647,6 +703,8 @@ select ss, max(cint2) from aggfns group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 13720 (10 rows) select min(cint2) from aggfns order by 1; @@ -674,8 +732,6 @@ select ss, min(cint2) from aggfns group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -683,6 +739,8 @@ select ss, min(cint2) from aggfns group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns order by 1; @@ -710,15 +768,15 @@ select ss, stddev(cint2) from aggfns group by ss order by 1; ss | stddev ----+------------------- 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 + 3 | 9466.351508971864 + 4 | 9469.021659499615 5 | 9467.599133444078 6 | 9468.362090451302 7 | 9467.745653535755 8 | 9466.743345080951 9 | 9468.145452253715 + 11 | 9467.946206136906 + | 9796.780548277639 (10 rows) select sum(cint2) from aggfns order by 1; @@ -743,18 +801,18 @@ select s, sum(cint2) from aggfns group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 + ss | sum +----+---------- + 0 | -845142 + 3 | -850523 + 4 | -800151 + 5 | -869747 + 6 | -834629 + 7 | -825791 + 8 | -811934 + 9 | -861420 + 11 | -1718122 + | -6365 (10 rows) select avg(cint4) from aggfns order by 1; @@ -782,15 +840,15 @@ select ss, avg(cint4) from aggfns group by ss order by 1; ss | avg ----+----------------------- 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 + 3 | -2682566.613082428307 + 4 | -2753845.761523447275 5 | -2850351.637450000000 6 | -2845789.891100000000 7 | -2804766.678700000000 8 | -2834269.365200000000 9 | -2814193.446750000000 + 11 | -2846001.238586671331 + | -146005017.57894737 (10 rows) select max(cint4) from aggfns order by 1; @@ -818,8 +876,6 @@ select ss, max(cint4) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -827,6 +883,8 @@ select ss, max(cint4) from aggfns group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 978482473 (10 rows) select min(cint4) from aggfns order by 1; @@ -854,8 +912,6 @@ select ss, min(cint4) from aggfns group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -863,6 +919,8 @@ select ss, min(cint4) from aggfns group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -960881516 (10 rows) select stddev(cint4) from aggfns order by 1; @@ -890,15 +948,15 @@ select ss, stddev(cint4) from aggfns group by ss order by 1; ss | stddev ----+----------- 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 + 3 | 620502162 + 4 | 620460588 5 | 620498014 6 | 620492575 7 | 620500389 8 | 620519080 9 | 620517247 + 11 | 620490348 + | 569369090 (10 rows) select sum(cint4) from aggfns order by 1; @@ -923,18 +981,18 @@ select s, sum(cint4) from aggfns group by s order by 1; (10 rows) select ss, sum(cint4) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 + ss | sum +----+--------------- + 0 | -58384962420 + 3 | -53600363496 + 4 | -55024592161 + 5 | -57007032749 + 6 | -56915797822 + 7 | -56095333574 + 8 | -56685387304 + 9 | -56283868935 + 11 | -113894123567 + | -2774095334 (10 rows) select avg(cint8) from aggfns order by 1; @@ -962,15 +1020,15 @@ select ss, avg(cint8) from aggfns group by ss order by 1; ss | avg ----+----------------------- 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 + 3 | -2653999.743206045743 + 4 | -3009394.583854661929 5 | -2845789.891100000000 6 | -2804766.678700000000 7 | -2834269.365200000000 8 | -2814193.446750000000 9 | -2819857.913500000000 + 11 | -2748620.862390364577 + | -127121035.31578947 (10 rows) select max(cint8) from aggfns order by 1; @@ -998,8 +1056,6 @@ select ss, max(cint8) from aggfns group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -1007,6 +1063,8 @@ select ss, max(cint8) from aggfns group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns order by 1; @@ -1034,8 +1092,6 @@ select ss, min(cint8) from aggfns group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -1043,6 +1099,8 @@ select ss, min(cint8) from aggfns group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -796158533 (10 rows) select stddev(cint8) from aggfns order by 1; @@ -1070,15 +1128,15 @@ select ss, stddev(cint8) from aggfns group by ss order by 1; ss | stddev ----+----------- 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 + 3 | 620514804 + 4 | 620462299 5 | 620492575 6 | 620500389 7 | 620519080 8 | 620517247 9 | 620524975 + 11 | 620478168 + | 609007799 (10 rows) select sum(cint8) from aggfns order by 1; @@ -1103,18 +1161,18 @@ select s, sum(cint8) from aggfns group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 + ss | sum +----+--------------- + 0 | -56727567295 + 3 | -53029568869 + 4 | -60130713180 + 5 | -56915797822 + 6 | -56095333574 + 7 | -56685387304 + 8 | -56283868935 + 9 | -56397158270 + 11 | -109997058292 + | -2415299671 (10 rows) select max(cts) from aggfns order by 1; @@ -1142,8 +1200,6 @@ select ss, max(cts) from aggfns group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:41 2021 @@ -1151,6 +1207,8 @@ select ss, max(cts) from aggfns group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns order by 1; @@ -1178,8 +1236,6 @@ select ss, min(cts) from aggfns group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -1187,6 +1243,8 @@ select ss, min(cts) from aggfns group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns order by 1; @@ -1214,8 +1272,6 @@ select ss, max(ctstz) from aggfns group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -1223,6 +1279,8 @@ select ss, max(ctstz) from aggfns group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns order by 1; @@ -1250,8 +1308,6 @@ select ss, min(ctstz) from aggfns group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -1259,6 +1315,8 @@ select ss, min(ctstz) from aggfns group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns order by 1; @@ -1286,8 +1344,6 @@ select ss, avg(s) from aggfns group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -1295,6 +1351,8 @@ select ss, avg(s) from aggfns group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5011869362053025 + | 3.0000000000000000 (10 rows) select count(s) from aggfns order by 1; @@ -1322,15 +1380,15 @@ select ss, count(s) from aggfns group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(s) from aggfns order by 1; @@ -1358,8 +1416,6 @@ select ss, max(s) from aggfns group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1367,6 +1423,8 @@ select ss, max(s) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns order by 1; @@ -1394,8 +1452,6 @@ select ss, min(s) from aggfns group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1403,6 +1459,8 @@ select ss, min(s) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns order by 1; @@ -1427,18 +1485,18 @@ select s, stddev(s) from aggfns group by s order by 1; (10 rows) select ss, stddev(s) from aggfns group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50284545977155885187 + | 0 (10 rows) select sum(s) from aggfns order by 1; @@ -1466,31 +1524,31 @@ select ss, sum(s) from aggfns group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 60076 + | 57 (10 rows) select avg(ss) from aggfns order by 1; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) select s, avg(ss) from aggfns group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -1502,8 +1560,6 @@ select ss, avg(ss) from aggfns group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -1511,22 +1567,60 @@ select ss, avg(ss) from aggfns group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns order by 1; + count +-------- + 199981 +(1 row) + +select s, count(ss) from aggfns group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 19981 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(ss) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 0 (10 rows) select max(ss) from aggfns order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -1538,8 +1632,6 @@ select ss, max(ss) from aggfns group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1547,6 +1639,8 @@ select ss, max(ss) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns order by 1; @@ -1559,8 +1653,8 @@ select s, min(ss) from aggfns group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -1574,8 +1668,6 @@ select ss, min(ss) from aggfns group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1583,35 +1675,35 @@ select ss, min(ss) from aggfns group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns order by 1; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) select s, stddev(ss) from aggfns group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.21565737387148452722 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -1619,22 +1711,24 @@ select ss, stddev(ss) from aggfns group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns order by 1; - sum --------- - 900000 + sum +--------- + 1280076 (1 row) select s, sum(ss) from aggfns group by s order by 1; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 1 | 220000 + 2 | 220000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 @@ -1646,15 +1740,15 @@ select ss, sum(ss) from aggfns group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 440209 + | (10 rows) select max(t) from aggfns order by 1; @@ -1682,8 +1776,6 @@ select ss, max(t) from aggfns group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 30000 - 2 | 40000 3 | 50000 4 | 60000 5 | 70000 @@ -1691,6 +1783,8 @@ select ss, max(t) from aggfns group by ss order by 1; 7 | 90000 8 | 100000 9 | 110000 + 11 | 59192 + | 49491 (10 rows) select min(t) from aggfns order by 1; @@ -1718,8 +1812,6 @@ select ss, min(t) from aggfns group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -1727,6 +1819,44 @@ select ss, min(t) from aggfns group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 30537 +(10 rows) + +select count(*) from aggfns where cfloat8 > 0 order by 1; + count +------- + 99430 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 9943 + 1 | 9943 + 2 | 9942 + 3 | 9942 + 4 | 9943 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 9943 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(cdate) from aggfns where cfloat8 > 0 order by 1; @@ -1754,8 +1884,6 @@ select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 10-04-2075 - 1 | 02-21-2103 - 2 | 07-08-2130 3 | 11-22-2157 4 | 04-11-2185 5 | 08-27-2212 @@ -1763,6 +1891,8 @@ select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 05-31-2267 8 | 10-15-2294 9 | 03-05-2322 + 11 | 03-03-2180 + | 07-03-2156 (10 rows) select min(cdate) from aggfns where cfloat8 > 0 order by 1; @@ -1790,8 +1920,6 @@ select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-11-2075 3 | 02-26-2103 4 | 07-13-2130 5 | 11-27-2157 @@ -1799,6 +1927,8 @@ select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 05-18-2110 (10 rows) select avg(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1826,15 +1956,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.542617154225893 - 1 | -0.540875748760701 - 2 | -0.541406464808325 3 | -Infinity - 4 | -0.544616367218129 + 4 | -0.545104747625541 5 | -0.544616367218129 6 | -0.547797322998719 7 | -0.547797322998719 8 | -0.544139963208192 9 | -0.547059247380753 + 11 | -0.540899217374597 + | -1.46971142292023 (10 rows) select count(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1862,15 +1992,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 + 3 | 9934 + 4 | 9932 5 | 9943 6 | 9944 7 | 9944 8 | 9943 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1898,8 +2028,6 @@ select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+--------- 0 | 49.9734 - 1 | 49.9734 - 2 | 49.9734 3 | 49.9734 4 | 49.9734 5 | 49.9734 @@ -1907,6 +2035,8 @@ select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 49.9734 8 | 49.9734 9 | 49.9734 + 11 | 49.9734 + | 24.3202 (10 rows) select min(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1934,8 +2064,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----------- 0 | -49.9722 - 1 | -49.9722 - 2 | -49.9722 3 | -Infinity 4 | -49.9722 5 | -49.9722 @@ -1943,6 +2071,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -49.9722 8 | -49.9722 9 | -49.9722 + 11 | -49.9722 + | -45.111 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -1970,15 +2100,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------ 0 | 28.889048755135 - 1 | 28.8872257367626 - 2 | 28.8886301576555 3 | NaN - 4 | 28.8889504423898 + 4 | 28.8896204728232 5 | 28.8889504423898 6 | 28.8892391773513 7 | 28.8892391773513 8 | 28.8883896891408 9 | 28.8893600799806 + 11 | 28.886867950284 + | 23.0946953685783 (10 rows) select sum(cfloat4) from aggfns where cfloat8 > 0 order by 1; @@ -2006,15 +2136,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+----------- 0 | -5395.24 - 1 | -5377.93 - 2 | -5382.66 3 | -Infinity - 4 | -5415.12 + 4 | -5413.98 5 | -5415.12 6 | -5447.3 7 | -5447.3 8 | -5410.38 9 | -5439.41 + 11 | -10761.7 + | -11.7577 (10 rows) select avg(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2042,15 +2172,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------ 0 | 25.0253254492148 - 1 | 25.0296791394684 - 2 | 25.0284447917954 - 3 | 25.0284447917954 - 4 | 25.0283891332554 + 3 | 25.0326248798677 + 4 | 25.0314280577154 5 | 25.0283891332554 6 | 25.0265337956144 7 | 25.0265337956144 8 | 25.0286117211772 9 | 25.0252759158804 + 11 | 25.0275446062773 + | 19.8378204280743 (10 rows) select max(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2075,18 +2205,18 @@ select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2114,8 +2244,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+--------------------- 0 | 0.00456937123090029 - 1 | 0.00456937123090029 - 2 | 0.00456937123090029 3 | 0.00456937123090029 4 | 0.00456937123090029 5 | 0.00456937123090029 @@ -2123,6 +2251,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 0.00456937123090029 8 | 0.00456937123090029 9 | 0.00456937123090029 + 11 | 0.00456937123090029 + | 0.0712367007508874 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2150,15 +2280,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------ 0 | 14.4393152148108 - 1 | 14.4397230124184 - 2 | 14.4399246592273 - 3 | 14.4399246592273 - 4 | 14.4391994993402 + 3 | 14.4385675470181 + 4 | 14.4418957208478 5 | 14.4391994993402 6 | 14.4396587086659 7 | 14.4396587086659 8 | 14.4388979969066 9 | 14.4386334818319 + 11 | 14.4381143863288 + | 16.2202029568666 (10 rows) select sum(cfloat8) from aggfns where cfloat8 > 0 order by 1; @@ -2186,15 +2316,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+------------------ 0 | 248826.810941542 - 1 | 248870.099683735 - 2 | 248832.79812003 - 3 | 248832.79812003 - 4 | 248857.273151958 + 3 | 248674.095556606 + 4 | 248612.143469229 5 | 248857.273151958 6 | 248863.85206359 7 | 248863.85206359 8 | 248859.486343665 9 | 248826.318431599 + 11 | 497948.027486494 + | 158.702563424595 (10 rows) select avg(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2219,18 +2349,18 @@ select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+--------------------- - 0 | 62.5336219045701631 - 1 | 61.1402396053558844 - 2 | 64.7349239907379442 - 3 | 60.4202577527184857 - 4 | 58.4389090177133655 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 + ss | avg +----+----------------------- + 0 | 62.5336219045701631 + 3 | 59.2794236195082628 + 4 | 60.5569773299748111 + 5 | 53.6134098459679855 + 6 | 59.4139909411172622 + 7 | 62.9917446894191080 + 8 | 57.2486665995773372 + 9 | 59.3958123615864707 + 11 | 61.8774966041153092 + | 1475.6250000000000000 (10 rows) select max(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2258,8 +2388,6 @@ select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------- 0 | 16377 - 1 | 16377 - 2 | 16377 3 | 16377 4 | 16377 5 | 16377 @@ -2267,6 +2395,8 @@ select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 16377 8 | 16377 9 | 16377 + 11 | 16377 + | 13720 (10 rows) select min(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2294,8 +2424,6 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+-------- 0 | -16374 - 1 | -16374 - 2 | -16374 3 | -16374 4 | -16374 5 | -16374 @@ -2303,6 +2431,8 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -16374 8 | -16374 9 | -16374 + 11 | -16374 + | -12426 (10 rows) select stddev(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2330,15 +2460,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+------------------- 0 | 9396.868628954375 - 1 | 9397.478004684803 - 2 | 9396.003979674052 - 3 | 9395.588131506675 - 4 | 9395.667525723886 + 3 | 9395.145600532270 + 4 | 9398.818234815872 5 | 9394.622668940645 6 | 9397.336273737402 7 | 9394.449892433625 8 | 9394.534603851403 9 | 9396.374239570388 + 11 | 9394.931149048751 + | 10506.43193392 (10 rows) select sum(cint2) from aggfns where cfloat8 > 0 order by 1; @@ -2363,18 +2493,18 @@ select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------- - 0 | 621209 - 1 | 607306 - 2 | 643012 - 3 | 600094 - 4 | 580649 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 + ss | sum +----+--------- + 0 | 621209 + 3 | 588289 + 4 | 601028 + 5 | 532542 + 6 | 590278 + 7 | 625697 + 8 | 568880 + 9 | 590038 + 11 | 1229939 + | 11805 (10 rows) select avg(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2399,18 +2529,18 @@ select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -3230391.667404203963 - 1 | -3063702.023936437695 - 2 | -3067528.135686984510 - 3 | -3067528.135686984510 - 4 | -2963500.289651010761 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 + ss | avg +----+------------------------ + 0 | -3230391.667404203963 + 3 | -2996690.484799677874 + 4 | -3090966.561316955296 + 5 | -2963500.289651010761 + 6 | -3033294.541331456154 + 7 | -3033294.541331456154 + 8 | -3023451.730664789299 + 9 | -2983069.716282812029 + 11 | -3001927.897165259349 + | -91030181.125000000000 (10 rows) select max(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2438,8 +2568,6 @@ select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 1073213373 - 1 | 1073213373 - 2 | 1073213373 3 | 1073213373 4 | 1073213373 5 | 1073213373 @@ -2447,6 +2575,8 @@ select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 1073213373 8 | 1073213373 9 | 1073213373 + 11 | 1073213373 + | 978482473 (10 rows) select min(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2474,8 +2604,6 @@ select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------- 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 3 | -1073053412 4 | -1073053412 5 | -1073053412 @@ -2483,6 +2611,8 @@ select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -1073053412 8 | -1073053412 9 | -1073053412 + 11 | -1073053412 + | -960881516 (10 rows) select stddev(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2510,15 +2640,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+----------- 0 | 622275017 - 1 | 622236051 - 2 | 622267230 - 3 | 622267230 - 4 | 622322391 + 3 | 622183925 + 4 | 622245451 5 | 622322391 6 | 622330015 7 | 622330015 8 | 622360538 9 | 622356873 + 11 | 622274449 + | 762095534 (10 rows) select sum(cint4) from aggfns where cfloat8 > 0 order by 1; @@ -2546,15 +2676,15 @@ select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+-------------- 0 | -32119784349 - 1 | -30462389224 - 2 | -30497364725 - 3 | -30497364725 - 4 | -29466083380 + 3 | -29769123276 + 4 | -30699479887 5 | -29466083380 6 | -30163080919 7 | -30163080919 8 | -30062180558 9 | -29660662189 + 11 | -59726357442 + | -728241449 (10 rows) select avg(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2582,15 +2712,15 @@ select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+----------------------- 0 | -7332793.526098762949 - 1 | -7334675.513225384693 - 2 | -7250229.067592033796 - 3 | -7250229.067592033796 - 4 | -7326050.594790304737 + 3 | -7271023.008153815180 + 4 | -7498519.579943616593 5 | -7326050.594790304737 6 | -7272459.754123089300 7 | -7272459.754123089300 8 | -7247017.818163532133 9 | -7258411.696771598109 + 11 | -7206377.192098914355 + | 18570646.625000000000 (10 rows) select max(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2618,8 +2748,6 @@ select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------ 0 | 1073659785 - 1 | 1073659785 - 2 | 1073659785 3 | 1073659785 4 | 1073659785 5 | 1073659785 @@ -2627,6 +2755,8 @@ select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 1073659785 8 | 1073659785 9 | 1073659785 + 11 | 1073659785 + | 969157980 (10 rows) select min(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2654,8 +2784,6 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -2663,6 +2791,8 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -672677796 (10 rows) select stddev(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2690,15 +2820,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+----------- 0 | 623613696 - 1 | 623613596 - 2 | 623588105 - 3 | 623588105 - 4 | 623602577 + 3 | 623600813 + 4 | 623575078 5 | 623602577 6 | 623594116 7 | 623594116 8 | 623620316 9 | 623635702 + 11 | 623598886 + | 648969761 (10 rows) select sum(cint8) from aggfns where cfloat8 > 0 order by 1; @@ -2723,18 +2853,18 @@ select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -72909966030 - 1 | -72928678628 - 2 | -72081777390 - 3 | -72081777390 - 4 | -72842921064 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 + ss | sum +----+--------------- + 0 | -72909966030 + 3 | -72230342563 + 4 | -74475296468 + 5 | -72842921064 + 6 | -72317339795 + 7 | -72317339795 + 8 | -72057098166 + 9 | -72170387501 + 11 | -143378080614 + | 148565173 (10 rows) select max(cts) from aggfns where cfloat8 > 0 order by 1; @@ -2762,8 +2892,6 @@ select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:20 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:40 2021 3 | Fri Jan 01 14:54:19 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:40 2021 @@ -2771,6 +2899,8 @@ select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Sat Jan 02 02:01:00 2021 8 | Sat Jan 02 04:47:39 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:09:56 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns where cfloat8 > 0 order by 1; @@ -2798,8 +2928,6 @@ select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:27 2021 3 | Fri Jan 01 09:21:06 2021 4 | Fri Jan 01 12:07:45 2021 5 | Fri Jan 01 14:54:24 2021 @@ -2807,6 +2935,8 @@ select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 10:05:04 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 > 0 order by 1; @@ -2834,8 +2964,6 @@ select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:20 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:40 2021 PST 3 | Fri Jan 01 14:54:19 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:40 2021 PST @@ -2843,6 +2971,8 @@ select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Sat Jan 02 02:01:00 2021 PST 8 | Sat Jan 02 04:47:39 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:09:56 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 > 0 order by 1; @@ -2870,8 +3000,6 @@ select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:27 2021 PST 3 | Fri Jan 01 09:21:06 2021 PST 4 | Fri Jan 01 12:07:45 2021 PST 5 | Fri Jan 01 14:54:24 2021 PST @@ -2879,6 +3007,8 @@ select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 10:05:04 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 > 0 order by 1; @@ -2906,8 +3036,6 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -2915,6 +3043,8 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5013570566948130 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 > 0 order by 1; @@ -2942,15 +3072,15 @@ select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 + 3 | 9934 + 4 | 9932 5 | 9943 6 | 9944 7 | 9944 8 | 9943 9 | 9943 + 11 | 19896 + | 8 (10 rows) select max(s) from aggfns where cfloat8 > 0 order by 1; @@ -2978,8 +3108,6 @@ select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -2987,6 +3115,8 @@ select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 > 0 order by 1; @@ -3014,8 +3144,6 @@ select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3023,6 +3151,8 @@ select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 > 0 order by 1; @@ -3047,18 +3177,18 @@ select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50331713731225271878 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 > 0 order by 1; @@ -3086,31 +3216,31 @@ select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+------- 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 + 3 | 29802 + 4 | 39728 5 | 49715 6 | 59664 7 | 69608 8 | 79544 9 | 89487 + 11 | 29871 + | 24 (10 rows) select avg(ss) from aggfns where cfloat8 > 0 order by 1; avg -------------------- - 4.5000804586141004 + 6.4010379996379071 (1 row) select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | avg ---+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0077441416071608 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -3122,8 +3252,6 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | avg ----+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -3131,22 +3259,60 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 > 0 order by 1; + count +------- + 99422 +(1 row) + +select s, count(ss) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 9943 + 1 | 9943 + 2 | 9942 + 3 | 9934 + 4 | 9943 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 9943 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + 11 | 19896 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 > 0 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -3158,8 +3324,6 @@ select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3167,6 +3331,8 @@ select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 > 0 order by 1; @@ -3179,8 +3345,8 @@ select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -3194,8 +3360,6 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3203,35 +3367,35 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 > 0 order by 1; stddev -------------------- - 2.8722957659869625 + 3.3528295838273201 (1 row) select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.23271112137690657933 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -3239,42 +3403,44 @@ select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 > 0 order by 1; sum -------- - 447443 + 636404 (1 row) select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 + s | sum +---+-------- + 0 | 0 + 1 | 109373 + 2 | 109362 + 3 | 29802 + 4 | 39849 + 5 | 49715 + 6 | 59664 + 7 | 69608 + 8 | 79544 + 9 | 89487 (10 rows) select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 + ss | sum +----+-------- + 0 | 0 + 3 | 29802 + 4 | 39728 + 5 | 49715 + 6 | 59664 + 7 | 69608 + 8 | 79544 + 9 | 89487 + 11 | 218856 + | (10 rows) select max(t) from aggfns where cfloat8 > 0 order by 1; @@ -3302,8 +3468,6 @@ select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; ss | max ----+-------- 0 | 19999 - 1 | 30000 - 2 | 39999 3 | 49998 4 | 60000 5 | 69999 @@ -3311,6 +3475,8 @@ select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 89999 8 | 99998 9 | 110000 + 11 | 58135 + | 49491 (10 rows) select min(t) from aggfns where cfloat8 > 0 order by 1; @@ -3338,8 +3504,6 @@ select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20006 3 | 30005 4 | 40004 5 | 50003 @@ -3347,6 +3511,44 @@ select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 32643 +(10 rows) + +select count(*) from aggfns where cfloat8 <= 0 order by 1; + count +-------- + 100570 +(1 row) + +select s, count(*) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 10057 + 1 | 10057 + 2 | 10058 + 3 | 10058 + 4 | 10057 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 10057 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(cdate) from aggfns where cfloat8 <= 0 order by 1; @@ -3374,8 +3576,6 @@ select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-20-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-10-2185 5 | 08-28-2212 @@ -3383,6 +3583,8 @@ select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-04-2322 + 11 | 01-24-2183 + | 08-15-2153 (10 rows) select min(cdate) from aggfns where cfloat8 <= 0 order by 1; @@ -3410,8 +3612,6 @@ select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------ 0 | 01-04-2021 - 1 | 05-21-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -3419,6 +3619,8 @@ select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 09-01-2212 8 | 01-17-2240 9 | 06-03-2267 + 11 | 05-21-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3446,15 +3648,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+------------------- 0 | 0.273710566446533 - 1 | NaN - 2 | Infinity - 3 | 0.271225418012403 - 4 | 0.274902188431565 + 3 | 0.281539709766287 + 4 | 0.290259015901558 5 | 0.278701234893647 6 | 0.279196201482741 7 | 0.281055561785383 8 | 0.276832673694496 9 | 0.276832673694496 + 11 | NaN + | -9.14947360483083 (10 rows) select count(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3482,15 +3684,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 + 3 | 10047 + 4 | 10049 5 | 10057 6 | 10056 7 | 10056 8 | 10057 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3515,18 +3717,18 @@ select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3554,8 +3756,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+---------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -49.9756 4 | -49.9756 5 | -49.9756 @@ -3563,6 +3763,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3590,15 +3792,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1 ss | stddev ----+------------------ 0 | 28.8948722701767 - 1 | NaN - 2 | NaN - 3 | 28.8971947735822 - 4 | 28.8962786797298 + 3 | 28.8951497341689 + 4 | 28.8918331282339 5 | 28.8969485514879 6 | 28.898342825597 7 | 28.8981465590944 8 | 28.8998126918449 9 | 28.8998126918449 + 11 | NaN + | 30.6521210689863 (10 rows) select sum(cfloat4) from aggfns where cfloat8 <= 0 order by 1; @@ -3626,15 +3828,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- 0 | 2752.71 - 1 | NaN - 2 | Infinity - 3 | 2727.99 - 4 | 2764.69 + 3 | 2828.63 + 4 | 2916.81 5 | 2802.9 6 | 2807.6 7 | 2826.29 8 | 2784.11 9 | 2784.11 + 11 | NaN + | -100.644 (10 rows) select avg(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3662,15 +3864,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+------------------- 0 | -25.0026878159296 - 1 | -25.0026878159296 - 2 | -25.0037259853644 - 3 | -25.0033035766331 - 4 | -25.0044243209649 + 3 | -25.0067336719196 + 4 | -24.9970119951125 5 | -25.0071564832908 6 | -25.0084381401581 7 | -25.0089627629465 8 | -25.0089281362381 9 | -25.0089281362381 + 11 | -25.0069089689736 + | -21.870379272679 (10 rows) select max(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3698,8 +3900,6 @@ select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----------------------- 0 | -0.000542588531970978 - 1 | -0.000542588531970978 - 2 | -0.000542588531970978 3 | -0.000542588531970978 4 | -0.000542588531970978 5 | -0.000542588531970978 @@ -3707,6 +3907,8 @@ select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -0.000542588531970978 8 | -0.000542588531970978 9 | -0.000542588531970978 + 11 | -0.000542588531970978 + | -4.53631093259901 (10 rows) select min(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3734,8 +3936,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -3743,6 +3943,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3770,15 +3972,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1 ss | stddev ----+------------------ 0 | 14.4821730365752 - 1 | 14.4821730365752 - 2 | 14.4818272972739 - 3 | 14.4815478866618 - 4 | 14.48183169158 + 3 | 14.485819356309 + 4 | 14.4810339821535 5 | 14.4805923063393 6 | 14.4807418968606 7 | 14.4812687827813 8 | 14.4805491499824 9 | 14.4805491499824 + 11 | 14.4820374611522 + | 9.77628724519737 (10 rows) select sum(cfloat8) from aggfns where cfloat8 <= 0 order by 1; @@ -3806,15 +4008,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------------------- 0 | -251452.031364804 - 1 | -251452.031364804 - 2 | -251487.475960795 - 3 | -251483.227373776 - 4 | -251469.495395944 + 3 | -251242.653201777 + 4 | -251194.973538886 5 | -251496.972752456 6 | -251484.85393743 7 | -251490.12954419 8 | -251514.790266147 9 | -251514.790266147 + 11 | -503214.029182657 + | -240.574171999469 (10 rows) select avg(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3839,18 +4041,18 @@ select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -145.9491390464815368 - 1 | -146.0055732484076433 - 2 | -145.5036823248407643 - 3 | -144.9877599761170266 - 4 | -141.3792931806869089 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 + ss | avg +----+------------------------ + 0 | -145.9491390464815368 + 3 | -143.3365212193664077 + 4 | -139.6013749128225565 + 5 | -139.5590167197452229 + 6 | -141.8382440772446745 + 7 | -144.4554140127388535 + 8 | -137.4765033851055356 + 9 | -144.4668060117447994 + 11 | -146.6405192996418623 + | -1651.8181818181818182 (10 rows) select max(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3878,8 +4080,6 @@ select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -3887,6 +4087,8 @@ select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 10616 (10 rows) select min(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3914,8 +4116,6 @@ select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -3923,6 +4123,8 @@ select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3950,15 +4152,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+------------------- 0 | 9538.832178541630 - 1 | 9537.717255354464 - 2 | 9540.157933140146 - 3 | 9535.281475740805 - 4 | 9537.335027198989 + 3 | 9535.623908566148 + 4 | 9537.357537825379 5 | 9538.686769657499 6 | 9537.494931550558 7 | 9538.995155888144 8 | 9537.123911034158 9 | 9537.962959664725 + 11 | 9538.688016316899 + | 9537.230025727405 (10 rows) select sum(cint2) from aggfns where cfloat8 <= 0 order by 1; @@ -3986,15 +4188,15 @@ select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- 0 | -1466351 - 1 | -1467064 - 2 | -1462021 - 3 | -1456982 - 4 | -1420155 + 3 | -1438812 + 4 | -1401179 5 | -1402289 6 | -1424907 7 | -1451488 8 | -1380814 9 | -1451458 + 11 | -2948061 + | -18170 (10 rows) select avg(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4022,15 +4224,15 @@ select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+----------------------- 0 | -2611631.507507208909 - 1 | -2611631.507507208909 - 2 | -2609754.938158679658 - 3 | -2572787.244482004375 - 4 | -2583154.535149647012 + 3 | -2371975.736040609137 + 4 | -2420650.042193253060 5 | -2738485.569155811872 6 | -2660373.598150357995 7 | -2578784.074681782021 8 | -2647231.455304762852 9 | -2647231.455304762852 + 11 | -2691833.530040252447 + | -185986716.81818182 (10 rows) select max(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4058,8 +4260,6 @@ select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -4067,6 +4267,8 @@ select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 556763469 (10 rows) select min(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4094,8 +4296,6 @@ select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -4103,6 +4303,8 @@ select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -888962001 (10 rows) select stddev(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4130,15 +4332,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+----------- 0 | 618765816 - 1 | 618765816 - 2 | 618735080 - 3 | 618695738 - 4 | 618725626 + 3 | 618865631 + 4 | 618722231 5 | 618719952 6 | 618701125 7 | 618716683 8 | 618723996 9 | 618723996 + 11 | 618736738 + | 415688814 (10 rows) select sum(cint4) from aggfns where cfloat8 <= 0 order by 1; @@ -4166,15 +4368,15 @@ select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+-------------- 0 | -26265178071 - 1 | -26265178071 - 2 | -26248915168 - 3 | -25877094105 - 4 | -25978785160 + 3 | -23831240220 + 4 | -24325112274 5 | -27540949369 6 | -26752716903 7 | -25932252655 8 | -26623206746 9 | -26623206746 + 11 | -54167766125 + | -2045853885 (10 rows) select avg(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4202,15 +4404,15 @@ select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------- 0 | 1609068.184846375659 - 1 | 1609068.184846375659 - 2 | 1561674.145953469875 - 3 | 1654097.121694173792 - 4 | 1574613.534354181167 + 3 | 1911095.221857270827 + 4 | 1427463.756393671012 5 | 1583685.317888038182 6 | 1613166.887529832936 7 | 1554490.104514717582 8 | 1568383.139206522820 9 | 1568383.139206522820 + 11 | 1658849.193559608408 + | -233078622.18181818 (10 rows) select max(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4238,8 +4440,6 @@ select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -4247,6 +4447,8 @@ select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4274,8 +4476,6 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------- 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 3 | -1073053412 4 | -1073053412 5 | -1073053412 @@ -4283,6 +4483,8 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | -1073053412 8 | -1073053412 9 | -1073053412 + 11 | -1073053412 + | -796158533 (10 rows) select stddev(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4310,15 +4512,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+----------- 0 | 617360997 - 1 | 617360997 - 2 | 617348601 - 3 | 617433171 - 4 | 617412408 + 3 | 617445433 + 4 | 617369297 5 | 617401473 6 | 617425094 7 | 617462874 8 | 617433744 9 | 617433744 + 11 | 617360997 + | 586053845 (10 rows) select sum(cint8) from aggfns where cfloat8 <= 0 order by 1; @@ -4346,15 +4548,15 @@ select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------------- 0 | 16182398735 - 1 | 16182398735 - 2 | 15707318560 - 3 | 16636908850 - 4 | 15835888315 + 3 | 19200773694 + 4 | 14344583288 5 | 15927123242 6 | 16222006221 7 | 15631952491 8 | 15773229231 9 | 15773229231 + 11 | 33381022322 + | -2563864844 (10 rows) select max(cts) from aggfns where cfloat8 <= 0 order by 1; @@ -4382,8 +4584,6 @@ select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:00 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:00 2021 5 | Fri Jan 01 20:27:41 2021 @@ -4391,6 +4591,8 @@ select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:20 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:28:19 2021 (10 rows) select min(cts) from aggfns where cfloat8 <= 0 order by 1; @@ -4418,8 +4620,6 @@ select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:04 2021 - 1 | Fri Jan 01 03:47:43 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -4427,6 +4627,8 @@ select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Fri Jan 01 20:27:45 2021 8 | Fri Jan 01 23:14:24 2021 9 | Sat Jan 02 02:01:03 2021 + 11 | Fri Jan 01 03:47:43 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 <= 0 order by 1; @@ -4454,8 +4656,6 @@ select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:00 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:00 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -4463,6 +4663,8 @@ select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:20 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:28:19 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 <= 0 order by 1; @@ -4490,8 +4692,6 @@ select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:04 2021 PST - 1 | Fri Jan 01 03:47:43 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -4499,6 +4699,8 @@ select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | Fri Jan 01 20:27:45 2021 PST 8 | Fri Jan 01 23:14:24 2021 PST 9 | Sat Jan 02 02:01:03 2021 PST + 11 | Fri Jan 01 03:47:43 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4526,8 +4728,6 @@ select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -4535,6 +4735,8 @@ select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5010187347810963 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4562,15 +4764,15 @@ select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 + 3 | 10047 + 4 | 10049 5 | 10057 6 | 10056 7 | 10056 8 | 10057 9 | 10057 + 11 | 20123 + | 11 (10 rows) select max(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4598,8 +4800,6 @@ select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4607,6 +4807,8 @@ select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4634,8 +4836,6 @@ select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4643,6 +4843,8 @@ select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4667,18 +4869,18 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50239111765906328317 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 <= 0 order by 1; @@ -4706,31 +4908,31 @@ select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+------- 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 + 3 | 30141 + 4 | 40196 5 | 50285 6 | 60336 7 | 70392 8 | 80456 9 | 90513 + 11 | 30205 + | 33 (10 rows) select avg(ss) from aggfns where cfloat8 <= 0 order by 1; avg -------------------- - 4.4999204534155315 + 6.4009387523742281 (1 row) select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0055682609127971 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -4742,8 +4944,6 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -4751,22 +4951,60 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 <= 0 order by 1; + count +-------- + 100559 +(1 row) + +select s, count(ss) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 10057 + 1 | 10057 + 2 | 10058 + 3 | 10047 + 4 | 10057 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 10057 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + 11 | 20123 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 <= 0 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -4778,8 +5016,6 @@ select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4787,6 +5023,8 @@ select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 <= 0 order by 1; @@ -4799,8 +5037,8 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -4814,8 +5052,6 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4823,35 +5059,35 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 <= 0 order by 1; stddev -------------------- - 2.8722956022845549 + 3.3528527058531930 (1 row) select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.19735930141067535100 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -4859,42 +5095,44 @@ select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 <= 0 order by 1; sum -------- - 452557 + 643672 (1 row) select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 + s | sum +---+-------- + 0 | 0 + 1 | 110627 + 2 | 110638 + 3 | 30141 + 4 | 40284 + 5 | 50285 + 6 | 60336 + 7 | 70392 + 8 | 80456 + 9 | 90513 (10 rows) select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 + ss | sum +----+-------- + 0 | 0 + 3 | 30141 + 4 | 40196 + 5 | 50285 + 6 | 60336 + 7 | 70392 + 8 | 80456 + 9 | 90513 + 11 | 221353 + | (10 rows) select max(t) from aggfns where cfloat8 <= 0 order by 1; @@ -4922,8 +5160,6 @@ select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 29999 - 2 | 40000 3 | 50000 4 | 59999 5 | 70000 @@ -4931,6 +5167,8 @@ select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 90000 8 | 100000 9 | 109999 + 11 | 59192 + | 48438 (10 rows) select min(t) from aggfns where cfloat8 <= 0 order by 1; @@ -4958,8 +5196,6 @@ select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | min ----+------- 0 | 3 - 1 | 10002 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -4967,6 +5203,44 @@ select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 70004 8 | 80003 9 | 90002 + 11 | 10002 + | 30537 +(10 rows) + +select count(*) from aggfns where cfloat8 < 1000 order by 1; + count +-------- + 200000 +(1 row) + +select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cdate) from aggfns where cfloat8 < 1000 order by 1; @@ -4994,8 +5268,6 @@ select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 3 | 11-24-2157 4 | 04-11-2185 5 | 08-28-2212 @@ -5003,6 +5275,8 @@ select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 06-01-2267 8 | 10-17-2294 9 | 03-05-2322 + 11 | 01-24-2183 + | 07-03-2156 (10 rows) select min(cdate) from aggfns where cfloat8 < 1000 order by 1; @@ -5030,8 +5304,6 @@ select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------ 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 3 | 02-22-2103 4 | 07-10-2130 5 | 11-25-2157 @@ -5039,6 +5311,8 @@ select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 08-29-2212 8 | 01-15-2240 9 | 06-02-2267 + 11 | 05-20-2048 + | 08-11-2104 (10 rows) select avg(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5066,15 +5340,15 @@ select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -0.13252146150968 + 4 | -0.124977103379316 5 | -0.130611110996222 6 | -0.131984978889441 7 | -0.131050092529273 8 | -0.131313872741675 9 | -0.132765194868064 + 11 | NaN + | -5.91588952823689 (10 rows) select count(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5102,15 +5376,15 @@ select ss, count(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5135,18 +5409,18 @@ select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + ss | max +----+--------- + 0 | 49.9977 + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 + 11 | NaN + | 48.478 (10 rows) select min(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5174,8 +5448,6 @@ select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----------- 0 | -49.9756 - 1 | NaN - 2 | -49.9756 3 | -Infinity 4 | -49.9756 5 | -49.9756 @@ -5183,6 +5455,8 @@ select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -49.9756 8 | -49.9756 9 | -49.9756 + 11 | NaN + | -46.7478 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5210,15 +5484,15 @@ select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by ss | stddev ----+------------------ 0 | 28.8941380063427 - 1 | NaN - 2 | NaN 3 | NaN - 4 | 28.8948189281654 + 4 | 28.89302954083 5 | 28.8951827753267 6 | 28.8960531969495 7 | 28.8959678301628 8 | 28.8963276918371 9 | 28.8968307405966 + 11 | NaN + | 27.2867943876683 (10 rows) select sum(cfloat4) from aggfns where cfloat8 < 1000 order by 1; @@ -5246,15 +5520,15 @@ select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+----------- 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 + 4 | -2497.17 5 | -2612.22 6 | -2639.7 7 | -2621 8 | -2626.28 9 | -2655.3 + 11 | NaN + | -112.402 (10 rows) select avg(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5282,15 +5556,15 @@ select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+-------------------- 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 + 3 | -0.128550004763072 + 4 | -0.129264304572168 5 | -0.131984980024863 6 | -0.131050093692029 7 | -0.13131387403002 8 | -0.132765196124092 9 | -0.134423591727391 + 11 | -0.131587538323368 + | -4.30903203025656 (10 rows) select max(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5315,18 +5589,18 @@ select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 + ss | max +----+------------------ + 0 | 49.997744965367 + 3 | 49.997744965367 + 4 | 49.997744965367 + 5 | 49.997744965367 + 6 | 49.997744965367 + 7 | 49.997744965367 + 8 | 49.997744965367 + 9 | 49.997744965367 + 11 | 49.997744965367 + | 49.2015035590157 (10 rows) select min(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5354,8 +5628,6 @@ select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------------- 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 3 | -49.9755693599582 4 | -49.9755693599582 5 | -49.9755693599582 @@ -5363,6 +5635,8 @@ select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -49.9755693599582 8 | -49.9755693599582 9 | -49.9755693599582 + 11 | -49.9755693599582 + | -38.3512130472809 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5390,15 +5664,15 @@ select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by ss | stddev ----+------------------ 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 + 3 | 28.8988694216911 + 4 | 28.8937408619903 5 | 28.8960532056265 6 | 28.8959678388464 7 | 28.8963277006942 8 | 28.8968307494196 9 | 28.8953209642426 + 11 | 28.8954978116663 + | 24.556507133269 (10 rows) select sum(cfloat8) from aggfns where cfloat8 < 1000 order by 1; @@ -5426,15 +5700,15 @@ select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+------------------- 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 + 3 | -2568.55764517095 + 4 | -2582.83006965648 5 | -2639.69960049726 6 | -2621.00187384058 7 | -2626.2774806004 8 | -2655.30392248183 9 | -2688.47183454782 + 11 | -5266.00169616286 + | -81.8716085748747 (10 rows) select avg(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5459,18 +5733,18 @@ select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 + ss | avg +----+----------------------- + 0 | -42.2972824182973825 + 3 | -42.6071034966436229 + 4 | -40.0837090471896604 + 5 | -43.5287022671537961 + 6 | -41.7711325759471498 + 7 | -41.3288123717531655 + 8 | -40.6353035383614434 + 9 | -43.1119563585406136 + 11 | -42.9734623946374528 + | -335.0000000000000000 (10 rows) select max(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5498,8 +5772,6 @@ select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------- 0 | 16383 - 1 | 16383 - 2 | 16383 3 | 16383 4 | 16383 5 | 16383 @@ -5507,6 +5779,8 @@ select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 16383 8 | 16383 9 | 16383 + 11 | 16383 + | 13720 (10 rows) select min(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5534,8 +5808,6 @@ select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+-------- 0 | -16375 - 1 | -16375 - 2 | -16375 3 | -16375 4 | -16375 5 | -16375 @@ -5543,6 +5815,8 @@ select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -16375 8 | -16375 9 | -16375 + 11 | -16375 + | -15206 (10 rows) select stddev(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5570,15 +5844,15 @@ select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+------------------- 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 + 3 | 9466.351508971864 + 4 | 9469.021659499615 5 | 9467.599133444078 6 | 9468.362090451302 7 | 9467.745653535755 8 | 9466.743345080951 9 | 9468.145452253715 + 11 | 9467.946206136906 + | 9796.780548277639 (10 rows) select sum(cint2) from aggfns where cfloat8 < 1000 order by 1; @@ -5603,18 +5877,18 @@ select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 + ss | sum +----+---------- + 0 | -845142 + 3 | -850523 + 4 | -800151 + 5 | -869747 + 6 | -834629 + 7 | -825791 + 8 | -811934 + 9 | -861420 + 11 | -1718122 + | -6365 (10 rows) select avg(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5642,15 +5916,15 @@ select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+----------------------- 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 + 3 | -2682566.613082428307 + 4 | -2753845.761523447275 5 | -2850351.637450000000 6 | -2845789.891100000000 7 | -2804766.678700000000 8 | -2834269.365200000000 9 | -2814193.446750000000 + 11 | -2846001.238586671331 + | -146005017.57894737 (10 rows) select max(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5678,8 +5952,6 @@ select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -5687,6 +5959,8 @@ select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 978482473 (10 rows) select min(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5714,8 +5988,6 @@ select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -5723,6 +5995,8 @@ select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -960881516 (10 rows) select stddev(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5750,15 +6024,15 @@ select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+----------- 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 + 3 | 620502162 + 4 | 620460588 5 | 620498014 6 | 620492575 7 | 620500389 8 | 620519080 9 | 620517247 + 11 | 620490348 + | 569369090 (10 rows) select sum(cint4) from aggfns where cfloat8 < 1000 order by 1; @@ -5783,18 +6057,18 @@ select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 + ss | sum +----+--------------- + 0 | -58384962420 + 3 | -53600363496 + 4 | -55024592161 + 5 | -57007032749 + 6 | -56915797822 + 7 | -56095333574 + 8 | -56685387304 + 9 | -56283868935 + 11 | -113894123567 + | -2774095334 (10 rows) select avg(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5822,15 +6096,15 @@ select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+----------------------- 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 + 3 | -2653999.743206045743 + 4 | -3009394.583854661929 5 | -2845789.891100000000 6 | -2804766.678700000000 7 | -2834269.365200000000 8 | -2814193.446750000000 9 | -2819857.913500000000 + 11 | -2748620.862390364577 + | -127121035.31578947 (10 rows) select max(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5858,8 +6132,6 @@ select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------ 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 3 | 1073660631 4 | 1073660631 5 | 1073660631 @@ -5867,6 +6139,8 @@ select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 1073660631 8 | 1073660631 9 | 1073660631 + 11 | 1073660631 + | 989667573 (10 rows) select min(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5894,8 +6168,6 @@ select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------- 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 3 | -1073184428 4 | -1073184428 5 | -1073184428 @@ -5903,6 +6175,8 @@ select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | -1073184428 8 | -1073184428 9 | -1073184428 + 11 | -1073184428 + | -796158533 (10 rows) select stddev(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5930,15 +6204,15 @@ select ss, stddev(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1 ss | stddev ----+----------- 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 + 3 | 620514804 + 4 | 620462299 5 | 620492575 6 | 620500389 7 | 620519080 8 | 620517247 9 | 620524975 + 11 | 620478168 + | 609007799 (10 rows) select sum(cint8) from aggfns where cfloat8 < 1000 order by 1; @@ -5963,18 +6237,18 @@ select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 + ss | sum +----+--------------- + 0 | -56727567295 + 3 | -53029568869 + 4 | -60130713180 + 5 | -56915797822 + 6 | -56095333574 + 7 | -56685387304 + 8 | -56283868935 + 9 | -56397158270 + 11 | -109997058292 + | -2415299671 (10 rows) select max(cts) from aggfns where cfloat8 < 1000 order by 1; @@ -6002,8 +6276,6 @@ select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+-------------------------- 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 3 | Fri Jan 01 14:54:21 2021 4 | Fri Jan 01 17:41:01 2021 5 | Fri Jan 01 20:27:41 2021 @@ -6011,6 +6283,8 @@ select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 8 | Sat Jan 02 04:47:41 2021 9 | Sat Jan 02 07:34:21 2021 + 11 | Fri Jan 01 17:27:33 2021 + | Fri Jan 01 14:45:52 2021 (10 rows) select min(cts) from aggfns where cfloat8 < 1000 order by 1; @@ -6038,8 +6312,6 @@ select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 3 | Fri Jan 01 09:21:02 2021 4 | Fri Jan 01 12:07:42 2021 5 | Fri Jan 01 14:54:22 2021 @@ -6047,6 +6319,8 @@ select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 8 | Fri Jan 01 23:14:22 2021 9 | Sat Jan 02 02:01:02 2021 + 11 | Fri Jan 01 03:47:42 2021 + | Fri Jan 01 09:29:58 2021 (10 rows) select max(ctstz) from aggfns where cfloat8 < 1000 order by 1; @@ -6074,8 +6348,6 @@ select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+------------------------------ 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST 3 | Fri Jan 01 14:54:21 2021 PST 4 | Fri Jan 01 17:41:01 2021 PST 5 | Fri Jan 01 20:27:41 2021 PST @@ -6083,6 +6355,8 @@ select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Sat Jan 02 02:01:01 2021 PST 8 | Sat Jan 02 04:47:41 2021 PST 9 | Sat Jan 02 07:34:21 2021 PST + 11 | Fri Jan 01 17:27:33 2021 PST + | Fri Jan 01 14:45:52 2021 PST (10 rows) select min(ctstz) from aggfns where cfloat8 < 1000 order by 1; @@ -6110,8 +6384,6 @@ select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST 3 | Fri Jan 01 09:21:02 2021 PST 4 | Fri Jan 01 12:07:42 2021 PST 5 | Fri Jan 01 14:54:22 2021 PST @@ -6119,6 +6391,8 @@ select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | Fri Jan 01 20:27:42 2021 PST 8 | Fri Jan 01 23:14:22 2021 PST 9 | Sat Jan 02 02:01:02 2021 PST + 11 | Fri Jan 01 03:47:42 2021 PST + | Fri Jan 01 09:29:58 2021 PST (10 rows) select avg(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6146,8 +6420,6 @@ select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -6155,6 +6427,8 @@ select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 1.5011869362053025 + | 3.0000000000000000 (10 rows) select count(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6182,15 +6456,15 @@ select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | count ----+------- 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 + 3 | 19981 + 4 | 19981 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 + 11 | 40019 + | 19 (10 rows) select max(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6218,8 +6492,6 @@ select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6227,6 +6499,8 @@ select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 4 + | 3 (10 rows) select min(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6254,8 +6528,6 @@ select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6263,6 +6535,8 @@ select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 1 + | 3 (10 rows) select stddev(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6287,18 +6561,18 @@ select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; (10 rows) select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0.50284545977155885187 + | 0 (10 rows) select sum(s) from aggfns where cfloat8 < 1000 order by 1; @@ -6326,31 +6600,31 @@ select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 60076 + | 57 (10 rows) select avg(ss) from aggfns where cfloat8 < 1000 order by 1; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -6362,8 +6636,6 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 @@ -6371,22 +6643,60 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + +select count(ss) from aggfns where cfloat8 < 1000 order by 1; + count +-------- + 199981 +(1 row) + +select s, count(ss) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 19981 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select ss, count(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 20000 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 + | 0 (10 rows) select max(ss) from aggfns where cfloat8 < 1000 order by 1; max ----- - 9 + 11 (1 row) select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 - 4 | 4 + 4 | 11 5 | 5 6 | 6 7 | 7 @@ -6398,8 +6708,6 @@ select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6407,6 +6715,8 @@ select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select min(ss) from aggfns where cfloat8 < 1000 order by 1; @@ -6419,8 +6729,8 @@ select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 + 1 | 11 + 2 | 11 3 | 3 4 | 4 5 | 5 @@ -6434,8 +6744,6 @@ select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6443,35 +6751,35 @@ select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 7 8 | 8 9 | 9 + 11 | 11 + | (10 rows) select stddev(ss) from aggfns where cfloat8 < 1000 order by 1; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0.21565737387148452722 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | stddev ----+-------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -6479,22 +6787,24 @@ select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 0 8 | 0 9 | 0 + 11 | 0 + | (10 rows) select sum(ss) from aggfns where cfloat8 < 1000 order by 1; - sum --------- - 900000 + sum +--------- + 1280076 (1 row) select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by 1; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 1 | 220000 + 2 | 220000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 @@ -6506,15 +6816,15 @@ select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 11 | 440209 + | (10 rows) select max(t) from aggfns where cfloat8 < 1000 order by 1; @@ -6542,8 +6852,6 @@ select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | max ----+-------- 0 | 20000 - 1 | 30000 - 2 | 40000 3 | 50000 4 | 60000 5 | 70000 @@ -6551,6 +6859,8 @@ select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 90000 8 | 100000 9 | 110000 + 11 | 59192 + | 49491 (10 rows) select min(t) from aggfns where cfloat8 < 1000 order by 1; @@ -6578,8 +6888,6 @@ select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | min ----+------- 0 | 1 - 1 | 10001 - 2 | 20001 3 | 30001 4 | 40001 5 | 50001 @@ -6587,8 +6895,26 @@ select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 70001 8 | 80001 9 | 90001 + 11 | 10001 + | 30537 (10 rows) +select count(*) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select max(cdate) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7207,6 +7533,22 @@ select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) +select count(ss) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select s, count(ss) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select ss, count(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select max(ss) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7302,6 +7644,41 @@ select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) +select count(*) from aggfns where cint2 is null order by 1; + count +------- + 190 +(1 row) + +select s, count(*) from aggfns where cint2 is null group by s order by 1; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select ss, count(*) from aggfns where cint2 is null group by ss order by 1; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select avg(cint2) from aggfns where cint2 is null order by 1; avg ----- @@ -7327,8 +7704,6 @@ select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; ss | avg ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7336,7 +7711,8 @@ select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select count(cint2) from aggfns where cint2 is null order by 1; count @@ -7363,8 +7739,6 @@ select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; ss | count ----+------- 0 | 0 - 1 | 0 - 2 | 0 3 | 0 4 | 0 5 | 0 @@ -7372,7 +7746,8 @@ select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 0 8 | 0 9 | 0 -(10 rows) + 11 | 0 +(9 rows) select max(cint2) from aggfns where cint2 is null order by 1; max @@ -7399,8 +7774,6 @@ select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; ss | max ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7408,7 +7781,8 @@ select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select min(cint2) from aggfns where cint2 is null order by 1; min @@ -7435,8 +7809,6 @@ select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; ss | min ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7444,7 +7816,8 @@ select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select stddev(cint2) from aggfns where cint2 is null order by 1; stddev @@ -7471,8 +7844,6 @@ select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; ss | stddev ----+-------- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7480,7 +7851,8 @@ select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) select sum(cint2) from aggfns where cint2 is null order by 1; sum @@ -7507,8 +7879,6 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; ss | sum ----+----- 0 | - 1 | - 2 | 3 | 4 | 5 | @@ -7516,5 +7886,6 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; 7 | 8 | 9 | -(10 rows) + 11 | +(9 rows) diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 35ec690bf07..b3bad3f812f 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -12,38 +12,57 @@ $$ LANGUAGE SQL; \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, cfloat4 float4, cfloat8 float8, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000::int + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, + (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, + (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t + 4) * 100)::float4 end as cfloat4, + (mix(s + t + 5) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; + alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); select count(compress_chunk(x)) from show_chunks('aggfns') x; +alter table aggfns add column ss int default 11; + +insert into aggfns +select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1; + +select count(compress_chunk(x)) from show_chunks('aggfns') x; + analyze aggfns; ---- Uncomment to generate reference. Note that there are minor discrepancies @@ -72,7 +91,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -99,8 +119,9 @@ where end and case + when variable = '*' then function = 'count' when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') + when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') else true end From cd7a1dce4bb2ac6798954493eb90b9feb1be9fc8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:06:42 +0100 Subject: [PATCH 038/242] spelling --- tsl/src/nodes/vector_agg/function/functions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 70785a5d802..18c43c163f1 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -29,7 +29,7 @@ typedef struct /* * Add the rows of the given arrow array to aggregate function states given - * by the respecitve offsets. + * by the respective offsets. */ void (*agg_many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); From 4c833b79366fefaf93108ad5e4fd6cb6d4411cc4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 21:32:08 +0100 Subject: [PATCH 039/242] license --- tsl/src/import/ts_simplehash.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index 18c3f73bb6a..5197e6d5bde 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -1,7 +1,14 @@ /* - * This file and its contents are licensed under the Apache License 2.0. + * This file and its contents are licensed under the Timescale License. * Please see the included NOTICE for copyright information and - * LICENSE-APACHE for a copy of the license. + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This file contains source code that was copied and/or modified from + * the PostgreSQL database, which is licensed under the open-source + * PostgreSQL License. Please see the NOTICE at the top level + * directory for a copy of the PostgreSQL License. */ /* From 4b2b4251d97f0b06cb95776f883b3d00a04d9e8e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:45:18 +0100 Subject: [PATCH 040/242] separate key storage --- .../nodes/vector_agg/grouping_policy_hash.c | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 8787e8dcb8a..a2e1b45121e 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -125,12 +125,11 @@ typedef struct HashTableFunctions functions; /* - * We have to track whether we are in the mode of returning the partial - * aggregation results, and also use a hash table iterator to track our - * progress between emit() calls. + * Whether we are in the mode of returning the partial aggregation results. + * Track the last returned aggregate state offset if we are. */ bool returning_results; - struct h_iterator iter; + uint32 last_returned_key; /* * In single-column grouping, we store the null key outside of the hash @@ -151,7 +150,7 @@ typedef struct * it in the policy because it is potentially too big to keep on stack, and * we don't want to reallocate it each batch. */ - uint32 *offsets; + uint32 *restrict offsets; uint64 num_allocated_offsets; /* @@ -163,8 +162,8 @@ typedef struct uint64 allocated_aggstate_rows; uint64 key_bytes; - uint64 allocated_key_rows; - void *keys; + uint64 num_allocated_keys; + void *restrict keys; /* * Some statistics for debugging. @@ -196,11 +195,13 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) } Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); - policy->key_bytes = g->value_bytes; + // GroupingColumn *g = linitial(policy->output_grouping_columns); + // policy->key_bytes = g->value_bytes; + policy->key_bytes = sizeof(Datum); Assert(policy->key_bytes > 0); - policy->allocated_key_rows = policy->allocated_aggstate_rows; - policy->keys = palloc0(policy->allocated_key_rows * policy->key_bytes); + + policy->num_allocated_keys = policy->allocated_aggstate_rows; + policy->keys = palloc(policy->key_bytes * policy->num_allocated_keys); policy->functions = (HashTableFunctions){ .create = (void *(*) (MemoryContext, uint32, void *) ) h_create, @@ -335,7 +336,9 @@ fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, HashEntry *restrict entry = h_insert(table, key, &found); if (!found) { - entry->agg_state_index = next_unused_state_index++; + const int index = next_unused_state_index++; + entry->agg_state_index = index; + ((Datum *restrict) policy->keys)[index] = key; } offsets[row] = entry->agg_state_index; } @@ -601,13 +604,24 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * first run. */ const uint32 hash_keys = policy->functions.get_num_keys(policy->table); - const uint32 last_initialized_state_index = hash_keys ? hash_keys + 2 : 1; - uint32 next_unused_state_index = hash_keys + 2; + const uint32 first_uninitialized_state_index = hash_keys ? hash_keys + 2 : 1; + + /* + * Allocate enough storage for keys, given that each bach row might be + * a separate new key. + */ + const uint32 num_possible_keys = first_uninitialized_state_index + (end_row - start_row); + if (num_possible_keys > policy->num_allocated_keys) + { + policy->num_allocated_keys = num_possible_keys; + policy->keys = repalloc(policy->keys, policy->key_bytes * num_possible_keys); + } /* * Match rows to aggregation states using a hash table. */ Assert((size_t) end_row <= policy->num_allocated_offsets); + uint32 next_unused_state_index = hash_keys + 2; switch ((int) key_column->decompression_type) { case DT_Scalar: @@ -657,7 +671,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Initialize the aggregate function states for the newly added keys. */ - if (next_unused_state_index > last_initialized_state_index) + if (next_unused_state_index > first_uninitialized_state_index) { if (next_unused_state_index > policy->allocated_aggstate_rows) { @@ -674,9 +688,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) { const VectorAggDef *agg_def = lfirst(aggdeflc); - agg_def->func.agg_init(agg_def->func.state_bytes * last_initialized_state_index + + agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + (char *) lfirst(aggstatelc), - next_unused_state_index - last_initialized_state_index); + next_unused_state_index - first_uninitialized_state_index); } } @@ -720,7 +734,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) if (!policy->returning_results) { policy->returning_results = true; - h_start_iterate(policy->table, &policy->iter); + policy->last_returned_key = 1 + !policy->have_null_key; const float keys = policy->functions.get_num_keys(policy->table) + policy->have_null_key; if (keys > 0) @@ -736,18 +750,14 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } } - - HashEntry null_key_entry = { .agg_state_index = 1 }; - HashEntry *entry = h_iterate(policy->table, &policy->iter); - bool key_is_null = false; - if (entry == NULL && policy->have_null_key) + else { - policy->have_null_key = false; - entry = &null_key_entry; - key_is_null = true; + policy->last_returned_key++; } - if (entry == NULL) + const uint32 current_key = policy->last_returned_key; + const uint32 keys_end = policy->functions.get_num_keys(policy->table) + 2; + if (current_key >= keys_end) { policy->returning_results = false; return false; @@ -758,7 +768,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_states = list_nth(policy->per_agg_states, i); - void *agg_state = entry->agg_state_index * agg_def->func.state_bytes + (char *) agg_states; + void *agg_state = current_key * agg_def->func.state_bytes + (char *) agg_states; agg_def->func.agg_emit(agg_state, &aggregated_slot->tts_values[agg_def->output_offset], &aggregated_slot->tts_isnull[agg_def->output_offset]); @@ -766,8 +776,8 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) Assert(list_length(policy->output_grouping_columns) == 1); GroupingColumn *col = linitial(policy->output_grouping_columns); - aggregated_slot->tts_values[col->output_offset] = entry->key; - aggregated_slot->tts_isnull[col->output_offset] = key_is_null; + aggregated_slot->tts_values[col->output_offset] = ((Datum *) policy->keys)[current_key]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == 1; return true; } From 99968619c6e840096ee43ab8f7f0977e1457fabc Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:45:09 +0100 Subject: [PATCH 041/242] specializations and text --- tsl/src/nodes/vector_agg/exec.c | 5 +- .../nodes/vector_agg/grouping_policy_hash.c | 500 +++++------------- .../nodes/vector_agg/grouping_policy_hash.h | 95 ++++ .../vector_agg/hash_table_functions_impl.c | 182 +++++++ tsl/src/nodes/vector_agg/plan.c | 5 + .../nodes/vector_agg/single_fixed_key_impl.c | 43 ++ 6 files changed, 446 insertions(+), 384 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/grouping_policy_hash.h create mode 100644 tsl/src/nodes/vector_agg/hash_table_functions_impl.c create mode 100644 tsl/src/nodes/vector_agg/single_fixed_key_impl.c diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 60aef1dea9b..5580e9295df 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -136,8 +136,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) (GroupingColumn *) linitial(vector_agg_state->output_grouping_columns); DecompressContext *dcontext = &decompress_state->decompress_context; CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; - if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && - (size_t) desc->value_bytes <= sizeof(Datum)) + // if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && + // (size_t) desc->value_bytes <= sizeof(Datum)) + if (desc->type == COMPRESSED_COLUMN) { /* * Hash grouping by a single fixed-size by-value compressed column. diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index a2e1b45121e..0b898c9fcae 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -11,6 +11,7 @@ #include +#include #include #include @@ -19,6 +20,8 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "grouping_policy_hash.h" + #ifdef USE_FLOAT8_BYVAL #define DEBUG_LOG(MSG, ...) elog(DEBUG3, MSG, __VA_ARGS__) #else @@ -34,6 +37,7 @@ * cycle, which is why it is sometimes used in the existing hash table * implementations. */ + #ifdef USE_SSE42_CRC32C #include static pg_attribute_always_inline uint64 @@ -58,120 +62,103 @@ hash64(uint64 x) } #endif -/* - * For the hash table, use the generic Datum key that is mapped to the aggregate - * state index. - */ -typedef struct -{ - Datum key; - uint32 status; - uint32 agg_state_index; -} HashEntry; - -#define SH_PREFIX h -#define SH_ELEMENT_TYPE HashEntry -#define SH_KEY_TYPE Datum -#define SH_KEY key -#define SH_HASH_KEY(tb, key) hash64(key) -#define SH_EQUAL(tb, a, b) a == b -#define SH_SCOPE static inline -#define SH_DECLARE -#define SH_DEFINE -#define SH_ENTRY_EMPTY(entry) (entry->agg_state_index == 0) -#include "import/ts_simplehash.h" - -struct h_hash; - -typedef struct -{ - void *(*create)(MemoryContext context, uint32 initial_rows, void *data); - void (*reset)(void *table); - uint32 (*get_num_keys)(void *table); - uint64 (*get_size_bytes)(void *table); -} HashTableFunctions; - -static uint32 -get_num_keys(void *table) -{ - struct h_hash *hash = (struct h_hash *) table; - return hash->members; -} +#define KEY_VARIANT single_fixed_2 +#define KEY_BYTES 2 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int16 +#define DATUM_TO_CTYPE DatumGetInt16 +#define CTYPE_TO_DATUM Int16GetDatum -static uint64 -get_size_bytes(void *table) -{ - struct h_hash *hash = (struct h_hash *) table; - return hash->members * sizeof(HashEntry); -} +#include "single_fixed_key_impl.c" -/* - * Hash grouping policy. - */ -typedef struct -{ - /* - * We're using data inheritance from the GroupingPolicy. - */ - GroupingPolicy funcs; +#include "hash_table_functions_impl.c" - List *agg_defs; - List *output_grouping_columns; +#define KEY_VARIANT single_fixed_4 +#define KEY_BYTES 4 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int32 +#define DATUM_TO_CTYPE DatumGetInt32 +#define CTYPE_TO_DATUM Int32GetDatum - /* - * The hash table we use for grouping. - */ - void *table; - HashTableFunctions functions; +#include "single_fixed_key_impl.c" - /* - * Whether we are in the mode of returning the partial aggregation results. - * Track the last returned aggregate state offset if we are. - */ - bool returning_results; - uint32 last_returned_key; +#include "hash_table_functions_impl.c" - /* - * In single-column grouping, we store the null key outside of the hash - * table, and it has a reserved aggregate state index 1. We also reset this - * flag after we output the null key during iteration. - */ - bool have_null_key; - /* - * A memory context for aggregate functions to allocate additional data, - * i.e. if they store strings or float8 datum on 32-bit systems. Valid until - * the grouping policy is reset. - */ - MemoryContext agg_extra_mctx; +#define KEY_VARIANT single_fixed_8 +#define KEY_BYTES 8 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int64 +#define DATUM_TO_CTYPE DatumGetInt64 +#define CTYPE_TO_DATUM Int64GetDatum - /* - * Temporary storage of aggregate state offsets for a given batch. We keep - * it in the policy because it is potentially too big to keep on stack, and - * we don't want to reallocate it each batch. - */ - uint32 *restrict offsets; - uint64 num_allocated_offsets; +#include "single_fixed_key_impl.c" - /* - * Storage of aggregate function states, each List entry is the array of - * states for the respective function from agg_defs. The state index 0 is - * invalid, and the state index 1 is reserved for a null key. - */ - List *per_agg_states; - uint64 allocated_aggstate_rows; +#include "hash_table_functions_impl.c" - uint64 key_bytes; - uint64 num_allocated_keys; - void *restrict keys; +static void +store_text_datum(CompressedColumnValues *column_values, int arrow_row) +{ + const uint32 start = ((uint32 *) column_values->buffers[1])[arrow_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[arrow_row + 1] - start; + Assert(value_bytes >= 0); + + const int total_bytes = value_bytes + VARHDRSZ; + Assert(DatumGetPointer(*column_values->output_value) != NULL); + SET_VARSIZE(*column_values->output_value, total_bytes); + memcpy(VARDATA(*column_values->output_value), + &((uint8 *) column_values->buffers[2])[start], + value_bytes); +} - /* - * Some statistics for debugging. - */ - uint64 stat_input_total_rows; - uint64 stat_input_valid_rows; - uint64 stat_bulk_filtered_rows; -} GroupingPolicyHash; +static pg_attribute_always_inline void +single_text_get_key(CompressedColumnValues column, int row, text **restrict key, + bool *restrict valid) +{ + if (unlikely(column.decompression_type == DT_Scalar)) + { + /* Already stored. */ + } + else if (column.decompression_type == DT_ArrowText) + { + store_text_datum(&column, row); + *column.output_isnull = !arrow_row_is_valid(column.buffers[0], row); + } + else if (column.decompression_type == DT_ArrowTextDict) + { + const int16 index = ((int16 *) column.buffers[3])[row]; + store_text_datum(&column, index); + *column.output_isnull = !arrow_row_is_valid(column.buffers[0], row); + } + else + { + pg_unreachable(); + } + *key = (text *) DatumGetPointer(*column.output_value); + *valid = !*column.output_isnull; +} + +static pg_attribute_always_inline text * +single_text_store_key(text *key, Datum *key_storage, MemoryContext key_memory_context) +{ + size_t size = VARSIZE_ANY(key); + text *stored = (text *) MemoryContextAlloc(key_memory_context, size); + memcpy(stored, key, size); + *key_storage = PointerGetDatum(stored); + return stored; +} + +#define KEY_VARIANT single_text +#define KEY_HASH(X) hash_bytes((const unsigned char *) VARDATA_ANY(X), VARSIZE_ANY_EXHDR(X)) +#define KEY_EQUAL(a, b) \ + (VARSIZE_ANY(a) == VARSIZE_ANY(b) && \ + memcmp(VARDATA_ANY(a), VARDATA_ANY(b), VARSIZE_ANY_EXHDR(a)) == 0) +#define SH_STORE_HASH +#define CTYPE text * +#include "hash_table_functions_impl.c" static const GroupingPolicy grouping_policy_hash_functions; @@ -195,20 +182,34 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) } Assert(list_length(policy->output_grouping_columns) == 1); - // GroupingColumn *g = linitial(policy->output_grouping_columns); + GroupingColumn *g = linitial(policy->output_grouping_columns); // policy->key_bytes = g->value_bytes; policy->key_bytes = sizeof(Datum); Assert(policy->key_bytes > 0); policy->num_allocated_keys = policy->allocated_aggstate_rows; policy->keys = palloc(policy->key_bytes * policy->num_allocated_keys); + policy->key_body_mctx = policy->agg_extra_mctx; - policy->functions = (HashTableFunctions){ - .create = (void *(*) (MemoryContext, uint32, void *) ) h_create, - .reset = (void (*)(void *)) h_reset, - .get_num_keys = get_num_keys, - .get_size_bytes = get_size_bytes, - }; + switch (g->value_bytes) + { + case 8: + policy->functions = single_fixed_8_functions; + break; + case 4: + policy->functions = single_fixed_4_functions; + break; + case 2: + policy->functions = single_fixed_2_functions; + break; + case -1: + Assert(g->typid == TEXTOID); + policy->functions = single_text_functions; + break; + default: + Assert(false); + break; + } policy->table = policy->functions.create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); @@ -308,234 +309,6 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } } -/* - * Fill the aggregation state offsets for all rows using a hash table. - */ -static pg_attribute_always_inline uint32 -fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, - const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) -{ - struct h_hash *restrict table = policy->table; - for (int row = start_row; row < end_row; row++) - { - bool key_valid = false; - Datum key = { 0 }; - get_key(column, row, &key, &key_valid); - - if (!arrow_row_is_valid(filter, row)) - { - continue; - } - - if (key_valid) - { - bool found = false; - HashEntry *restrict entry = h_insert(table, key, &found); - if (!found) - { - const int index = next_unused_state_index++; - entry->agg_state_index = index; - ((Datum *restrict) policy->keys)[index] = key; - } - offsets[row] = entry->agg_state_index; - } - else - { - policy->have_null_key = true; - offsets[row] = 1; - } - } - - return next_unused_state_index; -} - -/* - * This function exists just to nudge the compiler to generate simplified - * implementation for the important case where the entire batch matches and the - * key has no null values. - */ -static pg_attribute_always_inline uint32 -fill_offsets_dispatch(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) -{ - CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; - const uint64 *restrict filter = batch_state->vector_qual_result; - - if (filter == NULL && column.buffers[0] == NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter != NULL && column.buffers[0] == NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter == NULL && column.buffers[0] != NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter != NULL && column.buffers[0] != NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else - { - Assert(false); - } - - policy->stat_input_total_rows += batch_state->total_batch_rows; - policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); - return next_unused_state_index; -} - -/* - * Functions to get the key value from the decompressed column, depending on its - * width and whether it's a scalar column. - */ -static pg_attribute_always_inline void -get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) -{ - Assert(column.decompression_type == DT_Scalar); - *key = *column.output_value; - *valid = !*column.output_isnull; -} - -static pg_attribute_always_inline void -get_key_arrow_fixed(CompressedColumnValues column, int row, int key_bytes, Datum *restrict key, - bool *restrict valid) -{ - Assert(column.decompression_type == key_bytes); - const void *values = column.buffers[1]; - const uint64 *key_validity = column.buffers[0]; - *valid = arrow_row_is_valid(key_validity, row); - memcpy(key, key_bytes * row + (char *) values, key_bytes); -} - -static pg_attribute_always_inline void -get_key_arrow_fixed_2(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) -{ - get_key_arrow_fixed(column, row, 2, key, valid); -} - -static pg_attribute_always_inline void -get_key_arrow_fixed_4(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) -{ - get_key_arrow_fixed(column, row, 4, key, valid); -} - -static pg_attribute_always_inline void -get_key_arrow_fixed_8(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) -{ -#ifndef USE_FLOAT8_BYVAL - /* - * Shouldn't be called for this configuration, because we only use this - * grouping strategy for by-value types. - */ - Assert(false); -#endif - - get_key_arrow_fixed(column, row, 8, key, valid); -} - -/* - * Implementation of bulk hashing specialized for a given key width. - */ -static pg_noinline uint32 -fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_8); -} - -static pg_noinline uint32 -fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_4); -} - -static pg_noinline uint32 -fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_2); -} - -static pg_noinline uint32 -fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_scalar); -} - static void gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) { @@ -563,8 +336,8 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * columns. */ Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); - CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; + // GroupingColumn *g = linitial(policy->output_grouping_columns); + // CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; int start_row = 0; int end_row = 0; for (start_row = 0; start_row < n; start_row = end_row) @@ -622,48 +395,11 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) */ Assert((size_t) end_row <= policy->num_allocated_offsets); uint32 next_unused_state_index = hash_keys + 2; - switch ((int) key_column->decompression_type) - { - case DT_Scalar: - next_unused_state_index = fill_offsets_scalar(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 8: - next_unused_state_index = fill_offsets_arrow_fixed_8(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 4: - next_unused_state_index = fill_offsets_arrow_fixed_4(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 2: - next_unused_state_index = fill_offsets_arrow_fixed_2(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - default: - Assert(false); - break; - } + next_unused_state_index = policy->functions.fill_offsets(policy, + batch_state, + next_unused_state_index, + start_row, + end_row); ListCell *aggdeflc; ListCell *aggstatelc; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h new file mode 100644 index 00000000000..495f3f4ddb6 --- /dev/null +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -0,0 +1,95 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#include + +#include + +#include "grouping_policy.h" + +typedef struct DecompressBatchState DecompressBatchState; + +typedef struct GroupingPolicyHash GroupingPolicyHash; + +typedef struct +{ + void *(*create)(MemoryContext context, uint32 initial_rows, void *data); + void (*reset)(void *table); + uint32 (*get_num_keys)(void *table); + uint64 (*get_size_bytes)(void *table); + uint32 (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + uint32 next_unused_state_index, int start_row, int end_row); +} HashTableFunctions; + +/* + * Hash grouping policy. + */ +typedef struct GroupingPolicyHash +{ + /* + * We're using data inheritance from the GroupingPolicy. + */ + GroupingPolicy funcs; + + List *agg_defs; + List *output_grouping_columns; + + /* + * The hash table we use for grouping. + */ + void *table; + HashTableFunctions functions; + + /* + * Whether we are in the mode of returning the partial aggregation results. + * Track the last returned aggregate state offset if we are. + */ + bool returning_results; + uint32 last_returned_key; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and it has a reserved aggregate state index 1. We also reset this + * flag after we output the null key during iteration. + */ + bool have_null_key; + + /* + * A memory context for aggregate functions to allocate additional data, + * i.e. if they store strings or float8 datum on 32-bit systems. Valid until + * the grouping policy is reset. + */ + MemoryContext agg_extra_mctx; + + /* + * Temporary storage of aggregate state offsets for a given batch. We keep + * it in the policy because it is potentially too big to keep on stack, and + * we don't want to reallocate it each batch. + */ + uint32 *restrict offsets; + uint64 num_allocated_offsets; + + /* + * Storage of aggregate function states, each List entry is the array of + * states for the respective function from agg_defs. The state index 0 is + * invalid, and the state index 1 is reserved for a null key. + */ + List *per_agg_states; + uint64 allocated_aggstate_rows; + + uint64 key_bytes; + uint64 num_allocated_keys; + void *restrict keys; + MemoryContext key_body_mctx; + + /* + * Some statistics for debugging. + */ + uint64 stat_input_total_rows; + uint64 stat_input_valid_rows; + uint64 stat_bulk_filtered_rows; +} GroupingPolicyHash; diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c new file mode 100644 index 00000000000..4c231cb98e2 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -0,0 +1,182 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) + +/* + * For the hash table, use the generic Datum key that is mapped to the aggregate + * state index. + */ +typedef struct +{ + CTYPE key; +#ifdef SH_STORE_HASH + uint32 hash; +#endif + uint32 agg_state_index; +} FUNCTION_NAME(entry); + +#ifdef SH_STORE_HASH +#define SH_GET_HASH(tb, entry) entry->hash +#endif + +#define SH_PREFIX KEY_VARIANT +#define SH_ELEMENT_TYPE FUNCTION_NAME(entry) +#define SH_KEY_TYPE CTYPE +#define SH_KEY key +#define SH_HASH_KEY(tb, key) KEY_HASH(key) +#define SH_EQUAL(tb, a, b) KEY_EQUAL(a, b) +#define SH_SCOPE static inline +#define SH_DECLARE +#define SH_DEFINE +#define SH_ENTRY_EMPTY(entry) ((entry)->agg_state_index == 0) +#include "import/ts_simplehash.h" + +struct FUNCTION_NAME(hash); + +static uint32 +FUNCTION_NAME(get_num_keys)(void *table) +{ + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) table; + return hash->members; +} + +static uint64 +FUNCTION_NAME(get_size_bytes)(void *table) +{ + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) table; + return hash->members * sizeof(FUNCTION_NAME(entry)); +} + +/* + * Fill the aggregation state offsets for all rows using a hash table. + */ +static pg_attribute_always_inline uint32 +FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, + const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, + int end_row) +{ + uint32 *restrict offsets = policy->offsets; + Assert((size_t) end_row <= policy->num_allocated_offsets); + + struct FUNCTION_NAME(hash) *restrict table = policy->table; + + for (int row = start_row; row < end_row; row++) + { + bool key_valid = false; + CTYPE key; + FUNCTION_NAME(get_key)(column, row, &key, &key_valid); + + if (!arrow_row_is_valid(filter, row)) + { + continue; + } + + if (key_valid) + { + bool found = false; + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); + if (!found) + { + const int index = next_unused_state_index++; + entry->key = FUNCTION_NAME(store_key)(key, + &((Datum *restrict) policy->keys)[index], + policy->key_body_mctx); + entry->agg_state_index = index; + } + offsets[row] = entry->agg_state_index; + } + else + { + policy->have_null_key = true; + offsets[row] = 1; + } + } + + return next_unused_state_index; +} + +/* + * This function exists just to nudge the compiler to generate separate + * implementation for the important case where the entire batch matches and the + * key has no null values, and the unimportant corner case when we have a scalar + * column. + */ +static uint32 +FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + uint32 next_unused_state_index, int start_row, int end_row) +{ + Assert(list_length(policy->output_grouping_columns) == 1); + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + const uint64 *restrict filter = batch_state->vector_qual_result; + + if (unlikely(column.decompression_type == DT_Scalar)) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowText) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowTextDict) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (filter == NULL && column.buffers[0] == NULL) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (filter != NULL && column.buffers[0] == NULL) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (filter == NULL && column.buffers[0] != NULL) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (filter != NULL && column.buffers[0] != NULL) + { + next_unused_state_index = FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else + { + Assert(false); + } + + policy->stat_input_total_rows += batch_state->total_batch_rows; + policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); + return next_unused_state_index; +} + +HashTableFunctions FUNCTION_NAME(functions) = { + .create = (void *(*) (MemoryContext, uint32, void *) ) FUNCTION_NAME(create), + .reset = (void (*)(void *)) FUNCTION_NAME(reset), + .get_num_keys = FUNCTION_NAME(get_num_keys), + .get_size_bytes = FUNCTION_NAME(get_size_bytes), + .fill_offsets = FUNCTION_NAME(fill_offsets), +}; + +#undef KEY_VARIANT +#undef KEY_BYTES +#undef KEY_HASH +#undef KEY_EQUAL +#undef CTYPE +#undef DATUM_TO_CTYPE +#undef CTYPE_TO_DATUM + +#undef FUNCTION_NAME_HELPER2 +#undef FUNCTION_NAME_HELPER +#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 8c42cb43906..4312218c125 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -347,6 +347,11 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) { return true; } + + if (var->vartype == TEXTOID) + { + return true; + } } } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c new file mode 100644 index 00000000000..0142f3f1753 --- /dev/null +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -0,0 +1,43 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) + +static pg_attribute_always_inline void +FUNCTION_NAME(get_key)(CompressedColumnValues column, int row, CTYPE *restrict key, + bool *restrict valid) +{ + if (unlikely(column.decompression_type == DT_Scalar)) + { + *key = DATUM_TO_CTYPE(*column.output_value); + *valid = !*column.output_isnull; + } + else if (column.decompression_type == sizeof(CTYPE)) + { + const CTYPE *values = column.buffers[1]; + const uint64 *key_validity = column.buffers[0]; + *valid = arrow_row_is_valid(key_validity, row); + *key = values[row]; + } + else + { + pg_unreachable(); + } +} + +static pg_attribute_always_inline CTYPE +FUNCTION_NAME(store_key)(CTYPE key, Datum *key_storage, MemoryContext key_memory_context) +{ + /* Noop for fixed-size keys. */ + *key_storage = CTYPE_TO_DATUM(key); + return key; +} + +#undef FUNCTION_NAME_HELPER2 +#undef FUNCTION_NAME_HELPER +#undef FUNCTION_NAME From 757353dad0e31da72ba430e8bf5aa7c6604301b3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:51:11 +0100 Subject: [PATCH 042/242] hashing fixes and more tests --- tsl/src/nodes/vector_agg/CMakeLists.txt | 4 + tsl/src/nodes/vector_agg/grouping_policy.h | 2 + .../nodes/vector_agg/grouping_policy_hash.c | 188 +++------------- tsl/src/nodes/vector_agg/hash64.h | 36 +++ .../nodes/vector_agg/hash_single_fixed_2.c | 29 +++ .../nodes/vector_agg/hash_single_fixed_4.c | 29 +++ .../nodes/vector_agg/hash_single_fixed_8.c | 29 +++ tsl/src/nodes/vector_agg/hash_single_text.c | 82 +++++++ .../vector_agg/hash_table_functions_impl.c | 52 +++-- tsl/test/expected/vector_agg_functions.out | 209 ++++++++++++++++-- tsl/test/sql/vector_agg_functions.sql | 39 ++-- 11 files changed, 498 insertions(+), 201 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hash64.h create mode 100644 tsl/src/nodes/vector_agg/hash_single_fixed_2.c create mode 100644 tsl/src/nodes/vector_agg/hash_single_fixed_4.c create mode 100644 tsl/src/nodes/vector_agg/hash_single_fixed_8.c create mode 100644 tsl/src/nodes/vector_agg/hash_single_text.c diff --git a/tsl/src/nodes/vector_agg/CMakeLists.txt b/tsl/src/nodes/vector_agg/CMakeLists.txt index c3a85bbd30f..8df9e49baea 100644 --- a/tsl/src/nodes/vector_agg/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/CMakeLists.txt @@ -1,6 +1,10 @@ add_subdirectory(function) set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exec.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_2.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_4.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_8.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_text.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_batch.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_hash.c ${CMAKE_CURRENT_SOURCE_DIR}/plan.c) diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 8aaf9c99f47..00f153423ce 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -9,6 +9,8 @@ typedef struct DecompressBatchState DecompressBatchState; typedef struct GroupingPolicy GroupingPolicy; +typedef struct TupleTableSlot TupleTableSlot; + /* * This is a common interface for grouping policies which define how the rows * are grouped for aggregation -- e.g. there can be an implementation for no diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 0b898c9fcae..27e5a08d421 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -11,7 +11,6 @@ #include -#include #include #include @@ -32,133 +31,10 @@ #define DEBUG_LOG(...) #endif -/* - * We can use crc32 as a hash function, it has bad properties but takes only one - * cycle, which is why it is sometimes used in the existing hash table - * implementations. - */ - -#ifdef USE_SSE42_CRC32C -#include -static pg_attribute_always_inline uint64 -hash64(uint64 x) -{ - return _mm_crc32_u64(~0ULL, x); -} - -#else -/* - * When we don't have the crc32 instruction, use the SplitMix64 finalizer. - */ -static pg_attribute_always_inline uint64 -hash64(uint64 x) -{ - x ^= x >> 30; - x *= 0xbf58476d1ce4e5b9U; - x ^= x >> 27; - x *= 0x94d049bb133111ebU; - x ^= x >> 31; - return x; -} -#endif - -#define KEY_VARIANT single_fixed_2 -#define KEY_BYTES 2 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b -#define CTYPE int16 -#define DATUM_TO_CTYPE DatumGetInt16 -#define CTYPE_TO_DATUM Int16GetDatum - -#include "single_fixed_key_impl.c" - -#include "hash_table_functions_impl.c" - -#define KEY_VARIANT single_fixed_4 -#define KEY_BYTES 4 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b -#define CTYPE int32 -#define DATUM_TO_CTYPE DatumGetInt32 -#define CTYPE_TO_DATUM Int32GetDatum - -#include "single_fixed_key_impl.c" - -#include "hash_table_functions_impl.c" - - -#define KEY_VARIANT single_fixed_8 -#define KEY_BYTES 8 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b -#define CTYPE int64 -#define DATUM_TO_CTYPE DatumGetInt64 -#define CTYPE_TO_DATUM Int64GetDatum - -#include "single_fixed_key_impl.c" - -#include "hash_table_functions_impl.c" - -static void -store_text_datum(CompressedColumnValues *column_values, int arrow_row) -{ - const uint32 start = ((uint32 *) column_values->buffers[1])[arrow_row]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[arrow_row + 1] - start; - Assert(value_bytes >= 0); - - const int total_bytes = value_bytes + VARHDRSZ; - Assert(DatumGetPointer(*column_values->output_value) != NULL); - SET_VARSIZE(*column_values->output_value, total_bytes); - memcpy(VARDATA(*column_values->output_value), - &((uint8 *) column_values->buffers[2])[start], - value_bytes); -} - -static pg_attribute_always_inline void -single_text_get_key(CompressedColumnValues column, int row, text **restrict key, - bool *restrict valid) -{ - if (unlikely(column.decompression_type == DT_Scalar)) - { - /* Already stored. */ - } - else if (column.decompression_type == DT_ArrowText) - { - store_text_datum(&column, row); - *column.output_isnull = !arrow_row_is_valid(column.buffers[0], row); - } - else if (column.decompression_type == DT_ArrowTextDict) - { - const int16 index = ((int16 *) column.buffers[3])[row]; - store_text_datum(&column, index); - *column.output_isnull = !arrow_row_is_valid(column.buffers[0], row); - } - else - { - pg_unreachable(); - } - *key = (text *) DatumGetPointer(*column.output_value); - *valid = !*column.output_isnull; -} - -static pg_attribute_always_inline text * -single_text_store_key(text *key, Datum *key_storage, MemoryContext key_memory_context) -{ - size_t size = VARSIZE_ANY(key); - text *stored = (text *) MemoryContextAlloc(key_memory_context, size); - memcpy(stored, key, size); - *key_storage = PointerGetDatum(stored); - return stored; -} - -#define KEY_VARIANT single_text -#define KEY_HASH(X) hash_bytes((const unsigned char *) VARDATA_ANY(X), VARSIZE_ANY_EXHDR(X)) -#define KEY_EQUAL(a, b) \ - (VARSIZE_ANY(a) == VARSIZE_ANY(b) && \ - memcmp(VARDATA_ANY(a), VARDATA_ANY(b), VARSIZE_ANY_EXHDR(a)) == 0) -#define SH_STORE_HASH -#define CTYPE text * -#include "hash_table_functions_impl.c" +extern HashTableFunctions single_fixed_2_functions; +extern HashTableFunctions single_fixed_4_functions; +extern HashTableFunctions single_fixed_8_functions; +extern HashTableFunctions single_text_functions; static const GroupingPolicy grouping_policy_hash_functions; @@ -316,6 +192,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(!policy->returning_results); + const int num_fns = list_length(policy->agg_defs); + Assert(list_length(policy->per_agg_states) == num_fns); + const uint64_t *restrict filter = batch_state->vector_qual_result; const int n = batch_state->total_batch_rows; @@ -401,48 +280,47 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) start_row, end_row); - ListCell *aggdeflc; - ListCell *aggstatelc; - - /* - * Initialize the aggregate function states for the newly added keys. - */ - if (next_unused_state_index > first_uninitialized_state_index) + const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + for (int i = 0; i < num_fns; i++) { - if (next_unused_state_index > policy->allocated_aggstate_rows) + VectorAggDef *agg_def = list_nth(policy->agg_defs, i); + if (next_unused_state_index > first_uninitialized_state_index) { - policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) + if (next_unused_state_index > policy->allocated_aggstate_rows) { - VectorAggDef *agg_def = lfirst(aggdeflc); - lfirst(aggstatelc) = - repalloc(lfirst(aggstatelc), - policy->allocated_aggstate_rows * agg_def->func.state_bytes); + lfirst(list_nth_cell(policy->per_agg_states, i)) = + repalloc(list_nth(policy->per_agg_states, i), + new_aggstate_rows * agg_def->func.state_bytes); } - } - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { - const VectorAggDef *agg_def = lfirst(aggdeflc); + /* + * Initialize the aggregate function states for the newly added keys. + */ agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + - (char *) lfirst(aggstatelc), + (char *) list_nth(policy->per_agg_states, i), next_unused_state_index - first_uninitialized_state_index); } - } - /* - * Update the aggregate function states. - */ - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { + /* + * Update the aggregate function states. + */ compute_single_aggregate(batch_state, start_row, end_row, - lfirst(aggdeflc), - lfirst(aggstatelc), + agg_def, + list_nth(policy->per_agg_states, i), policy->offsets, policy->agg_extra_mctx); } + + /* + * Record the newly allocated number of rows in case we had to reallocate. + */ + if (next_unused_state_index > policy->allocated_aggstate_rows) + { + Assert(new_aggstate_rows >= policy->allocated_aggstate_rows); + policy->allocated_aggstate_rows = new_aggstate_rows; + } } Assert(end_row == n); } diff --git a/tsl/src/nodes/vector_agg/hash64.h b/tsl/src/nodes/vector_agg/hash64.h new file mode 100644 index 00000000000..4d988ac6eb4 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash64.h @@ -0,0 +1,36 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +/* + * We can use crc32 as a hash function, it has bad properties but takes only one + * cycle, which is why it is sometimes used in the existing hash table + * implementations. + */ + +#ifdef USE_SSE42_CRC32C +#include +static pg_attribute_always_inline uint64 +hash64(uint64 x) +{ + return _mm_crc32_u64(~0ULL, x); +} + +#else +/* + * When we don't have the crc32 instruction, use the SplitMix64 finalizer. + */ +static pg_attribute_always_inline uint64 +hash64(uint64 x) +{ + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + return x; +} +#endif diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c new file mode 100644 index 00000000000..d00e50f12dd --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -0,0 +1,29 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 2-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "grouping_policy_hash.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" + +#define KEY_VARIANT single_fixed_2 +#define KEY_BYTES 2 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int16 +#define DATUM_TO_CTYPE DatumGetInt16 +#define CTYPE_TO_DATUM Int16GetDatum + +#include "single_fixed_key_impl.c" + +#include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c new file mode 100644 index 00000000000..928ef31e1da --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -0,0 +1,29 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 2-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "grouping_policy_hash.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" + +#define KEY_VARIANT single_fixed_4 +#define KEY_BYTES 4 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int32 +#define DATUM_TO_CTYPE DatumGetInt32 +#define CTYPE_TO_DATUM Int32GetDatum + +#include "single_fixed_key_impl.c" + +#include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c new file mode 100644 index 00000000000..b8646766caa --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -0,0 +1,29 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 8-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "grouping_policy_hash.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" + +#define KEY_VARIANT single_fixed_8 +#define KEY_BYTES 8 +#define KEY_HASH hash64 +#define KEY_EQUAL(a, b) a == b +#define CTYPE int64 +#define DATUM_TO_CTYPE DatumGetInt64 +#define CTYPE_TO_DATUM Int64GetDatum + +#include "single_fixed_key_impl.c" + +#include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c new file mode 100644 index 00000000000..9f561d62194 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -0,0 +1,82 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single text column. + */ + +#include + +#include + +#include "compression/arrow_c_data_interface.h" +#include "grouping_policy_hash.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" + +typedef struct TextView +{ + uint32 len; + const uint8 *data; +} TextView; + +static TextView +get_text_view(CompressedColumnValues *column_values, int arrow_row) +{ + const uint32 start = ((uint32 *) column_values->buffers[1])[arrow_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[arrow_row + 1] - start; + Assert(value_bytes >= 0); + + return (TextView){ .len = value_bytes, .data = &((uint8 *) column_values->buffers[2])[start] }; +} + +static pg_attribute_always_inline void +single_text_get_key(CompressedColumnValues column, int row, TextView *restrict key, + bool *restrict valid) +{ + if (unlikely(column.decompression_type == DT_Scalar)) + { + /* Already stored. */ + key->len = VARSIZE_ANY_EXHDR(*column.output_value); + key->data = (const uint8 *) VARDATA_ANY(*column.output_value); + *valid = !*column.output_isnull; + } + else if (column.decompression_type == DT_ArrowText) + { + *key = get_text_view(&column, row); + *valid = arrow_row_is_valid(column.buffers[0], row); + } + else if (column.decompression_type == DT_ArrowTextDict) + { + const int16 index = ((int16 *) column.buffers[3])[row]; + *key = get_text_view(&column, index); + *valid = arrow_row_is_valid(column.buffers[0], row); + } + else + { + pg_unreachable(); + } +} + +static pg_attribute_always_inline TextView +single_text_store_key(TextView key, Datum *key_storage, MemoryContext key_memory_context) +{ + const int total_bytes = key.len + VARHDRSZ; + text *stored = (text *) MemoryContextAlloc(key_memory_context, total_bytes); + SET_VARSIZE(stored, total_bytes); + memcpy(VARDATA(stored), key.data, key.len); + key.data = (uint8 *) VARDATA(stored); + *key_storage = PointerGetDatum(stored); + return key; +} + +#define KEY_VARIANT single_text +#define KEY_HASH(X) hash_bytes(X.data, X.len) +#define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) +#define SH_STORE_HASH +#define CTYPE TextView +#include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 4c231cb98e2..a8408e8998d 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -101,6 +101,33 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, return next_unused_state_index; } +static pg_attribute_always_inline uint32 +FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *policy, CompressedColumnValues column, + const uint64 *restrict filter, uint32 next_unused_state_index, + int start_row, int end_row) +{ + if (unlikely(column.decompression_type == DT_Scalar)) + { + return FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowText) + { + return FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowTextDict) + { + return FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } + else + { + return FUNCTION_NAME( + impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + } +} + /* * This function exists just to nudge the compiler to generate separate * implementation for the important case where the entire batch matches and the @@ -116,40 +143,25 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; const uint64 *restrict filter = batch_state->vector_qual_result; - if (unlikely(column.decompression_type == DT_Scalar)) - { - next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (column.decompression_type == DT_ArrowText) + if (filter == NULL && column.buffers[0] == NULL) { next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (column.decompression_type == DT_ArrowTextDict) - { - next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (filter == NULL && column.buffers[0] == NULL) - { - next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); } else if (filter != NULL && column.buffers[0] == NULL) { next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); } else if (filter == NULL && column.buffers[0] != NULL) { next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); } else if (filter != NULL && column.buffers[0] != NULL) { next_unused_state_index = FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); } else { diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index c79c667d15a..3bd63121cdd 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -50,19 +50,23 @@ select count(compress_chunk(x)) from show_chunks('aggfns') x; (1 row) alter table aggfns add column ss int default 11; +alter table aggfns add column x text default '11'; insert into aggfns -select *, - case - -- null in entire batch - when s = 2 then null - -- null for some rows - when s = 3 and t % 1053 = 0 then null - -- for some rows same as default - when s = 4 and t % 1057 = 0 then 11 - -- not null for entire batch - else s - end as ss -from source where s != 1; +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; select count(compress_chunk(x)) from show_chunks('aggfns') x; count ------- @@ -114,7 +118,8 @@ from unnest(array[ null, 's', - 'ss']) with ordinality as grouping(grouping, n) + 'ss', + 'x']) with ordinality as grouping(grouping, n) where case -- when explain is not null then condition is null and grouping = 's' @@ -124,6 +129,9 @@ where and case when variable = '*' then function = 'count' + -- No need to test the aggregate functions themselves again for string + -- grouping. + when grouping = 'x' then function = 'count' and variable = 'cfloat4' when condition = 'cint2 is null' then variable = 'cint2' when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') @@ -167,6 +175,21 @@ select ss, count(*) from aggfns group by ss order by 1; | 19 (10 rows) +select x, count(*) from aggfns group by x order by 1; + x | count +----+------- + 0 | 20000 + 11 | 40019 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + | 19 +(10 rows) + select max(cdate) from aggfns order by 1; max ------------ @@ -311,6 +334,21 @@ select ss, count(cfloat4) from aggfns group by ss order by 1; | 19 (10 rows) +select x, count(cfloat4) from aggfns group by x order by 1; + x | count +----+------- + 0 | 20000 + 11 | 40019 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + | 19 +(10 rows) + select max(cfloat4) from aggfns order by 1; max ----- @@ -1859,6 +1897,21 @@ select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; | 8 (10 rows) +select x, count(*) from aggfns where cfloat8 > 0 group by x order by 1; + x | count +----+------- + 0 | 9943 + 11 | 19896 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + | 8 +(10 rows) + select max(cdate) from aggfns where cfloat8 > 0 order by 1; max ------------ @@ -2003,6 +2056,21 @@ select ss, count(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; | 8 (10 rows) +select x, count(cfloat4) from aggfns where cfloat8 > 0 group by x order by 1; + x | count +----+------- + 0 | 9943 + 11 | 19896 + 3 | 9934 + 4 | 9932 + 5 | 9943 + 6 | 9944 + 7 | 9944 + 8 | 9943 + 9 | 9943 + | 8 +(10 rows) + select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; max --------- @@ -3551,6 +3619,21 @@ select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; | 11 (10 rows) +select x, count(*) from aggfns where cfloat8 <= 0 group by x order by 1; + x | count +----+------- + 0 | 10057 + 11 | 20123 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + | 11 +(10 rows) + select max(cdate) from aggfns where cfloat8 <= 0 order by 1; max ------------ @@ -3695,6 +3778,21 @@ select ss, count(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; | 11 (10 rows) +select x, count(cfloat4) from aggfns where cfloat8 <= 0 group by x order by 1; + x | count +----+------- + 0 | 10057 + 11 | 20123 + 3 | 10047 + 4 | 10049 + 5 | 10057 + 6 | 10056 + 7 | 10056 + 8 | 10057 + 9 | 10057 + | 11 +(10 rows) + select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; max ----- @@ -5243,6 +5341,21 @@ select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; | 19 (10 rows) +select x, count(*) from aggfns where cfloat8 < 1000 group by x order by 1; + x | count +----+------- + 0 | 20000 + 11 | 40019 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + | 19 +(10 rows) + select max(cdate) from aggfns where cfloat8 < 1000 order by 1; max ------------ @@ -5387,6 +5500,21 @@ select ss, count(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by | 19 (10 rows) +select x, count(cfloat4) from aggfns where cfloat8 < 1000 group by x order by 1; + x | count +----+------- + 0 | 20000 + 11 | 40019 + 3 | 19981 + 4 | 19981 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + | 19 +(10 rows) + select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; max ----- @@ -6915,6 +7043,11 @@ select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+------- (0 rows) +select x, count(*) from aggfns where cfloat8 > 1000 group by x order by 1; + x | count +---+------- +(0 rows) + select max(cdate) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -6979,6 +7112,11 @@ select ss, count(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by ----+------- (0 rows) +select x, count(cfloat4) from aggfns where cfloat8 > 1000 group by x order by 1; + x | count +---+------- +(0 rows) + select max(cfloat4) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7679,6 +7817,34 @@ select ss, count(*) from aggfns where cint2 is null group by ss order by 1; 11 | 38 (9 rows) +select x, count(*) from aggfns where cint2 is null group by x order by 1; + x | count +----+------- + 0 | 19 + 11 | 38 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(9 rows) + +select x, count(cfloat4) from aggfns where cint2 is null group by x order by 1; + x | count +----+------- + 0 | 19 + 11 | 38 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(9 rows) + select avg(cint2) from aggfns where cint2 is null order by 1; avg ----- @@ -7889,3 +8055,20 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) +select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 +order by count(*) desc, cint2 limit 10 +; + count | count | min | cint2 +-------+-------+----------+-------- + 190 | 0 | -49.6472 | + 60 | 60 | -13.3701 | -11208 + 60 | 60 | -48.5206 | 1924 + 50 | 50 | -44.7573 | -11714 + 50 | 50 | -22.1541 | -11331 + 50 | 50 | -35.9287 | -6252 + 50 | 50 | -9.84793 | -120 + 50 | 50 | -36.2595 | 15467 + 50 | 50 | -30.1285 | 15889 + 40 | 40 | -33.4605 | -15975 +(10 rows) + diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index b3bad3f812f..2cc8ca78640 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -46,20 +46,24 @@ alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't' select count(compress_chunk(x)) from show_chunks('aggfns') x; alter table aggfns add column ss int default 11; +alter table aggfns add column x text default '11'; insert into aggfns -select *, - case - -- null in entire batch - when s = 2 then null - -- null for some rows - when s = 3 and t % 1053 = 0 then null - -- for some rows same as default - when s = 4 and t % 1057 = 0 then 11 - -- not null for entire batch - else s - end as ss -from source where s != 1; +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; select count(compress_chunk(x)) from show_chunks('aggfns') x; @@ -110,7 +114,8 @@ from unnest(array[ null, 's', - 'ss']) with ordinality as grouping(grouping, n) + 'ss', + 'x']) with ordinality as grouping(grouping, n) where case -- when explain is not null then condition is null and grouping = 's' @@ -120,6 +125,9 @@ where and case when variable = '*' then function = 'count' + -- No need to test the aggregate functions themselves again for string + -- grouping. + when grouping = 'x' then function = 'count' and variable = 'cfloat4' when condition = 'cint2 is null' then variable = 'cint2' when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') @@ -127,3 +135,8 @@ where else true end order by explain, condition.n, variable, function, grouping.n \gexec + + +select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 +order by count(*) desc, cint2 limit 10 +; From cc05e8d83d621b37d8e53bc58ba12eb1a456cdd4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:58:13 +0100 Subject: [PATCH 043/242] gcc doesn't like my inline --- tsl/src/import/ts_simplehash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index 5197e6d5bde..c8e0792fbe6 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -575,7 +575,7 @@ SH_GROW(SH_TYPE *tb, uint64 newsize) * This is a separate static inline function, so it can be reliably be inlined * into its wrapper functions even if SH_SCOPE is extern. */ -static pg_attribute_always_inline SH_ELEMENT_TYPE * +static inline SH_ELEMENT_TYPE * SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool *found) { /* From 238c743b0af57989d99446865ef3fbde75aa65ca Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:58:27 +0100 Subject: [PATCH 044/242] benchmark vectorized hash grouping (with text) (2024-10-17 no. 13) From 4c71b9c8c173c96c2457ac52b8a3b543865490af Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:08:09 +0100 Subject: [PATCH 045/242] fixes --- .../nodes/vector_agg/grouping_policy_hash.c | 213 ++++++------- tsl/src/nodes/vector_agg/hash_single_text.c | 10 +- tsl/test/expected/vector_agg_functions.out | 280 ++++++++---------- tsl/test/sql/vector_agg_functions.sql | 34 ++- 4 files changed, 269 insertions(+), 268 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 27e5a08d421..3596870757a 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -186,143 +186,150 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } static void -gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) +add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, const int start_row, + const int end_row) { - GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - - Assert(!policy->returning_results); - const int num_fns = list_length(policy->agg_defs); Assert(list_length(policy->per_agg_states) == num_fns); - const uint64_t *restrict filter = batch_state->vector_qual_result; const int n = batch_state->total_batch_rows; + Assert(start_row < end_row); + Assert(end_row <= n); + /* - * Initialize the array for storing the aggregate state offsets corresponding - * to a given batch row. + * Remember which aggregation states have already existed, and which we + * have to initialize. State index zero is invalid, and state index one + * is for null key. We have to initialize the null key state at the + * first run. */ - if ((size_t) n > policy->num_allocated_offsets) + const uint32 hash_keys = policy->functions.get_num_keys(policy->table); + const uint32 first_uninitialized_state_index = hash_keys ? hash_keys + 2 : 1; + + /* + * Allocate enough storage for keys, given that each bach row might be + * a separate new key. + */ + const uint32 num_possible_keys = first_uninitialized_state_index + (end_row - start_row); + if (num_possible_keys > policy->num_allocated_keys) { - policy->num_allocated_offsets = n; - policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + policy->num_allocated_keys = num_possible_keys; + policy->keys = repalloc(policy->keys, policy->key_bytes * num_possible_keys); } - memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); /* - * For the partial aggregation node, the grouping columns are always in the - * output, so we don't have to separately look at the list of the grouping - * columns. + * Match rows to aggregation states using a hash table. */ - Assert(list_length(policy->output_grouping_columns) == 1); - // GroupingColumn *g = linitial(policy->output_grouping_columns); - // CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; - int start_row = 0; - int end_row = 0; - for (start_row = 0; start_row < n; start_row = end_row) + Assert((size_t) end_row <= policy->num_allocated_offsets); + uint32 next_unused_state_index = hash_keys + 2; + next_unused_state_index = policy->functions.fill_offsets(policy, + batch_state, + next_unused_state_index, + start_row, + end_row); + + const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + for (int i = 0; i < num_fns; i++) { - /* - * If we have a highly selective filter, it's easy to skip the rows for - * which the entire words of the filter bitmap are zero. - */ - if (filter) + VectorAggDef *agg_def = list_nth(policy->agg_defs, i); + if (next_unused_state_index > first_uninitialized_state_index) { - if (filter[start_row / 64] == 0) + if (next_unused_state_index > policy->allocated_aggstate_rows) { - end_row = MIN(start_row + 64, n); - policy->stat_bulk_filtered_rows += 64; - continue; + lfirst(list_nth_cell(policy->per_agg_states, i)) = + repalloc(list_nth(policy->per_agg_states, i), + new_aggstate_rows * agg_def->func.state_bytes); } - for (end_row = start_row; end_row < n; end_row = MIN(end_row + 64, n)) - { - if (filter[end_row / 64] == 0) - { - break; - } - } - } - else - { - end_row = n; + /* + * Initialize the aggregate function states for the newly added keys. + */ + agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + + (char *) list_nth(policy->per_agg_states, i), + next_unused_state_index - first_uninitialized_state_index); } - Assert(start_row <= end_row); - Assert(end_row <= n); /* - * Remember which aggregation states have already existed, and which we - * have to initialize. State index zero is invalid, and state index one - * is for null key. We have to initialize the null key state at the - * first run. + * Update the aggregate function states. */ - const uint32 hash_keys = policy->functions.get_num_keys(policy->table); - const uint32 first_uninitialized_state_index = hash_keys ? hash_keys + 2 : 1; + compute_single_aggregate(batch_state, + start_row, + end_row, + agg_def, + list_nth(policy->per_agg_states, i), + policy->offsets, + policy->agg_extra_mctx); + } - /* - * Allocate enough storage for keys, given that each bach row might be - * a separate new key. - */ - const uint32 num_possible_keys = first_uninitialized_state_index + (end_row - start_row); - if (num_possible_keys > policy->num_allocated_keys) - { - policy->num_allocated_keys = num_possible_keys; - policy->keys = repalloc(policy->keys, policy->key_bytes * num_possible_keys); - } + /* + * Record the newly allocated number of rows in case we had to reallocate. + */ + if (next_unused_state_index > policy->allocated_aggstate_rows) + { + Assert(new_aggstate_rows >= policy->allocated_aggstate_rows); + policy->allocated_aggstate_rows = new_aggstate_rows; + } +} + +static void +gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + + Assert(!policy->returning_results); + + const int n = batch_state->total_batch_rows; + + /* + * Initialize the array for storing the aggregate state offsets corresponding + * to a given batch row. + */ + if ((size_t) n > policy->num_allocated_offsets) + { + policy->num_allocated_offsets = n; + policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + } + memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); + const uint64_t *restrict filter = batch_state->vector_qual_result; + if (filter == NULL) + { + add_one_range(policy, batch_state, 0, n); + } + else + { /* - * Match rows to aggregation states using a hash table. + * If we have a filter, skip the rows for which the entire words of the + * filter bitmap are zero. This improves performance for highly + * selective filters. */ - Assert((size_t) end_row <= policy->num_allocated_offsets); - uint32 next_unused_state_index = hash_keys + 2; - next_unused_state_index = policy->functions.fill_offsets(policy, - batch_state, - next_unused_state_index, - start_row, - end_row); - - const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; - for (int i = 0; i < num_fns; i++) + int start_word = 0; + int end_word = 0; + int past_the_end_word = (n - 1) / 64 + 1; + for (;;) { - VectorAggDef *agg_def = list_nth(policy->agg_defs, i); - if (next_unused_state_index > first_uninitialized_state_index) - { - if (next_unused_state_index > policy->allocated_aggstate_rows) - { - lfirst(list_nth_cell(policy->per_agg_states, i)) = - repalloc(list_nth(policy->per_agg_states, i), - new_aggstate_rows * agg_def->func.state_bytes); - } + for (start_word = end_word; start_word < past_the_end_word && filter[start_word] == 0; + start_word++) + ; - /* - * Initialize the aggregate function states for the newly added keys. - */ - agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + - (char *) list_nth(policy->per_agg_states, i), - next_unused_state_index - first_uninitialized_state_index); + if (start_word >= past_the_end_word) + { + break; } + for (end_word = start_word + 1; end_word < past_the_end_word && filter[end_word] != 0; + end_word++) + ; + + const int start_row = start_word * 64 + pg_rightmost_one_pos64(filter[start_word]); /* - * Update the aggregate function states. + * The bits for past-the-end rows must be set to zero, so this + * calculation should yield no more than n. */ - compute_single_aggregate(batch_state, - start_row, - end_row, - agg_def, - list_nth(policy->per_agg_states, i), - policy->offsets, - policy->agg_extra_mctx); - } - - /* - * Record the newly allocated number of rows in case we had to reallocate. - */ - if (next_unused_state_index > policy->allocated_aggstate_rows) - { - Assert(new_aggstate_rows >= policy->allocated_aggstate_rows); - policy->allocated_aggstate_rows = new_aggstate_rows; + int end_row = (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; + add_one_range(policy, batch_state, start_row, end_row); } } - Assert(end_row == n); } static bool diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 9f561d62194..e54002d3349 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -74,8 +74,16 @@ single_text_store_key(TextView key, Datum *key_storage, MemoryContext key_memory return key; } +static pg_attribute_always_inline uint32 +hash_text(TextView view) +{ + uint32 valll = -1; + COMP_CRC32C(valll, view.data, view.len); + return valll; +} + #define KEY_VARIANT single_text -#define KEY_HASH(X) hash_bytes(X.data, X.len) +#define KEY_HASH(X) hash_text(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define SH_STORE_HASH #define CTYPE TextView diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 3bd63121cdd..2e163661f45 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -73,10 +73,36 @@ select count(compress_chunk(x)) from show_chunks('aggfns') x; 2 (1 row) -analyze aggfns; +vacuum freeze analyze aggfns; +create table edges(t int, s int, ss int, f1 int); +select create_hypertable('edges', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +-------------------- + (3,public,edges,t) +(1 row) + +alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); +NOTICE: default order by for hypertable "edges" is set to "t DESC" +insert into edges select + s * 10000 + f1 as t, + s, + s, + f1 +from generate_series(0, 10) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64) f1 +; +select count(compress_chunk(x)) from show_chunks('edges') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze edges; +set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s) from aggfns%s%s order by 1;', explain, @@ -136,6 +162,8 @@ where when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') + -- This is not vectorized yet. + when function = 'stddev' then variable != 'cint8' else true end order by explain, condition.n, variable, function, grouping.n \gexec @@ -1141,42 +1169,6 @@ select ss, min(cint8) from aggfns group by ss order by 1; | -796158533 (10 rows) -select stddev(cint8) from aggfns order by 1; - stddev ------------ - 620482773 -(1 row) - -select s, stddev(cint8) from aggfns group by s order by 1; - s | stddev ----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select ss, stddev(cint8) from aggfns group by ss order by 1; - ss | stddev -----+----------- - 0 | 620477996 - 3 | 620514804 - 4 | 620462299 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 - 11 | 620478168 - | 609007799 -(10 rows) - select sum(cint8) from aggfns order by 1; sum --------------- @@ -2863,42 +2855,6 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; | -672677796 (10 rows) -select stddev(cint8) from aggfns where cfloat8 > 0 order by 1; - stddev ------------ - 623577068 -(1 row) - -select s, stddev(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+----------- - 0 | 623613696 - 1 | 623613596 - 2 | 623588105 - 3 | 623588105 - 4 | 623602577 - 5 | 623602577 - 6 | 623594116 - 7 | 623594116 - 8 | 623620316 - 9 | 623635702 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 623613696 - 3 | 623600813 - 4 | 623575078 - 5 | 623602577 - 6 | 623594116 - 7 | 623594116 - 8 | 623620316 - 9 | 623635702 - 11 | 623598886 - | 648969761 -(10 rows) - select sum(cint8) from aggfns where cfloat8 > 0 order by 1; sum --------------- @@ -4585,42 +4541,6 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; | -796158533 (10 rows) -select stddev(cint8) from aggfns where cfloat8 <= 0 order by 1; - stddev ------------ - 617379684 -(1 row) - -select s, stddev(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+----------- - 0 | 617360997 - 1 | 617360997 - 2 | 617348601 - 3 | 617433171 - 4 | 617412408 - 5 | 617401473 - 6 | 617425094 - 7 | 617462874 - 8 | 617433744 - 9 | 617433744 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 617360997 - 3 | 617445433 - 4 | 617369297 - 5 | 617401473 - 6 | 617425094 - 7 | 617462874 - 8 | 617433744 - 9 | 617433744 - 11 | 617360997 - | 586053845 -(10 rows) - select sum(cint8) from aggfns where cfloat8 <= 0 order by 1; sum -------------- @@ -6307,42 +6227,6 @@ select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; | -796158533 (10 rows) -select stddev(cint8) from aggfns where cfloat8 < 1000 order by 1; - stddev ------------ - 620482773 -(1 row) - -select s, stddev(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+----------- - 0 | 620477996 - 3 | 620514804 - 4 | 620462299 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 - 11 | 620478168 - | 609007799 -(10 rows) - select sum(cint8) from aggfns where cfloat8 < 1000 order by 1; sum --------------- @@ -7466,21 +7350,6 @@ select ss, min(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) -select stddev(cint8) from aggfns where cfloat8 > 1000 order by 1; - stddev --------- -(0 rows) - -select s, stddev(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; - s | stddev ----+-------- -(0 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - select sum(cint8) from aggfns where cfloat8 > 1000 order by 1; sum ----- @@ -8055,6 +7924,7 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) +-- Test multiple aggregate functions as well. select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 order by count(*) desc, cint2 limit 10 ; @@ -8072,3 +7942,91 @@ order by count(*) desc, cint2 limit 10 40 | 40 | -33.4605 | -15975 (10 rows) +select s, count(*) from edges group by 1 order by 1; + s | count +----+------- + 0 | 61 + 1 | 62 + 2 | 63 + 3 | 64 + 4 | 65 + 5 | 130 + 6 | 131 + 7 | 132 + 8 | 133 + 9 | 134 + 10 | 199 +(11 rows) + +select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; + s | count | min +----+-------+----- + 3 | 1 | 63 + 4 | 1 | 63 + 5 | 1 | 63 + 6 | 1 | 63 + 7 | 1 | 63 + 8 | 1 | 63 + 9 | 1 | 63 + 10 | 1 | 63 +(8 rows) + +select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; + s | count | min +----+-------+----- + 4 | 1 | 64 + 5 | 1 | 64 + 6 | 1 | 64 + 7 | 1 | 64 + 8 | 1 | 64 + 9 | 1 | 64 + 10 | 1 | 64 +(7 rows) + +select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + s | count | min +----+-------+----- + 5 | 1 | 65 + 6 | 1 | 65 + 7 | 1 | 65 + 8 | 1 | 65 + 9 | 1 | 65 + 10 | 1 | 65 +(6 rows) + +select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; + ss | count | min +----+-------+----- + 3 | 1 | 63 + 4 | 1 | 63 + 5 | 1 | 63 + 6 | 1 | 63 + 7 | 1 | 63 + 8 | 1 | 63 + 9 | 1 | 63 + 10 | 1 | 63 +(8 rows) + +select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; + ss | count | min +----+-------+----- + 4 | 1 | 64 + 5 | 1 | 64 + 6 | 1 | 64 + 7 | 1 | 64 + 8 | 1 | 64 + 9 | 1 | 64 + 10 | 1 | 64 +(7 rows) + +select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + ss | count | min +----+-------+----- + 5 | 1 | 65 + 6 | 1 | 65 + 7 | 1 | 65 + 8 | 1 | 65 + 9 | 1 | 65 + 10 | 1 | 65 +(6 rows) + diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 2cc8ca78640..e1bbd833951 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -64,14 +64,29 @@ select *, ss::text as x from ( from source where s != 1 ) t ; - select count(compress_chunk(x)) from show_chunks('aggfns') x; +vacuum freeze analyze aggfns; + -analyze aggfns; +create table edges(t int, s int, ss int, f1 int); +select create_hypertable('edges', 't'); +alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); +insert into edges select + s * 10000 + f1 as t, + s, + s, + f1 +from generate_series(0, 10) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64) f1 +; +select count(compress_chunk(x)) from show_chunks('edges') x; +vacuum freeze analyze edges; + +set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s) from aggfns%s%s order by 1;', @@ -132,11 +147,24 @@ where when function = 'count' then variable in ('cfloat4', 's', 'ss') when variable = 't' then function in ('min', 'max') when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') + -- This is not vectorized yet. + when function = 'stddev' then variable != 'cint8' else true end order by explain, condition.n, variable, function, grouping.n \gexec +-- Test multiple aggregate functions as well. select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 order by count(*) desc, cint2 limit 10 ; + +select s, count(*) from edges group by 1 order by 1; + +select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; +select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; +select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + +select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; +select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; +select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; From 24e20ab6121ff5212b199c61cf8cdaf23894fb4c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:08:24 +0100 Subject: [PATCH 046/242] benchmark vectorized hash grouping (with text) (2024-10-18 no. 14) From ae0f865ab6eee2aa34c265da55fddb30fe05392f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 19 Oct 2024 10:10:27 +0100 Subject: [PATCH 047/242] benchmark vectorized hash grouping (with text) (2024-10-19 no. 15) From 2e1cb26e09ed80177fc39815f55d8a70a55cddf3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 19 Oct 2024 10:58:08 +0100 Subject: [PATCH 048/242] consecutive keys optimization --- tsl/src/import/ts_simplehash.h | 6 +- .../nodes/vector_agg/grouping_policy_hash.c | 10 ++-- .../nodes/vector_agg/grouping_policy_hash.h | 1 + .../vector_agg/hash_table_functions_impl.c | 57 +++++++++++++------ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/tsl/src/import/ts_simplehash.h b/tsl/src/import/ts_simplehash.h index c8e0792fbe6..a2a1451753b 100644 --- a/tsl/src/import/ts_simplehash.h +++ b/tsl/src/import/ts_simplehash.h @@ -575,7 +575,7 @@ SH_GROW(SH_TYPE *tb, uint64 newsize) * This is a separate static inline function, so it can be reliably be inlined * into its wrapper functions even if SH_SCOPE is extern. */ -static inline SH_ELEMENT_TYPE * +static pg_attribute_always_inline SH_ELEMENT_TYPE * SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool *found) { /* @@ -661,7 +661,7 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) { SH_GROW(tb, tb->size * 2); - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); + return SH_INSERT_HASH(tb, key, hash, found); } } @@ -698,7 +698,7 @@ SH_INSERT_HASH_INTERNAL(SH_TYPE *restrict tb, SH_KEY_TYPE key, uint32 hash, bool ((double) tb->members / tb->size) >= SH_GROW_MIN_FILLFACTOR) { SH_GROW(tb, tb->size * 2); - return SH_INSERT_HASH_INTERNAL(tb, key, hash, found); + return SH_INSERT_HASH(tb, key, hash, found); } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 3596870757a..d90c8c76247 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -111,6 +111,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->stat_input_valid_rows = 0; policy->stat_input_total_rows = 0; policy->stat_bulk_filtered_rows = 0; + policy->stat_consecutive_keys = 0; } static void @@ -192,10 +193,8 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con const int num_fns = list_length(policy->agg_defs); Assert(list_length(policy->per_agg_states) == num_fns); - const int n = batch_state->total_batch_rows; - Assert(start_row < end_row); - Assert(end_row <= n); + Assert(end_row <= batch_state->total_batch_rows); /* * Remember which aggregation states have already existed, and which we @@ -360,11 +359,12 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) const float keys = policy->functions.get_num_keys(policy->table) + policy->have_null_key; if (keys > 0) { - DEBUG_LOG("spill after %ld input %ld valid %ld bulk filtered %.0f keys %f ratio %ld " - "curctx bytes %ld aggstate bytes", + DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " + "%f ratio, %ld curctx bytes, %ld aggstate bytes", policy->stat_input_total_rows, policy->stat_input_valid_rows, policy->stat_bulk_filtered_rows, + policy->stat_consecutive_keys, keys, policy->stat_input_valid_rows / keys, MemoryContextMemAllocated(CurrentMemoryContext, false), diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 495f3f4ddb6..f91ceb78ae0 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -92,4 +92,5 @@ typedef struct GroupingPolicyHash uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; + uint64 stat_consecutive_keys; } GroupingPolicyHash; diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index a8408e8998d..3b40a4b5626 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -66,36 +66,61 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, struct FUNCTION_NAME(hash) *restrict table = policy->table; + CTYPE last_key; + uint32 last_key_index = 0; for (int row = start_row; row < end_row; row++) { bool key_valid = false; - CTYPE key; + CTYPE key = { 0 }; FUNCTION_NAME(get_key)(column, row, &key, &key_valid); if (!arrow_row_is_valid(filter, row)) { + /* The row doesn't pass the filter. */ continue; } - if (key_valid) - { - bool found = false; - FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); - if (!found) - { - const int index = next_unused_state_index++; - entry->key = FUNCTION_NAME(store_key)(key, - &((Datum *restrict) policy->keys)[index], - policy->key_body_mctx); - entry->agg_state_index = index; - } - offsets[row] = entry->agg_state_index; - } - else + if (unlikely(!key_valid)) { + /* The key is null. */ policy->have_null_key = true; offsets[row] = 1; + continue; + } + + if (likely(last_key_index != 0) && KEY_EQUAL(key, last_key)) + { + /* + * In real data sets, we often see consecutive rows with the + * same key, so checking for this case improves performance. + */ + Assert(last_key_index >= 2); + offsets[row] = last_key_index; +#ifndef NDEBUG + policy->stat_consecutive_keys++; +#endif + continue; + } + + /* + * Find the key using the hash table. + */ + bool found = false; + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); + if (!found) + { + /* + * New key, have to store it persistently. + */ + const int index = next_unused_state_index++; + entry->key = FUNCTION_NAME( + store_key)(key, &((Datum *restrict) policy->keys)[index], policy->key_body_mctx); + entry->agg_state_index = index; } + offsets[row] = entry->agg_state_index; + + last_key_index = entry->agg_state_index; + last_key = key; } return next_unused_state_index; From f59c5404b7c46407bfd77064cac36a2721f282f9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:30:14 +0100 Subject: [PATCH 049/242] cleanup --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 7 +++++++ tsl/src/nodes/vector_agg/hash_table_functions_impl.c | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d90c8c76247..8c094091fdc 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -302,6 +302,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * filter bitmap are zero. This improves performance for highly * selective filters. */ + int stat_range_rows = 0; int start_word = 0; int end_word = 0; int past_the_end_word = (n - 1) / 64 + 1; @@ -327,8 +328,14 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) */ int end_row = (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; add_one_range(policy, batch_state, start_row, end_row); + + stat_range_rows += end_row - start_row; } + policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - stat_range_rows; } + + policy->stat_input_total_rows += batch_state->total_batch_rows; + policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); } static bool diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 3b40a4b5626..6b5e689829f 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -193,8 +193,6 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba Assert(false); } - policy->stat_input_total_rows += batch_state->total_batch_rows; - policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); return next_unused_state_index; } From d38ca5c8d6a4d9937a169e8ceeb64b3816f9f523 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 20 Oct 2024 16:50:29 +0100 Subject: [PATCH 050/242] consecutive keys with hash --- .../function/agg_many_vector_helper.c | 6 +-- tsl/src/nodes/vector_agg/hash_single_text.c | 2 +- .../vector_agg/hash_table_functions_impl.c | 37 +++++++++++++------ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index 47916e29131..df09a33f8e2 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -14,19 +14,19 @@ static void FUNCTION_NAME(many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) { - MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); + FUNCTION_NAME(state) *restrict states = (FUNCTION_NAME(state) *) agg_states; const CTYPE *values = vector->buffers[1]; const uint64 *valid = vector->buffers[0]; + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); for (int row = start_row; row < end_row; row++) { - FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); const CTYPE value = values[row]; const bool row_passes = (offsets[row] != 0); const bool value_notnull = arrow_row_is_valid(valid, row); if (row_passes && value_notnull) { - FUNCTION_NAME(one)(state, value); + FUNCTION_NAME(one)(&states[offsets[row]], value); } } MemoryContextSwitchTo(old); diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index e54002d3349..2aff2134372 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -85,6 +85,6 @@ hash_text(TextView view) #define KEY_VARIANT single_text #define KEY_HASH(X) hash_text(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) -#define SH_STORE_HASH +#define STORE_HASH #define CTYPE TextView #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 6b5e689829f..375e2a62fa9 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -15,16 +15,12 @@ typedef struct { CTYPE key; -#ifdef SH_STORE_HASH +#ifdef STORE_HASH uint32 hash; #endif uint32 agg_state_index; } FUNCTION_NAME(entry); -#ifdef SH_STORE_HASH -#define SH_GET_HASH(tb, entry) entry->hash -#endif - #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) #define SH_KEY_TYPE CTYPE @@ -35,6 +31,10 @@ typedef struct #define SH_DECLARE #define SH_DEFINE #define SH_ENTRY_EMPTY(entry) ((entry)->agg_state_index == 0) +#ifdef STORE_HASH +#define SH_GET_HASH(tb, entry) entry->hash +#define SH_STORE_HASH +#endif #include "import/ts_simplehash.h" struct FUNCTION_NAME(hash); @@ -68,6 +68,9 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, CTYPE last_key; uint32 last_key_index = 0; +#ifdef STORE_HASH + uint32 last_hash = 0; +#endif for (int row = start_row; row < end_row; row++) { bool key_valid = false; @@ -88,7 +91,12 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, continue; } - if (likely(last_key_index != 0) && KEY_EQUAL(key, last_key)) + uint32 current_hash = KEY_HASH(key); + if (likely(last_key_index != 0) +#ifdef STORE_HASH + && last_hash == current_hash +#endif + && KEY_EQUAL(key, last_key)) { /* * In real data sets, we often see consecutive rows with the @@ -106,7 +114,8 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, * Find the key using the hash table. */ bool found = false; - FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); + FUNCTION_NAME(entry) *restrict entry = + FUNCTION_NAME(insert_hash)(table, key, current_hash, &found); if (!found) { /* @@ -121,11 +130,18 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, last_key_index = entry->agg_state_index; last_key = key; +#ifdef STORE_HASH + last_hash = current_hash; +#endif } return next_unused_state_index; } +/* + * Nudge the compiler to generate separate implementations for different key + * decompression types. + */ static pg_attribute_always_inline uint32 FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *policy, CompressedColumnValues column, const uint64 *restrict filter, uint32 next_unused_state_index, @@ -154,10 +170,9 @@ FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *policy, CompressedColumnValues } /* - * This function exists just to nudge the compiler to generate separate - * implementation for the important case where the entire batch matches and the - * key has no null values, and the unimportant corner case when we have a scalar - * column. + * Nudge the compiler to generate separate implementation for the important case + * where the entire batch matches and the key has no null values, and the + * unimportant corner case when we have a scalar column. */ static uint32 FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, From e12f56387442a2b4fd965dd11fca59920d95da22 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 20 Oct 2024 16:52:53 +0100 Subject: [PATCH 051/242] consecutive keys w/o hash --- .../nodes/vector_agg/hash_table_functions_impl.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 375e2a62fa9..a85403567c9 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -68,9 +68,6 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, CTYPE last_key; uint32 last_key_index = 0; -#ifdef STORE_HASH - uint32 last_hash = 0; -#endif for (int row = start_row; row < end_row; row++) { bool key_valid = false; @@ -91,12 +88,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, continue; } - uint32 current_hash = KEY_HASH(key); - if (likely(last_key_index != 0) -#ifdef STORE_HASH - && last_hash == current_hash -#endif - && KEY_EQUAL(key, last_key)) + if (likely(last_key_index != 0) && KEY_EQUAL(key, last_key)) { /* * In real data sets, we often see consecutive rows with the @@ -114,8 +106,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, * Find the key using the hash table. */ bool found = false; - FUNCTION_NAME(entry) *restrict entry = - FUNCTION_NAME(insert_hash)(table, key, current_hash, &found); + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); if (!found) { /* @@ -130,9 +121,6 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, last_key_index = entry->agg_state_index; last_key = key; -#ifdef STORE_HASH - last_hash = current_hash; -#endif } return next_unused_state_index; From fdad239228b45c6e6f740d23a714edb7bee1b9ad Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:38:19 +0100 Subject: [PATCH 052/242] a stub for serialized hashing policy --- tsl/src/nodes/vector_agg/CMakeLists.txt | 1 + tsl/src/nodes/vector_agg/bytes_view.h | 20 +++++++++++ tsl/src/nodes/vector_agg/hash_serialized.c | 40 +++++++++++++++++++++ tsl/src/nodes/vector_agg/hash_single_text.c | 36 ++++++------------- 4 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/bytes_view.h create mode 100644 tsl/src/nodes/vector_agg/hash_serialized.c diff --git a/tsl/src/nodes/vector_agg/CMakeLists.txt b/tsl/src/nodes/vector_agg/CMakeLists.txt index 8df9e49baea..934800f64bf 100644 --- a/tsl/src/nodes/vector_agg/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/CMakeLists.txt @@ -5,6 +5,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_4.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_8.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_text.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_serialized.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_batch.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_hash.c ${CMAKE_CURRENT_SOURCE_DIR}/plan.c) diff --git a/tsl/src/nodes/vector_agg/bytes_view.h b/tsl/src/nodes/vector_agg/bytes_view.h new file mode 100644 index 00000000000..ac9d148feab --- /dev/null +++ b/tsl/src/nodes/vector_agg/bytes_view.h @@ -0,0 +1,20 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +typedef struct BytesView +{ + uint32 len; + const uint8 *data; +} BytesView; + +static pg_attribute_always_inline uint32 +hash_bytes_view(BytesView view) +{ + uint32 valll = -1; + COMP_CRC32C(valll, view.data, view.len); + return valll; +} diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c new file mode 100644 index 00000000000..8d7b573065d --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -0,0 +1,40 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for multiple serialized columns. + */ + +#include + +#include + +#include "compression/arrow_c_data_interface.h" +#include "grouping_policy_hash.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "bytes_view.h" + +static pg_attribute_always_inline void +serialized_get_key(CompressedColumnValues column, int row, BytesView *restrict key, + bool *restrict valid) +{ + Assert(false); +} + +static pg_attribute_always_inline BytesView +serialized_store_key(BytesView key, Datum *key_storage, MemoryContext key_memory_context) +{ + Assert(false); + return key; +} + +#define KEY_VARIANT serialized +#define KEY_HASH(X) hash_bytes_view(X) +#define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) +#define STORE_HASH +#define CTYPE BytesView +#include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 2aff2134372..6164d93016b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -14,28 +14,22 @@ #include "compression/arrow_c_data_interface.h" #include "grouping_policy_hash.h" -#include "hash64.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "bytes_view.h" -typedef struct TextView -{ - uint32 len; - const uint8 *data; -} TextView; - -static TextView -get_text_view(CompressedColumnValues *column_values, int arrow_row) +static BytesView +get_bytes_view(CompressedColumnValues *column_values, int arrow_row) { const uint32 start = ((uint32 *) column_values->buffers[1])[arrow_row]; const int32 value_bytes = ((uint32 *) column_values->buffers[1])[arrow_row + 1] - start; Assert(value_bytes >= 0); - return (TextView){ .len = value_bytes, .data = &((uint8 *) column_values->buffers[2])[start] }; + return (BytesView){ .len = value_bytes, .data = &((uint8 *) column_values->buffers[2])[start] }; } static pg_attribute_always_inline void -single_text_get_key(CompressedColumnValues column, int row, TextView *restrict key, +single_text_get_key(CompressedColumnValues column, int row, BytesView *restrict key, bool *restrict valid) { if (unlikely(column.decompression_type == DT_Scalar)) @@ -47,13 +41,13 @@ single_text_get_key(CompressedColumnValues column, int row, TextView *restrict k } else if (column.decompression_type == DT_ArrowText) { - *key = get_text_view(&column, row); + *key = get_bytes_view(&column, row); *valid = arrow_row_is_valid(column.buffers[0], row); } else if (column.decompression_type == DT_ArrowTextDict) { const int16 index = ((int16 *) column.buffers[3])[row]; - *key = get_text_view(&column, index); + *key = get_bytes_view(&column, index); *valid = arrow_row_is_valid(column.buffers[0], row); } else @@ -62,8 +56,8 @@ single_text_get_key(CompressedColumnValues column, int row, TextView *restrict k } } -static pg_attribute_always_inline TextView -single_text_store_key(TextView key, Datum *key_storage, MemoryContext key_memory_context) +static pg_attribute_always_inline BytesView +single_text_store_key(BytesView key, Datum *key_storage, MemoryContext key_memory_context) { const int total_bytes = key.len + VARHDRSZ; text *stored = (text *) MemoryContextAlloc(key_memory_context, total_bytes); @@ -74,17 +68,9 @@ single_text_store_key(TextView key, Datum *key_storage, MemoryContext key_memory return key; } -static pg_attribute_always_inline uint32 -hash_text(TextView view) -{ - uint32 valll = -1; - COMP_CRC32C(valll, view.data, view.len); - return valll; -} - #define KEY_VARIANT single_text -#define KEY_HASH(X) hash_text(X) +#define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define STORE_HASH -#define CTYPE TextView +#define CTYPE BytesView #include "hash_table_functions_impl.c" From 9716313b6b87c649bebcf66feb8d2943855322e9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:38:56 +0100 Subject: [PATCH 053/242] format --- tsl/src/nodes/vector_agg/hash_serialized.c | 4 ++-- tsl/src/nodes/vector_agg/hash_single_text.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 8d7b573065d..9ef52ee14ea 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -12,15 +12,15 @@ #include +#include "bytes_view.h" #include "compression/arrow_c_data_interface.h" #include "grouping_policy_hash.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" -#include "bytes_view.h" static pg_attribute_always_inline void serialized_get_key(CompressedColumnValues column, int row, BytesView *restrict key, - bool *restrict valid) + bool *restrict valid) { Assert(false); } diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 6164d93016b..0b18e878c8a 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -12,11 +12,11 @@ #include +#include "bytes_view.h" #include "compression/arrow_c_data_interface.h" #include "grouping_policy_hash.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" -#include "bytes_view.h" static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) From 87b2ffc0d81179f27f1028a093fa6479d337db37 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 20 Oct 2024 19:07:01 +0100 Subject: [PATCH 054/242] agg filter planning draft --- tsl/src/nodes/decompress_chunk/planner.c | 25 ++---- tsl/src/nodes/decompress_chunk/vector_quals.h | 12 ++- tsl/src/nodes/vector_agg/bytes_view.h | 4 + tsl/src/nodes/vector_agg/plan.c | 78 +++++++++++++++++-- 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/planner.c b/tsl/src/nodes/decompress_chunk/planner.c index c1f7648c9e3..24c2550228d 100644 --- a/tsl/src/nodes/decompress_chunk/planner.c +++ b/tsl/src/nodes/decompress_chunk/planner.c @@ -146,12 +146,6 @@ typedef struct } DecompressionMapContext; -typedef struct VectorQualInfoDecompressChunk -{ - VectorQualInfo vqinfo; - const UncompressedColumnInfo *colinfo; -} VectorQualInfoDecompressChunk; - static bool * build_vector_attrs_array(const UncompressedColumnInfo *colinfo, const CompressionInfo *info) { @@ -887,8 +881,12 @@ static void find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *path, List *qual_list, List **vectorized, List **nonvectorized) { - ListCell *lc; + VectorQualInfo vqi = { + .vector_attrs = build_vector_attrs_array(context->uncompressed_attno_info, path->info), + .rti = path->info->chunk_rel->relid, + }; + ListCell *lc; foreach (lc, qual_list) { Node *source_qual = lfirst(lc); @@ -901,14 +899,7 @@ find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *pat */ Node *transformed_comparison = (Node *) ts_transform_cross_datatype_comparison((Expr *) source_qual); - VectorQualInfoDecompressChunk vqidc = { - .vqinfo = { - .vector_attrs = build_vector_attrs_array(context->uncompressed_attno_info, path->info), - .rti = path->info->chunk_rel->relid, - }, - .colinfo = context->uncompressed_attno_info, - }; - Node *vectorized_qual = vector_qual_make(transformed_comparison, &vqidc.vqinfo); + Node *vectorized_qual = vector_qual_make(transformed_comparison, &vqi); if (vectorized_qual) { *vectorized = lappend(*vectorized, vectorized_qual); @@ -917,9 +908,9 @@ find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *pat { *nonvectorized = lappend(*nonvectorized, source_qual); } - - pfree(vqidc.vqinfo.vector_attrs); } + + pfree(vqi.vector_attrs); } /* diff --git a/tsl/src/nodes/decompress_chunk/vector_quals.h b/tsl/src/nodes/decompress_chunk/vector_quals.h index a3184d875c7..4fd2e058e4a 100644 --- a/tsl/src/nodes/decompress_chunk/vector_quals.h +++ b/tsl/src/nodes/decompress_chunk/vector_quals.h @@ -18,12 +18,16 @@ */ typedef struct VectorQualInfo { - /* The range-table index of the relation to compute vectorized quals - * for */ + /* + * The range-table index of the relation to compute vectorized quals + * for. + */ Index rti; - /* AttrNumber-indexed array indicating whether an attribute/column is a - * vectorizable type */ + /* + * Array indexed by uncompressed attno indicating whether an + * attribute/column is a vectorizable type. + */ bool *vector_attrs; } VectorQualInfo; diff --git a/tsl/src/nodes/vector_agg/bytes_view.h b/tsl/src/nodes/vector_agg/bytes_view.h index ac9d148feab..1930186b51b 100644 --- a/tsl/src/nodes/vector_agg/bytes_view.h +++ b/tsl/src/nodes/vector_agg/bytes_view.h @@ -5,6 +5,10 @@ */ #pragma once +#include + +#include + typedef struct BytesView { uint32 len; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 4312218c125..5f9bae69591 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -17,6 +17,7 @@ #include "exec.h" #include "nodes/decompress_chunk/planner.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" #include "utils.h" @@ -253,14 +254,8 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) } static bool -can_vectorize_aggref(Aggref *aggref, CustomScan *custom) +can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) { - if (aggref->aggfilter != NULL) - { - /* Filter clause on aggregate is not supported. */ - return false; - } - if (aggref->aggdirectargs != NIL) { /* Can't process ordered-set aggregates with direct arguments. */ @@ -282,6 +277,11 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) if (aggref->aggfilter != NULL) { /* Can't process aggregates with filter clause. */ + fprintf(stderr, "nonvectorized:\n"); + my_print(aggref->aggfilter); + Node *aggfilter_vectorized = vector_qual_make((Node *) aggref->aggfilter, vqi); + fprintf(stderr, "vectorized:\n"); + my_print(aggfilter_vectorized); return false; } @@ -549,6 +549,68 @@ try_insert_vector_agg_node(Plan *plan) return plan; } + // VectorQualInfo vqi = { .rti = custom->scan.scanrelid }; + VectorQualInfo vqi = { .rti = OUTER_VAR }; + fprintf(stderr, "scanrelid is %d\n", vqi.rti); + + /* + * Bulk decompression can be disabled for all columns in the DecompressChunk + * node settings, we can't do vectorized aggregation for compressed columns + * in that case. For segmentby columns it's still possible. + */ + List *settings = linitial(custom->custom_private); + const bool bulk_decompression_enabled_globally = + list_nth_int(settings, DCS_EnableBulkDecompression); + /* + * Now, we have to translate the decompressed varno into the compressed + * column index, to check if the column supports bulk decompression. + */ + List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); + List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); + List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); + + int maxattno = 0; + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) + { + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno > maxattno) + { + maxattno = custom_scan_attno; + } + } + + vqi.vector_attrs = (bool *) palloc0(sizeof(bool) * (maxattno + 1)); + + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) + { + const bool bulk_decompression_enabled_for_column = + list_nth_int(bulk_decompression_column, compressed_column_index); + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + /* + * Check if this column is a segmentby. + */ + const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); + + /* + * We support vectorized aggregation either for segmentby columns or for + * columns with bulk decompression enabled. + */ + vqi.vector_attrs[custom_scan_attno] = + (is_segmentby || + (bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)); + fprintf(stderr, + "bulk decompression for column %d: %d\n", + custom_scan_attno, + vqi.vector_attrs[custom_scan_attno]); + } + /* Now check the aggregate functions themselves. */ ListCell *lc; foreach (lc, agg->plan.targetlist) @@ -560,7 +622,7 @@ try_insert_vector_agg_node(Plan *plan) } Aggref *aggref = castNode(Aggref, target_entry->expr); - if (!can_vectorize_aggref(aggref, custom)) + if (!can_vectorize_aggref(aggref, custom, &vqi)) { return plan; } From a619abbf6aafb51ac00af86bcb94fc51313e851e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:54:28 +0300 Subject: [PATCH 055/242] some prototyping for vectorized filter clause --- .../nodes/decompress_chunk/compressed_batch.c | 14 +- .../nodes/decompress_chunk/compressed_batch.h | 16 + tsl/src/nodes/decompress_chunk/planner.c | 2 + tsl/src/nodes/vector_agg/exec.c | 39 +- tsl/src/nodes/vector_agg/exec.h | 2 + .../function/agg_many_vector_helper.c | 11 +- tsl/src/nodes/vector_agg/function/functions.c | 19 +- tsl/src/nodes/vector_agg/function/functions.h | 9 +- .../nodes/vector_agg/grouping_policy_batch.c | 29 +- .../nodes/vector_agg/grouping_policy_hash.c | 62 +- .../nodes/vector_agg/grouping_policy_hash.h | 3 + tsl/src/nodes/vector_agg/plan.c | 135 +- tsl/test/expected/vector_agg_functions.out | 1637 ++++++++++++----- tsl/test/sql/vector_agg_functions.sql | 40 +- 14 files changed, 1411 insertions(+), 607 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index eef5617c95e..d7614baa15d 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -20,18 +20,6 @@ #include "nodes/decompress_chunk/vector_predicates.h" #include "nodes/decompress_chunk/vector_quals.h" -/* - * VectorQualState for a compressed batch used to pass - * DecompressChunk-specific data to vector qual functions that are shared - * across scan nodes. - */ -typedef struct CompressedBatchVectorQualState -{ - VectorQualState vqstate; - DecompressBatchState *batch_state; - DecompressContext *dcontext; -} CompressedBatchVectorQualState; - /* * Create a single-value ArrowArray of an arithmetic type. This is a specialized * function because arithmetic types have a particular layout of ArrowArrays. @@ -309,7 +297,7 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state * VectorQualState->get_arrow_array() function used to interface with the * vector qual code across different scan nodes. */ -static const ArrowArray * +const ArrowArray * compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_default_value) { CompressedBatchVectorQualState *cbvqstate = (CompressedBatchVectorQualState *) vqstate; diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.h b/tsl/src/nodes/decompress_chunk/compressed_batch.h index 3131c2c7fd2..9871503e37c 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.h +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.h @@ -7,6 +7,7 @@ #include "compression/compression.h" #include "nodes/decompress_chunk/decompress_context.h" +#include "nodes/decompress_chunk/vector_quals.h" #include typedef struct ArrowArray ArrowArray; @@ -172,3 +173,18 @@ compressed_batch_current_tuple(DecompressBatchState *batch_state) Assert(batch_state->per_batch_context != NULL); return &batch_state->decompressed_scan_slot_data.base; } + +/* + * VectorQualState for a compressed batch used to pass + * DecompressChunk-specific data to vector qual functions that are shared + * across scan nodes. + */ +typedef struct CompressedBatchVectorQualState +{ + VectorQualState vqstate; + DecompressBatchState *batch_state; + DecompressContext *dcontext; +} CompressedBatchVectorQualState; + +const ArrowArray *compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, + bool *is_default_value); diff --git a/tsl/src/nodes/decompress_chunk/planner.c b/tsl/src/nodes/decompress_chunk/planner.c index 24c2550228d..4e12633df0f 100644 --- a/tsl/src/nodes/decompress_chunk/planner.c +++ b/tsl/src/nodes/decompress_chunk/planner.c @@ -808,6 +808,8 @@ vector_qual_make(Node *qual, const VectorQualInfo *vqinfo) if (!vqinfo->vector_attrs[var->varattno]) { /* This column doesn't support bulk decompression. */ + // fprintf(stderr, "doesn't support bulk decompression:\n"); + // my_print(var); return NULL; } diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 5580e9295df..7556fc6ca07 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -18,6 +18,7 @@ #include "guc.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/decompress_chunk/exec.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" static int @@ -47,7 +48,10 @@ get_input_offset(DecompressChunkState *decompress_state, Var *var) Assert(value_column_description->type == COMPRESSED_COLUMN || value_column_description->type == SEGMENTBY_COLUMN); - return value_column_description - dcontext->compressed_chunk_columns; + const int index = value_column_description - dcontext->compressed_chunk_columns; + // fprintf(stderr, "index %d for var:\n", index); + // my_print(var); + return index; } static void @@ -88,6 +92,10 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) def->output_offset = i; Aggref *aggref = castNode(Aggref, tlentry->expr); + + // fprintf(stderr, "the aggref at execution is:\n"); + // my_print(aggref); + VectorAggFunctions *func = get_vector_aggregate(aggref->aggfnoid); Assert(func != NULL); def->func = *func; @@ -106,6 +114,11 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) { def->input_offset = -1; } + + if (aggref->aggfilter != NULL) + { + def->filter_clauses = list_make1(aggref->aggfilter); + } } else { @@ -263,6 +276,30 @@ vector_agg_exec(CustomScanState *node) dcontext->ps->instrument->tuplecount += not_filtered_rows; } + const int naggs = list_length(vector_agg_state->agg_defs); + for (int i = 0; i < naggs; i++) + { + VectorAggDef *agg_def = (VectorAggDef *) list_nth(vector_agg_state->agg_defs, i); + if (agg_def->filter_clauses == NIL) + { + continue; + } + CompressedBatchVectorQualState cbvqstate = { + .vqstate = { + .vectorized_quals_constified = agg_def->filter_clauses, + .num_results = batch_state->total_batch_rows, + .per_vector_mcxt = batch_state->per_batch_context, + .slot = compressed_slot, + .get_arrow_array = compressed_batch_get_arrow_array, + }, + .batch_state = batch_state, + .dcontext = dcontext, + }; + VectorQualState *vqstate = &cbvqstate.vqstate; + vector_qual_compute(vqstate); + agg_def->filter_result = vqstate->vector_qual_result; + } + grouping->gp_add_batch(grouping, batch_state); compressed_batch_discard_tuples(batch_state); diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index f991729125f..b66a190c290 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -18,6 +18,8 @@ typedef struct VectorAggFunctions func; int input_offset; int output_offset; + List *filter_clauses; + uint64 *filter_result; } VectorAggDef; typedef struct diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index df09a33f8e2..59e93a729f2 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -11,20 +11,17 @@ * aggregate function state. */ static void -FUNCTION_NAME(many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) +FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) { FUNCTION_NAME(state) *restrict states = (FUNCTION_NAME(state) *) agg_states; const CTYPE *values = vector->buffers[1]; - const uint64 *valid = vector->buffers[0]; MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); for (int row = start_row; row < end_row; row++) { const CTYPE value = values[row]; - const bool row_passes = (offsets[row] != 0); - const bool value_notnull = arrow_row_is_valid(valid, row); - - if (row_passes && value_notnull) + if (arrow_row_is_valid(filter, row)) { FUNCTION_NAME(one)(&states[offsets[row]], value); } diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index fc141762497..2e0ddb87bfe 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -53,19 +53,17 @@ count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, Datum constvalue, bool constisnull, +count_star_many_scalar(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx) { CountState *states = (CountState *) agg_states; for (int row = start_row; row < end_row; row++) { - if (offsets[row] == 0) + if (arrow_row_is_valid(filter, row)) { - continue; + states[offsets[row]].count++; } - - states[offsets[row]].count++; } } @@ -132,16 +130,13 @@ count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *f } static void -count_any_many(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, - const ArrowArray *vector, MemoryContext agg_extra_mctx) +count_any_many(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) { - const uint64 *valid = vector->buffers[0]; for (int row = start_row; row < end_row; row++) { CountState *state = (offsets[row] + (CountState *) agg_states); - const bool row_passes = (offsets[row] != 0); - const bool value_notnull = arrow_row_is_valid(valid, row); - if (row_passes && value_notnull) + if (arrow_row_is_valid(filter, row)) { state->count++; } diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 18c43c163f1..67cecf554e1 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -31,15 +31,16 @@ typedef struct * Add the rows of the given arrow array to aggregate function states given * by the respective offsets. */ - void (*agg_many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx); + void (*agg_many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx); /* * Same as above, but for a scalar argument. This is mostly important for * count(*) and can be NULL. */ - void (*agg_many_scalar)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, Datum constvalue, bool constisnull, + void (*agg_many_scalar)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, MemoryContext agg_extra_mctx); /* Emit a partial aggregation result. */ diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index f7c7db9ee46..783d601b757 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -98,6 +98,20 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de Datum arg_datum = 0; bool arg_isnull = true; + uint64 *filter = batch_state->vector_qual_result; + if (agg_def->filter_result != NULL) + { + filter = agg_def->filter_result; + if (batch_state->vector_qual_result != NULL) + { + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + for (size_t i = 0; i < num_words; i++) + { + filter[i] &= batch_state->vector_qual_result[i]; + } + } + } + /* * We have functions with one argument, and one function with no arguments * (count(*)). Collect the arguments. @@ -126,10 +140,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func.agg_vector(agg_state, - arg_arrow, - batch_state->vector_qual_result, - agg_extra_mctx); + agg_def->func.agg_vector(agg_state, arg_arrow, filter, agg_extra_mctx); } else { @@ -137,16 +148,18 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de * Scalar argument, or count(*). Have to also count the valid rows in * the batch. */ - const int n = - arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows); + const int n = arrow_num_valid(filter, batch_state->total_batch_rows); /* * The batches that are fully filtered out by vectorized quals should * have been skipped by the caller. */ - Assert(n > 0); + // Assert(n > 0); - agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + if (n > 0) + { + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + } } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 8c094091fdc..badc87c549c 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -115,11 +115,11 @@ gp_hash_reset(GroupingPolicy *obj) } static void -compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int end_row, - VectorAggDef *agg_def, void *agg_states, uint32 *offsets, - MemoryContext agg_extra_mctx) +compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState *batch_state, + int start_row, int end_row, VectorAggDef *agg_def, void *agg_states, + const uint32 *offsets, MemoryContext agg_extra_mctx) { - ArrowArray *arg_arrow = NULL; + const ArrowArray *arg_arrow = NULL; Datum arg_datum = 0; bool arg_isnull = true; @@ -129,7 +129,8 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e */ if (agg_def->input_offset >= 0) { - CompressedColumnValues *values = &batch_state->compressed_columns[agg_def->input_offset]; + const CompressedColumnValues *values = + &batch_state->compressed_columns[agg_def->input_offset]; Assert(values->decompression_type != DT_Invalid); Assert(values->decompression_type != DT_Iterator); @@ -145,14 +146,44 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } } + uint64 *restrict filter = NULL; + if (batch_state->vector_qual_result != NULL || agg_def->filter_result != NULL || + (arg_arrow != NULL && arg_arrow->buffers[0] != NULL)) + { + filter = policy->tmp_filter; + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + for (size_t i = 0; i < num_words; i++) + { + uint64 word = -1; + if (batch_state->vector_qual_result != NULL) + { + word &= batch_state->vector_qual_result[i]; + } + if (agg_def->filter_result != NULL) + { + word &= agg_def->filter_result[i]; + } + if (arg_arrow != NULL && arg_arrow->buffers[0] != NULL) + { + word &= ((uint64 *) arg_arrow->buffers[0])[i]; + } + filter[i] = word; + } + } + /* * Now call the function. */ if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func - .agg_many_vector(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); + agg_def->func.agg_many_vector(agg_states, + offsets, + filter, + start_row, + end_row, + arg_arrow, + agg_extra_mctx); } else { @@ -164,6 +195,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e { agg_def->func.agg_many_scalar(agg_states, offsets, + filter, start_row, end_row, arg_datum, @@ -174,7 +206,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e { for (int i = start_row; i < end_row; i++) { - if (offsets[i] == 0) + if (!arrow_row_is_valid(filter, i)) { continue; } @@ -251,7 +283,8 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con /* * Update the aggregate function states. */ - compute_single_aggregate(batch_state, + compute_single_aggregate(policy, + batch_state, start_row, end_row, agg_def, @@ -290,6 +323,17 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); + /* + * Allocate the temporary filter array for computing the combined results of + * batch filter, aggregate filter and column validity. + */ + const size_t num_words = (n + 63) / 64; + if (num_words > policy->num_tmp_filter_words) + { + policy->tmp_filter = palloc(sizeof(*policy->tmp_filter) * (num_words * 2 + 1)); + policy->num_tmp_filter_words = (num_words * 2 + 1); + } + const uint64_t *restrict filter = batch_state->vector_qual_result; if (filter == NULL) { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index f91ceb78ae0..9020922207d 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -86,6 +86,9 @@ typedef struct GroupingPolicyHash void *restrict keys; MemoryContext key_body_mctx; + uint64 *tmp_filter; + uint64 num_tmp_filter_words; + /* * Some statistics for debugging. */ diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 5f9bae69591..88a55b1fb72 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -179,27 +179,7 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) return false; } - Var *aggregated_var = castNode(Var, expr); - - /* - * Check if this particular column is a segmentby or has bulk decompression - * enabled. This hook is called after set_plan_refs, and at this stage the - * output targetlist of the aggregation node uses OUTER_VAR references into - * the child scan targetlist, so first we have to translate this. - */ - Assert(aggregated_var->varno == OUTER_VAR); - TargetEntry *decompressed_target_entry = - list_nth(custom->scan.plan.targetlist, AttrNumberGetAttrOffset(aggregated_var->varattno)); - - if (!IsA(decompressed_target_entry->expr, Var)) - { - /* - * Can only aggregate the plain Vars. Not sure if this is redundant with - * the similar check above. - */ - return false; - } - Var *decompressed_var = castNode(Var, decompressed_target_entry->expr); + Var *decompressed_var = castNode(Var, expr); /* * Now, we have to translate the decompressed varno into the compressed @@ -211,7 +191,28 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) int compressed_column_index = 0; for (; compressed_column_index < list_length(decompression_map); compressed_column_index++) { - if (list_nth_int(decompression_map, compressed_column_index) == decompressed_var->varattno) + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + int uncompressed_chunk_attno = 0; + if (custom->custom_scan_tlist == NIL) + { + uncompressed_chunk_attno = custom_scan_attno; + } + else + { + Var *var = castNode(Var, + castNode(TargetEntry, + list_nth(custom->custom_scan_tlist, + AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + uncompressed_chunk_attno = var->varattno; + } + + if (uncompressed_chunk_attno == decompressed_var->varattno) { break; } @@ -276,13 +277,15 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) if (aggref->aggfilter != NULL) { - /* Can't process aggregates with filter clause. */ - fprintf(stderr, "nonvectorized:\n"); - my_print(aggref->aggfilter); + /* Can process aggregates with filter clause if it's vectorizable. */ Node *aggfilter_vectorized = vector_qual_make((Node *) aggref->aggfilter, vqi); - fprintf(stderr, "vectorized:\n"); - my_print(aggfilter_vectorized); - return false; + if (aggfilter_vectorized == NULL) + { + // fprintf(stderr, "not vectorizable:\n"); + // my_print(aggref->aggfilter); + return false; + } + aggref->aggfilter = (Expr *) aggfilter_vectorized; } if (get_vector_aggregate(aggref->aggfnoid) == NULL) @@ -325,6 +328,9 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) return true; } + /* FIXME */ + List *aggregated_tlist_resolved = resolve_outer_special_vars(agg->plan.targetlist, custom); + /* * We support hashed vectorized grouping by one fixed-size by-value * compressed column. @@ -334,7 +340,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) if (agg->numCols == 1 && agg->aggstrategy == AGG_HASHED) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); - TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); bool is_segmentby = false; if (is_vector_var(custom, entry->expr, &is_segmentby)) @@ -361,7 +367,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); bool is_segmentby = false; if (!is_vector_var(custom, entry->expr, &is_segmentby)) @@ -549,9 +555,8 @@ try_insert_vector_agg_node(Plan *plan) return plan; } - // VectorQualInfo vqi = { .rti = custom->scan.scanrelid }; - VectorQualInfo vqi = { .rti = OUTER_VAR }; - fprintf(stderr, "scanrelid is %d\n", vqi.rti); + // VectorQualInfo vqi = { .rti = OUTER_VAR }; + VectorQualInfo vqi = { .rti = custom->scan.scanrelid }; /* * Bulk decompression can be disabled for all columns in the DecompressChunk @@ -569,14 +574,37 @@ try_insert_vector_agg_node(Plan *plan) List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); + /* FIXME */ + List *aggregated_tlist_resolved = resolve_outer_special_vars(agg->plan.targetlist, custom); + int maxattno = 0; for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); compressed_column_index++) { const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); - if (custom_scan_attno > maxattno) + if (custom_scan_attno <= 0) + { + continue; + } + + int uncompressed_chunk_attno = 0; + if (custom->custom_scan_tlist == NIL) + { + uncompressed_chunk_attno = custom_scan_attno; + } + else { - maxattno = custom_scan_attno; + Var *var = castNode(Var, + castNode(TargetEntry, + list_nth(custom->custom_scan_tlist, + AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + uncompressed_chunk_attno = var->varattno; + } + + if (uncompressed_chunk_attno > maxattno) + { + maxattno = uncompressed_chunk_attno; } } @@ -587,12 +615,28 @@ try_insert_vector_agg_node(Plan *plan) { const bool bulk_decompression_enabled_for_column = list_nth_int(bulk_decompression_column, compressed_column_index); + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); if (custom_scan_attno <= 0) { continue; } + int uncompressed_chunk_attno = 0; + if (custom->custom_scan_tlist == NIL) + { + uncompressed_chunk_attno = custom_scan_attno; + } + else + { + Var *var = castNode(Var, + castNode(TargetEntry, + list_nth(custom->custom_scan_tlist, + AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + uncompressed_chunk_attno = var->varattno; + } + /* * Check if this column is a segmentby. */ @@ -602,18 +646,21 @@ try_insert_vector_agg_node(Plan *plan) * We support vectorized aggregation either for segmentby columns or for * columns with bulk decompression enabled. */ - vqi.vector_attrs[custom_scan_attno] = - (is_segmentby || - (bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)); - fprintf(stderr, - "bulk decompression for column %d: %d\n", - custom_scan_attno, - vqi.vector_attrs[custom_scan_attno]); + const bool is_vector_var = (is_segmentby || (bulk_decompression_enabled_for_column && + bulk_decompression_enabled_globally)); + vqi.vector_attrs[uncompressed_chunk_attno] = is_vector_var; + +// fprintf(stderr, +// "compressed %d -> uncompressed %d custom scan %d vector %d\n", +// compressed_column_index, +// uncompressed_chunk_attno, +// custom_scan_attno, +// is_vector_var); } /* Now check the aggregate functions themselves. */ ListCell *lc; - foreach (lc, agg->plan.targetlist) + foreach (lc, aggregated_tlist_resolved) { TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); if (!IsA(target_entry->expr, Aggref)) @@ -622,6 +669,8 @@ try_insert_vector_agg_node(Plan *plan) } Aggref *aggref = castNode(Aggref, target_entry->expr); + // fprintf(stderr, "the final aggref is:\n"); + // my_print(aggref); if (!can_vectorize_aggref(aggref, custom, &vqi)) { return plan; diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 2e163661f45..56b5e289776 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -104,10 +104,11 @@ set timescaledb.debug_require_vector_agg = 'require'; ---- on float4 due to different numeric stability in our and PG implementations. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s) from aggfns%s%s order by 1;', + format('%sselect %s%s(%s)%s from aggfns%s%s order by 1;', explain, grouping || ', ', function, variable, + ' filter (where ' || agg_filter || ')', ' where ' || condition, ' group by ' || grouping ) from @@ -145,27 +146,24 @@ from null, 's', 'ss', - 'x']) with ordinality as grouping(grouping, n) + 'x']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) where - case --- when explain is not null then condition is null and grouping = 's' - when explain is not null then false - when true then true - end - and - case - when variable = '*' then function = 'count' - -- No need to test the aggregate functions themselves again for string - -- grouping. - when grouping = 'x' then function = 'count' and variable = 'cfloat4' - when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's', 'ss') - when variable = 't' then function in ('min', 'max') - when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') - -- This is not vectorized yet. - when function = 'stddev' then variable != 'cint8' - else true end -order by explain, condition.n, variable, function, grouping.n + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') + and (variable not in ('t', 'cts', 'ctstz', 'cdate') or function in ('min', 'max')) + -- This is not vectorized yet + and (variable != 'cint8' or function != 'stddev') + and (function != 'count' or variable in ('cint2', 's', '*')) + and (agg_filter is null or (function = 'count') or (function = 'sum' and variable in ('cint2', 'cint4'))) + and (condition is distinct from 'cint2 is null' or variable = 'cint2') + -- No need to test the aggregate functions themselves again for string + -- grouping. + and (grouping is distinct from 'x' or (function = 'count' and variable in ('cint2', '*') and agg_filter is null)) +order by explain, condition.n, variable, function, grouping.n, agg_filter.n \gexec select count(*) from aggfns order by 1; count @@ -173,6 +171,12 @@ select count(*) from aggfns order by 1; 200000 (1 row) +select count(*) filter (where cint4 > 0) from aggfns order by 1; + count +------- + 99428 +(1 row) + select s, count(*) from aggfns group by s order by 1; s | count ---+------- @@ -188,6 +192,21 @@ select s, count(*) from aggfns group by s order by 1; 9 | 20000 (10 rows) +select s, count(*) filter (where cint4 > 0) from aggfns group by s order by 1; + s | count +---+------- + 0 | 9942 + 1 | 9943 + 2 | 9943 + 3 | 9943 + 4 | 9943 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 +(10 rows) + select ss, count(*) from aggfns group by ss order by 1; ss | count ----+------- @@ -203,6 +222,21 @@ select ss, count(*) from aggfns group by ss order by 1; | 19 (10 rows) +select ss, count(*) filter (where cint4 > 0) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 9942 + 3 | 9937 + 4 | 9932 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 + 11 | 19897 + | 6 +(10 rows) + select x, count(*) from aggfns group by x order by 1; x | count ----+------- @@ -326,57 +360,6 @@ select ss, avg(cfloat4) from aggfns group by ss order by 1; | -5.91588952823689 (10 rows) -select count(cfloat4) from aggfns order by 1; - count --------- - 200000 -(1 row) - -select s, count(cfloat4) from aggfns group by s order by 1; - s | count ----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select ss, count(cfloat4) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 - | 19 -(10 rows) - -select x, count(cfloat4) from aggfns group by x order by 1; - x | count -----+------- - 0 | 20000 - 11 | 40019 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - | 19 -(10 rows) - select max(cfloat4) from aggfns order by 1; max ----- @@ -737,6 +720,93 @@ select ss, avg(cint2) from aggfns group by ss order by 1; | -335.0000000000000000 (10 rows) +select count(cint2) from aggfns order by 1; + count +-------- + 199810 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfns order by 1; + count +------- + 99342 +(1 row) + +select s, count(cint2) from aggfns group by s order by 1; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfns group by s order by 1; + s | count +---+------- + 0 | 9936 + 1 | 9935 + 2 | 9935 + 3 | 9934 + 4 | 9933 + 5 | 9933 + 6 | 9932 + 7 | 9936 + 8 | 9933 + 9 | 9935 +(10 rows) + +select ss, count(cint2) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 19981 + 3 | 19962 + 4 | 19962 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 + | 19 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 9936 + 3 | 9928 + 4 | 9922 + 5 | 9933 + 6 | 9932 + 7 | 9936 + 8 | 9933 + 9 | 9935 + 11 | 19881 + | 6 +(10 rows) + +select x, count(cint2) from aggfns group by x order by 1; + x | count +----+------- + 0 | 19981 + 11 | 39981 + 3 | 19962 + 4 | 19962 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + | 19 +(10 rows) + select max(cint2) from aggfns order by 1; max ------- @@ -851,6 +921,12 @@ select sum(cint2) from aggfns order by 1; -8423824 (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns order by 1; + sum +----------- + -17618159 +(1 row) + select s, sum(cint2) from aggfns group by s order by 1; s | sum ---+--------- @@ -866,6 +942,21 @@ select s, sum(cint2) from aggfns group by s order by 1; 9 | -861420 (10 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns group by s order by 1; + s | sum +---+---------- + 0 | -1788968 + 1 | -1806454 + 2 | -1747433 + 3 | -1738178 + 4 | -1717456 + 5 | -1788759 + 6 | -1746163 + 7 | -1731851 + 8 | -1741688 + 9 | -1811209 +(10 rows) + select ss, sum(cint2) from aggfns group by ss order by 1; ss | sum ----+---------- @@ -881,6 +972,21 @@ select ss, sum(cint2) from aggfns group by ss order by 1; | -6365 (10 rows) +select ss, sum(cint2) filter (where cint4 > 0) from aggfns group by ss order by 1; + ss | sum +----+---------- + 0 | -1788968 + 3 | -1737816 + 4 | -1696920 + 5 | -1788759 + 6 | -1746163 + 7 | -1731851 + 8 | -1741688 + 9 | -1811209 + 11 | -3574423 + | -362 +(10 rows) + select avg(cint4) from aggfns order by 1; avg ----------------------- @@ -1031,6 +1137,12 @@ select sum(cint4) from aggfns order by 1; -566665557362 (1 row) +select sum(cint4) filter (where cint4 > 0) from aggfns order by 1; + sum +---------------- + 53436167838463 +(1 row) + select s, sum(cint4) from aggfns group by s order by 1; s | sum ---+-------------- @@ -1046,6 +1158,21 @@ select s, sum(cint4) from aggfns group by s order by 1; 9 | -56283868935 (10 rows) +select s, sum(cint4) filter (where cint4 > 0) from aggfns group by s order by 1; + s | sum +---+--------------- + 0 | 5342690615367 + 1 | 5343370718252 + 2 | 5343352005654 + 3 | 5343352005654 + 4 | 5344281595944 + 5 | 5343480575409 + 6 | 5343480575409 + 7 | 5344006156678 + 8 | 5344006156678 + 9 | 5344147433418 +(10 rows) + select ss, sum(cint4) from aggfns group by ss order by 1; ss | sum ----+--------------- @@ -1061,6 +1188,21 @@ select ss, sum(cint4) from aggfns group by ss order by 1; | -2774095334 (10 rows) +select ss, sum(cint4) filter (where cint4 > 0) from aggfns group by ss order by 1; + ss | sum +----+---------------- + 0 | 5342690615367 + 3 | 5340469357420 + 4 | 5338771617836 + 5 | 5343480575409 + 6 | 5343480575409 + 7 | 5344006156678 + 8 | 5344006156678 + 9 | 5344147433418 + 11 | 10692232702014 + | 2882648234 +(10 rows) + select avg(cint8) from aggfns order by 1; avg ----------------------- @@ -1391,6 +1533,12 @@ select count(s) from aggfns order by 1; 200000 (1 row) +select count(s) filter (where cint4 > 0) from aggfns order by 1; + count +------- + 99428 +(1 row) + select s, count(s) from aggfns group by s order by 1; s | count ---+------- @@ -1406,6 +1554,21 @@ select s, count(s) from aggfns group by s order by 1; 9 | 20000 (10 rows) +select s, count(s) filter (where cint4 > 0) from aggfns group by s order by 1; + s | count +---+------- + 0 | 9942 + 1 | 9943 + 2 | 9943 + 3 | 9943 + 4 | 9943 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 +(10 rows) + select ss, count(s) from aggfns group by ss order by 1; ss | count ----+------- @@ -1421,6 +1584,21 @@ select ss, count(s) from aggfns group by ss order by 1; | 19 (10 rows) +select ss, count(s) filter (where cint4 > 0) from aggfns group by ss order by 1; + ss | count +----+------- + 0 | 9942 + 3 | 9937 + 4 | 9932 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 + 11 | 19897 + | 6 +(10 rows) + select max(s) from aggfns order by 1; max ----- @@ -1601,42 +1779,6 @@ select ss, avg(ss) from aggfns group by ss order by 1; | (10 rows) -select count(ss) from aggfns order by 1; - count --------- - 199981 -(1 row) - -select s, count(ss) from aggfns group by s order by 1; - s | count ----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 19981 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select ss, count(ss) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 - | 0 -(10 rows) - select max(ss) from aggfns order by 1; max ----- @@ -1859,6 +2001,12 @@ select count(*) from aggfns where cfloat8 > 0 order by 1; 99430 (1 row) +select count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + count +------- + 49288 +(1 row) + select s, count(*) from aggfns where cfloat8 > 0 group by s order by 1; s | count ---+------- @@ -1874,6 +2022,21 @@ select s, count(*) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9943 (10 rows) +select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 4928 + 1 | 4929 + 2 | 4928 + 3 | 4928 + 4 | 4929 + 5 | 4929 + 6 | 4929 + 7 | 4929 + 8 | 4929 + 9 | 4930 +(10 rows) + select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- @@ -1889,6 +2052,21 @@ select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; | 8 (10 rows) +select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 4928 + 3 | 4925 + 4 | 4922 + 5 | 4929 + 6 | 4929 + 7 | 4929 + 8 | 4929 + 9 | 4930 + 11 | 9864 + | 3 +(10 rows) + select x, count(*) from aggfns where cfloat8 > 0 group by x order by 1; x | count ----+------- @@ -2012,57 +2190,6 @@ select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; | -1.46971142292023 (10 rows) -select count(cfloat4) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99430 -(1 row) - -select s, count(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 9943 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 - 11 | 19896 - | 8 -(10 rows) - -select x, count(cfloat4) from aggfns where cfloat8 > 0 group by x order by 1; - x | count -----+------- - 0 | 9943 - 11 | 19896 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 - | 8 -(10 rows) - select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; max --------- @@ -2423,6 +2550,93 @@ select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; | 1475.6250000000000000 (10 rows) +select count(cint2) from aggfns where cfloat8 > 0 order by 1; + count +------- + 99340 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + count +------- + 49247 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 9934 + 1 | 9933 + 2 | 9933 + 3 | 9932 + 4 | 9936 + 5 | 9933 + 6 | 9935 + 7 | 9933 + 8 | 9937 + 9 | 9934 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 4926 + 1 | 4925 + 2 | 4924 + 3 | 4922 + 4 | 4925 + 5 | 4923 + 6 | 4925 + 7 | 4924 + 8 | 4927 + 9 | 4926 +(10 rows) + +select ss, count(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 9934 + 3 | 9924 + 4 | 9925 + 5 | 9933 + 6 | 9935 + 7 | 9933 + 8 | 9937 + 9 | 9934 + 11 | 19877 + | 8 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 4926 + 3 | 4919 + 4 | 4918 + 5 | 4923 + 6 | 4925 + 7 | 4924 + 8 | 4927 + 9 | 4926 + 11 | 9856 + | 3 +(10 rows) + +select x, count(cint2) from aggfns where cfloat8 > 0 group by x order by 1; + x | count +----+------- + 0 | 9934 + 11 | 19877 + 3 | 9924 + 4 | 9925 + 5 | 9933 + 6 | 9935 + 7 | 9933 + 8 | 9937 + 9 | 9934 + | 8 +(10 rows) + select max(cint2) from aggfns where cfloat8 > 0 order by 1; max ------- @@ -2537,6 +2751,12 @@ select sum(cint2) from aggfns where cfloat8 > 0 order by 1; 5959705 (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + sum +---------- + -6198630 +(1 row) + select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; s | sum ---+-------- @@ -2552,6 +2772,21 @@ select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 590038 (10 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; + s | sum +---+--------- + 0 | -629182 + 1 | -633190 + 2 | -579865 + 3 | -604326 + 4 | -630147 + 5 | -665070 + 6 | -620684 + 7 | -570776 + 8 | -639376 + 9 | -626014 +(10 rows) + select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+--------- @@ -2567,9 +2802,24 @@ select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; | 11805 (10 rows) -select avg(cint4) from aggfns where cfloat8 > 0 order by 1; - avg ------------------------ +select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | sum +----+---------- + 0 | -629182 + 3 | -592786 + 4 | -624445 + 5 | -665070 + 6 | -620684 + 7 | -570776 + 8 | -639376 + 9 | -626014 + 11 | -1218757 + | -11540 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 > 0 order by 1; + avg +----------------------- -3042925.418565825204 (1 row) @@ -2717,6 +2967,12 @@ select sum(cint4) from aggfns where cfloat8 > 0 order by 1; -302558074368 (1 row) +select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + sum +---------------- + 26671252627657 +(1 row) + select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by 1; s | sum ---+-------------- @@ -2732,6 +2988,21 @@ select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by 1; 9 | -29660662189 (10 rows) +select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; + s | sum +---+--------------- + 0 | 2665908254089 + 1 | 2666588356974 + 2 | 2666553381473 + 3 | 2666553381473 + 4 | 2667584662818 + 5 | 2667584662818 + 6 | 2667584662818 + 7 | 2667584662818 + 8 | 2667584662818 + 9 | 2667725939558 +(10 rows) + select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; ss | sum ----+-------------- @@ -2747,6 +3018,21 @@ select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; | -728241449 (10 rows) +select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | sum +----+--------------- + 0 | 2665908254089 + 3 | 2664401125147 + 4 | 2663415726889 + 5 | 2667584662818 + 6 | 2667584662818 + 7 | 2667584662818 + 8 | 2667584662818 + 9 | 2667725939558 + 11 | 5337310674376 + | 2152256326 +(10 rows) + select avg(cint8) from aggfns where cfloat8 > 0 order by 1; avg ----------------------- @@ -3077,6 +3363,12 @@ select count(s) from aggfns where cfloat8 > 0 order by 1; 99430 (1 row) +select count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + count +------- + 49288 +(1 row) + select s, count(s) from aggfns where cfloat8 > 0 group by s order by 1; s | count ---+------- @@ -3092,6 +3384,21 @@ select s, count(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9943 (10 rows) +select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; + s | count +---+------- + 0 | 4928 + 1 | 4929 + 2 | 4928 + 3 | 4928 + 4 | 4929 + 5 | 4929 + 6 | 4929 + 7 | 4929 + 8 | 4929 + 9 | 4930 +(10 rows) + select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; ss | count ----+------- @@ -3107,6 +3414,21 @@ select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; | 8 (10 rows) +select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + ss | count +----+------- + 0 | 4928 + 3 | 4925 + 4 | 4922 + 5 | 4929 + 6 | 4929 + 7 | 4929 + 8 | 4929 + 9 | 4930 + 11 | 9864 + | 3 +(10 rows) + select max(s) from aggfns where cfloat8 > 0 order by 1; max ----- @@ -3287,42 +3609,6 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; | (10 rows) -select count(ss) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99422 -(1 row) - -select s, count(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9934 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select ss, count(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 9943 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 - 11 | 19896 - | 0 -(10 rows) - select max(ss) from aggfns where cfloat8 > 0 order by 1; max ----- @@ -3545,6 +3831,12 @@ select count(*) from aggfns where cfloat8 <= 0 order by 1; 100570 (1 row) +select count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; + count +------- + 50140 +(1 row) + select s, count(*) from aggfns where cfloat8 <= 0 group by s order by 1; s | count ---+------- @@ -3560,6 +3852,21 @@ select s, count(*) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 10057 (10 rows) +select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 5014 + 1 | 5014 + 2 | 5015 + 3 | 5015 + 4 | 5014 + 5 | 5013 + 6 | 5013 + 7 | 5014 + 8 | 5014 + 9 | 5014 +(10 rows) + select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- @@ -3575,6 +3882,21 @@ select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; | 11 (10 rows) +select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 5014 + 3 | 5012 + 4 | 5010 + 5 | 5013 + 6 | 5013 + 7 | 5014 + 8 | 5014 + 9 | 5014 + 11 | 10033 + | 3 +(10 rows) + select x, count(*) from aggfns where cfloat8 <= 0 group by x order by 1; x | count ----+------- @@ -3698,57 +4020,6 @@ select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; | -9.14947360483083 (10 rows) -select count(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - count --------- - 100570 -(1 row) - -select s, count(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 10057 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 - 11 | 20123 - | 11 -(10 rows) - -select x, count(cfloat4) from aggfns where cfloat8 <= 0 group by x order by 1; - x | count -----+------- - 0 | 10057 - 11 | 20123 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 - | 11 -(10 rows) - select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; max ----- @@ -4109,6 +4380,93 @@ select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; | -1651.8181818181818182 (10 rows) +select count(cint2) from aggfns where cfloat8 <= 0 order by 1; + count +-------- + 100470 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; + count +------- + 50095 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 10047 + 1 | 10048 + 2 | 10048 + 3 | 10049 + 4 | 10045 + 5 | 10048 + 6 | 10046 + 7 | 10048 + 8 | 10044 + 9 | 10047 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 5010 + 1 | 5010 + 2 | 5011 + 3 | 5012 + 4 | 5008 + 5 | 5010 + 6 | 5007 + 7 | 5012 + 8 | 5006 + 9 | 5009 +(10 rows) + +select ss, count(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 10047 + 3 | 10038 + 4 | 10037 + 5 | 10048 + 6 | 10046 + 7 | 10048 + 8 | 10044 + 9 | 10047 + 11 | 20104 + | 11 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 5010 + 3 | 5009 + 4 | 5004 + 5 | 5010 + 6 | 5007 + 7 | 5012 + 8 | 5006 + 9 | 5009 + 11 | 10025 + | 3 +(10 rows) + +select x, count(cint2) from aggfns where cfloat8 <= 0 group by x order by 1; + x | count +----+------- + 0 | 10047 + 11 | 20104 + 3 | 10038 + 4 | 10037 + 5 | 10048 + 6 | 10046 + 7 | 10048 + 8 | 10044 + 9 | 10047 + | 11 +(10 rows) + select max(cint2) from aggfns where cfloat8 <= 0 order by 1; max ------- @@ -4223,6 +4581,12 @@ select sum(cint2) from aggfns where cfloat8 <= 0 order by 1; -14383529 (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; + sum +----------- + -11419529 +(1 row) + select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; s | sum ---+---------- @@ -4238,6 +4602,21 @@ select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | -1451458 (10 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; + s | sum +---+---------- + 0 | -1159786 + 1 | -1173264 + 2 | -1167568 + 3 | -1133852 + 4 | -1087309 + 5 | -1123689 + 6 | -1125479 + 7 | -1161075 + 8 | -1102312 + 9 | -1185195 +(10 rows) + select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+---------- @@ -4253,6 +4632,21 @@ select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; | -18170 (10 rows) +select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | sum +----+---------- + 0 | -1159786 + 3 | -1145030 + 4 | -1072475 + 5 | -1123689 + 6 | -1125479 + 7 | -1161075 + 8 | -1102312 + 9 | -1185195 + 11 | -2355666 + | 11178 +(10 rows) + select avg(cint4) from aggfns where cfloat8 <= 0 order by 1; avg ----------------------- @@ -4403,6 +4797,12 @@ select sum(cint4) from aggfns where cfloat8 <= 0 order by 1; -264107482994 (1 row) +select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; + sum +---------------- + 26764915210806 +(1 row) + select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; s | sum ---+-------------- @@ -4418,6 +4818,21 @@ select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | -26623206746 (10 rows) +select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; + s | sum +---+--------------- + 0 | 2676782361278 + 1 | 2676782361278 + 2 | 2676798624181 + 3 | 2676798624181 + 4 | 2676696933126 + 5 | 2675895912591 + 6 | 2675895912591 + 7 | 2676421493860 + 8 | 2676421493860 + 9 | 2676421493860 +(10 rows) + select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | sum ----+-------------- @@ -4433,6 +4848,21 @@ select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; | -2045853885 (10 rows) +select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | sum +----+--------------- + 0 | 2676782361278 + 3 | 2676068232273 + 4 | 2675355890947 + 5 | 2675895912591 + 6 | 2675895912591 + 7 | 2676421493860 + 8 | 2676421493860 + 9 | 2676421493860 + 11 | 5354922027638 + | 730391908 +(10 rows) + select avg(cint8) from aggfns where cfloat8 <= 0 order by 1; avg ---------------------- @@ -4763,6 +5193,12 @@ select count(s) from aggfns where cfloat8 <= 0 order by 1; 100570 (1 row) +select count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; + count +------- + 50140 +(1 row) + select s, count(s) from aggfns where cfloat8 <= 0 group by s order by 1; s | count ---+------- @@ -4778,6 +5214,21 @@ select s, count(s) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 10057 (10 rows) +select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; + s | count +---+------- + 0 | 5014 + 1 | 5014 + 2 | 5015 + 3 | 5015 + 4 | 5014 + 5 | 5013 + 6 | 5013 + 7 | 5014 + 8 | 5014 + 9 | 5014 +(10 rows) + select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; ss | count ----+------- @@ -4793,6 +5244,21 @@ select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; | 11 (10 rows) +select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + ss | count +----+------- + 0 | 5014 + 3 | 5012 + 4 | 5010 + 5 | 5013 + 6 | 5013 + 7 | 5014 + 8 | 5014 + 9 | 5014 + 11 | 10033 + | 3 +(10 rows) + select max(s) from aggfns where cfloat8 <= 0 order by 1; max ----- @@ -4973,42 +5439,6 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; | (10 rows) -select count(ss) from aggfns where cfloat8 <= 0 order by 1; - count --------- - 100559 -(1 row) - -select s, count(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10047 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select ss, count(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 10057 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 - 11 | 20123 - | 0 -(10 rows) - select max(ss) from aggfns where cfloat8 <= 0 order by 1; max ----- @@ -5231,6 +5661,12 @@ select count(*) from aggfns where cfloat8 < 1000 order by 1; 200000 (1 row) +select count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; + count +------- + 99428 +(1 row) + select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; s | count ---+------- @@ -5246,6 +5682,21 @@ select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) +select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 9942 + 1 | 9943 + 2 | 9943 + 3 | 9943 + 4 | 9943 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 +(10 rows) + select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | count ----+------- @@ -5261,6 +5712,21 @@ select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; | 19 (10 rows) +select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 9942 + 3 | 9937 + 4 | 9932 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 + 11 | 19897 + | 6 +(10 rows) + select x, count(*) from aggfns where cfloat8 < 1000 group by x order by 1; x | count ----+------- @@ -5384,76 +5850,25 @@ select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; | -5.91588952823689 (10 rows) -select count(cfloat4) from aggfns where cfloat8 < 1000 order by 1; - count --------- - 200000 +select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; + max +----- + NaN (1 row) -select s, count(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | count ----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 - | 19 -(10 rows) - -select x, count(cfloat4) from aggfns where cfloat8 < 1000 group by x order by 1; - x | count -----+------- - 0 | 20000 - 11 | 40019 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - | 19 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; - max ------ - NaN -(1 row) - -select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 +select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; + s | max +---+---------- + 0 | 49.9977 + 1 | NaN + 2 | Infinity + 3 | 49.9977 + 4 | 49.9977 + 5 | 49.9977 + 6 | 49.9977 + 7 | 49.9977 + 8 | 49.9977 + 9 | 49.9977 (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; @@ -5795,6 +6210,93 @@ select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; | -335.0000000000000000 (10 rows) +select count(cint2) from aggfns where cfloat8 < 1000 order by 1; + count +-------- + 199810 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; + count +------- + 99342 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 9936 + 1 | 9935 + 2 | 9935 + 3 | 9934 + 4 | 9933 + 5 | 9933 + 6 | 9932 + 7 | 9936 + 8 | 9933 + 9 | 9935 +(10 rows) + +select ss, count(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 19981 + 3 | 19962 + 4 | 19962 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 + | 19 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 9936 + 3 | 9928 + 4 | 9922 + 5 | 9933 + 6 | 9932 + 7 | 9936 + 8 | 9933 + 9 | 9935 + 11 | 19881 + | 6 +(10 rows) + +select x, count(cint2) from aggfns where cfloat8 < 1000 group by x order by 1; + x | count +----+------- + 0 | 19981 + 11 | 39981 + 3 | 19962 + 4 | 19962 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + | 19 +(10 rows) + select max(cint2) from aggfns where cfloat8 < 1000 order by 1; max ------- @@ -5909,6 +6411,12 @@ select sum(cint2) from aggfns where cfloat8 < 1000 order by 1; -8423824 (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; + sum +----------- + -17618159 +(1 row) + select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; s | sum ---+--------- @@ -5924,6 +6432,21 @@ select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | -861420 (10 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; + s | sum +---+---------- + 0 | -1788968 + 1 | -1806454 + 2 | -1747433 + 3 | -1738178 + 4 | -1717456 + 5 | -1788759 + 6 | -1746163 + 7 | -1731851 + 8 | -1741688 + 9 | -1811209 +(10 rows) + select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+---------- @@ -5939,6 +6462,21 @@ select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; | -6365 (10 rows) +select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | sum +----+---------- + 0 | -1788968 + 3 | -1737816 + 4 | -1696920 + 5 | -1788759 + 6 | -1746163 + 7 | -1731851 + 8 | -1741688 + 9 | -1811209 + 11 | -3574423 + | -362 +(10 rows) + select avg(cint4) from aggfns where cfloat8 < 1000 order by 1; avg ----------------------- @@ -6089,6 +6627,12 @@ select sum(cint4) from aggfns where cfloat8 < 1000 order by 1; -566665557362 (1 row) +select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; + sum +---------------- + 53436167838463 +(1 row) + select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; s | sum ---+-------------- @@ -6104,6 +6648,21 @@ select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | -56283868935 (10 rows) +select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; + s | sum +---+--------------- + 0 | 5342690615367 + 1 | 5343370718252 + 2 | 5343352005654 + 3 | 5343352005654 + 4 | 5344281595944 + 5 | 5343480575409 + 6 | 5343480575409 + 7 | 5344006156678 + 8 | 5344006156678 + 9 | 5344147433418 +(10 rows) + select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | sum ----+--------------- @@ -6119,6 +6678,21 @@ select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; | -2774095334 (10 rows) +select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | sum +----+---------------- + 0 | 5342690615367 + 3 | 5340469357420 + 4 | 5338771617836 + 5 | 5343480575409 + 6 | 5343480575409 + 7 | 5344006156678 + 8 | 5344006156678 + 9 | 5344147433418 + 11 | 10692232702014 + | 2882648234 +(10 rows) + select avg(cint8) from aggfns where cfloat8 < 1000 order by 1; avg ----------------------- @@ -6449,6 +7023,12 @@ select count(s) from aggfns where cfloat8 < 1000 order by 1; 200000 (1 row) +select count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; + count +------- + 99428 +(1 row) + select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; s | count ---+------- @@ -6464,6 +7044,21 @@ select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) +select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; + s | count +---+------- + 0 | 9942 + 1 | 9943 + 2 | 9943 + 3 | 9943 + 4 | 9943 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 +(10 rows) + select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; ss | count ----+------- @@ -6479,6 +7074,21 @@ select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; | 19 (10 rows) +select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + ss | count +----+------- + 0 | 9942 + 3 | 9937 + 4 | 9932 + 5 | 9942 + 6 | 9942 + 7 | 9943 + 8 | 9943 + 9 | 9944 + 11 | 19897 + | 6 +(10 rows) + select max(s) from aggfns where cfloat8 < 1000 order by 1; max ----- @@ -6659,42 +7269,6 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select count(ss) from aggfns where cfloat8 < 1000 order by 1; - count --------- - 199981 -(1 row) - -select s, count(ss) from aggfns where cfloat8 < 1000 group by s order by 1; - s | count ----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 19981 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select ss, count(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 - | 0 -(10 rows) - select max(ss) from aggfns where cfloat8 < 1000 order by 1; max ----- @@ -6917,16 +7491,32 @@ select count(*) from aggfns where cfloat8 > 1000 order by 1; 0 (1 row) +select count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + select s, count(*) from aggfns where cfloat8 > 1000 group by s order by 1; s | count ---+------- (0 rows) +select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by 1; ss | count ----+------- (0 rows) +select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select x, count(*) from aggfns where cfloat8 > 1000 group by x order by 1; x | count ---+------- @@ -6980,27 +7570,6 @@ select ss, avg(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) -select count(cfloat4) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select s, count(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select x, count(cfloat4) from aggfns where cfloat8 > 1000 group by x order by 1; - x | count ----+------- -(0 rows) - select max(cfloat4) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7161,6 +7730,43 @@ select ss, avg(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) +select count(cint2) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + +select ss, count(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + +select x, count(cint2) from aggfns where cfloat8 > 1000 group by x order by 1; + x | count +---+------- +(0 rows) + select max(cint2) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7214,16 +7820,32 @@ select sum(cint2) from aggfns where cfloat8 > 1000 order by 1; (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; + sum +----- + +(1 row) + select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; s | sum ---+----- (0 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; + s | sum +---+----- +(0 rows) + select ss, sum(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; ss | sum ----+----- (0 rows) +select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | sum +----+----- +(0 rows) + select avg(cint4) from aggfns where cfloat8 > 1000 order by 1; avg ----- @@ -7293,16 +7915,32 @@ select sum(cint4) from aggfns where cfloat8 > 1000 order by 1; (1 row) +select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; + sum +----- + +(1 row) + select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; s | sum ---+----- (0 rows) +select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; + s | sum +---+----- +(0 rows) + select ss, sum(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; ss | sum ----+----- (0 rows) +select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | sum +----+----- +(0 rows) + select avg(cint8) from aggfns where cfloat8 > 1000 order by 1; avg ----- @@ -7451,16 +8089,32 @@ select count(s) from aggfns where cfloat8 > 1000 order by 1; 0 (1 row) +select count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; + count +------- + 0 +(1 row) + select s, count(s) from aggfns where cfloat8 > 1000 group by s order by 1; s | count ---+------- (0 rows) +select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; + s | count +---+------- +(0 rows) + select ss, count(s) from aggfns where cfloat8 > 1000 group by ss order by 1; ss | count ----+------- (0 rows) +select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; + ss | count +----+------- +(0 rows) + select max(s) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7540,22 +8194,6 @@ select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) -select count(ss) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select s, count(ss) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select ss, count(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - select max(ss) from aggfns where cfloat8 > 1000 order by 1; max ----- @@ -7651,69 +8289,6 @@ select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by 1; ----+----- (0 rows) -select count(*) from aggfns where cint2 is null order by 1; - count -------- - 190 -(1 row) - -select s, count(*) from aggfns where cint2 is null group by s order by 1; - s | count ----+------- - 0 | 19 - 1 | 19 - 2 | 19 - 3 | 19 - 4 | 19 - 5 | 19 - 6 | 19 - 7 | 19 - 8 | 19 - 9 | 19 -(10 rows) - -select ss, count(*) from aggfns where cint2 is null group by ss order by 1; - ss | count -----+------- - 0 | 19 - 3 | 19 - 4 | 19 - 5 | 19 - 6 | 19 - 7 | 19 - 8 | 19 - 9 | 19 - 11 | 38 -(9 rows) - -select x, count(*) from aggfns where cint2 is null group by x order by 1; - x | count -----+------- - 0 | 19 - 11 | 38 - 3 | 19 - 4 | 19 - 5 | 19 - 6 | 19 - 7 | 19 - 8 | 19 - 9 | 19 -(9 rows) - -select x, count(cfloat4) from aggfns where cint2 is null group by x order by 1; - x | count -----+------- - 0 | 19 - 11 | 38 - 3 | 19 - 4 | 19 - 5 | 19 - 6 | 19 - 7 | 19 - 8 | 19 - 9 | 19 -(9 rows) - select avg(cint2) from aggfns where cint2 is null order by 1; avg ----- @@ -7755,6 +8330,12 @@ select count(cint2) from aggfns where cint2 is null order by 1; 0 (1 row) +select count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null order by 1; + count +------- + 0 +(1 row) + select s, count(cint2) from aggfns where cint2 is null group by s order by 1; s | count ---+------- @@ -7770,6 +8351,21 @@ select s, count(cint2) from aggfns where cint2 is null group by s order by 1; 9 | 0 (10 rows) +select s, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by s order by 1; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; ss | count ----+------- @@ -7784,6 +8380,34 @@ select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | 0 (9 rows) +select ss, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by ss order by 1; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select x, count(cint2) from aggfns where cint2 is null group by x order by 1; + x | count +----+------- + 0 | 0 + 11 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(9 rows) + select max(cint2) from aggfns where cint2 is null order by 1; max ----- @@ -7895,6 +8519,12 @@ select sum(cint2) from aggfns where cint2 is null order by 1; (1 row) +select sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null order by 1; + sum +----- + +(1 row) + select s, sum(cint2) from aggfns where cint2 is null group by s order by 1; s | sum ---+----- @@ -7910,6 +8540,21 @@ select s, sum(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) +select s, sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by s order by 1; + s | sum +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; ss | sum ----+----- @@ -7924,6 +8569,20 @@ select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) +select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by ss order by 1; + ss | sum +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + -- Test multiple aggregate functions as well. select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 order by count(*) desc, cint2 limit 10 diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index e1bbd833951..074572a7a31 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -89,10 +89,11 @@ set timescaledb.debug_require_vector_agg = 'require'; --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s) from aggfns%s%s order by 1;', + format('%sselect %s%s(%s)%s from aggfns%s%s order by 1;', explain, grouping || ', ', function, variable, + ' filter (where ' || agg_filter || ')', ' where ' || condition, ' group by ' || grouping ) from @@ -130,27 +131,24 @@ from null, 's', 'ss', - 'x']) with ordinality as grouping(grouping, n) + 'x']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) where - case --- when explain is not null then condition is null and grouping = 's' - when explain is not null then false - when true then true - end - and - case - when variable = '*' then function = 'count' - -- No need to test the aggregate functions themselves again for string - -- grouping. - when grouping = 'x' then function = 'count' and variable = 'cfloat4' - when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's', 'ss') - when variable = 't' then function in ('min', 'max') - when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') - -- This is not vectorized yet. - when function = 'stddev' then variable != 'cint8' - else true end -order by explain, condition.n, variable, function, grouping.n + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') + and (variable not in ('t', 'cts', 'ctstz', 'cdate') or function in ('min', 'max')) + -- This is not vectorized yet + and (variable != 'cint8' or function != 'stddev') + and (function != 'count' or variable in ('cint2', 's', '*')) + and (agg_filter is null or (function = 'count') or (function = 'sum' and variable in ('cint2', 'cint4'))) + and (condition is distinct from 'cint2 is null' or variable = 'cint2') + -- No need to test the aggregate functions themselves again for string + -- grouping. + and (grouping is distinct from 'x' or (function = 'count' and variable in ('cint2', '*') and agg_filter is null)) +order by explain, condition.n, variable, function, grouping.n, agg_filter.n \gexec From 234028032a183500bdd4ead41527be277d739417 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:59:06 +0300 Subject: [PATCH 056/242] separate implementation for no filters --- .../function/agg_many_vector_helper.c | 25 ++++++++++++++++--- tsl/src/nodes/vector_agg/plan.c | 12 ++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index 59e93a729f2..724fe9120ca 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -10,10 +10,10 @@ * FUNCTION_NAME(one) function, which adds one passing non-null row to the given * aggregate function state. */ -static void -FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, - int start_row, int end_row, const ArrowArray *vector, - MemoryContext agg_extra_mctx) +static pg_attribute_always_inline void +FUNCTION_NAME(many_vector_impl)(void *restrict agg_states, const uint32 *offsets, + const uint64 *filter, int start_row, int end_row, + const ArrowArray *vector, MemoryContext agg_extra_mctx) { FUNCTION_NAME(state) *restrict states = (FUNCTION_NAME(state) *) agg_states; const CTYPE *values = vector->buffers[1]; @@ -28,3 +28,20 @@ FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, con } MemoryContextSwitchTo(old); } + +static void +FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + if (filter == NULL) + { + FUNCTION_NAME(many_vector_impl) + (agg_states, offsets, NULL, start_row, end_row, vector, agg_extra_mctx); + } + else + { + FUNCTION_NAME(many_vector_impl) + (agg_states, offsets, filter, start_row, end_row, vector, agg_extra_mctx); + } +} diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 88a55b1fb72..80b3cb51a73 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -650,12 +650,12 @@ try_insert_vector_agg_node(Plan *plan) bulk_decompression_enabled_globally)); vqi.vector_attrs[uncompressed_chunk_attno] = is_vector_var; -// fprintf(stderr, -// "compressed %d -> uncompressed %d custom scan %d vector %d\n", -// compressed_column_index, -// uncompressed_chunk_attno, -// custom_scan_attno, -// is_vector_var); + // fprintf(stderr, + // "compressed %d -> uncompressed %d custom scan %d vector %d\n", + // compressed_column_index, + // uncompressed_chunk_attno, + // custom_scan_attno, + // is_vector_var); } /* Now check the aggregate functions themselves. */ From a2806eac5a2d082fc2ff22645f083f7159c402ba Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:25:49 +0300 Subject: [PATCH 057/242] fixing the unified bitmap --- tsl/src/compression/arrow_c_data_interface.h | 29 ++++++++++++ tsl/src/nodes/vector_agg/function/functions.c | 22 +++++---- .../nodes/vector_agg/grouping_policy_batch.c | 45 ++++++++++++------- .../nodes/vector_agg/grouping_policy_hash.c | 34 +++++--------- 4 files changed, 77 insertions(+), 53 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 6a1d7ae114d..f075465c6fd 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -182,6 +182,35 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) Assert(arrow_row_is_valid(bitmap, row_number) == value); } +static inline uint64 * +arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, + const uint64 *filter2, const uint64 *filter3) +{ + if (filter1 == NULL && filter2 == NULL && filter3 == NULL) + { + return NULL; + } + + for (size_t i = 0; i < num_words; i++) + { + uint64 word = ~0; + if (filter1 != NULL) + { + word &= filter1[i]; + } + if (filter2 != NULL) + { + word &= filter2[i]; + } + if (filter3 != NULL) + { + word &= filter3[i]; + } + storage[i] = word; + } + + return storage; +} /* Increase the `source_value` to be an even multiple of `pad_to`. */ static inline uint64 pad_to_multiple(uint64 pad_to, uint64 source_value) diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 2e0ddb87bfe..60411c8c86d 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -92,28 +92,25 @@ count_any_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, - MemoryContext agg_extra_mctx) +count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; const int n = vector->length; - const uint64 *restrict validity = (uint64 *) vector->buffers[0]; /* First, process the full words. */ for (int i = 0; i < n / 64; i++) { - const uint64 validity_word = validity ? validity[i] : ~0ULL; const uint64 filter_word = filter ? filter[i] : ~0ULL; - const uint64 resulting_word = validity_word & filter_word; #ifdef HAVE__BUILTIN_POPCOUNT - state->count += __builtin_popcountll(resulting_word); + state->count += __builtin_popcountll(filter_word); #else /* * Unfortunately, we have to have this fallback for Windows. */ for (uint16 i = 0; i < 64; i++) { - const bool this_bit = (resulting_word >> i) & 1; + const bool this_bit = (filter_word >> i) & 1; state->count += this_bit; } #endif @@ -125,13 +122,14 @@ count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *f */ for (int i = 64 * (n / 64); i < n; i++) { - state->count += arrow_row_is_valid(validity, i) * arrow_row_is_valid(filter, i); + state->count += arrow_row_is_valid(filter, i); } } static void -count_any_many(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, - int start_row, int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) +count_any_many_vector(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) { for (int row = start_row; row < end_row; row++) { @@ -148,8 +146,8 @@ VectorAggFunctions count_any_agg = { .agg_init = count_init, .agg_emit = count_emit, .agg_scalar = count_any_scalar, - .agg_vector = count_any_many_vector, - .agg_many_vector = count_any_many, + .agg_vector = count_any_vector, + .agg_many_vector = count_any_many_vector, }; /* diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 783d601b757..405cc53534d 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -36,6 +36,9 @@ typedef struct * the grouping policy is reset. */ MemoryContext agg_extra_mctx; + + uint64 *tmp_filter; + uint64 num_tmp_filter_words; } GroupingPolicyBatch; static const GroupingPolicy grouping_policy_batch_functions; @@ -91,27 +94,13 @@ gp_batch_reset(GroupingPolicy *obj) } static void -compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_def, void *agg_state, - MemoryContext agg_extra_mctx) +compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batch_state, + VectorAggDef *agg_def, void *agg_state, MemoryContext agg_extra_mctx) { ArrowArray *arg_arrow = NULL; Datum arg_datum = 0; bool arg_isnull = true; - uint64 *filter = batch_state->vector_qual_result; - if (agg_def->filter_result != NULL) - { - filter = agg_def->filter_result; - if (batch_state->vector_qual_result != NULL) - { - const size_t num_words = (batch_state->total_batch_rows + 63) / 64; - for (size_t i = 0; i < num_words; i++) - { - filter[i] &= batch_state->vector_qual_result[i]; - } - } - } - /* * We have functions with one argument, and one function with no arguments * (count(*)). Collect the arguments. @@ -134,6 +123,16 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de } } + /* + * Compute the unified validity bitmap. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + const uint64 *filter = arrow_combine_validity(num_words, + policy->tmp_filter, + batch_state->vector_qual_result, + agg_def->filter_result, + arg_arrow != NULL ? arg_arrow->buffers[0] : NULL); + /* * Now call the function. */ @@ -167,12 +166,24 @@ static void gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) { GroupingPolicyBatch *policy = (GroupingPolicyBatch *) gp; + + /* + * Allocate the temporary filter array for computing the combined results of + * batch filter, aggregate filter and column validity. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + if (num_words > policy->num_tmp_filter_words) + { + policy->tmp_filter = palloc(sizeof(*policy->tmp_filter) * (num_words * 2 + 1)); + policy->num_tmp_filter_words = (num_words * 2 + 1); + } + const int naggs = list_length(policy->agg_defs); for (int i = 0; i < naggs; i++) { VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); void *agg_state = (void *) list_nth(policy->agg_states, i); - compute_single_aggregate(batch_state, agg_def, agg_state, policy->agg_extra_mctx); + compute_single_aggregate(policy, batch_state, agg_def, agg_state, policy->agg_extra_mctx); } const int ngrp = list_length(policy->output_grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index badc87c549c..0dca4310da6 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -146,30 +146,16 @@ compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState } } - uint64 *restrict filter = NULL; - if (batch_state->vector_qual_result != NULL || agg_def->filter_result != NULL || - (arg_arrow != NULL && arg_arrow->buffers[0] != NULL)) - { - filter = policy->tmp_filter; - const size_t num_words = (batch_state->total_batch_rows + 63) / 64; - for (size_t i = 0; i < num_words; i++) - { - uint64 word = -1; - if (batch_state->vector_qual_result != NULL) - { - word &= batch_state->vector_qual_result[i]; - } - if (agg_def->filter_result != NULL) - { - word &= agg_def->filter_result[i]; - } - if (arg_arrow != NULL && arg_arrow->buffers[0] != NULL) - { - word &= ((uint64 *) arg_arrow->buffers[0])[i]; - } - filter[i] = word; - } - } + /* + * Compute the unified validity bitmap. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + uint64 *restrict filter = + arrow_combine_validity(num_words, + policy->tmp_filter, + batch_state->vector_qual_result, + agg_def->filter_result, + arg_arrow != NULL ? arg_arrow->buffers[0] : NULL); /* * Now call the function. From c18ded955348b0abf0e8b34da7bd23441f546469 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:26:04 +0300 Subject: [PATCH 058/242] benchmark the unified bitmap (2024-10-22 no. 16) From c723a5ab81e3b34990a346ac82569b62bc425a28 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:25:02 +0300 Subject: [PATCH 059/242] cleanup --- .../function/agg_many_vector_helper.c | 4 +++- .../vector_agg/hash_table_functions_impl.c | 20 +++---------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index 724fe9120ca..aae48bb2230 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -21,9 +21,11 @@ FUNCTION_NAME(many_vector_impl)(void *restrict agg_states, const uint32 *offsets for (int row = start_row; row < end_row; row++) { const CTYPE value = values[row]; + FUNCTION_NAME(state) *restrict state = &states[offsets[row]]; if (arrow_row_is_valid(filter, row)) { - FUNCTION_NAME(one)(&states[offsets[row]], value); + Assert(offsets[row] != 0); + FUNCTION_NAME(one)(state, value); } } MemoryContextSwitchTo(old); diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index a85403567c9..aa043dac8ef 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -171,30 +171,16 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; const uint64 *restrict filter = batch_state->vector_qual_result; - if (filter == NULL && column.buffers[0] == NULL) + if (filter == NULL) { next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, column, NULL, next_unused_state_index, start_row, end_row); } - else if (filter != NULL && column.buffers[0] == NULL) - { - next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (filter == NULL && column.buffers[0] != NULL) - { - next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (filter != NULL && column.buffers[0] != NULL) + else { next_unused_state_index = FUNCTION_NAME( dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); } - else - { - Assert(false); - } return next_unused_state_index; } From 00910dee16b175673dc006909978a28b4ff7084a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 22 Oct 2024 19:38:34 +0300 Subject: [PATCH 060/242] cleanup --- .../function/agg_vector_validity_helper.c | 40 +++++-------------- .../function/float48_accum_single.c | 30 +++++--------- .../vector_agg/function/int128_accum_single.c | 6 +-- .../function/int24_avg_accum_single.c | 6 +-- .../vector_agg/function/int24_sum_single.c | 6 +-- .../function/minmax_arithmetic_single.c | 6 +-- .../vector_agg/function/sum_float_single.c | 10 ++--- 7 files changed, 37 insertions(+), 67 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c b/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c index ac3a95055a0..9dc1cfe853c 100644 --- a/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c @@ -11,62 +11,40 @@ */ static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl_arrow)(void *agg_state, const ArrowArray *vector, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl_arrow)(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { const int n = vector->length; const CTYPE *values = vector->buffers[1]; - FUNCTION_NAME(vector_impl)(agg_state, n, values, valid1, valid2, agg_extra_mctx); + FUNCTION_NAME(vector_impl)(agg_state, n, values, filter, agg_extra_mctx); } static pg_noinline void FUNCTION_NAME(vector_all_valid)(void *agg_state, const ArrowArray *vector, MemoryContext agg_extra_mctx) { - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, NULL, NULL, agg_extra_mctx); + FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, NULL, agg_extra_mctx); } static pg_noinline void -FUNCTION_NAME(vector_one_validity)(void *agg_state, const ArrowArray *vector, const uint64 *valid, +FUNCTION_NAME(vector_one_validity)(void *agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx) { - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, valid, NULL, agg_extra_mctx); -} - -static pg_noinline void -FUNCTION_NAME(vector_two_validity)(void *agg_state, const ArrowArray *vector, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) -{ - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, valid1, valid2, agg_extra_mctx); + FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, filter, agg_extra_mctx); } static void FUNCTION_NAME(vector)(void *agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx) { - const uint64 *row_validity = vector->buffers[0]; - - if (row_validity == NULL && filter == NULL) + if (filter == NULL) { /* All rows are valid and we don't have to check any validity bitmaps. */ FUNCTION_NAME(vector_all_valid)(agg_state, vector, agg_extra_mctx); } - else if (row_validity != NULL && filter == NULL) - { - /* Have to check only one bitmap -- row validity bitmap. */ - FUNCTION_NAME(vector_one_validity)(agg_state, vector, row_validity, agg_extra_mctx); - } - else if (filter != NULL && row_validity == NULL) - { - /* Have to check only one bitmap -- results of the vectorized filter. */ - FUNCTION_NAME(vector_one_validity)(agg_state, vector, filter, agg_extra_mctx); - } else { - /* - * Have to check both the row validity bitmap and the results of the - * vectorized filter. - */ - FUNCTION_NAME(vector_two_validity)(agg_state, vector, row_validity, filter, agg_extra_mctx); + /* Have to check only one combined validity bitmap. */ + FUNCTION_NAME(vector_one_validity)(agg_state, vector, filter, agg_extra_mctx); } } diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index 73743c5aa1a..deb2998d784 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -99,8 +99,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) * Youngs-Cramer update for rows after the first. */ static pg_attribute_always_inline void -FUNCTION_NAME(update)(const uint64 *valid1, const uint64 *valid2, const CTYPE *values, int row, - double *N, double *Sx +FUNCTION_NAME(update)(const uint64 *filter, const CTYPE *values, int row, double *N, double *Sx #ifdef NEED_SXX , double *Sxx @@ -108,7 +107,7 @@ FUNCTION_NAME(update)(const uint64 *valid1, const uint64 *valid2, const CTYPE *v ) { const CTYPE newval = values[row]; - if (!arrow_row_both_valid(valid1, valid2, row)) + if (!arrow_row_is_valid(filter, row)) { return; } @@ -185,20 +184,19 @@ FUNCTION_NAME(combine)(double *inout_N, double *inout_Sx, } #ifdef NEED_SXX -#define UPDATE(valid1, valid2, values, row, N, Sx, Sxx) \ - FUNCTION_NAME(update)(valid1, valid2, values, row, N, Sx, Sxx) +#define UPDATE(filter, values, row, N, Sx, Sxx) \ + FUNCTION_NAME(update)(filter, values, row, N, Sx, Sxx) #define COMBINE(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) \ FUNCTION_NAME(combine)(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) #else -#define UPDATE(valid1, valid2, values, row, N, Sx, Sxx) \ - FUNCTION_NAME(update)(valid1, valid2, values, row, N, Sx) +#define UPDATE(filter, values, row, N, Sx, Sxx) FUNCTION_NAME(update)(filter, values, row, N, Sx) #define COMBINE(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) \ FUNCTION_NAME(combine)(inout_N, inout_Sx, N2, Sx2) #endif static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { /* * Vector registers can be up to 512 bits wide. @@ -228,7 +226,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (; row < n; row++) { const CTYPE newval = values[row]; - if (arrow_row_both_valid(valid1, valid2, row)) + if (arrow_row_is_valid(filter, row)) { Narray[inner] = 1; Sxarray[inner] = newval; @@ -246,7 +244,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (size_t inner = row % UNROLL_SIZE; inner > 0 && inner < UNROLL_SIZE && row < n; inner++, row++) { - UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); + UPDATE(filter, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } #endif @@ -258,13 +256,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const { for (size_t inner = 0; inner < UNROLL_SIZE; inner++) { - UPDATE(valid1, - valid2, - values, - row + inner, - &Narray[inner], - &Sxarray[inner], - &Sxxarray[inner]); + UPDATE(filter, values, row + inner, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } } @@ -274,7 +266,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (; row < n; row++) { const size_t inner = row % UNROLL_SIZE; - UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); + UPDATE(filter, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } /* diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index bf60e64cd12..2e0b9ca25f2 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -72,8 +72,8 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) } static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { int64 N = 0; int128 sumX = 0; @@ -82,7 +82,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #endif for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); const CTYPE value = values[row]; N += row_ok; sumX += value * row_ok; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 62ebb5ad52b..fb90f116255 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -11,14 +11,14 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { int64 batch_count = 0; int64 batch_sum = 0; for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); batch_count += row_ok; batch_sum += values[row] * row_ok; } diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index 8bfb15676ae..f7251599a90 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -11,8 +11,8 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { Int24SumState *state = (Int24SumState *) agg_state; @@ -37,7 +37,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui bool have_result = false; for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); batch_sum += values[row] * row_ok; have_result |= row_ok; } diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index 6d110fcdc34..e4b94abdf21 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -10,8 +10,8 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): return &FUNCTION_NAME(argdef); #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { MinMaxState *state = (MinMaxState *) agg_state; @@ -20,7 +20,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui for (int row = 0; row < n; row++) { const CTYPE new_value = values[row]; - const bool new_value_ok = arrow_row_both_valid(valid1, valid2, row); + const bool new_value_ok = arrow_row_is_valid(filter, row); /* * Note that we have to properly handle NaNs and Infinities for floats. diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 6b56b433c89..c8fbea2d43a 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -21,8 +21,8 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) } static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { /* * Vector registers can be up to 512 bits wide. @@ -46,15 +46,15 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui * infinities and NaNs. */ #define INNER_LOOP \ - const bool valid = arrow_row_both_valid(valid1, valid2, row); \ + const bool row_valid = arrow_row_is_valid(filter, row); \ union \ { \ CTYPE f; \ MASKTYPE m; \ } u = { .f = values[row] }; \ - u.m &= valid ? ~(MASKTYPE) 0 : (MASKTYPE) 0; \ + u.m &= row_valid ? ~(MASKTYPE) 0 : (MASKTYPE) 0; \ *dest += u.f; \ - *have_result |= valid; + *have_result |= row_valid; INNER_LOOP } From 4ab971403eaa784bcaebdbad0ac76413c4eb9061 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 09:29:45 +0300 Subject: [PATCH 061/242] serialized -- half done --- .../decompress_chunk/decompress_context.h | 1 + tsl/src/nodes/decompress_chunk/exec.c | 2 +- tsl/src/nodes/vector_agg/exec.c | 28 +-- tsl/src/nodes/vector_agg/exec.h | 1 + .../nodes/vector_agg/grouping_policy_hash.c | 26 ++- tsl/src/nodes/vector_agg/hash_serialized.c | 173 +++++++++++++++++- tsl/src/nodes/vector_agg/hash_single_text.c | 23 ++- .../vector_agg/hash_table_functions_impl.c | 77 ++++---- tsl/src/nodes/vector_agg/plan.c | 34 ++-- .../nodes/vector_agg/single_fixed_key_impl.c | 24 ++- 10 files changed, 309 insertions(+), 80 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/decompress_context.h b/tsl/src/nodes/decompress_chunk/decompress_context.h index bd12927d77e..6eae55d5467 100644 --- a/tsl/src/nodes/decompress_chunk/decompress_context.h +++ b/tsl/src/nodes/decompress_chunk/decompress_context.h @@ -29,6 +29,7 @@ typedef struct CompressionColumnDescription Oid typid; int16 value_bytes; bool by_value; + char typalign; /* * Attno of the decompressed column in the scan tuple of DecompressChunk node. diff --git a/tsl/src/nodes/decompress_chunk/exec.c b/tsl/src/nodes/decompress_chunk/exec.c index c59bcfba072..1e2790f2e39 100644 --- a/tsl/src/nodes/decompress_chunk/exec.c +++ b/tsl/src/nodes/decompress_chunk/exec.c @@ -295,7 +295,7 @@ decompress_chunk_begin(CustomScanState *node, EState *estate, int eflags) TupleDescAttr(desc, AttrNumberGetAttrOffset(column.custom_scan_attno)); column.typid = attribute->atttypid; - get_typlenbyval(column.typid, &column.value_bytes, &column.by_value); + get_typlenbyvalalign(column.typid, &column.value_bytes, &column.by_value, &column.typalign); if (list_nth_int(chunk_state->is_segmentby_column, compressed_index)) column.type = SEGMENTBY_COLUMN; diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 7556fc6ca07..7424bffa321 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -140,29 +140,26 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) col->typid = desc->typid; col->value_bytes = desc->value_bytes; col->by_value = desc->by_value; + col->typalign = desc->typalign; } } - if (list_length(vector_agg_state->output_grouping_columns) == 1) + bool all_segmentby = true; + for (int i = 0; i < list_length(vector_agg_state->output_grouping_columns); i++) { GroupingColumn *col = - (GroupingColumn *) linitial(vector_agg_state->output_grouping_columns); + (GroupingColumn *) list_nth(vector_agg_state->output_grouping_columns, i); DecompressContext *dcontext = &decompress_state->decompress_context; CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; // if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && // (size_t) desc->value_bytes <= sizeof(Datum)) - if (desc->type == COMPRESSED_COLUMN) + if (desc->type != SEGMENTBY_COLUMN) { - /* - * Hash grouping by a single fixed-size by-value compressed column. - */ - vector_agg_state->grouping = - create_grouping_policy_hash(vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns); + all_segmentby = false; + break; } } - - if (vector_agg_state->grouping == NULL) + if (all_segmentby) { /* * Per-batch grouping. @@ -171,6 +168,15 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) create_grouping_policy_batch(vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); } + else + { + /* + * Hash grouping. + */ + vector_agg_state->grouping = + create_grouping_policy_hash(vector_agg_state->agg_defs, + vector_agg_state->output_grouping_columns); + } } static void diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index b66a190c290..1920f243119 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -30,6 +30,7 @@ typedef struct Oid typid; int16 value_bytes; bool by_value; + char typalign; } GroupingColumn; typedef struct diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 0dca4310da6..794d4c13f3b 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -35,6 +35,7 @@ extern HashTableFunctions single_fixed_2_functions; extern HashTableFunctions single_fixed_4_functions; extern HashTableFunctions single_fixed_8_functions; extern HashTableFunctions single_text_functions; +extern HashTableFunctions serialized_functions; static const GroupingPolicy grouping_policy_hash_functions; @@ -57,8 +58,6 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); } - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); // policy->key_bytes = g->value_bytes; policy->key_bytes = sizeof(Datum); Assert(policy->key_bytes > 0); @@ -67,8 +66,11 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->keys = palloc(policy->key_bytes * policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; - switch (g->value_bytes) + if (list_length(policy->output_grouping_columns) == 1) { + GroupingColumn *g = linitial(policy->output_grouping_columns); + switch (g->value_bytes) + { case 8: policy->functions = single_fixed_8_functions; break; @@ -85,6 +87,11 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) default: Assert(false); break; + } + } + else + { + policy->functions = serialized_functions; } policy->table = @@ -231,7 +238,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con if (num_possible_keys > policy->num_allocated_keys) { policy->num_allocated_keys = num_possible_keys; - policy->keys = repalloc(policy->keys, policy->key_bytes * num_possible_keys); + policy->keys = repalloc(policy->keys, list_length(policy->output_grouping_columns) * policy->key_bytes * num_possible_keys); } /* @@ -432,10 +439,13 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) &aggregated_slot->tts_isnull[agg_def->output_offset]); } - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *col = linitial(policy->output_grouping_columns); - aggregated_slot->tts_values[col->output_offset] = ((Datum *) policy->keys)[current_key]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == 1; + const int num_keys = list_length(policy->output_grouping_columns); + for (int i = 0; i < num_keys; i++) + { + GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + aggregated_slot->tts_values[col->output_offset] = ((Datum *) policy->keys)[current_key * num_keys + i]; + aggregated_slot->tts_isnull[col->output_offset] = false; //current_key == 1; + } return true; } diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 9ef52ee14ea..3cedc2de33c 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,19 +19,184 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(CompressedColumnValues column, int row, BytesView *restrict key, +serialized_get_key(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, int row, int next_key_index, BytesView *restrict key, bool *restrict valid) { - Assert(false); + if (list_length(policy->output_grouping_columns) == 1) + { + pg_unreachable(); + } + + uint64 *restrict validity_bitmap; + + const int num_columns = list_length(policy->output_grouping_columns); + Assert(num_columns <= 64); + size_t num_bytes = 0; + for (int i = 0; i < num_columns; i++) + { + const GroupingColumn *def = list_nth(policy->output_grouping_columns, i); + num_bytes = att_align_nominal(num_bytes, def->typalign); + if (def->by_value) + { + num_bytes += def->value_bytes; + } + else + { + const CompressedColumnValues *column = &batch_state->compressed_columns[def->input_offset]; + if (unlikely(column->decompression_type == DT_Scalar)) + { + num_bytes += (*column->output_isnull) ? 0 : VARSIZE_ANY(*column->output_value); + } + else if (column->decompression_type == DT_ArrowText) + { + if (arrow_row_is_valid(column->buffers[0], row)) + { + const uint32 start = ((uint32 *) column->buffers[1])[row]; + const int32 value_bytes = ((uint32 *) column->buffers[1])[row + 1] - start; + num_bytes += value_bytes + VARHDRSZ; + } + } + else if (column->decompression_type == DT_ArrowTextDict) + { + if (arrow_row_is_valid(column->buffers[0], row)) + { + const int16 index = ((int16 *) column->buffers[3])[row]; + const uint32 start = ((uint32 *) column->buffers[1])[index]; + const int32 value_bytes = ((uint32 *) column->buffers[1])[index + 1] - start; + num_bytes += value_bytes + VARHDRSZ; + } + } + else + { + pg_unreachable(); + } + } + } + + /* The optional null bitmap. */ + num_bytes = att_align_nominal(num_bytes, TYPALIGN_DOUBLE); + num_bytes += sizeof(*validity_bitmap); + + + Datum *restrict key_data = &((Datum *) policy->keys)[num_columns * next_key_index]; + uint8 *restrict key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); + validity_bitmap = (uint64 *) &((char *) key_storage)[num_bytes - sizeof(*validity_bitmap)]; + *validity_bitmap = ~0ULL; + + uint32 offset = 0; + for (int i = 0; i < num_columns; i++) + { + const GroupingColumn *def = list_nth(policy->output_grouping_columns, i); + offset = att_align_nominal(offset, def->typalign); + + const CompressedColumnValues *column = &batch_state->compressed_columns[def->input_offset]; + if (column->decompression_type > 0) + { + Assert(offset <= UINT_MAX - column->decompression_type); + memcpy(&key_storage[offset], + ((char *) column->buffers[1]) + column->decompression_type * row, + column->decompression_type); + arrow_set_row_validity(validity_bitmap, i, arrow_row_is_valid(column->buffers[0], row)); + offset += column->decompression_type; + + memcpy(&key_data[i], + ((char *) column->buffers[1]) + column->decompression_type * row, + column->decompression_type); + } + else if (unlikely(column->decompression_type == DT_Scalar)) + { + const bool is_valid = !*column->output_isnull; + arrow_set_row_validity(validity_bitmap, i, is_valid); + if (is_valid) + { + if (def->by_value) + { + memcpy(&key_storage[offset], column->output_value, def->value_bytes); + offset += def->value_bytes; + + memcpy(&key_data[row], column->output_value, def->value_bytes); + } + else + { + memcpy(&key_storage[offset], DatumGetPointer(*column->output_value), VARSIZE_ANY(column->output_value)); + + key_data[row] = PointerGetDatum(&key_storage[offset]); + + offset += VARSIZE_ANY(column->output_value); + } + } + } + else if (column->decompression_type == DT_ArrowText) + { + const bool is_valid = arrow_row_is_valid(column->buffers[0], row); + arrow_set_row_validity(validity_bitmap, i, is_valid); + if (is_valid) + { + const uint32 start = ((uint32 *) column->buffers[1])[row]; + const int32 value_bytes = ((uint32 *) column->buffers[1])[row + 1] - start; + const int32 total_bytes = value_bytes + VARHDRSZ; + + SET_VARSIZE(&key_storage[offset], total_bytes); + memcpy(VARDATA(&key_storage[offset]), &((uint8 *) column->buffers[2])[start], + value_bytes); + + key_data[i] = PointerGetDatum(&key_storage[offset]); + + offset += total_bytes; + } + } + else if (column->decompression_type == DT_ArrowTextDict) + { + const bool is_valid = arrow_row_is_valid(column->buffers[0], row); + arrow_set_row_validity(validity_bitmap, i, is_valid); + if (is_valid) + { + const int16 index = ((int16 *) column->buffers[3])[row]; + const uint32 start = ((uint32 *) column->buffers[1])[index]; + const int32 value_bytes = ((uint32 *) column->buffers[1])[index + 1] - start; + const int32 total_bytes = value_bytes + VARHDRSZ; + + SET_VARSIZE(&key_storage[offset], total_bytes); + memcpy(VARDATA(&key_storage[offset]), &((uint8 *) column->buffers[2])[start], + value_bytes); + + key_data[i] = PointerGetDatum(&key_storage[offset]); + + offset += total_bytes; + } + } + else + { + pg_unreachable(); + } + } + + Assert((void *) &key_storage[att_align_nominal(offset, TYPALIGN_DOUBLE)] == (void *) validity_bitmap); + + if (*validity_bitmap != ~0ULL) + { + offset = att_align_nominal(offset, TYPALIGN_DOUBLE) + sizeof(*validity_bitmap); + Assert(offset == num_bytes); + } + + *key = (BytesView) { .data = key_storage, .len = offset }; + *valid = true; } static pg_attribute_always_inline BytesView -serialized_store_key(BytesView key, Datum *key_storage, MemoryContext key_memory_context) +serialized_store_key(GroupingPolicyHash *restrict policy, BytesView key, uint32 key_index) { - Assert(false); + /* Noop, all done in get_key. */ return key; } +static pg_attribute_always_inline void +serialized_destroy_key(BytesView key) +{ + pfree((void *) key.data); +} + #define KEY_VARIANT serialized #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 0b18e878c8a..a811e82cc05 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -29,9 +29,18 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(CompressedColumnValues column, int row, BytesView *restrict key, +single_text_get_key(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, int row, int next_key_index, BytesView *restrict key, bool *restrict valid) { + if (list_length(policy->output_grouping_columns) != 1) + { + pg_unreachable(); + } + + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + if (unlikely(column.decompression_type == DT_Scalar)) { /* Already stored. */ @@ -57,17 +66,23 @@ single_text_get_key(CompressedColumnValues column, int row, BytesView *restrict } static pg_attribute_always_inline BytesView -single_text_store_key(BytesView key, Datum *key_storage, MemoryContext key_memory_context) +single_text_store_key(GroupingPolicyHash *restrict policy, BytesView key, uint32 key_index) { const int total_bytes = key.len + VARHDRSZ; - text *stored = (text *) MemoryContextAlloc(key_memory_context, total_bytes); + text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), key.data, key.len); key.data = (uint8 *) VARDATA(stored); - *key_storage = PointerGetDatum(stored); + ((Datum *restrict) policy->keys)[key_index] = PointerGetDatum(stored); return key; } +static pg_attribute_always_inline void +single_text_destroy_key(BytesView key) +{ + /* Noop. */ +} + #define KEY_VARIANT single_text #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index aa043dac8ef..f7ee01b1fb5 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -57,8 +57,8 @@ FUNCTION_NAME(get_size_bytes)(void *table) * Fill the aggregation state offsets for all rows using a hash table. */ static pg_attribute_always_inline uint32 -FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, - const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, +FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, uint32 next_unused_state_index, int start_row, int end_row) { uint32 *restrict offsets = policy->offsets; @@ -72,11 +72,12 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, { bool key_valid = false; CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(column, row, &key, &key_valid); + FUNCTION_NAME(get_key)(policy, batch_state, row, next_unused_state_index, &key, &key_valid); - if (!arrow_row_is_valid(filter, row)) + if (!arrow_row_is_valid(batch_state->vector_qual_result, row)) { /* The row doesn't pass the filter. */ + FUNCTION_NAME(destroy_key)(key); continue; } @@ -85,6 +86,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, /* The key is null. */ policy->have_null_key = true; offsets[row] = 1; + FUNCTION_NAME(destroy_key)(key); continue; } @@ -96,6 +98,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, */ Assert(last_key_index >= 2); offsets[row] = last_key_index; + FUNCTION_NAME(destroy_key)(key); #ifndef NDEBUG policy->stat_consecutive_keys++; #endif @@ -113,14 +116,15 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, * New key, have to store it persistently. */ const int index = next_unused_state_index++; - entry->key = FUNCTION_NAME( - store_key)(key, &((Datum *restrict) policy->keys)[index], policy->key_body_mctx); + entry->key = FUNCTION_NAME(store_key)(policy, key, index); entry->agg_state_index = index; } offsets[row] = entry->agg_state_index; last_key_index = entry->agg_state_index; - last_key = key; + last_key = entry->key; + + FUNCTION_NAME(destroy_key)(key); } return next_unused_state_index; @@ -131,30 +135,38 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *policy, CompressedColumnValues column, * decompression types. */ static pg_attribute_always_inline uint32 -FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *policy, CompressedColumnValues column, - const uint64 *restrict filter, uint32 next_unused_state_index, +FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, uint32 next_unused_state_index, int start_row, int end_row) { - if (unlikely(column.decompression_type == DT_Scalar)) - { - return FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (column.decompression_type == DT_ArrowText) - { - return FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else if (column.decompression_type == DT_ArrowTextDict) + if (list_length(policy->output_grouping_columns) == 1) { - return FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); - } - else - { - return FUNCTION_NAME( - impl)(policy, column, filter, next_unused_state_index, start_row, end_row); + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + + if (unlikely(column.decompression_type == DT_Scalar)) + { + return FUNCTION_NAME( + impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowText) + { + return FUNCTION_NAME( + impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + } + else if (column.decompression_type == DT_ArrowTextDict) + { + return FUNCTION_NAME( + impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + } + else + { + return FUNCTION_NAME( + impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + } } + + return FUNCTION_NAME(impl)(policy, batch_state, next_unused_state_index, start_row, end_row); } /* @@ -166,20 +178,15 @@ static uint32 FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, uint32 next_unused_state_index, int start_row, int end_row) { - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); - CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; - const uint64 *restrict filter = batch_state->vector_qual_result; - - if (filter == NULL) + if (batch_state->vector_qual_result == NULL) { next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, column, NULL, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, batch_state, next_unused_state_index, start_row, end_row); } else { next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, column, filter, next_unused_state_index, start_row, end_row); + dispatch_type)(policy, batch_state, next_unused_state_index, start_row, end_row); } return next_unused_state_index; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 80b3cb51a73..5ac2d7eafe7 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -337,28 +337,36 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) * We cannot use it when the plan has GroupAggregate because the * latter requires sorted output. */ - if (agg->numCols == 1 && agg->aggstrategy == AGG_HASHED) + if (agg->aggstrategy == AGG_HASHED) { - int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); - TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); - - bool is_segmentby = false; - if (is_vector_var(custom, entry->expr, &is_segmentby)) + bool have_wrong_type = false; + for (int i = 0; i < agg->numCols; i++) { + int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); + TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); + + bool is_segmentby = false; + if (!is_vector_var(custom, entry->expr, &is_segmentby)) + { + have_wrong_type = true; + break; + } Var *var = castNode(Var, entry->expr); int16 typlen; bool typbyval; get_typlenbyval(var->vartype, &typlen, &typbyval); - if (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) + if (!( + (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) + || (var->vartype == TEXTOID))) { - return true; - } - - if (var->vartype == TEXTOID) - { - return true; + have_wrong_type = true; + break; } } + if (!have_wrong_type) + { + return true; + } } /* diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 0142f3f1753..29e48c1cf23 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -9,9 +9,19 @@ #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(CompressedColumnValues column, int row, CTYPE *restrict key, +FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, int row, int next_key_index, CTYPE *restrict key, bool *restrict valid) { + if (list_length(policy->output_grouping_columns) != 1) + { + Assert(false); + pg_unreachable(); + } + + GroupingColumn *g = linitial(policy->output_grouping_columns); + CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + if (unlikely(column.decompression_type == DT_Scalar)) { *key = DATUM_TO_CTYPE(*column.output_value); @@ -30,14 +40,20 @@ FUNCTION_NAME(get_key)(CompressedColumnValues column, int row, CTYPE *restrict k } } + static pg_attribute_always_inline CTYPE -FUNCTION_NAME(store_key)(CTYPE key, Datum *key_storage, MemoryContext key_memory_context) +FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key, uint32 key_index) { - /* Noop for fixed-size keys. */ - *key_storage = CTYPE_TO_DATUM(key); + ((Datum *restrict) policy->keys)[key_index] = CTYPE_TO_DATUM(key); return key; } +static pg_attribute_always_inline void +FUNCTION_NAME(destroy_key)(CTYPE key) +{ + /* Noop for fixed-size keys. */ +} + #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER #undef FUNCTION_NAME From ebd8755a18f60ebba8348b80128e639aac298b82 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 11:54:30 +0300 Subject: [PATCH 062/242] Fix use-after-free in per-batch vectorized grouping policy The grouping column values are references into the compressed batch, so we can reset it only after we have returned the partial aggregation result. --- tsl/src/nodes/vector_agg/exec.c | 11 ++- tsl/test/expected/vector_agg_segmentby.out | 89 ++++++++++++++++++++++ tsl/test/sql/vector_agg_segmentby.sql | 22 ++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 381944f5172..7e8e59de1cd 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -193,6 +193,15 @@ vector_agg_exec(CustomScanState *node) */ while (!grouping->gp_should_emit(grouping)) { + /* + * We discard the previous compressed batch here and not earlier, + * because the grouping column values returned by the batch grouping + * policy are owned by the compressed batch memory context. This is done + * to avoid generic value copying in the grouping policy to simplify its + * code. + */ + compressed_batch_discard_tuples(batch_state); + TupleTableSlot *compressed_slot = ExecProcNode(linitial(decompress_state->csstate.custom_ps)); @@ -233,8 +242,6 @@ vector_agg_exec(CustomScanState *node) } grouping->gp_add_batch(grouping, batch_state); - - compressed_batch_discard_tuples(batch_state); } if (grouping->gp_do_emit(grouping, aggregated_slot)) diff --git a/tsl/test/expected/vector_agg_segmentby.out b/tsl/test/expected/vector_agg_segmentby.out index 310c73af7b0..ee203af4ca2 100644 --- a/tsl/test/expected/vector_agg_segmentby.out +++ b/tsl/test/expected/vector_agg_segmentby.out @@ -178,4 +178,93 @@ select sum(t) from svagg group by s order by 1; 2000010000 (10 rows) +reset timescaledb.debug_require_vector_agg; +-- text segmentby column +select count(decompress_chunk(x)) from show_chunks('svagg') x; + count +------- + 2 +(1 row) + +alter table svagg set (timescaledb.compress = false); +alter table svagg add column x text; +update svagg set x = repeat(s::text, 100); +alter table svagg set (timescaledb.compress, timescaledb.compress_segmentby = 'x'); +NOTICE: default order by for hypertable "svagg" is set to "s DESC" +select count(compress_chunk(x)) from show_chunks('svagg') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference +--set timescaledb.debug_require_vector_agg = 'forbid'; +--set timescaledb.enable_vectorized_aggregation to off; +select substr(x, 1, 2), sum(t), count(*) from svagg where f >= 0 group by x order by x; + substr | sum | count +--------+------------+------- + 00 | 200010000 | 20000 + 11 | 400010000 | 20000 + 22 | 600010000 | 20000 + 33 | 800010000 | 20000 + 44 | 1000010000 | 20000 + 55 | 1200010000 | 20000 + 66 | 1400010000 | 20000 + 77 | 1600010000 | 20000 + 88 | 1800010000 | 20000 + 99 | 2000010000 | 20000 +(10 rows) + +select substr(x, 1, 2), sum(t), count(*) from svagg where f = 0 group by x order by x; + substr | sum | count +--------+-----------+------- + 00 | 28578571 | 2857 + 11 | 57145714 | 2857 + 22 | 85712857 | 2857 + 33 | 114280000 | 2857 + 44 | 142847143 | 2857 + 55 | 171414286 | 2857 + 66 | 200061429 | 2858 + 77 | 228568571 | 2857 + 88 | 257135714 | 2857 + 99 | 285702857 | 2857 +(10 rows) + +select substr(x, 1, 2), sum(t), count(*) from svagg where f in (0, 1) group by x order by x; + substr | sum | count +--------+-----------+------- + 00 | 57160000 | 5715 + 11 | 114294285 | 5714 + 22 | 171428571 | 5714 + 33 | 228562857 | 5714 + 44 | 285697143 | 5714 + 55 | 342831429 | 5714 + 66 | 400045715 | 5715 + 77 | 457210000 | 5715 + 88 | 514274285 | 5714 + 99 | 571408571 | 5714 +(10 rows) + +select substr(x, 1, 2), sum(t), count(*) from svagg where f in (0, 1, 3) group by x order by x; + substr | sum | count +--------+-----------+------- + 00 | 85727143 | 8572 + 11 | 171428571 | 8571 + 22 | 257170000 | 8572 + 33 | 342851428 | 8571 + 44 | 428552857 | 8571 + 55 | 514254286 | 8571 + 66 | 600035715 | 8572 + 77 | 685767143 | 8572 + 88 | 771398571 | 8571 + 99 | 857210000 | 8572 +(10 rows) + +select substr(x, 1, 2), sum(t), count(*) from svagg where f > 10 group by x order by x; + substr | sum | count +--------+-----+------- +(0 rows) + +reset timescaledb.debug_require_vector_agg; drop table svagg; diff --git a/tsl/test/sql/vector_agg_segmentby.sql b/tsl/test/sql/vector_agg_segmentby.sql index 987ddd911ff..e76641e649f 100644 --- a/tsl/test/sql/vector_agg_segmentby.sql +++ b/tsl/test/sql/vector_agg_segmentby.sql @@ -70,5 +70,27 @@ select sum(t), s, count(*) from svagg group by s order by s; select sum(t) from svagg group by s order by 1; +reset timescaledb.debug_require_vector_agg; + +-- text segmentby column +select count(decompress_chunk(x)) from show_chunks('svagg') x; +alter table svagg set (timescaledb.compress = false); +alter table svagg add column x text; +update svagg set x = repeat(s::text, 100); +alter table svagg set (timescaledb.compress, timescaledb.compress_segmentby = 'x'); +select count(compress_chunk(x)) from show_chunks('svagg') x; + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference +--set timescaledb.debug_require_vector_agg = 'forbid'; +--set timescaledb.enable_vectorized_aggregation to off; + +select substr(x, 1, 2), sum(t), count(*) from svagg where f >= 0 group by x order by x; +select substr(x, 1, 2), sum(t), count(*) from svagg where f = 0 group by x order by x; +select substr(x, 1, 2), sum(t), count(*) from svagg where f in (0, 1) group by x order by x; +select substr(x, 1, 2), sum(t), count(*) from svagg where f in (0, 1, 3) group by x order by x; +select substr(x, 1, 2), sum(t), count(*) from svagg where f > 10 group by x order by x; + +reset timescaledb.debug_require_vector_agg; drop table svagg; From 46cea325327c2877011a480fa6174e9d48a771b0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:23:50 +0300 Subject: [PATCH 063/242] refactor null key handling --- tsl/src/nodes/decompress_chunk/exec.c | 5 +- tsl/src/nodes/vector_agg/exec.c | 8 +- .../nodes/vector_agg/grouping_policy_hash.c | 93 ++++++----- .../nodes/vector_agg/grouping_policy_hash.h | 22 ++- tsl/src/nodes/vector_agg/hash_serialized.c | 155 +++++++++++------- tsl/src/nodes/vector_agg/hash_single_text.c | 7 +- .../vector_agg/hash_table_functions_impl.c | 17 +- tsl/src/nodes/vector_agg/plan.c | 90 +++++----- .../nodes/vector_agg/single_fixed_key_impl.c | 7 +- 9 files changed, 230 insertions(+), 174 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/exec.c b/tsl/src/nodes/decompress_chunk/exec.c index 1e2790f2e39..8642382f0f4 100644 --- a/tsl/src/nodes/decompress_chunk/exec.c +++ b/tsl/src/nodes/decompress_chunk/exec.c @@ -295,7 +295,10 @@ decompress_chunk_begin(CustomScanState *node, EState *estate, int eflags) TupleDescAttr(desc, AttrNumberGetAttrOffset(column.custom_scan_attno)); column.typid = attribute->atttypid; - get_typlenbyvalalign(column.typid, &column.value_bytes, &column.by_value, &column.typalign); + get_typlenbyvalalign(column.typid, + &column.value_bytes, + &column.by_value, + &column.typalign); if (list_nth_int(chunk_state->is_segmentby_column, compressed_index)) column.type = SEGMENTBY_COLUMN; diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 3aced0323b9..ae6861e7d30 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -171,11 +171,11 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) else { /* - * Hash grouping. - */ + * Hash grouping. + */ vector_agg_state->grouping = - create_grouping_policy_hash(vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns); + create_grouping_policy_hash(vector_agg_state->agg_defs, + vector_agg_state->output_grouping_columns); } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 794d4c13f3b..7b82cce72fa 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -58,12 +58,10 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); } - // policy->key_bytes = g->value_bytes; - policy->key_bytes = sizeof(Datum); - Assert(policy->key_bytes > 0); - policy->num_allocated_keys = policy->allocated_aggstate_rows; - policy->keys = palloc(policy->key_bytes * policy->num_allocated_keys); + policy->output_keys = + palloc((sizeof(uint64) + list_length(policy->output_grouping_columns) * sizeof(Datum)) * + policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; if (list_length(policy->output_grouping_columns) == 1) @@ -71,22 +69,22 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) GroupingColumn *g = linitial(policy->output_grouping_columns); switch (g->value_bytes) { - case 8: - policy->functions = single_fixed_8_functions; - break; - case 4: - policy->functions = single_fixed_4_functions; - break; - case 2: - policy->functions = single_fixed_2_functions; - break; - case -1: - Assert(g->typid == TEXTOID); - policy->functions = single_text_functions; - break; - default: - Assert(false); - break; + case 8: + policy->functions = single_fixed_8_functions; + break; + case 4: + policy->functions = single_fixed_4_functions; + break; + case 2: + policy->functions = single_fixed_2_functions; + break; + case -1: + Assert(g->typid == TEXTOID); + policy->functions = single_text_functions; + break; + default: + Assert(false); + break; } } else @@ -96,7 +94,8 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->table = policy->functions.create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); - policy->have_null_key = false; + policy->null_key_index = 0; + policy->next_unused_key_index = 1; policy->returning_results = false; @@ -113,7 +112,9 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; policy->functions.reset(policy->table); - policy->have_null_key = false; + + policy->null_key_index = 0; + policy->next_unused_key_index = 1; policy->stat_input_valid_rows = 0; policy->stat_input_total_rows = 0; @@ -223,12 +224,9 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con /* * Remember which aggregation states have already existed, and which we - * have to initialize. State index zero is invalid, and state index one - * is for null key. We have to initialize the null key state at the - * first run. + * have to initialize. State index zero is invalid. */ - const uint32 hash_keys = policy->functions.get_num_keys(policy->table); - const uint32 first_uninitialized_state_index = hash_keys ? hash_keys + 2 : 1; + const uint32 first_uninitialized_state_index = policy->next_unused_key_index; /* * Allocate enough storage for keys, given that each bach row might be @@ -238,27 +236,31 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con if (num_possible_keys > policy->num_allocated_keys) { policy->num_allocated_keys = num_possible_keys; - policy->keys = repalloc(policy->keys, list_length(policy->output_grouping_columns) * policy->key_bytes * num_possible_keys); + policy->output_keys = + repalloc(policy->output_keys, + (sizeof(uint64) + + list_length(policy->output_grouping_columns) * sizeof(Datum)) * + num_possible_keys); } /* * Match rows to aggregation states using a hash table. */ Assert((size_t) end_row <= policy->num_allocated_offsets); - uint32 next_unused_state_index = hash_keys + 2; - next_unused_state_index = policy->functions.fill_offsets(policy, - batch_state, - next_unused_state_index, - start_row, - end_row); + uint32 next_unused_key_index = policy->next_unused_key_index; + next_unused_key_index = policy->functions.fill_offsets(policy, + batch_state, + next_unused_key_index, + start_row, + end_row); const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; for (int i = 0; i < num_fns; i++) { VectorAggDef *agg_def = list_nth(policy->agg_defs, i); - if (next_unused_state_index > first_uninitialized_state_index) + if (next_unused_key_index > first_uninitialized_state_index) { - if (next_unused_state_index > policy->allocated_aggstate_rows) + if (next_unused_key_index > policy->allocated_aggstate_rows) { lfirst(list_nth_cell(policy->per_agg_states, i)) = repalloc(list_nth(policy->per_agg_states, i), @@ -270,7 +272,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con */ agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + (char *) list_nth(policy->per_agg_states, i), - next_unused_state_index - first_uninitialized_state_index); + next_unused_key_index - first_uninitialized_state_index); } /* @@ -289,11 +291,13 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con /* * Record the newly allocated number of rows in case we had to reallocate. */ - if (next_unused_state_index > policy->allocated_aggstate_rows) + if (next_unused_key_index > policy->allocated_aggstate_rows) { Assert(new_aggstate_rows >= policy->allocated_aggstate_rows); policy->allocated_aggstate_rows = new_aggstate_rows; } + + policy->next_unused_key_index = next_unused_key_index; } static void @@ -398,9 +402,9 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) if (!policy->returning_results) { policy->returning_results = true; - policy->last_returned_key = 1 + !policy->have_null_key; + policy->last_returned_key = 1; - const float keys = policy->functions.get_num_keys(policy->table) + policy->have_null_key; + const float keys = policy->next_unused_key_index; if (keys > 0) { DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " @@ -421,7 +425,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) } const uint32 current_key = policy->last_returned_key; - const uint32 keys_end = policy->functions.get_num_keys(policy->table) + 2; + const uint32 keys_end = policy->next_unused_key_index; if (current_key >= keys_end) { policy->returning_results = false; @@ -443,8 +447,9 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) for (int i = 0; i < num_keys; i++) { GroupingColumn *col = list_nth(policy->output_grouping_columns, i); - aggregated_slot->tts_values[col->output_offset] = ((Datum *) policy->keys)[current_key * num_keys + i]; - aggregated_slot->tts_isnull[col->output_offset] = false; //current_key == 1; + aggregated_slot->tts_values[col->output_offset] = + gp_hash_output_keys(policy, current_key)[i]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; } return true; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 9020922207d..d738ef9a101 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -56,7 +56,7 @@ typedef struct GroupingPolicyHash * table, and it has a reserved aggregate state index 1. We also reset this * flag after we output the null key during iteration. */ - bool have_null_key; + uint32 null_key_index; /* * A memory context for aggregate functions to allocate additional data, @@ -81,10 +81,10 @@ typedef struct GroupingPolicyHash List *per_agg_states; uint64 allocated_aggstate_rows; - uint64 key_bytes; uint64 num_allocated_keys; - void *restrict keys; + void *restrict output_keys; MemoryContext key_body_mctx; + uint32 next_unused_key_index; uint64 *tmp_filter; uint64 num_tmp_filter_words; @@ -97,3 +97,19 @@ typedef struct GroupingPolicyHash uint64 stat_bulk_filtered_rows; uint64 stat_consecutive_keys; } GroupingPolicyHash; + +static inline uint64 * +gp_hash_key_validity_bitmap(GroupingPolicyHash *policy, int key_index) +{ + return ( + uint64 *) ((char *) policy->output_keys + + (sizeof(uint64) + sizeof(Datum) * list_length(policy->output_grouping_columns)) * + key_index); +} + +static inline Datum * +gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) +{ + Assert(key_index != 0); + return (Datum *) &gp_hash_key_validity_bitmap(policy, key_index)[1]; +} diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 3cedc2de33c..fa6dc62c03f 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,16 +19,15 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int row, int next_key_index, BytesView *restrict key, - bool *restrict valid) +serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + int row, int next_key_index, BytesView *restrict key, bool *restrict valid) { - if (list_length(policy->output_grouping_columns) == 1) - { - pg_unreachable(); - } + // if (list_length(policy->output_grouping_columns) == 1) + // { + // pg_unreachable(); + // } - uint64 *restrict validity_bitmap; + uint64 *restrict serialized_key_validity_word; const int num_columns = list_length(policy->output_grouping_columns); Assert(num_columns <= 64); @@ -43,7 +42,8 @@ serialized_get_key(GroupingPolicyHash *restrict policy, } else { - const CompressedColumnValues *column = &batch_state->compressed_columns[def->input_offset]; + const CompressedColumnValues *column = + &batch_state->compressed_columns[def->input_offset]; if (unlikely(column->decompression_type == DT_Scalar)) { num_bytes += (*column->output_isnull) ? 0 : VARSIZE_ANY(*column->output_value); @@ -76,95 +76,120 @@ serialized_get_key(GroupingPolicyHash *restrict policy, /* The optional null bitmap. */ num_bytes = att_align_nominal(num_bytes, TYPALIGN_DOUBLE); - num_bytes += sizeof(*validity_bitmap); + num_bytes += sizeof(*serialized_key_validity_word); - - Datum *restrict key_data = &((Datum *) policy->keys)[num_columns * next_key_index]; - uint8 *restrict key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); - validity_bitmap = (uint64 *) &((char *) key_storage)[num_bytes - sizeof(*validity_bitmap)]; - *validity_bitmap = ~0ULL; + uint64 *restrict output_key_validity_word = gp_hash_key_validity_bitmap(policy, next_key_index); + Datum *restrict output_key_datums = gp_hash_output_keys(policy, next_key_index); + uint8 *restrict serialized_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); + serialized_key_validity_word = (uint64 *) &( + (char *) serialized_key_storage)[num_bytes - sizeof(*serialized_key_validity_word)]; + *serialized_key_validity_word = ~0ULL; uint32 offset = 0; - for (int i = 0; i < num_columns; i++) + for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = list_nth(policy->output_grouping_columns, i); + const GroupingColumn *def = list_nth(policy->output_grouping_columns, column_index); offset = att_align_nominal(offset, def->typalign); - const CompressedColumnValues *column = &batch_state->compressed_columns[def->input_offset]; - if (column->decompression_type > 0) + const CompressedColumnValues *column_values = + &batch_state->compressed_columns[def->input_offset]; + if (column_values->decompression_type > 0) { - Assert(offset <= UINT_MAX - column->decompression_type); - memcpy(&key_storage[offset], - ((char *) column->buffers[1]) + column->decompression_type * row, - column->decompression_type); - arrow_set_row_validity(validity_bitmap, i, arrow_row_is_valid(column->buffers[0], row)); - offset += column->decompression_type; - - memcpy(&key_data[i], - ((char *) column->buffers[1]) + column->decompression_type * row, - column->decompression_type); + Assert(offset <= UINT_MAX - column_values->decompression_type); + memcpy(&serialized_key_storage[offset], + ((char *) column_values->buffers[1]) + column_values->decompression_type * row, + column_values->decompression_type); + arrow_set_row_validity(serialized_key_validity_word, + column_index, + arrow_row_is_valid(column_values->buffers[0], row)); + offset += column_values->decompression_type; + + memcpy(&output_key_datums[column_index], + ((char *) column_values->buffers[1]) + column_values->decompression_type * row, + column_values->decompression_type); } - else if (unlikely(column->decompression_type == DT_Scalar)) + else if (unlikely(column_values->decompression_type == DT_Scalar)) { - const bool is_valid = !*column->output_isnull; - arrow_set_row_validity(validity_bitmap, i, is_valid); + const bool is_valid = !*column_values->output_isnull; + arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); if (is_valid) { if (def->by_value) { - memcpy(&key_storage[offset], column->output_value, def->value_bytes); + memcpy(&serialized_key_storage[offset], + column_values->output_value, + def->value_bytes); offset += def->value_bytes; - memcpy(&key_data[row], column->output_value, def->value_bytes); + memcpy(&output_key_datums[column_index], + column_values->output_value, + def->value_bytes); } else { - memcpy(&key_storage[offset], DatumGetPointer(*column->output_value), VARSIZE_ANY(column->output_value)); + memcpy(&serialized_key_storage[offset], + DatumGetPointer(*column_values->output_value), + VARSIZE_ANY(*column_values->output_value)); - key_data[row] = PointerGetDatum(&key_storage[offset]); + output_key_datums[column_index] = + PointerGetDatum(&serialized_key_storage[offset]); - offset += VARSIZE_ANY(column->output_value); + offset += VARSIZE_ANY(*column_values->output_value); } } + else + { + output_key_datums[column_index] = PointerGetDatum(NULL); + } } - else if (column->decompression_type == DT_ArrowText) + else if (column_values->decompression_type == DT_ArrowText) { - const bool is_valid = arrow_row_is_valid(column->buffers[0], row); - arrow_set_row_validity(validity_bitmap, i, is_valid); + const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); + arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); if (is_valid) { - const uint32 start = ((uint32 *) column->buffers[1])[row]; - const int32 value_bytes = ((uint32 *) column->buffers[1])[row + 1] - start; + const uint32 start = ((uint32 *) column_values->buffers[1])[row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[row + 1] - start; const int32 total_bytes = value_bytes + VARHDRSZ; - SET_VARSIZE(&key_storage[offset], total_bytes); - memcpy(VARDATA(&key_storage[offset]), &((uint8 *) column->buffers[2])[start], - value_bytes); + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + memcpy(VARDATA(&serialized_key_storage[offset]), + &((uint8 *) column_values->buffers[2])[start], + value_bytes); - key_data[i] = PointerGetDatum(&key_storage[offset]); + output_key_datums[column_index] = PointerGetDatum(&serialized_key_storage[offset]); offset += total_bytes; } + else + { + output_key_datums[column_index] = PointerGetDatum(NULL); + } } - else if (column->decompression_type == DT_ArrowTextDict) + else if (column_values->decompression_type == DT_ArrowTextDict) { - const bool is_valid = arrow_row_is_valid(column->buffers[0], row); - arrow_set_row_validity(validity_bitmap, i, is_valid); + const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); + arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); if (is_valid) { - const int16 index = ((int16 *) column->buffers[3])[row]; - const uint32 start = ((uint32 *) column->buffers[1])[index]; - const int32 value_bytes = ((uint32 *) column->buffers[1])[index + 1] - start; + const int16 index = ((int16 *) column_values->buffers[3])[row]; + const uint32 start = ((uint32 *) column_values->buffers[1])[index]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[index + 1] - start; const int32 total_bytes = value_bytes + VARHDRSZ; - SET_VARSIZE(&key_storage[offset], total_bytes); - memcpy(VARDATA(&key_storage[offset]), &((uint8 *) column->buffers[2])[start], - value_bytes); + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + memcpy(VARDATA(&serialized_key_storage[offset]), + &((uint8 *) column_values->buffers[2])[start], + value_bytes); - key_data[i] = PointerGetDatum(&key_storage[offset]); + output_key_datums[column_index] = PointerGetDatum(&serialized_key_storage[offset]); offset += total_bytes; } + else + { + output_key_datums[column_index] = PointerGetDatum(NULL); + } } else { @@ -172,15 +197,25 @@ serialized_get_key(GroupingPolicyHash *restrict policy, } } - Assert((void *) &key_storage[att_align_nominal(offset, TYPALIGN_DOUBLE)] == (void *) validity_bitmap); + Assert((void *) &serialized_key_storage[att_align_nominal(offset, TYPALIGN_DOUBLE)] == + (void *) serialized_key_validity_word); - if (*validity_bitmap != ~0ULL) + if (*serialized_key_validity_word != ~0ULL) { - offset = att_align_nominal(offset, TYPALIGN_DOUBLE) + sizeof(*validity_bitmap); + offset = att_align_nominal(offset, TYPALIGN_DOUBLE) + sizeof(*serialized_key_validity_word); Assert(offset == num_bytes); } - *key = (BytesView) { .data = key_storage, .len = offset }; + *output_key_validity_word = *serialized_key_validity_word; + + // fprintf(stderr, "key is %d bytes: ", offset); + // for (size_t i = 0; i < offset; i++) + // { + // fprintf(stderr, "%.2x.", key_storage[i]); + // } + // fprintf(stderr, "\n"); + + *key = (BytesView){ .data = serialized_key_storage, .len = offset }; *valid = true; } diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index a811e82cc05..e77c5299b3e 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -29,9 +29,8 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int row, int next_key_index, BytesView *restrict key, - bool *restrict valid) +single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + int row, int next_key_index, BytesView *restrict key, bool *restrict valid) { if (list_length(policy->output_grouping_columns) != 1) { @@ -73,7 +72,7 @@ single_text_store_key(GroupingPolicyHash *restrict policy, BytesView key, uint32 SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), key.data, key.len); key.data = (uint8 *) VARDATA(stored); - ((Datum *restrict) policy->keys)[key_index] = PointerGetDatum(stored); + gp_hash_output_keys(policy, key_index)[0] = PointerGetDatum(stored); return key; } diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index f7ee01b1fb5..4dcd9e9d3cf 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -57,9 +57,8 @@ FUNCTION_NAME(get_size_bytes)(void *table) * Fill the aggregation state offsets for all rows using a hash table. */ static pg_attribute_always_inline uint32 -FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, uint32 next_unused_state_index, int start_row, - int end_row) +FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + uint32 next_unused_state_index, int start_row, int end_row) { uint32 *restrict offsets = policy->offsets; Assert((size_t) end_row <= policy->num_allocated_offsets); @@ -84,8 +83,11 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, if (unlikely(!key_valid)) { /* The key is null. */ - policy->have_null_key = true; - offsets[row] = 1; + if (policy->null_key_index == 0) + { + policy->null_key_index = next_unused_state_index++; + } + offsets[row] = policy->null_key_index; FUNCTION_NAME(destroy_key)(key); continue; } @@ -96,7 +98,6 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, * In real data sets, we often see consecutive rows with the * same key, so checking for this case improves performance. */ - Assert(last_key_index >= 2); offsets[row] = last_key_index; FUNCTION_NAME(destroy_key)(key); #ifndef NDEBUG @@ -136,8 +137,8 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, */ static pg_attribute_always_inline uint32 FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, uint32 next_unused_state_index, - int start_row, int end_row) + DecompressBatchState *restrict batch_state, + uint32 next_unused_state_index, int start_row, int end_row) { if (list_length(policy->output_grouping_columns) == 1) { diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 5ac2d7eafe7..72d6d925040 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -118,9 +118,9 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) static Plan * vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) { - CustomScan *custom = (CustomScan *) makeNode(CustomScan); - custom->custom_plans = list_make1(decompress_chunk); - custom->methods = &scan_methods; + CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); + vector_agg->custom_plans = list_make1(decompress_chunk); + vector_agg->methods = &scan_methods; /* * Note that this is being called from the post-planning hook, and therefore @@ -128,32 +128,33 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) * the previous planning stages, and they contain special varnos referencing * the scan targetlists. */ - custom->custom_scan_tlist = resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); - custom->scan.plan.targetlist = - build_trivial_custom_output_targetlist(custom->custom_scan_tlist); + vector_agg->custom_scan_tlist = + resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); + vector_agg->scan.plan.targetlist = + build_trivial_custom_output_targetlist(vector_agg->custom_scan_tlist); /* * Copy the costs from the normal aggregation node, so that they show up in * the EXPLAIN output. They are not used for any other purposes, because * this hook is called after the planning is finished. */ - custom->scan.plan.plan_rows = agg->plan.plan_rows; - custom->scan.plan.plan_width = agg->plan.plan_width; - custom->scan.plan.startup_cost = agg->plan.startup_cost; - custom->scan.plan.total_cost = agg->plan.total_cost; + vector_agg->scan.plan.plan_rows = agg->plan.plan_rows; + vector_agg->scan.plan.plan_width = agg->plan.plan_width; + vector_agg->scan.plan.startup_cost = agg->plan.startup_cost; + vector_agg->scan.plan.total_cost = agg->plan.total_cost; - custom->scan.plan.parallel_aware = false; - custom->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; - custom->scan.plan.async_capable = false; + vector_agg->scan.plan.parallel_aware = false; + vector_agg->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; + vector_agg->scan.plan.async_capable = false; - custom->scan.plan.plan_node_id = agg->plan.plan_node_id; + vector_agg->scan.plan.plan_node_id = agg->plan.plan_node_id; Assert(agg->plan.qual == NIL); - custom->scan.plan.initPlan = agg->plan.initPlan; + vector_agg->scan.plan.initPlan = agg->plan.initPlan; - custom->scan.plan.extParam = bms_copy(agg->plan.extParam); - custom->scan.plan.allParam = bms_copy(agg->plan.allParam); + vector_agg->scan.plan.extParam = bms_copy(agg->plan.extParam); + vector_agg->scan.plan.allParam = bms_copy(agg->plan.allParam); List *grouping_child_output_offsets = NIL; for (int i = 0; i < agg->numCols; i++) @@ -161,9 +162,9 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) grouping_child_output_offsets = lappend_int(grouping_child_output_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); } - custom->custom_private = list_make1(grouping_child_output_offsets); + vector_agg->custom_private = list_make1(grouping_child_output_offsets); - return (Plan *) custom; + return (Plan *) vector_agg; } /* @@ -334,40 +335,37 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) /* * We support hashed vectorized grouping by one fixed-size by-value * compressed column. - * We cannot use it when the plan has GroupAggregate because the - * latter requires sorted output. + * We can use our hash table for GroupAggregate as well, because it preserves + * the input order of the keys. + * FIXME write a test for that. */ - if (agg->aggstrategy == AGG_HASHED) + bool have_wrong_type = false; + for (int i = 0; i < agg->numCols; i++) { - bool have_wrong_type = false; - for (int i = 0; i < agg->numCols; i++) - { - int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); + int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); + TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); - bool is_segmentby = false; - if (!is_vector_var(custom, entry->expr, &is_segmentby)) - { - have_wrong_type = true; - break; - } - Var *var = castNode(Var, entry->expr); - int16 typlen; - bool typbyval; - get_typlenbyval(var->vartype, &typlen, &typbyval); - if (!( - (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) - || (var->vartype == TEXTOID))) - { - have_wrong_type = true; - break; - } + bool is_segmentby = false; + if (!is_vector_var(custom, entry->expr, &is_segmentby)) + { + have_wrong_type = true; + break; } - if (!have_wrong_type) + Var *var = castNode(Var, entry->expr); + int16 typlen; + bool typbyval; + get_typlenbyval(var->vartype, &typlen, &typbyval); + if (!((typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) || + (var->vartype == TEXTOID))) { - return true; + have_wrong_type = true; + break; } } + if (!have_wrong_type) + { + return true; + } /* * We support grouping by any number of columns if all of them are segmentby. diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 29e48c1cf23..253883dfdc4 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -10,8 +10,8 @@ static pg_attribute_always_inline void FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int row, int next_key_index, CTYPE *restrict key, - bool *restrict valid) + DecompressBatchState *restrict batch_state, int row, int next_key_index, + CTYPE *restrict key, bool *restrict valid) { if (list_length(policy->output_grouping_columns) != 1) { @@ -40,11 +40,10 @@ FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, } } - static pg_attribute_always_inline CTYPE FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key, uint32 key_index) { - ((Datum *restrict) policy->keys)[key_index] = CTYPE_TO_DATUM(key); + gp_hash_output_keys(policy, key_index)[0] = CTYPE_TO_DATUM(key); return key; } From a9c9bd2d03d91d68920d6fa02da0a0a566e74534 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:33:28 +0300 Subject: [PATCH 064/242] benchmark groupagg (2024-10-24 no. 17) From 69750044d6e979463c84f99b874c18c10fcd2dbb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 17:15:00 +0300 Subject: [PATCH 065/242] benchmark groupagg (2024-10-24 no. 18) From 343603b1eb3e84a1f7e413a5a50a296b0832a4db Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:58:54 +0300 Subject: [PATCH 066/242] fixes --- .../nodes/vector_agg/grouping_policy_hash.c | 2 +- tsl/src/nodes/vector_agg/plan.c | 65 ++++++++++--------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 7b82cce72fa..ec072cd278b 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -404,7 +404,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) policy->returning_results = true; policy->last_returned_key = 1; - const float keys = policy->next_unused_key_index; + const float keys = policy->next_unused_key_index - 1; if (keys > 0) { DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 72d6d925040..7e217e9eafa 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -83,21 +83,21 @@ resolve_outer_special_vars_mutator(Node *node, void *context) CustomScan *custom = castNode(CustomScan, context); TargetEntry *decompress_chunk_tentry = castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, aggregated_var->varattno - 1)); - Var *decompressed_var = castNode(Var, decompress_chunk_tentry->expr); - if (decompressed_var->varno == INDEX_VAR) + Expr *decompressed_expr = decompress_chunk_tentry->expr; + if (IsA(decompressed_expr, Var) && castNode(Var, decompressed_expr)->varno == INDEX_VAR) { /* * This is a reference into the custom scan targetlist, we have to resolve * it as well. */ - decompressed_var = - castNode(Var, - castNode(TargetEntry, - list_nth(custom->custom_scan_tlist, decompressed_var->varattno - 1)) - ->expr); - } - Assert(decompressed_var->varno > 0); - return (Node *) copyObject(decompressed_var); + TargetEntry *custom_scan_tentry = + castNode(TargetEntry, + list_nth(custom->custom_scan_tlist, + castNode(Var, decompressed_expr)->varattno - 1)); + decompressed_expr = custom_scan_tentry->expr; + } + Assert(!IsA(decompressed_expr, Var) || castNode(Var, decompressed_expr)->varno > 0); + return (Node *) copyObject(decompressed_expr); } /* @@ -339,33 +339,36 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) * the input order of the keys. * FIXME write a test for that. */ - bool have_wrong_type = false; - for (int i = 0; i < agg->numCols; i++) + if (agg->numCols == 1) { - int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); - - bool is_segmentby = false; - if (!is_vector_var(custom, entry->expr, &is_segmentby)) + bool have_wrong_type = false; + for (int i = 0; i < agg->numCols; i++) { - have_wrong_type = true; - break; + int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); + TargetEntry *entry = list_nth(aggregated_tlist_resolved, offset); + + bool is_segmentby = false; + if (!is_vector_var(custom, entry->expr, &is_segmentby)) + { + have_wrong_type = true; + break; + } + Var *var = castNode(Var, entry->expr); + int16 typlen; + bool typbyval; + get_typlenbyval(var->vartype, &typlen, &typbyval); + if (!((typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) || + (var->vartype == TEXTOID))) + { + have_wrong_type = true; + break; + } } - Var *var = castNode(Var, entry->expr); - int16 typlen; - bool typbyval; - get_typlenbyval(var->vartype, &typlen, &typbyval); - if (!((typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) || - (var->vartype == TEXTOID))) + if (!have_wrong_type) { - have_wrong_type = true; - break; + return true; } } - if (!have_wrong_type) - { - return true; - } /* * We support grouping by any number of columns if all of them are segmentby. From 5854815da6d3049a23876f054342ae32f8a9fe64 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:59:00 +0300 Subject: [PATCH 067/242] benchmark groupagg (2024-10-24 no. 19) From 43cdee9640101ac23665614c7beccc135f24be27 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:00:08 +0300 Subject: [PATCH 068/242] serialized policy only --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 10 ++++++++-- tsl/src/nodes/vector_agg/grouping_policy_hash.h | 5 +++++ tsl/src/nodes/vector_agg/hash_single_text.c | 13 +++++++++++++ .../nodes/vector_agg/hash_table_functions_impl.c | 11 +++++++++-- tsl/src/nodes/vector_agg/plan.c | 2 +- tsl/src/nodes/vector_agg/single_fixed_key_impl.c | 5 +++-- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index ec072cd278b..764ff7d2565 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -64,7 +64,7 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; - if (list_length(policy->output_grouping_columns) == 1) + if (false && list_length(policy->output_grouping_columns) == 1) { GroupingColumn *g = linitial(policy->output_grouping_columns); switch (g->value_bytes) @@ -449,9 +449,15 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) GroupingColumn *col = list_nth(policy->output_grouping_columns, i); aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[i]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; + aggregated_slot->tts_isnull[col->output_offset] = + !arrow_row_is_valid(gp_hash_key_validity_bitmap(policy, current_key), i); } + DEBUG_PRINT("%p: output key index %d valid %lx\n", + policy, + current_key, + gp_hash_key_validity_bitmap(policy, current_key)[0]); + return true; } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index d738ef9a101..309e54560e1 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -113,3 +113,8 @@ gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) Assert(key_index != 0); return (Datum *) &gp_hash_key_validity_bitmap(policy, key_index)[1]; } + +// #define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(...) +#endif diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index e77c5299b3e..a91610714e7 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -62,6 +62,19 @@ single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *r { pg_unreachable(); } + + gp_hash_key_validity_bitmap(policy, next_key_index)[0] = *valid; + + DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", + policy, + row, + next_key_index, + key->len); + for (size_t i = 0; i < key->len; i++) + { + DEBUG_PRINT("%.2x.", key->data[i]); + } + DEBUG_PRINT("\n"); } static pg_attribute_always_inline BytesView diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 4dcd9e9d3cf..20c668f7d98 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -75,6 +75,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r if (!arrow_row_is_valid(batch_state->vector_qual_result, row)) { + DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); /* The row doesn't pass the filter. */ FUNCTION_NAME(destroy_key)(key); continue; @@ -88,6 +89,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r policy->null_key_index = next_unused_state_index++; } offsets[row] = policy->null_key_index; + DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); FUNCTION_NAME(destroy_key)(key); continue; } @@ -103,6 +105,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r #ifndef NDEBUG policy->stat_consecutive_keys++; #endif + DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, last_key_index); continue; } @@ -119,13 +122,17 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r const int index = next_unused_state_index++; entry->key = FUNCTION_NAME(store_key)(policy, key, index); entry->agg_state_index = index; + DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); + } + else + { + DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->agg_state_index); + FUNCTION_NAME(destroy_key)(key); } offsets[row] = entry->agg_state_index; last_key_index = entry->agg_state_index; last_key = entry->key; - - FUNCTION_NAME(destroy_key)(key); } return next_unused_state_index; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 7e217e9eafa..ecd7d4a9a65 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -339,7 +339,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) * the input order of the keys. * FIXME write a test for that. */ - if (agg->numCols == 1) + if (true || agg->numCols == 1) { bool have_wrong_type = false; for (int i = 0; i < agg->numCols; i++) diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 253883dfdc4..263b762c840 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -15,7 +15,6 @@ FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, { if (list_length(policy->output_grouping_columns) != 1) { - Assert(false); pg_unreachable(); } @@ -38,12 +37,14 @@ FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, { pg_unreachable(); } + + gp_hash_output_keys(policy, next_key_index)[0] = CTYPE_TO_DATUM(*key); + gp_hash_key_validity_bitmap(policy, next_key_index)[0] = *valid; } static pg_attribute_always_inline CTYPE FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key, uint32 key_index) { - gp_hash_output_keys(policy, key_index)[0] = CTYPE_TO_DATUM(key); return key; } From bbd6f714070ab2ff54cba13fb82f45d95e74bb88 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:00:22 +0300 Subject: [PATCH 069/242] benchmark serialized (2024-10-25 no. 20) From 46d655b2163e2fad81712acf0cd1d4ae4fe4954b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:58:57 +0300 Subject: [PATCH 070/242] tests --- .../nodes/vector_agg/grouping_policy_hash.c | 2 +- tsl/test/expected/vector_agg_filter.out | 3961 +++++++ tsl/test/expected/vector_agg_functions.out | 9546 ++++++++--------- tsl/test/expected/vector_agg_grouping.out | 372 + tsl/test/sql/CMakeLists.txt | 2 + tsl/test/sql/vector_agg_filter.sql | 107 + tsl/test/sql/vector_agg_functions.sql | 40 +- tsl/test/sql/vector_agg_grouping.sql | 100 + 8 files changed, 8823 insertions(+), 5307 deletions(-) create mode 100644 tsl/test/expected/vector_agg_filter.out create mode 100644 tsl/test/expected/vector_agg_grouping.out create mode 100644 tsl/test/sql/vector_agg_filter.sql create mode 100644 tsl/test/sql/vector_agg_grouping.sql diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 764ff7d2565..d38ddebb2ab 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -64,7 +64,7 @@ create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; - if (false && list_length(policy->output_grouping_columns) == 1) + if (list_length(policy->output_grouping_columns) == 1) { GroupingColumn *g = linitial(policy->output_grouping_columns); switch (g->value_bytes) diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out new file mode 100644 index 00000000000..0cc68d15e4d --- /dev/null +++ b/tsl/test/expected/vector_agg_filter.out @@ -0,0 +1,3961 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +------------------------ + (1,public,aggfilter,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into aggfilter select * from source where s = 1; +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 1 +(1 row) + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze aggfilter; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's', + 'ss']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec +select count(*) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select s, count(*) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select ss, count(*) from aggfilter group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select ss, count(*) filter (where cint2 < 0) from aggfilter group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 12 + 3 | 10076 + 4 | 10064 + 0 | 9968 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 + 11 | 20008 +(10 rows) + +select ss, count(*) filter (where ss > 1000) from aggfilter group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 4 | 0 + 0 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(10 rows) + +select ss, count(*) filter (where cint4 > 0) from aggfilter group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 11 + 3 | 10052 + 4 | 9988 + 0 | 10002 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 + 11 | 19938 +(10 rows) + +select count(cint2) from aggfilter; + count +-------- + 199810 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter; + count +------- + 99946 +(1 row) + +select s, count(cint2) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9993 + 1 | 10034 + 2 | 9876 + 3 | 10052 + 4 | 9990 + 5 | 10095 + 6 | 9968 + 7 | 9976 + 8 | 10010 + 9 | 9952 +(10 rows) + +select ss, count(cint2) from aggfilter group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + +select ss, count(cint2) filter (where cint2 < 0) from aggfilter group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 12 + 3 | 10076 + 4 | 10064 + 0 | 9968 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 + 11 | 20008 +(10 rows) + +select ss, count(cint2) filter (where ss > 1000) from aggfilter group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 4 | 0 + 0 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfilter group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 11 + 3 | 10041 + 4 | 9983 + 0 | 9993 + 5 | 10095 + 6 | 9968 + 7 | 9976 + 8 | 10010 + 9 | 9952 + 11 | 19917 +(10 rows) + +select min(cint2) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 4 | + 5 | + 6 | + 2 | + 7 | + 8 | + 3 | + 1 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16380 + 4 | -16381 + 5 | -16383 + 6 | -16379 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16380 + 1 | -16378 + 9 | -16375 +(10 rows) + +select ss, min(cint2) from aggfilter group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + +select ss, min(cint2) filter (where cint2 < 0) from aggfilter group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + +select ss, min(cint2) filter (where ss > 1000) from aggfilter group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 4 | + 5 | + 6 | + 7 | + 8 | + 11 | + 3 | + 9 | + | +(10 rows) + +select ss, min(cint2) filter (where cint4 > 0) from aggfilter group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16380 + 4 | -16381 + 5 | -16383 + 6 | -16379 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16380 + 9 | -16375 + | -16100 +(10 rows) + +select count(cint4) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select s, count(cint4) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select ss, count(cint4) from aggfilter group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select ss, count(cint4) filter (where cint2 < 0) from aggfilter group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 12 + 3 | 10076 + 4 | 10064 + 0 | 9968 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 + 11 | 20008 +(10 rows) + +select ss, count(cint4) filter (where ss > 1000) from aggfilter group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 4 | 0 + 0 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint4) filter (where cint4 > 0) from aggfilter group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 11 + 3 | 10052 + 4 | 9988 + 0 | 10002 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 + 11 | 19938 +(10 rows) + +select min(cint4) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter; + min +----- + 1 +(1 row) + +select s, min(cint4) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16382 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16381 + 8 | -16382 + 9 | -16381 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 2 | + 7 | + 1 | + 3 | + 4 | + 6 | + 8 | + 9 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 2 | 2 + 7 | 1 + 1 | 3 + 3 | 2 + 4 | 2 + 6 | 2 + 8 | 2 + 9 | 2 + 5 | 2 +(10 rows) + +select ss, min(cint4) from aggfilter group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 + | -15907 +(10 rows) + +select ss, min(cint4) filter (where cint2 < 0) from aggfilter group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16382 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16381 + 8 | -16382 + 9 | -16381 + 5 | -16380 + | -15907 +(10 rows) + +select ss, min(cint4) filter (where ss > 1000) from aggfilter group by ss order by min(cint4), ss limit 10; + ss | min +----+----- + 0 | + 7 | + 11 | + 3 | + 4 | + 6 | + 8 | + 9 | + 5 | + | +(10 rows) + +select ss, min(cint4) filter (where cint4 > 0) from aggfilter group by ss order by min(cint4), ss limit 10; + ss | min +----+------ + 0 | 1 + 7 | 1 + 11 | 2 + 3 | 2 + 4 | 2 + 6 | 2 + 8 | 2 + 9 | 2 + 5 | 2 + | 4132 +(10 rows) + +select count(s) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select s, count(s) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select ss, count(s) from aggfilter group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select ss, count(s) filter (where cint2 < 0) from aggfilter group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 12 + 3 | 10076 + 4 | 10064 + 0 | 9968 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 + 11 | 20008 +(10 rows) + +select ss, count(s) filter (where ss > 1000) from aggfilter group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 4 | 0 + 0 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(10 rows) + +select ss, count(s) filter (where cint4 > 0) from aggfilter group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 11 + 3 | 10052 + 4 | 9988 + 0 | 10002 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 + 11 | 19938 +(10 rows) + +select min(s) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) from aggfilter group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) filter (where cint2 < 0) from aggfilter group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) filter (where ss > 1000) from aggfilter group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | + 11 | + 3 | + | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select ss, min(s) filter (where cint4 > 0) from aggfilter group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter; + count +-------- + 199981 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter; + count +-------- + 100127 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter; + count +-------- + 100027 +(1 row) + +select s, count(ss) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10076 + 0 | 9968 + 1 | 9885 + 2 | 10113 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 0 + 0 | 0 + 1 | 0 + 2 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10052 + 0 | 10002 + 1 | 10046 + 2 | 9885 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select ss, count(ss) from aggfilter group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select ss, count(ss) filter (where cint2 < 0) from aggfilter group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 10076 + 4 | 10064 + 0 | 9968 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 + 11 | 20008 +(10 rows) + +select ss, count(ss) filter (where ss > 1000) from aggfilter group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 4 | 0 + 0 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(10 rows) + +select ss, count(ss) filter (where cint4 > 0) from aggfilter group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 10052 + 4 | 9988 + 0 | 10002 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 + 11 | 19938 +(10 rows) + +select min(ss) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select ss, min(ss) from aggfilter group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + +select ss, min(ss) filter (where cint2 < 0) from aggfilter group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + +select ss, min(ss) filter (where ss > 1000) from aggfilter group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | + | +(10 rows) + +select ss, min(ss) filter (where cint4 > 0) from aggfilter group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + +select count(*) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select s, count(*) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select ss, count(*) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(*) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 4 + 3 | 4968 + 6 | 4911 + 4 | 4944 + 8 | 4929 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 5 | 5167 + 11 | 9990 +(10 rows) + +select count(cint2) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select s, count(cint2) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select ss, count(cint2) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 4 + 3 | 4968 + 6 | 4911 + 4 | 4944 + 8 | 4929 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 5 | 5167 + 11 | 9990 +(10 rows) + +select min(cint2) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select s, min(cint2) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 4 + 2 | 4 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 6 + 6 | 3 + 0 | 6 + 4 | 4 +(10 rows) + +select ss, min(cint2) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+------ + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 11 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 3667 +(10 rows) + +select ss, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 3 | + 5 | + 7 | + 8 | + 11 | + 9 | + 6 | + 0 | + 4 | + | +(10 rows) + +select ss, min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 3 | + 5 | + 7 | + 8 | + 11 | + 9 | + 6 | + 0 | + 4 | + | +(10 rows) + +select ss, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+------ + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 11 | 4 + 9 | 6 + 6 | 3 + 0 | 6 + 4 | 4 + | 3667 +(10 rows) + +select count(cint4) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select s, count(cint4) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select ss, count(cint4) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 4 + 3 | 4968 + 6 | 4911 + 4 | 4944 + 8 | 4929 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 5 | 5167 + 11 | 9990 +(10 rows) + +select min(cint4) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select s, min(cint4) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | -16375 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 1 | 7 + 3 | 2 + 4 | 5 + 6 | 2 + 7 | 1 + 9 | 2 + 2 | 2 + 8 | 5 + 5 | 2 +(10 rows) + +select ss, min(cint4) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 11 | -16382 + 8 | -16377 + 5 | -16375 + | -11573 +(10 rows) + +select ss, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 6 | + 7 | + 9 | + 11 | + 8 | + 5 | + | +(10 rows) + +select ss, min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 6 | + 7 | + 9 | + 11 | + 8 | + 5 | + | +(10 rows) + +select ss, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+------ + 0 | 1 + 3 | 2 + 4 | 5 + 6 | 2 + 7 | 1 + 9 | 2 + 11 | 2 + 8 | 5 + 5 | 2 + | 4132 +(10 rows) + +select count(s) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select s, count(s) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select ss, count(s) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 4 + 3 | 4968 + 6 | 4911 + 4 | 4944 + 8 | 4929 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 5 | 5167 + 11 | 9990 +(10 rows) + +select min(s) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | + 11 | + 3 | + | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select ss, min(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | + 11 | + 3 | + | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select ss, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 > 0; + count +------- + 99657 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49813 +(1 row) + +select s, count(ss) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 4923 + 3 | 4968 + 6 | 4911 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select ss, count(ss) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 0 + 6 | 0 + 4 | 0 + 8 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 5 | 0 + 11 | 0 +(10 rows) + +select ss, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 4968 + 6 | 4911 + 4 | 4944 + 8 | 4929 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 5 | 5167 + 11 | 9990 +(10 rows) + +select min(ss) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select ss, min(ss) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + +select ss, min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | + | +(10 rows) + +select ss, min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | + | +(10 rows) + +select ss, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + +select count(*) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select s, count(*) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select ss, count(*) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select ss, count(*) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(*) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; + ss | count +----+------- + 0 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 + 11 | 21 +(9 rows) + +select count(cint2) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select s, count(cint2) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select ss, count(cint2) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select min(cint2) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select s, min(cint2) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select ss, min(cint2) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select ss, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select ss, min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select ss, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select count(cint4) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select s, count(cint4) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select ss, count(cint4) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select ss, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + 0 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 + 11 | 21 +(9 rows) + +select min(cint4) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 473 +(1 row) + +select s, min(cint4) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | -15279 + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+------ + 0 | 701 + 7 | 1695 + 4 | 1821 + 5 | 587 + 2 | 2876 + 6 | 1003 + 9 | 2489 + 8 | 1334 + 1 | 2034 + 3 | 473 +(10 rows) + +select ss, min(cint4) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | -15279 + 11 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 3 | -9908 +(9 rows) + +select ss, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; + ss | min +----+----- + 0 | + 7 | + 4 | + 5 | + 11 | + 6 | + 9 | + 8 | + 3 | +(9 rows) + +select ss, min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; + ss | min +----+----- + 0 | + 7 | + 4 | + 5 | + 11 | + 6 | + 9 | + 8 | + 3 | +(9 rows) + +select ss, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; + ss | min +----+------ + 0 | 701 + 7 | 1695 + 4 | 1821 + 5 | 587 + 11 | 2034 + 6 | 1003 + 9 | 2489 + 8 | 1334 + 3 | 473 +(9 rows) + +select count(s) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select s, count(s) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select ss, count(s) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select ss, count(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(s) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; + ss | count +----+------- + 0 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 + 11 | 21 +(9 rows) + +select min(s) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select ss, min(s) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(9 rows) + +select ss, min(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select ss, min(s) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select ss, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(9 rows) + +select count(ss) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select s, count(ss) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select ss, count(ss) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select ss, count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + +select ss, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; + ss | count +----+------- + 0 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 + 11 | 21 +(9 rows) + +select min(ss) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select ss, min(ss) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 +(9 rows) + +select ss, min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select ss, min(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +select ss, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 +(9 rows) + diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 56b5e289776..b14850f6fbe 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -23,19 +23,20 @@ NOTICE: adding not-null constraint to column "s" (1 row) create view source as -select s * 10000::int + t as t, +select s * 10000 + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, - (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, - (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end as cfloat4, - (mix(s + t + 5) * 100)::float8 as cfloat8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, - '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate + else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, + (mix(s + t * 1039) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) @@ -102,15 +103,16 @@ vacuum freeze analyze edges; set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +-- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s)%s from aggfns%s%s order by 1;', + format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, grouping || ', ', function, variable, - ' filter (where ' || agg_filter || ')', ' where ' || condition, - ' group by ' || grouping ) + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) from unnest(array[ 'explain (costs off) ', @@ -145,11 +147,7 @@ from unnest(array[ null, 's', - 'ss', - 'x']) with ordinality as grouping(grouping, n), - unnest(array[ - null, - 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -158,26 +156,16 @@ where -- This is not vectorized yet and (variable != 'cint8' or function != 'stddev') and (function != 'count' or variable in ('cint2', 's', '*')) - and (agg_filter is null or (function = 'count') or (function = 'sum' and variable in ('cint2', 'cint4'))) and (condition is distinct from 'cint2 is null' or variable = 'cint2') - -- No need to test the aggregate functions themselves again for string - -- grouping. - and (grouping is distinct from 'x' or (function = 'count' and variable in ('cint2', '*') and agg_filter is null)) -order by explain, condition.n, variable, function, grouping.n, agg_filter.n +order by explain, condition.n, variable, function, grouping.n \gexec -select count(*) from aggfns order by 1; +select count(*) from aggfns; count -------- 200000 (1 row) -select count(*) filter (where cint4 > 0) from aggfns order by 1; - count -------- - 99428 -(1 row) - -select s, count(*) from aggfns group by s order by 1; +select s, count(*) from aggfns group by s order by count(*), s limit 10; s | count ---+------- 0 | 20000 @@ -192,547 +180,496 @@ select s, count(*) from aggfns group by s order by 1; 9 | 20000 (10 rows) -select s, count(*) filter (where cint4 > 0) from aggfns group by s order by 1; - s | count ----+------- - 0 | 9942 - 1 | 9943 - 2 | 9943 - 3 | 9943 - 4 | 9943 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 -(10 rows) - -select ss, count(*) from aggfns group by ss order by 1; +select ss, count(*) from aggfns group by ss order by count(*), ss limit 10; ss | count ----+------- - 0 | 20000 + | 19 3 | 19981 4 | 19981 + 0 | 20000 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 11 | 40019 - | 19 -(10 rows) - -select ss, count(*) filter (where cint4 > 0) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 9942 - 3 | 9937 - 4 | 9932 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 - 11 | 19897 - | 6 -(10 rows) - -select x, count(*) from aggfns group by x order by 1; - x | count -----+------- - 0 | 20000 - 11 | 40019 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - | 19 (10 rows) -select max(cdate) from aggfns order by 1; +select max(cdate) from aggfns; max ------------ - 03-05-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns group by s order by 1; +select s, max(cdate) from aggfns group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, max(cdate) from aggfns group by ss order by max(cdate), ss limit 10; ss | max ----+------------ - 0 | 10-05-2075 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 - 11 | 01-24-2183 - | 07-03-2156 -(10 rows) - -select min(cdate) from aggfns order by 1; + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns; min ------------ - 01-02-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns group by s order by 1; +select s, min(cdate) from aggfns group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, min(cdate) from aggfns group by ss order by min(cdate), ss limit 10; ss | min ----+------------ - 0 | 01-02-2021 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 - 11 | 05-20-2048 - | 08-11-2104 -(10 rows) - -select avg(cfloat4) from aggfns order by 1; + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns; avg ----- NaN (1 row) -select s, avg(cfloat4) from aggfns group by s order by 1; - s | avg ----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select ss, avg(cfloat4) from aggfns group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.132126759885764 - 3 | -Infinity - 4 | -0.124977103379316 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 - 11 | NaN - | -5.91588952823689 -(10 rows) - -select max(cfloat4) from aggfns order by 1; +select s, avg(cfloat4) from aggfns group by s order by avg(cfloat4), s limit 10; + s | avg +---+---------------------- + 3 | -Infinity + 9 | -0.292700759558938 + 4 | -0.177721596086072 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 2 | Infinity + 1 | NaN +(10 rows) + +select ss, avg(cfloat4) from aggfns group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+---------------------- + 3 | -Infinity + | -1.39583652270468 + 9 | -0.292700759558938 + 4 | -0.169252917487522 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 11 | NaN +(10 rows) + +select max(cfloat4) from aggfns; max ----- NaN (1 row) -select s, max(cfloat4) from aggfns group by s order by 1; +select s, max(cfloat4) from aggfns group by s order by max(cfloat4), s limit 10; s | max ---+---------- - 0 | 49.9977 - 1 | NaN + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + 1 | NaN (10 rows) -select ss, max(cfloat4) from aggfns group by ss order by 1; +select ss, max(cfloat4) from aggfns group by ss order by max(cfloat4), ss limit 10; ss | max ----+--------- - 0 | 49.9977 - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + | 47.2047 + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 11 | NaN - | 48.478 (10 rows) -select min(cfloat4) from aggfns order by 1; +select min(cfloat4) from aggfns; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns group by s order by 1; +select s, min(cfloat4) from aggfns group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns group by ss order by 1; + 4 | -49.9999 + 6 | -49.9995 + 2 | -49.9991 + 7 | -49.9984 + 1 | -49.9974 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 +(10 rows) + +select ss, min(cfloat4) from aggfns group by ss order by min(cfloat4), ss limit 10; ss | min ----+----------- - 0 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 + 4 | -49.9999 + 6 | -49.9995 + 7 | -49.9984 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 + | -45.4083 11 | NaN - | -46.7478 (10 rows) -select stddev(cfloat4) from aggfns order by 1; +select stddev(cfloat4) from aggfns; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns group by s order by 1; +select s, stddev(cfloat4) from aggfns group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8941380063426 + 0 | 28.7274163912974 + 7 | 28.7892027644317 + 4 | 28.8273136003882 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270615 1 | NaN 2 | NaN 3 | NaN - 4 | 28.8948189281653 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301629 - 8 | 28.8963276918371 - 9 | 28.8968307405967 (10 rows) -select ss, stddev(cfloat4) from aggfns group by ss order by 1; +select ss, stddev(cfloat4) from aggfns group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - 0 | 28.8941380063427 + 0 | 28.7274163912974 + 7 | 28.7892027644318 + 4 | 28.8220943927954 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270614 + | 30.6324072248673 3 | NaN - 4 | 28.89302954083 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301628 - 8 | 28.8963276918371 - 9 | 28.8968307405966 11 | NaN - | 27.2867943876683 (10 rows) -select sum(cfloat4) from aggfns order by 1; +select sum(cfloat4) from aggfns; sum ----- NaN (1 row) -select s, sum(cfloat4) from aggfns group by s order by 1; +select s, sum(cfloat4) from aggfns group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 + 9 | -5854.02 + 4 | -3554.43 + 6 | -122.193 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 2 | Infinity + 1 | NaN (10 rows) -select ss, sum(cfloat4) from aggfns group by ss order by 1; +select ss, sum(cfloat4) from aggfns group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+----------- - 0 | -2642.54 3 | -Infinity - 4 | -2497.17 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 + 9 | -5854.02 + 4 | -3381.84 + 6 | -122.193 + | -26.5209 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 11 | NaN - | -112.402 (10 rows) -select avg(cfloat8) from aggfns order by 1; +select avg(cfloat8) from aggfns; avg -------------------- - -0.131776180773973 + -0.162669734027353 (1 row) -select s, avg(cfloat8) from aggfns group by s order by 1; - s | avg ----+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select ss, avg(cfloat8) from aggfns group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.131261021163082 - 3 | -0.128550004763072 - 4 | -0.129264304572168 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 - 11 | -0.131587538323368 - | -4.30903203025656 -(10 rows) - -select max(cfloat8) from aggfns order by 1; - max ------------------ - 49.997744965367 +select s, avg(cfloat8) from aggfns group by s order by avg(cfloat8), s limit 10; + s | avg +---+----------------------- + 8 | -0.607624531147303 + 7 | -0.454194548579399 + 9 | -0.448788876848994 + 3 | -0.364286396751413 + 0 | -0.306925132697215 + 1 | -0.0518103775125928 + 6 | -4.20950399711728e-05 + 5 | 0.0180876209540293 + 4 | 0.032399496253347 + 2 | 0.55648750109598 +(10 rows) + +select ss, avg(cfloat8) from aggfns group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+----------------------- + | -6.85744955032868 + 8 | -0.607624531147303 + 7 | -0.454194548579399 + 9 | -0.448788876848994 + 3 | -0.358112026103399 + 0 | -0.306925132697215 + 6 | -4.20950399711728e-05 + 5 | 0.0180876209540293 + 4 | 0.0258167200477049 + 11 | 0.25552084043733 +(10 rows) + +select max(cfloat8) from aggfns; + max +------------------ + 49.9996809987351 (1 row) -select s, max(cfloat8) from aggfns group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns group by ss order by 1; +select s, max(cfloat8) from aggfns group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 1 | 49.9971219105646 + 2 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select ss, max(cfloat8) from aggfns group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - 0 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 - 11 | 49.997744965367 - | 49.2015035590157 -(10 rows) - -select min(cfloat8) from aggfns order by 1; + | 41.8287402018905 + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 11 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select min(cfloat8) from aggfns; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns group by s order by 1; +select s, min(cfloat8) from aggfns group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns group by ss order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 1 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + 2 | -49.9854512279853 +(10 rows) + +select ss, min(cfloat8) from aggfns group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- - 0 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 - 11 | -49.9755693599582 - | -38.3512130472809 -(10 rows) - -select stddev(cfloat8) from aggfns order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 11 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + | -40.4587021796033 +(10 rows) + +select stddev(cfloat8) from aggfns; stddev ----------------- - 28.894749851557 + 28.892061623641 (1 row) -select s, stddev(cfloat8) from aggfns group by s order by 1; +select s, stddev(cfloat8) from aggfns group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840889 - 5 | 28.8960532056264 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select ss, stddev(cfloat8) from aggfns group by ss order by 1; + 8 | 28.785076111741 + 9 | 28.7991243564982 + 4 | 28.8027578036838 + 7 | 28.8638207913961 + 2 | 28.871977070659 + 3 | 28.8844659681246 + 1 | 28.9470128733139 + 0 | 28.965342556856 + 5 | 28.9663806098752 + 6 | 29.0218963292706 +(10 rows) + +select ss, stddev(cfloat8) from aggfns group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - 0 | 28.893219634188 - 3 | 28.8988694216911 - 4 | 28.8937408619903 - 5 | 28.8960532056265 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 - 11 | 28.8954978116663 - | 24.556507133269 -(10 rows) - -select sum(cfloat8) from aggfns order by 1; + | 27.2393448599587 + 8 | 28.7850761117411 + 9 | 28.7991243564982 + 4 | 28.8000379619243 + 7 | 28.863820791396 + 3 | 28.8859339629585 + 11 | 28.9120343325061 + 0 | 28.9653425568561 + 5 | 28.9663806098753 + 6 | 29.0218963292706 +(10 rows) + +select sum(cfloat8) from aggfns; sum ------------------- - -26355.2361547947 + -32533.9468054706 (1 row) -select s, sum(cfloat8) from aggfns group by s order by 1; - s | sum ----+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select ss, sum(cfloat8) from aggfns group by ss order by 1; - ss | sum -----+------------------- - 0 | -2625.22042326164 - 3 | -2568.55764517095 - 4 | -2582.83006965648 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 - 11 | -5266.00169616286 - | -81.8716085748747 -(10 rows) - -select avg(cint2) from aggfns order by 1; +select s, sum(cfloat8) from aggfns group by s order by sum(cfloat8), s limit 10; + s | sum +---+-------------------- + 8 | -12152.4906229461 + 7 | -9083.89097158797 + 9 | -8975.77753697988 + 3 | -7285.72793502826 + 0 | -6138.50265394431 + 1 | -1036.20755025186 + 6 | -0.841900799423456 + 5 | 361.752419080585 + 4 | 647.98992506694 + 2 | 11129.7500219196 +(10 rows) + +select ss, sum(cfloat8) from aggfns group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+-------------------- + 8 | -12152.4906229461 + 7 | -9083.89097158797 + 9 | -8975.77753697988 + 3 | -7155.43639357202 + 0 | -6138.50265394431 + | -130.291541456245 + 6 | -0.841900799423456 + 5 | 361.752419080585 + 4 | 515.843883273192 + 11 | 10225.6885134615 +(10 rows) + +select avg(cint2) from aggfns; avg ---------------------- - -42.1591712126520194 + -33.1461788699264301 (1 row) -select s, avg(cint2) from aggfns group by s order by 1; - s | avg ----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select ss, avg(cint2) from aggfns group by ss order by 1; - ss | avg -----+----------------------- - 0 | -42.2972824182973825 - 3 | -42.6071034966436229 - 4 | -40.0837090471896604 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 - 11 | -42.9734623946374528 - | -335.0000000000000000 -(10 rows) - -select count(cint2) from aggfns order by 1; +select s, avg(cint2) from aggfns group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 2 | -158.3178019118162254 + 8 | -129.4959711726139833 + 3 | -95.7656773935238477 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 4 | -28.7127771382813673 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 1 | 91.9493518842900756 + 5 | 110.0305290025524248 +(10 rows) + +select ss, avg(cint2) from aggfns group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -1368.1578947368421053 + 8 | -129.4959711726139833 + 3 | -94.5546037471195271 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 11 | -33.7550336409794652 + 4 | -27.5652740206392145 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 5 | 110.0305290025524248 +(10 rows) + +select count(cint2) from aggfns; count -------- 199810 (1 row) -select count(cint2) filter (where cint4 > 0) from aggfns order by 1; - count -------- - 99342 -(1 row) - -select s, count(cint2) from aggfns group by s order by 1; +select s, count(cint2) from aggfns group by s order by count(cint2), s limit 10; s | count ---+------- 0 | 19981 @@ -747,757 +684,640 @@ select s, count(cint2) from aggfns group by s order by 1; 9 | 19981 (10 rows) -select s, count(cint2) filter (where cint4 > 0) from aggfns group by s order by 1; - s | count ----+------- - 0 | 9936 - 1 | 9935 - 2 | 9935 - 3 | 9934 - 4 | 9933 - 5 | 9933 - 6 | 9932 - 7 | 9936 - 8 | 9933 - 9 | 9935 -(10 rows) - -select ss, count(cint2) from aggfns group by ss order by 1; +select ss, count(cint2) from aggfns group by ss order by count(cint2), ss limit 10; ss | count ----+------- - 0 | 19981 + | 19 3 | 19962 4 | 19962 + 0 | 19981 5 | 19981 6 | 19981 7 | 19981 8 | 19981 9 | 19981 11 | 39981 - | 19 -(10 rows) - -select ss, count(cint2) filter (where cint4 > 0) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 9936 - 3 | 9928 - 4 | 9922 - 5 | 9933 - 6 | 9932 - 7 | 9936 - 8 | 9933 - 9 | 9935 - 11 | 19881 - | 6 -(10 rows) - -select x, count(cint2) from aggfns group by x order by 1; - x | count -----+------- - 0 | 19981 - 11 | 39981 - 3 | 19962 - 4 | 19962 - 5 | 19981 - 6 | 19981 - 7 | 19981 - 8 | 19981 - 9 | 19981 - | 19 (10 rows) -select max(cint2) from aggfns order by 1; +select max(cint2) from aggfns; max ------- 16383 (1 row) -select s, max(cint2) from aggfns group by s order by 1; +select s, max(cint2) from aggfns group by s order by max(cint2), s limit 10; s | max ---+------- + 3 | 16380 + 2 | 16381 + 5 | 16381 + 7 | 16381 + 8 | 16382 0 | 16383 1 | 16383 - 2 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns group by ss order by 1; +select ss, max(cint2) from aggfns group by ss order by max(cint2), ss limit 10; ss | max ----+------- + | 16362 + 3 | 16380 + 5 | 16381 + 7 | 16381 + 8 | 16382 0 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 9 | 16383 11 | 16383 - | 13720 (10 rows) -select min(cint2) from aggfns order by 1; +select min(cint2) from aggfns; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns group by s order by 1; +select s, min(cint2) from aggfns group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns group by ss order by 1; +select ss, min(cint2) from aggfns group by ss order by min(cint2), ss limit 10; ss | min ----+-------- - 0 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 9 | -16375 - 11 | -16375 - | -15206 + | -16100 (10 rows) -select stddev(cint2) from aggfns order by 1; +select stddev(cint2) from aggfns; stddev ------------------- - 9467.689085960139 + 9475.597346265432 (1 row) -select s, stddev(cint2) from aggfns group by s order by 1; +select s, stddev(cint2) from aggfns group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select ss, stddev(cint2) from aggfns group by ss order by 1; + 9 | 9450.322790943425 + 2 | 9458.737760855119 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9473.424234931108 + 8 | 9477.586839536066 + 4 | 9483.720025499142 + 0 | 9484.907423282680 + 1 | 9528.039076724276 +(10 rows) + +select ss, stddev(cint2) from aggfns group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+------------------- - 0 | 9468.854793575036 - 3 | 9466.351508971864 - 4 | 9469.021659499615 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 - 11 | 9467.946206136906 - | 9796.780548277639 -(10 rows) - -select sum(cint2) from aggfns order by 1; + | 8413.549166956554 + 9 | 9450.322790943425 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9474.482349111595 + 8 | 9477.586839536066 + 4 | 9483.611454519949 + 0 | 9484.907423282680 + 11 | 9494.206429493352 +(10 rows) + +select sum(cint2) from aggfns; sum ---------- - -8423824 -(1 row) - -select sum(cint2) filter (where cint4 > 0) from aggfns order by 1; - sum ------------ - -17618159 + -6622938 (1 row) -select s, sum(cint2) from aggfns group by s order by 1; - s | sum ----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns group by s order by 1; +select s, sum(cint2) from aggfns group by s order by sum(cint2), s limit 10; s | sum ---+---------- - 0 | -1788968 - 1 | -1806454 - 2 | -1747433 - 3 | -1738178 - 4 | -1717456 - 5 | -1788759 - 6 | -1746163 - 7 | -1731851 - 8 | -1741688 - 9 | -1811209 -(10 rows) - -select ss, sum(cint2) from aggfns group by ss order by 1; - ss | sum -----+---------- - 0 | -845142 - 3 | -850523 - 4 | -800151 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 - 11 | -1718122 - | -6365 -(10 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns group by ss order by 1; + 2 | -3163348 + 8 | -2587459 + 3 | -1913494 + 6 | -1220352 + 7 | -1116329 + 4 | -573710 + 9 | -435575 + 0 | 351569 + 1 | 1837240 + 5 | 2198520 +(10 rows) + +select ss, sum(cint2) from aggfns group by ss order by sum(cint2), ss limit 10; ss | sum ----+---------- - 0 | -1788968 - 3 | -1737816 - 4 | -1696920 - 5 | -1788759 - 6 | -1746163 - 7 | -1731851 - 8 | -1741688 - 9 | -1811209 - 11 | -3574423 - | -362 -(10 rows) - -select avg(cint4) from aggfns order by 1; - avg ------------------------ - -2833327.786810000000 + 8 | -2587459 + 3 | -1887499 + 11 | -1349560 + 6 | -1220352 + 7 | -1116329 + 4 | -550258 + 9 | -435575 + | -25995 + 0 | 351569 + 5 | 2198520 +(10 rows) + +select avg(cint4) from aggfns; + avg +--------------------- + -4.9369150000000000 (1 row) -select s, avg(cint4) from aggfns group by s order by 1; +select s, avg(cint4) from aggfns group by s order by avg(cint4), s limit 10; s | avg ---+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select ss, avg(cint4) from aggfns group by ss order by 1; + 9 | -102.4283000000000000 + 2 | -101.3952000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 4 | 6.6530500000000000 + 0 | 27.7536500000000000 + 3 | 70.4102500000000000 + 1 | 71.5608500000000000 + 5 | 103.1069000000000000 +(10 rows) + +select ss, avg(cint4) from aggfns group by ss order by avg(cint4), ss limit 10; ss | avg ----+----------------------- - 0 | -2919248.121000000000 - 3 | -2682566.613082428307 - 4 | -2753845.761523447275 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 - 11 | -2846001.238586671331 - | -146005017.57894737 -(10 rows) - -select max(cint4) from aggfns order by 1; - max ------------- - 1073660631 + 9 | -102.4283000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 11 | -16.4247732327144606 + 4 | 9.6930584054852110 + 0 | 27.7536500000000000 + 3 | 68.3874180471447875 + 5 | 103.1069000000000000 + | 2197.6842105263157895 +(10 rows) + +select max(cint4) from aggfns; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 978482473 -(10 rows) - -select min(cint4) from aggfns order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -960881516 -(10 rows) - -select stddev(cint4) from aggfns order by 1; - stddev ------------ - 620480022 +select s, max(cint4) from aggfns group by s order by max(cint4), s limit 10; + s | max +---+------- + 3 | 16379 + 5 | 16379 + 7 | 16379 + 2 | 16381 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 +(10 rows) + +select ss, max(cint4) from aggfns group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + +select min(cint4) from aggfns; + min +-------- + -16383 (1 row) -select s, stddev(cint4) from aggfns group by s order by 1; - s | stddev ----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select ss, stddev(cint4) from aggfns group by ss order by 1; - ss | stddev -----+----------- - 0 | 620497458 - 3 | 620502162 - 4 | 620460588 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 - 11 | 620490348 - | 569369090 -(10 rows) - -select sum(cint4) from aggfns order by 1; - sum ---------------- - -566665557362 -(1 row) - -select sum(cint4) filter (where cint4 > 0) from aggfns order by 1; - sum ----------------- - 53436167838463 -(1 row) - -select s, sum(cint4) from aggfns group by s order by 1; - s | sum ----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select s, sum(cint4) filter (where cint4 > 0) from aggfns group by s order by 1; - s | sum ----+--------------- - 0 | 5342690615367 - 1 | 5343370718252 - 2 | 5343352005654 - 3 | 5343352005654 - 4 | 5344281595944 - 5 | 5343480575409 - 6 | 5343480575409 - 7 | 5344006156678 - 8 | 5344006156678 - 9 | 5344147433418 -(10 rows) - -select ss, sum(cint4) from aggfns group by ss order by 1; - ss | sum -----+--------------- - 0 | -58384962420 - 3 | -53600363496 - 4 | -55024592161 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 - 11 | -113894123567 - | -2774095334 -(10 rows) - -select ss, sum(cint4) filter (where cint4 > 0) from aggfns group by ss order by 1; - ss | sum -----+---------------- - 0 | 5342690615367 - 3 | 5340469357420 - 4 | 5338771617836 - 5 | 5343480575409 - 6 | 5343480575409 - 7 | 5344006156678 - 8 | 5344006156678 - 9 | 5344147433418 - 11 | 10692232702014 - | 2882648234 -(10 rows) - -select avg(cint8) from aggfns order by 1; - avg ------------------------ - -2823388.766060000000 +select s, min(cint4) from aggfns group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select ss, min(cint4) from aggfns group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 + | -15907 +(10 rows) + +select stddev(cint4) from aggfns; + stddev +------------------- + 9450.334382392243 +(1 row) + +select s, stddev(cint4) from aggfns group by s order by stddev(cint4), s limit 10; + s | stddev +---+------------------- + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 2 | 9440.675087350597 + 4 | 9443.098516157448 + 8 | 9450.281544631633 + 1 | 9459.538662433945 + 3 | 9474.762271621918 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select ss, stddev(cint4) from aggfns group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + | 9361.317298404296 + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 4 | 9442.480718256247 + 8 | 9450.281544631633 + 11 | 9450.690059613938 + 3 | 9474.873657491443 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select sum(cint4) from aggfns; + sum +--------- + -987383 (1 row) -select s, avg(cint8) from aggfns group by s order by 1; +select s, sum(cint4) from aggfns group by s order by sum(cint4), s limit 10; + s | sum +---+---------- + 9 | -2048566 + 2 | -2027904 + 6 | -1063133 + 7 | -852243 + 8 | -585231 + 4 | 133061 + 0 | 555073 + 3 | 1408205 + 1 | 1431217 + 5 | 2062138 +(10 rows) + +select ss, sum(cint4) from aggfns group by ss order by sum(cint4), ss limit 10; + ss | sum +----+---------- + 9 | -2048566 + 6 | -1063133 + 7 | -852243 + 11 | -657303 + 8 | -585231 + | 41756 + 4 | 193677 + 0 | 555073 + 3 | 1366449 + 5 | 2062138 +(10 rows) + +select avg(cint8) from aggfns; + avg +---------------------- + -12.1026800000000000 +(1 row) + +select s, avg(cint8) from aggfns group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select ss, avg(cint8) from aggfns group by ss order by 1; + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 1 | -25.4401500000000000 + 4 | -19.5071500000000000 + 2 | -2.4691500000000000 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 39.9743500000000000 + 9 | 61.7467500000000000 +(10 rows) + +select ss, avg(cint8) from aggfns group by ss order by avg(cint8), ss limit 10; ss | avg ----+----------------------- - 0 | -2836378.364750000000 - 3 | -2653999.743206045743 - 4 | -3009394.583854661929 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 - 11 | -2748620.862390364577 - | -127121035.31578947 -(10 rows) - -select max(cint8) from aggfns order by 1; - max ------------- - 1073660631 + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 4 | -17.0811771182623492 + 11 | -15.1685449411529523 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 37.6662329212752115 + 9 | 61.7467500000000000 + | 2467.2631578947368421 +(10 rows) + +select max(cint8) from aggfns; + max +------- + 16383 (1 row) -select s, max(cint8) from aggfns group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 989667573 -(10 rows) - -select min(cint8) from aggfns order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -796158533 -(10 rows) - -select sum(cint8) from aggfns order by 1; - sum ---------------- - -564677753212 -(1 row) - -select s, sum(cint8) from aggfns group by s order by 1; - s | sum ----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select ss, sum(cint8) from aggfns group by ss order by 1; - ss | sum -----+--------------- - 0 | -56727567295 - 3 | -53029568869 - 4 | -60130713180 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 - 11 | -109997058292 - | -2415299671 -(10 rows) - -select max(cts) from aggfns order by 1; +select s, max(cint8) from aggfns group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16379 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 5 | 16383 +(10 rows) + +select ss, max(cint8) from aggfns group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 4 | 16383 + 5 | 16383 + 11 | 16383 +(10 rows) + +select min(cint8) from aggfns; + min +-------- + -16383 +(1 row) + +select s, min(cint8) from aggfns group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 2 | -16379 + 3 | -16378 +(10 rows) + +select ss, min(cint8) from aggfns group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 3 | -16378 + | -14174 +(10 rows) + +select sum(cint8) from aggfns; + sum +---------- + -2420536 +(1 row) + +select s, sum(cint8) from aggfns group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -2369740 + 5 | -1633911 + 1 | -508803 + 4 | -390143 + 2 | -49383 + 7 | -47127 + 6 | 238113 + 0 | 306036 + 3 | 799487 + 9 | 1234935 +(10 rows) + +select ss, sum(cint8) from aggfns group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -2369740 + 5 | -1633911 + 11 | -607030 + 4 | -341299 + 7 | -47127 + | 46878 + 6 | 238113 + 0 | 306036 + 3 | 752609 + 9 | 1234935 +(10 rows) + +select max(cts) from aggfns; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns group by s order by 1; +select s, max(cts) from aggfns group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, max(cts) from aggfns group by ss order by max(cts), ss limit 10; ss | max ----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 - 11 | Fri Jan 01 17:27:33 2021 - | Fri Jan 01 14:45:52 2021 -(10 rows) - -select min(cts) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns group by s order by 1; +select s, min(cts) from aggfns group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, min(cts) from aggfns group by ss order by min(cts), ss limit 10; ss | min ----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 - 11 | Fri Jan 01 03:47:42 2021 - | Fri Jan 01 09:29:58 2021 -(10 rows) - -select max(ctstz) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns group by s order by 1; +select s, max(ctstz) from aggfns group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, max(ctstz) from aggfns group by ss order by max(ctstz), ss limit 10; ss | max ----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST - 11 | Fri Jan 01 17:27:33 2021 PST - | Fri Jan 01 14:45:52 2021 PST -(10 rows) - -select min(ctstz) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns group by s order by 1; +select s, min(ctstz) from aggfns group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, min(ctstz) from aggfns group by ss order by min(ctstz), ss limit 10; ss | min ----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST - 11 | Fri Jan 01 03:47:42 2021 PST - | Fri Jan 01 09:29:58 2021 PST -(10 rows) - -select avg(s) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns; avg -------------------- 4.5000000000000000 (1 row) -select s, avg(s) from aggfns group by s order by 1; +select s, avg(s) from aggfns group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 @@ -1512,34 +1332,28 @@ select s, avg(s) from aggfns group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns group by ss order by 1; +select ss, avg(s) from aggfns group by ss order by avg(s), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 + 11 | 1.5011869362053025 3 | 3.0000000000000000 + | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 - 11 | 1.5011869362053025 - | 3.0000000000000000 (10 rows) -select count(s) from aggfns order by 1; +select count(s) from aggfns; count -------- 200000 (1 row) -select count(s) filter (where cint4 > 0) from aggfns order by 1; - count -------- - 99428 -(1 row) - -select s, count(s) from aggfns group by s order by 1; +select s, count(s) from aggfns group by s order by count(s), s limit 10; s | count ---+------- 0 | 20000 @@ -1554,58 +1368,28 @@ select s, count(s) from aggfns group by s order by 1; 9 | 20000 (10 rows) -select s, count(s) filter (where cint4 > 0) from aggfns group by s order by 1; - s | count ----+------- - 0 | 9942 - 1 | 9943 - 2 | 9943 - 3 | 9943 - 4 | 9943 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 -(10 rows) - -select ss, count(s) from aggfns group by ss order by 1; +select ss, count(s) from aggfns group by ss order by count(s), ss limit 10; ss | count ----+------- - 0 | 20000 + | 19 3 | 19981 4 | 19981 + 0 | 20000 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 11 | 40019 - | 19 (10 rows) -select ss, count(s) filter (where cint4 > 0) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 9942 - 3 | 9937 - 4 | 9932 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 - 11 | 19897 - | 6 -(10 rows) - -select max(s) from aggfns order by 1; +select max(s) from aggfns; max ----- 9 (1 row) -select s, max(s) from aggfns group by s order by 1; +select s, max(s) from aggfns group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -1620,28 +1404,28 @@ select s, max(s) from aggfns group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns group by ss order by 1; +select ss, max(s) from aggfns group by ss order by max(s), ss limit 10; ss | max ----+----- 0 | 0 3 | 3 + | 3 4 | 4 + 11 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 4 - | 3 (10 rows) -select min(s) from aggfns order by 1; +select min(s) from aggfns; min ----- 0 (1 row) -select s, min(s) from aggfns group by s order by 1; +select s, min(s) from aggfns group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -1656,28 +1440,28 @@ select s, min(s) from aggfns group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns group by ss order by 1; +select ss, min(s) from aggfns group by ss order by min(s), ss limit 10; ss | min ----+----- 0 | 0 + 11 | 1 3 | 3 + | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 1 - | 3 (10 rows) -select stddev(s) from aggfns order by 1; +select stddev(s) from aggfns; stddev -------------------- 2.8722885039992502 (1 row) -select s, stddev(s) from aggfns group by s order by 1; +select s, stddev(s) from aggfns group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -1692,7 +1476,7 @@ select s, stddev(s) from aggfns group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns group by ss order by 1; +select ss, stddev(s) from aggfns group by ss order by stddev(s), ss limit 10; ss | stddev ----+------------------------ 0 | 0 @@ -1703,17 +1487,17 @@ select ss, stddev(s) from aggfns group by ss order by 1; 7 | 0 8 | 0 9 | 0 - 11 | 0.50284545977155885187 | 0 + 11 | 0.50284545977155885187 (10 rows) -select sum(s) from aggfns order by 1; +select sum(s) from aggfns; sum -------- 900000 (1 row) -select s, sum(s) from aggfns group by s order by 1; +select s, sum(s) from aggfns group by s order by sum(s), s limit 10; s | sum ---+-------- 0 | 0 @@ -1728,33 +1512,31 @@ select s, sum(s) from aggfns group by s order by 1; 9 | 180000 (10 rows) -select ss, sum(s) from aggfns group by ss order by 1; +select ss, sum(s) from aggfns group by ss order by sum(s), ss limit 10; ss | sum ----+-------- 0 | 0 + | 57 3 | 59943 + 11 | 60076 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 - 11 | 60076 - | 57 (10 rows) -select avg(ss) from aggfns order by 1; +select avg(ss) from aggfns; avg -------------------- 6.4009880938689175 (1 row) -select s, avg(ss) from aggfns group by s order by 1; +select s, avg(ss) from aggfns group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 11.0000000000000000 - 2 | 11.0000000000000000 3 | 3.0000000000000000 4 | 4.0066500000000000 5 | 5.0000000000000000 @@ -1762,9 +1544,11 @@ select s, avg(ss) from aggfns group by s order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns group by ss order by 1; +select ss, avg(ss) from aggfns group by ss order by avg(ss), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 @@ -1779,28 +1563,28 @@ select ss, avg(ss) from aggfns group by ss order by 1; | (10 rows) -select max(ss) from aggfns order by 1; +select max(ss) from aggfns; max ----- 11 (1 row) -select s, max(ss) from aggfns group by s order by 1; +select s, max(ss) from aggfns group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 - 4 | 11 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns group by ss order by 1; +select ss, max(ss) from aggfns group by ss order by max(ss), ss limit 10; ss | max ----+----- 0 | 0 @@ -1815,18 +1599,16 @@ select ss, max(ss) from aggfns group by ss order by 1; | (10 rows) -select min(ss) from aggfns order by 1; +select min(ss) from aggfns; min ----- 0 (1 row) -select s, min(ss) from aggfns group by s order by 1; +select s, min(ss) from aggfns group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 4 | 4 5 | 5 @@ -1834,9 +1616,11 @@ select s, min(ss) from aggfns group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns group by ss order by 1; +select ss, min(ss) from aggfns group by ss order by min(ss), ss limit 10; ss | min ----+----- 0 | 0 @@ -1851,28 +1635,28 @@ select ss, min(ss) from aggfns group by ss order by 1; | (10 rows) -select stddev(ss) from aggfns order by 1; +select stddev(ss) from aggfns; stddev -------------------- 3.3528328280068652 (1 row) -select s, stddev(ss) from aggfns group by s order by 1; +select s, stddev(ss) from aggfns group by s order by stddev(ss), s limit 10; s | stddev ---+------------------------ 0 | 0 1 | 0 2 | 0 3 | 0 - 4 | 0.21565737387148452722 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 + 4 | 0.21565737387148452722 (10 rows) -select ss, stddev(ss) from aggfns group by ss order by 1; +select ss, stddev(ss) from aggfns group by ss order by stddev(ss), ss limit 10; ss | stddev ----+-------- 0 | 0 @@ -1887,18 +1671,16 @@ select ss, stddev(ss) from aggfns group by ss order by 1; | (10 rows) -select sum(ss) from aggfns order by 1; +select sum(ss) from aggfns; sum --------- 1280076 (1 row) -select s, sum(ss) from aggfns group by s order by 1; +select s, sum(ss) from aggfns group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 220000 - 2 | 220000 3 | 59943 4 | 80133 5 | 100000 @@ -1906,9 +1688,11 @@ select s, sum(ss) from aggfns group by s order by 1; 7 | 140000 8 | 160000 9 | 180000 + 1 | 220000 + 2 | 220000 (10 rows) -select ss, sum(ss) from aggfns group by ss order by 1; +select ss, sum(ss) from aggfns group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 @@ -1923,13 +1707,13 @@ select ss, sum(ss) from aggfns group by ss order by 1; | (10 rows) -select max(t) from aggfns order by 1; +select max(t) from aggfns; max -------- 110000 (1 row) -select s, max(t) from aggfns group by s order by 1; +select s, max(t) from aggfns group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 @@ -1944,28 +1728,28 @@ select s, max(t) from aggfns group by s order by 1; 9 | 110000 (10 rows) -select ss, max(t) from aggfns group by ss order by 1; +select ss, max(t) from aggfns group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 20000 + | 49491 3 | 50000 + 11 | 59192 4 | 60000 5 | 70000 6 | 80000 7 | 90000 8 | 100000 9 | 110000 - 11 | 59192 - | 49491 (10 rows) -select min(t) from aggfns order by 1; +select min(t) from aggfns; min ----- 1 (1 row) -select s, min(t) from aggfns group by s order by 1; +select s, min(t) from aggfns group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 @@ -1980,1354 +1764,1180 @@ select s, min(t) from aggfns group by s order by 1; 9 | 90001 (10 rows) -select ss, min(t) from aggfns group by ss order by 1; +select ss, min(t) from aggfns group by ss order by min(t), ss limit 10; ss | min ----+------- 0 | 1 + 11 | 10001 3 | 30001 + | 30537 4 | 40001 5 | 50001 6 | 60001 7 | 70001 8 | 80001 9 | 90001 - 11 | 10001 - | 30537 (10 rows) -select count(*) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99430 -(1 row) - -select count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; +select count(*) from aggfns where cfloat8 > 0; count ------- - 49288 + 99508 (1 row) -select s, count(*) from aggfns where cfloat8 > 0 group by s order by 1; +select s, count(*) from aggfns where cfloat8 > 0 group by s order by count(*), s limit 10; s | count ---+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 4928 - 1 | 4929 - 2 | 4928 - 3 | 4928 - 4 | 4929 - 5 | 4929 - 6 | 4929 - 7 | 4929 - 8 | 4929 - 9 | 4930 -(10 rows) - -select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by 1; + 8 | 9788 + 7 | 9873 + 9 | 9879 + 0 | 9881 + 3 | 9902 + 1 | 9959 + 6 | 10004 + 5 | 10009 + 4 | 10038 + 2 | 10175 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by count(*), ss limit 10; ss | count ----+------- - 0 | 9943 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 - 11 | 19896 - | 8 -(10 rows) - -select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 4928 - 3 | 4925 - 4 | 4922 - 5 | 4929 - 6 | 4929 - 7 | 4929 - 8 | 4929 - 9 | 4930 - 11 | 9864 - | 3 -(10 rows) - -select x, count(*) from aggfns where cfloat8 > 0 group by x order by 1; - x | count -----+------- - 0 | 9943 - 11 | 19896 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 | 8 -(10 rows) - -select max(cdate) from aggfns where cfloat8 > 0 order by 1; + 8 | 9788 + 7 | 9873 + 9 | 9879 + 0 | 9881 + 3 | 9894 + 6 | 10004 + 5 | 10009 + 4 | 10026 + 11 | 20146 +(10 rows) + +select max(cdate) from aggfns where cfloat8 > 0; max ------------ - 03-05-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 > 0 group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-04-2075 - 1 | 02-21-2103 - 2 | 07-08-2130 - 3 | 11-22-2157 - 4 | 04-11-2185 - 5 | 08-27-2212 - 6 | 01-14-2240 - 7 | 05-31-2267 - 8 | 10-15-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by max(cdate), ss limit 10; ss | max ----+------------ - 0 | 10-04-2075 - 3 | 11-22-2157 - 4 | 04-11-2185 - 5 | 08-27-2212 - 6 | 01-14-2240 - 7 | 05-31-2267 - 8 | 10-15-2294 - 9 | 03-05-2322 - 11 | 03-03-2180 - | 07-03-2156 -(10 rows) - -select min(cdate) from aggfns where cfloat8 > 0 order by 1; + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns where cfloat8 > 0; min ------------ - 01-02-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 > 0 group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-11-2075 - 3 | 02-26-2103 - 4 | 07-13-2130 - 5 | 11-27-2157 - 6 | 04-13-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by min(cdate), ss limit 10; ss | min ----+------------ - 0 | 01-02-2021 - 3 | 02-26-2103 - 4 | 07-13-2130 - 5 | 11-27-2157 - 6 | 04-13-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 - 11 | 05-20-2048 - | 05-18-2110 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 > 0 order by 1; - avg ------------ - -Infinity + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns where cfloat8 > 0; + avg +----- + NaN (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+-------------------- - 0 | -0.542617154225893 - 1 | -0.540875748760701 - 2 | -0.541406464808325 - 3 | -Infinity - 4 | -0.544616367218129 - 5 | -0.544616367218129 - 6 | -0.547797322998719 - 7 | -0.547797322998719 - 8 | -0.544139963208192 - 9 | -0.547059247380753 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.542617154225893 - 3 | -Infinity - 4 | -0.545104747625541 - 5 | -0.544616367218129 - 6 | -0.547797322998719 - 7 | -0.547797322998719 - 8 | -0.544139963208192 - 9 | -0.547059247380753 - 11 | -0.540899217374597 - | -1.46971142292023 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; - max ---------- - 49.9734 +select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by avg(cfloat4), s limit 10; + s | avg +---+---------------------- + 3 | -Infinity + 9 | -0.571001239751741 + 4 | -0.553028167922753 + 0 | -0.334856044433109 + 7 | 0.000229969466191699 + 6 | 0.128349247144726 + 5 | 0.259525063716658 + 8 | 0.547502054482631 + 2 | Infinity + 1 | NaN +(10 rows) + +select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+---------------------- + 3 | -Infinity + | -7.18416403234005 + 9 | -0.571001239751741 + 4 | -0.538788339134091 + 0 | -0.334856044433109 + 7 | 0.000229969466191699 + 6 | 0.128349247144726 + 5 | 0.259525063716658 + 8 | 0.547502054482631 + 11 | NaN +(10 rows) + +select max(cfloat4) from aggfns where cfloat8 > 0; + max +----- + NaN (1 row) -select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+--------- - 0 | 49.9734 - 1 | 49.9734 - 2 | 49.9734 - 3 | 49.9734 - 4 | 49.9734 - 5 | 49.9734 - 6 | 49.9734 - 7 | 49.9734 - 8 | 49.9734 - 9 | 49.9734 -(10 rows) - -select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; +select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by max(cfloat4), s limit 10; + s | max +---+---------- + 9 | 49.967 + 0 | 49.9863 + 8 | 49.9869 + 7 | 49.992 + 6 | 49.994 + 4 | 49.9946 + 3 | 49.9979 + 5 | 49.9992 + 2 | Infinity + 1 | NaN +(10 rows) + +select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by max(cfloat4), ss limit 10; ss | max ----+--------- - 0 | 49.9734 - 3 | 49.9734 - 4 | 49.9734 - 5 | 49.9734 - 6 | 49.9734 - 7 | 49.9734 - 8 | 49.9734 - 9 | 49.9734 - 11 | 49.9734 - | 24.3202 -(10 rows) - -select min(cfloat4) from aggfns where cfloat8 > 0 order by 1; + | 47.2047 + 9 | 49.967 + 0 | 49.9863 + 8 | 49.9869 + 7 | 49.992 + 6 | 49.994 + 4 | 49.9946 + 3 | 49.9979 + 5 | 49.9992 + 11 | NaN +(10 rows) + +select min(cfloat4) from aggfns where cfloat8 > 0; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9722 - 1 | -49.9722 - 2 | -49.9722 3 | -Infinity - 4 | -49.9722 - 5 | -49.9722 - 6 | -49.9722 - 7 | -49.9722 - 8 | -49.9722 - 9 | -49.9722 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; + 4 | -49.9999 + 2 | -49.9991 + 6 | -49.9985 + 8 | -49.9969 + 7 | -49.9969 + 0 | -49.9915 + 9 | -49.9911 + 5 | -49.9892 + 1 | -49.9631 +(10 rows) + +select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by min(cfloat4), ss limit 10; ss | min ----+----------- - 0 | -49.9722 3 | -Infinity - 4 | -49.9722 - 5 | -49.9722 - 6 | -49.9722 - 7 | -49.9722 - 8 | -49.9722 - 9 | -49.9722 - 11 | -49.9722 - | -45.111 + 4 | -49.9999 + 6 | -49.9985 + 8 | -49.9969 + 7 | -49.9969 + 0 | -49.9915 + 9 | -49.9911 + 5 | -49.9892 + | -41.6131 + 11 | NaN (10 rows) -select stddev(cfloat4) from aggfns where cfloat8 > 0 order by 1; +select stddev(cfloat4) from aggfns where cfloat8 > 0; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.889048755135 - 1 | 28.8872257367626 - 2 | 28.8886301576555 + 9 | 28.674138151974 + 0 | 28.7315562731003 + 7 | 28.732480405586 + 5 | 28.8919716001815 + 6 | 28.910903762573 + 8 | 28.9950881019358 + 4 | 29.0042743342058 + 1 | NaN + 2 | NaN 3 | NaN - 4 | 28.8889504423898 - 5 | 28.8889504423898 - 6 | 28.8892391773513 - 7 | 28.8892391773513 - 8 | 28.8883896891409 - 9 | 28.8893600799806 (10 rows) -select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - 0 | 28.889048755135 + | 28.5013049189088 + 9 | 28.674138151974 + 0 | 28.7315562731003 + 7 | 28.732480405586 + 5 | 28.8919716001816 + 6 | 28.9109037625729 + 4 | 28.9941139499009 + 8 | 28.9950881019358 3 | NaN - 4 | 28.8896204728232 - 5 | 28.8889504423898 - 6 | 28.8892391773513 - 7 | 28.8892391773513 - 8 | 28.8883896891408 - 9 | 28.8893600799806 - 11 | 28.886867950284 - | 23.0946953685783 -(10 rows) - -select sum(cfloat4) from aggfns where cfloat8 > 0 order by 1; - sum ------------ - -Infinity + 11 | NaN +(10 rows) + +select sum(cfloat4) from aggfns where cfloat8 > 0; + sum +----- + NaN (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -5395.24 - 1 | -5377.93 - 2 | -5382.66 3 | -Infinity - 4 | -5415.12 - 5 | -5415.12 - 6 | -5447.3 - 7 | -5447.3 - 8 | -5410.38 - 9 | -5439.41 + 9 | -5640.92 + 4 | -5551.3 + 0 | -3308.71 + 7 | 2.27051 + 6 | 1284.01 + 5 | 2597.59 + 8 | 5358.95 + 2 | Infinity + 1 | NaN (10 rows) -select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+----------- - 0 | -5395.24 3 | -Infinity - 4 | -5413.98 - 5 | -5415.12 - 6 | -5447.3 - 7 | -5447.3 - 8 | -5410.38 - 9 | -5439.41 - 11 | -10761.7 - | -11.7577 + 9 | -5640.92 + 4 | -5401.89 + 0 | -3308.71 + | -57.4733 + 7 | 2.27049 + 6 | 1284.01 + 5 | 2597.59 + 8 | 5358.95 + 11 | NaN (10 rows) -select avg(cfloat8) from aggfns where cfloat8 > 0 order by 1; +select avg(cfloat8) from aggfns where cfloat8 > 0; avg ------------------ - 25.0275627282681 + 24.9952835571616 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------ - 0 | 25.0253254492148 - 1 | 25.0296791394684 - 2 | 25.0284447917954 - 3 | 25.0284447917954 - 4 | 25.0283891332554 - 5 | 25.0283891332554 - 6 | 25.0265337956144 - 7 | 25.0265337956144 - 8 | 25.0286117211772 - 9 | 25.0252759158804 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; + 9 | 24.7725645778889 + 4 | 24.8521087115606 + 8 | 24.8544030681421 + 3 | 24.8618573121353 + 7 | 24.8695268926044 + 0 | 25.0776526587937 + 5 | 25.1286151190947 + 1 | 25.1502211388742 + 2 | 25.1714788850795 + 6 | 25.2046932748616 +(10 rows) + +select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat8), ss limit 10; ss | avg ----+------------------ - 0 | 25.0253254492148 - 3 | 25.0326248798677 - 4 | 25.0314280577154 - 5 | 25.0283891332554 - 6 | 25.0265337956144 - 7 | 25.0265337956144 - 8 | 25.0286117211772 - 9 | 25.0252759158804 - 11 | 25.0275446062773 - | 19.8378204280743 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 > 0 order by 1; - max ------------------ - 49.997744965367 + | 19.1114503482822 + 9 | 24.7725645778889 + 4 | 24.8486849063598 + 8 | 24.8544030681421 + 3 | 24.8665069235878 + 7 | 24.8695268926044 + 0 | 25.0776526587937 + 5 | 25.1286151190947 + 11 | 25.1624839845733 + 6 | 25.2046932748616 +(10 rows) + +select max(cfloat8) from aggfns where cfloat8 > 0; + max +------------------ + 49.9996809987351 (1 row) -select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; +select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 1 | 49.9971219105646 + 2 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - 0 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 - 11 | 49.997744965367 - | 49.2015035590157 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 > 0 order by 1; - min ---------------------- - 0.00456937123090029 + | 41.8287402018905 + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 11 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select min(cfloat8) from aggfns where cfloat8 > 0; + min +-------------------- + 0.0010170042514801 (1 row) -select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by min(cfloat8), s limit 10; s | min ---+--------------------- - 0 | 0.00456937123090029 - 1 | 0.00456937123090029 - 2 | 0.00456937123090029 - 3 | 0.00456937123090029 - 4 | 0.00456937123090029 - 5 | 0.00456937123090029 - 6 | 0.00456937123090029 - 7 | 0.00456937123090029 - 8 | 0.00456937123090029 - 9 | 0.00456937123090029 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; + 4 | 0.0010170042514801 + 8 | 0.0024349894374609 + 0 | 0.00247885473072529 + 2 | 0.00317355152219534 + 5 | 0.00554935541003942 + 3 | 0.0064867315813899 + 1 | 0.00709095038473606 + 6 | 0.00739246606826782 + 9 | 0.00767894089221954 + 7 | 0.011315057054162 +(10 rows) + +select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by min(cfloat8), ss limit 10; ss | min ----+--------------------- - 0 | 0.00456937123090029 - 3 | 0.00456937123090029 - 4 | 0.00456937123090029 - 5 | 0.00456937123090029 - 6 | 0.00456937123090029 - 7 | 0.00456937123090029 - 8 | 0.00456937123090029 - 9 | 0.00456937123090029 - 11 | 0.00456937123090029 - | 0.0712367007508874 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 > 0 order by 1; + 4 | 0.0010170042514801 + 8 | 0.0024349894374609 + 0 | 0.00247885473072529 + 11 | 0.00317355152219534 + 5 | 0.00554935541003942 + 3 | 0.0064867315813899 + 6 | 0.00739246606826782 + 9 | 0.00767894089221954 + 7 | 0.011315057054162 + | 1.90123561769724 +(10 rows) + +select stddev(cfloat8) from aggfns where cfloat8 > 0; stddev ------------------ - 14.4387600969317 + 14.4329501580672 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 14.4393152148108 - 1 | 14.4397230124184 - 2 | 14.4399246592273 - 3 | 14.4399246592273 - 4 | 14.4391994993402 - 5 | 14.4391994993402 - 6 | 14.4396587086659 - 7 | 14.4396587086659 - 8 | 14.4388979969066 - 9 | 14.4386334818318 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; + 6 | 14.3328227216185 + 2 | 14.3582158038201 + 5 | 14.3890422905482 + 7 | 14.40630591898 + 1 | 14.41953078787 + 9 | 14.4290904798623 + 0 | 14.4509605112521 + 8 | 14.4600764022666 + 3 | 14.518507589479 + 4 | 14.5634752749342 +(10 rows) + +select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - 0 | 14.4393152148108 - 3 | 14.4385675470181 - 4 | 14.4418957208478 - 5 | 14.4391994993402 - 6 | 14.4396587086659 - 7 | 14.4396587086659 - 8 | 14.4388979969066 - 9 | 14.4386334818319 - 11 | 14.4381143863288 - | 16.2202029568666 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 > 0 order by 1; - sum ------------------ - 2488490.5620717 + 6 | 14.3328227216185 + 5 | 14.3890422905482 + 11 | 14.3891033811778 + 7 | 14.40630591898 + 9 | 14.4290904798623 + 0 | 14.4509605112521 + 8 | 14.4600764022666 + 3 | 14.5154972360802 + 4 | 14.5618677753879 + | 18.0721539273599 +(10 rows) + +select sum(cfloat8) from aggfns where cfloat8 > 0; + sum +------------------ + 2487230.67620604 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------ - 0 | 248826.810941542 - 1 | 248870.099683735 - 2 | 248832.79812003 - 3 | 248832.79812003 - 4 | 248857.273151958 - 5 | 248857.273151958 - 6 | 248863.85206359 - 7 | 248863.85206359 - 8 | 248859.486343665 - 9 | 248826.318431599 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; + 8 | 243274.897230975 + 9 | 244728.165464965 + 7 | 245536.839010683 + 3 | 246182.111104764 + 0 | 247792.285921541 + 4 | 249465.467246645 + 1 | 250471.052322048 + 5 | 251512.308727019 + 6 | 252147.751521715 + 2 | 256119.797655684 +(10 rows) + +select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by sum(cfloat8), ss limit 10; ss | sum ----+------------------ - 0 | 248826.810941542 - 3 | 248674.095556606 - 4 | 248612.143469229 - 5 | 248857.273151958 - 6 | 248863.85206359 - 7 | 248863.85206359 - 8 | 248859.486343665 - 9 | 248826.318431599 - 11 | 497948.027486494 - | 158.702563424595 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 > 0 order by 1; - avg ---------------------- - 59.9930038252466277 -(1 row) - -select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+--------------------- - 0 | 62.5336219045701631 - 1 | 61.1402396053558844 - 2 | 64.7349239907379442 - 3 | 60.4202577527184857 - 4 | 58.4389090177133655 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | 62.5336219045701631 - 3 | 59.2794236195082628 - 4 | 60.5569773299748111 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 - 11 | 61.8774966041153092 - | 1475.6250000000000000 -(10 rows) - -select count(cint2) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99340 + | 152.891602786258 + 8 | 243274.897230975 + 9 | 244728.165464965 + 7 | 245536.839010683 + 3 | 246029.219501978 + 0 | 247792.285921541 + 4 | 249132.914871164 + 5 | 251512.308727019 + 6 | 252147.751521715 + 11 | 506923.402353213 +(10 rows) + +select avg(cint2) from aggfns where cfloat8 > 0; + avg +---------------------- + -33.4239400492883368 (1 row) -select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; +select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 2 | -192.2076529608498918 + 8 | -130.5056237218813906 + 6 | -118.4532719631779067 + 7 | -93.6346582843236666 + 9 | -31.1112687474665586 + 4 | -28.4397806580259222 + 3 | 6.3638661409362046 + 0 | 28.7771364925070879 + 5 | 73.4329298789636891 + 1 | 153.3246909858305698 +(10 rows) + +select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -3486.7500000000000000 + 8 | -130.5056237218813906 + 6 | -118.4532719631779067 + 7 | -93.6346582843236666 + 9 | -31.1112687474665586 + 4 | -26.8886005190656818 + 11 | -22.0641860002980774 + 3 | 9.1914398462005464 + 0 | 28.7771364925070879 + 5 | 73.4329298789636891 +(10 rows) + +select count(cint2) from aggfns where cfloat8 > 0; count ------- - 49247 + 99415 (1 row) -select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by count(cint2), s limit 10; s | count ---+------- - 0 | 9934 - 1 | 9933 - 2 | 9933 - 3 | 9932 - 4 | 9936 - 5 | 9933 - 6 | 9935 - 7 | 9933 - 8 | 9937 - 9 | 9934 -(10 rows) - -select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 4926 - 1 | 4925 - 2 | 4924 - 3 | 4922 - 4 | 4925 - 5 | 4923 - 6 | 4925 - 7 | 4924 - 8 | 4927 - 9 | 4926 -(10 rows) - -select ss, count(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 9934 - 3 | 9924 - 4 | 9925 - 5 | 9933 - 6 | 9935 - 7 | 9933 - 8 | 9937 - 9 | 9934 - 11 | 19877 - | 8 -(10 rows) - -select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; + 8 | 9780 + 7 | 9862 + 9 | 9868 + 0 | 9876 + 3 | 9891 + 1 | 9951 + 6 | 9994 + 5 | 9997 + 4 | 10030 + 2 | 10166 +(10 rows) + +select ss, count(cint2) from aggfns where cfloat8 > 0 group by ss order by count(cint2), ss limit 10; ss | count ----+------- - 0 | 4926 - 3 | 4919 - 4 | 4918 - 5 | 4923 - 6 | 4925 - 7 | 4924 - 8 | 4927 - 9 | 4926 - 11 | 9856 - | 3 -(10 rows) - -select x, count(cint2) from aggfns where cfloat8 > 0 group by x order by 1; - x | count -----+------- - 0 | 9934 - 11 | 19877 - 3 | 9924 - 4 | 9925 - 5 | 9933 - 6 | 9935 - 7 | 9933 - 8 | 9937 - 9 | 9934 | 8 -(10 rows) - -select max(cint2) from aggfns where cfloat8 > 0 order by 1; + 8 | 9780 + 7 | 9862 + 9 | 9868 + 0 | 9876 + 3 | 9883 + 6 | 9994 + 5 | 9997 + 4 | 10018 + 11 | 20129 +(10 rows) + +select max(cint2) from aggfns where cfloat8 > 0; max ------- - 16377 + 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by max(cint2), s limit 10; s | max ---+------- - 0 | 16377 - 1 | 16377 - 2 | 16377 - 3 | 16377 - 4 | 16377 - 5 | 16377 - 6 | 16377 - 7 | 16377 + 7 | 16376 8 | 16377 - 9 | 16377 + 3 | 16378 + 2 | 16381 + 5 | 16381 + 6 | 16381 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by max(cint2), ss limit 10; ss | max ----+------- - 0 | 16377 - 3 | 16377 - 4 | 16377 - 5 | 16377 - 6 | 16377 - 7 | 16377 + | 16362 + 7 | 16376 8 | 16377 - 9 | 16377 - 11 | 16377 - | 13720 + 3 | 16378 + 5 | 16381 + 6 | 16381 + 0 | 16383 + 4 | 16383 + 9 | 16383 + 11 | 16383 (10 rows) -select min(cint2) from aggfns where cfloat8 > 0 order by 1; +select min(cint2) from aggfns where cfloat8 > 0; min -------- - -16374 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16374 - 1 | -16374 - 2 | -16374 - 3 | -16374 - 4 | -16374 - 5 | -16374 - 6 | -16374 - 7 | -16374 - 8 | -16374 - 9 | -16374 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 8 | -16382 + 3 | -16381 + 7 | -16380 + 1 | -16375 + 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by min(cint2), ss limit 10; ss | min ----+-------- - 0 | -16374 - 3 | -16374 - 4 | -16374 - 5 | -16374 - 6 | -16374 - 7 | -16374 - 8 | -16374 - 9 | -16374 - 11 | -16374 - | -12426 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 7 | -16380 + 9 | -16375 + | -16100 (10 rows) -select stddev(cint2) from aggfns where cfloat8 > 0 order by 1; +select stddev(cint2) from aggfns where cfloat8 > 0; stddev ------------------- - 9395.467286148261 + 9482.476108257174 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 0 | 9396.868628954375 - 1 | 9397.478004684803 - 2 | 9396.003979674052 - 3 | 9395.588131506675 - 4 | 9395.667525723886 - 5 | 9394.622668940645 - 6 | 9397.336273737402 - 7 | 9394.449892433625 - 8 | 9394.534603851403 - 9 | 9396.374239570388 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; + 7 | 9443.605223480219 + 9 | 9445.366293176026 + 2 | 9449.155608372061 + 5 | 9459.529677447783 + 6 | 9486.777343214059 + 8 | 9492.639754117457 + 4 | 9493.176100060461 + 3 | 9515.443968190559 + 1 | 9518.651130887721 + 0 | 9519.824544774386 +(10 rows) + +select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+------------------- - 0 | 9396.868628954375 - 3 | 9395.145600532270 - 4 | 9398.818234815872 - 5 | 9394.622668940645 - 6 | 9397.336273737402 - 7 | 9394.449892433625 - 8 | 9394.534603851403 - 9 | 9396.374239570388 - 11 | 9394.931149048751 - | 10506.43193392 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 > 0 order by 1; - sum ---------- - 5959705 -(1 row) - -select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; + 7 | 9443.605223480219 + 9 | 9445.366293176026 + 5 | 9459.529677447783 + 11 | 9484.466820490862 + 6 | 9486.777343214059 + 8 | 9492.639754117457 + 4 | 9494.123547409782 + 3 | 9514.580778499309 + 0 | 9519.824544774386 + | 10616.58070796 +(10 rows) + +select sum(cint2) from aggfns where cfloat8 > 0; sum ---------- - -6198630 + -3322841 (1 row) -select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------- - 0 | 621209 - 1 | 607306 - 2 | 643012 - 3 | 600094 - 4 | 580649 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 -(10 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+--------- - 0 | -629182 - 1 | -633190 - 2 | -579865 - 3 | -604326 - 4 | -630147 - 5 | -665070 - 6 | -620684 - 7 | -570776 - 8 | -639376 - 9 | -626014 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+--------- - 0 | 621209 - 3 | 588289 - 4 | 601028 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 - 11 | 1229939 - | 11805 -(10 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; +select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 2 | -1953983 + 8 | -1276345 + 6 | -1183822 + 7 | -923425 + 9 | -307006 + 4 | -285251 + 3 | 62945 + 0 | 284203 + 5 | 734109 + 1 | 1525734 +(10 rows) + +select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by sum(cint2), ss limit 10; ss | sum ----+---------- - 0 | -629182 - 3 | -592786 - 4 | -624445 - 5 | -665070 - 6 | -620684 - 7 | -570776 - 8 | -639376 - 9 | -626014 - 11 | -1218757 - | -11540 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 > 0 order by 1; - avg ------------------------ - -3042925.418565825204 + 8 | -1276345 + 6 | -1183822 + 7 | -923425 + 11 | -444130 + 9 | -307006 + 4 | -269370 + | -27894 + 3 | 90839 + 0 | 284203 + 5 | 734109 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 > 0; + avg +--------------------- + 16.4940105318165374 (1 row) -select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by avg(cint4), s limit 10; s | avg ---+----------------------- - 0 | -3230391.667404203963 - 1 | -3063702.023936437695 - 2 | -3067528.135686984510 - 3 | -3067528.135686984510 - 4 | -2963500.289651010761 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; + 9 | -117.7671829132503290 + 6 | -107.0337864854058377 + 8 | -41.8582958724969350 + 2 | -22.1725798525798526 + 3 | 2.1840032316703696 + 5 | 44.2106104505944650 + 0 | 78.5152312518975812 + 7 | 90.9036766940139775 + 1 | 116.6009639522040365 + 4 | 120.7540346682606097 +(10 rows) + +select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 9 | -117.7671829132503290 + 6 | -107.0337864854058377 + 8 | -41.8582958724969350 + 3 | 2.0119264200525571 + 11 | 43.0645785763923359 + 5 | 44.2106104505944650 + 0 | 78.5152312518975812 + 7 | 90.9036766940139775 + 4 | 127.6853181727508478 + | 215.0000000000000000 +(10 rows) + +select max(cint4) from aggfns where cfloat8 > 0; + max +------- + 16383 +(1 row) + +select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by max(cint4), s limit 10; + s | max +---+------- + 8 | 16378 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16380 + 2 | 16381 + 4 | 16382 + 1 | 16383 + 6 | 16383 + 9 | 16383 +(10 rows) + +select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 8 | 16378 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16380 + 4 | 16382 + 6 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + +select min(cint4) from aggfns where cfloat8 > 0; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 2 | -16383 + 0 | -16382 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 7 | -16382 + 9 | -16382 + 6 | -16381 + 5 | -16380 + 8 | -16370 +(10 rows) + +select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 11 | -16383 + 0 | -16382 + 3 | -16382 + 4 | -16382 + 7 | -16382 + 9 | -16382 + 6 | -16381 + 5 | -16380 + 8 | -16370 + | -15907 +(10 rows) + +select stddev(cint4) from aggfns where cfloat8 > 0; + stddev +------------------- + 9450.307594212300 +(1 row) + +select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by stddev(cint4), s limit 10; + s | stddev +---+------------------- + 0 | 9368.404782340758 + 6 | 9401.528449816030 + 9 | 9409.138533616049 + 1 | 9417.758518179972 + 3 | 9465.021007666210 + 4 | 9468.463171050067 + 8 | 9473.020262302973 + 7 | 9483.434940826228 + 5 | 9496.029307690310 + 2 | 9517.950578375538 +(10 rows) + +select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + 0 | 9368.404782340758 + 6 | 9401.528449816030 + 9 | 9409.138533616049 + 3 | 9464.282001021753 + 4 | 9468.064640965656 + 11 | 9468.713124828893 + 8 | 9473.020262302973 + 7 | 9483.434940826228 + 5 | 9496.029307690310 + | 11050.03141560 +(10 rows) + +select sum(cint4) from aggfns where cfloat8 > 0; + sum +--------- + 1641286 +(1 row) + +select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by sum(cint4), s limit 10; + s | sum +---+---------- + 9 | -1163422 + 6 | -1070766 + 8 | -409709 + 2 | -225606 + 3 | 21626 + 5 | 442504 + 0 | 775809 + 7 | 897492 + 1 | 1161229 + 4 | 1212129 +(10 rows) + +select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by sum(cint4), ss limit 10; + ss | sum +----+---------- + 9 | -1163422 + 6 | -1070766 + 8 | -409709 + | 1720 + 3 | 19906 + 5 | 442504 + 0 | 775809 + 11 | 867579 + 7 | 897492 + 4 | 1280173 +(10 rows) + +select avg(cint8) from aggfns where cfloat8 > 0; + avg +-------------------- + 8.1991196687703501 +(1 row) + +select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by avg(cint8), s limit 10; + s | avg +---+---------------------- + 1 | -96.1673862837634301 + 5 | -90.0727345389149765 + 8 | -59.1858398038414385 + 3 | -12.3414461724904060 + 4 | -2.5818888224745965 + 2 | 21.0509090909090909 + 6 | 35.7028188724510196 + 0 | 42.9815808116587390 + 7 | 64.3715182821837334 + 9 | 179.2666261767385363 +(10 rows) + +select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by avg(cint8), ss limit 10; ss | avg ----+------------------------ - 0 | -3230391.667404203963 - 3 | -2996690.484799677874 - 4 | -3090966.561316955296 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 - 11 | -3001927.897165259349 - | -91030181.125000000000 -(10 rows) - -select max(cint4) from aggfns where cfloat8 > 0 order by 1; - max ------------- - 1073213373 + 5 | -90.0727345389149765 + 8 | -59.1858398038414385 + 11 | -38.8234388960587710 + 3 | -13.0468971093592076 + 4 | 1.26491123079992020746 + 6 | 35.7028188724510196 + 0 | 42.9815808116587390 + 7 | 64.3715182821837334 + 9 | 179.2666261767385363 + | 860.1250000000000000 +(10 rows) + +select max(cint8) from aggfns where cfloat8 > 0; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+------------ - 0 | 1073213373 - 1 | 1073213373 - 2 | 1073213373 - 3 | 1073213373 - 4 | 1073213373 - 5 | 1073213373 - 6 | 1073213373 - 7 | 1073213373 - 8 | 1073213373 - 9 | 1073213373 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073213373 - 3 | 1073213373 - 4 | 1073213373 - 5 | 1073213373 - 6 | 1073213373 - 7 | 1073213373 - 8 | 1073213373 - 9 | 1073213373 - 11 | 1073213373 - | 978482473 -(10 rows) - -select min(cint4) from aggfns where cfloat8 > 0 order by 1; - min -------------- - -1073053412 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | min ----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 - 11 | -1073053412 - | -960881516 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 > 0 order by 1; - stddev ------------ - 622278617 -(1 row) +select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16372 + 8 | 16374 + 0 | 16380 + 6 | 16380 + 7 | 16380 + 3 | 16381 + 9 | 16382 + 1 | 16383 + 4 | 16383 + 5 | 16383 +(10 rows) -select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+----------- - 0 | 622275017 - 1 | 622236051 - 2 | 622267230 - 3 | 622267230 - 4 | 622322391 - 5 | 622322391 - 6 | 622330015 - 7 | 622330015 - 8 | 622360538 - 9 | 622356873 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 622275017 - 3 | 622183925 - 4 | 622245451 - 5 | 622322391 - 6 | 622330015 - 7 | 622330015 - 8 | 622360538 - 9 | 622356873 - 11 | 622274449 - | 762095534 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 > 0 order by 1; - sum ---------------- - -302558074368 -(1 row) - -select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; - sum ----------------- - 26671252627657 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------------- - 0 | -32119784349 - 1 | -30462389224 - 2 | -30497364725 - 3 | -30497364725 - 4 | -29466083380 - 5 | -29466083380 - 6 | -30163080919 - 7 | -30163080919 - 8 | -30062180558 - 9 | -29660662189 -(10 rows) - -select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+--------------- - 0 | 2665908254089 - 1 | 2666588356974 - 2 | 2666553381473 - 3 | 2666553381473 - 4 | 2667584662818 - 5 | 2667584662818 - 6 | 2667584662818 - 7 | 2667584662818 - 8 | 2667584662818 - 9 | 2667725939558 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -32119784349 - 3 | -29769123276 - 4 | -30699479887 - 5 | -29466083380 - 6 | -30163080919 - 7 | -30163080919 - 8 | -30062180558 - 9 | -29660662189 - 11 | -59726357442 - | -728241449 -(10 rows) - -select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+--------------- - 0 | 2665908254089 - 3 | 2664401125147 - 4 | 2663415726889 - 5 | 2667584662818 - 6 | 2667584662818 - 7 | 2667584662818 - 8 | 2667584662818 - 9 | 2667725939558 - 11 | 5337310674376 - | 2152256326 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 > 0 order by 1; - avg ------------------------ - -7287038.185889570552 +select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 8 | 16374 + 0 | 16380 + 6 | 16380 + 7 | 16380 + 3 | 16381 + 9 | 16382 + 4 | 16383 + 5 | 16383 + 11 | 16383 +(10 rows) + +select min(cint8) from aggfns where cfloat8 > 0; + min +-------- + -16383 (1 row) -select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+----------------------- - 0 | -7332793.526098762949 - 1 | -7334675.513225384693 - 2 | -7250229.067592033796 - 3 | -7250229.067592033796 - 4 | -7326050.594790304737 - 5 | -7326050.594790304737 - 6 | -7272459.754123089300 - 7 | -7272459.754123089300 - 8 | -7247017.818163532133 - 9 | -7258411.696771598109 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -7332793.526098762949 - 3 | -7271023.008153815180 - 4 | -7498519.579943616593 - 5 | -7326050.594790304737 - 6 | -7272459.754123089300 - 7 | -7272459.754123089300 - 8 | -7247017.818163532133 - 9 | -7258411.696771598109 - 11 | -7206377.192098914355 - | 18570646.625000000000 -(10 rows) - -select max(cint8) from aggfns where cfloat8 > 0 order by 1; - max ------------- - 1073659785 +select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 1 | -16383 + 7 | -16383 + 5 | -16382 + 4 | -16381 + 6 | -16381 + 9 | -16380 + 0 | -16379 + 2 | -16378 + 3 | -16378 + 8 | -16374 +(10 rows) + +select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 7 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 6 | -16381 + 9 | -16380 + 0 | -16379 + 3 | -16378 + 8 | -16374 + | -14174 +(10 rows) + +select sum(cint8) from aggfns where cfloat8 > 0; + sum +-------- + 815878 (1 row) -select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+------------ - 0 | 1073659785 - 1 | 1073659785 - 2 | 1073659785 - 3 | 1073659785 - 4 | 1073659785 - 5 | 1073659785 - 6 | 1073659785 - 7 | 1073659785 - 8 | 1073659785 - 9 | 1073659785 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073659785 - 3 | 1073659785 - 4 | 1073659785 - 5 | 1073659785 - 6 | 1073659785 - 7 | 1073659785 - 8 | 1073659785 - 9 | 1073659785 - 11 | 1073659785 - | 969157980 -(10 rows) - -select min(cint8) from aggfns where cfloat8 > 0 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -672677796 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 > 0 order by 1; - sum ---------------- - -724550206823 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------------- - 0 | -72909966030 - 1 | -72928678628 - 2 | -72081777390 - 3 | -72081777390 - 4 | -72842921064 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+--------------- - 0 | -72909966030 - 3 | -72230342563 - 4 | -74475296468 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 - 11 | -143378080614 - | 148565173 -(10 rows) - -select max(cts) from aggfns where cfloat8 > 0 order by 1; +select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by sum(cint8), s limit 10; + s | sum +---+--------- + 1 | -957731 + 5 | -901538 + 8 | -579311 + 3 | -122205 + 4 | -25917 + 2 | 214193 + 6 | 357171 + 0 | 424701 + 7 | 635540 + 9 | 1770975 +(10 rows) + +select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+--------- + 5 | -901538 + 11 | -782137 + 8 | -579311 + 3 | -129086 + | 6881 + 4 | 12682 + 6 | 357171 + 0 | 424701 + 7 | 635540 + 9 | 1770975 +(10 rows) + +select max(cts) from aggfns where cfloat8 > 0; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 > 0 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:20 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:40 2021 - 3 | Fri Jan 01 14:54:19 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:40 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:00 2021 - 8 | Sat Jan 02 04:47:39 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by max(cts), ss limit 10; ss | max ----+-------------------------- - 0 | Fri Jan 01 06:34:20 2021 - 3 | Fri Jan 01 14:54:19 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:40 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:00 2021 - 8 | Sat Jan 02 04:47:39 2021 - 9 | Sat Jan 02 07:34:21 2021 - 11 | Fri Jan 01 17:09:56 2021 - | Fri Jan 01 14:45:52 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns where cfloat8 > 0; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 > 0 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:27 2021 - 3 | Fri Jan 01 09:21:06 2021 - 4 | Fri Jan 01 12:07:45 2021 - 5 | Fri Jan 01 14:54:24 2021 - 6 | Fri Jan 01 17:41:03 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by min(cts), ss limit 10; ss | min ----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 3 | Fri Jan 01 09:21:06 2021 - 4 | Fri Jan 01 12:07:45 2021 - 5 | Fri Jan 01 14:54:24 2021 - 6 | Fri Jan 01 17:41:03 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 - 11 | Fri Jan 01 03:47:42 2021 - | Fri Jan 01 10:05:04 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns where cfloat8 > 0; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 > 0 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:20 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:40 2021 PST - 3 | Fri Jan 01 14:54:19 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:40 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:00 2021 PST - 8 | Sat Jan 02 04:47:39 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by max(ctstz), ss limit 10; ss | max ----+------------------------------ - 0 | Fri Jan 01 06:34:20 2021 PST - 3 | Fri Jan 01 14:54:19 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:40 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:00 2021 PST - 8 | Sat Jan 02 04:47:39 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST - 11 | Fri Jan 01 17:09:56 2021 PST - | Fri Jan 01 14:45:52 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 > 0; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 > 0 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:27 2021 PST - 3 | Fri Jan 01 09:21:06 2021 PST - 4 | Fri Jan 01 12:07:45 2021 PST - 5 | Fri Jan 01 14:54:24 2021 PST - 6 | Fri Jan 01 17:41:03 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by min(ctstz), ss limit 10; ss | min ----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 3 | Fri Jan 01 09:21:06 2021 PST - 4 | Fri Jan 01 12:07:45 2021 PST - 5 | Fri Jan 01 14:54:24 2021 PST - 6 | Fri Jan 01 17:41:03 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST - 11 | Fri Jan 01 03:47:42 2021 PST - | Fri Jan 01 10:05:04 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns where cfloat8 > 0; avg -------------------- - 4.5000804586141004 + 4.4876994814487277 (1 row) -select s, avg(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 > 0 group by s order by avg(s), s limit 10; s | avg ---+------------------------ 0 | 0.00000000000000000000 @@ -3342,100 +2952,64 @@ select s, avg(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by avg(s), ss limit 10; ss | avg ----+------------------------ 0 | 0.00000000000000000000 + 11 | 1.5068499950362355 3 | 3.0000000000000000 + | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 - 11 | 1.5013570566948130 - | 3.0000000000000000 (10 rows) -select count(s) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99430 -(1 row) - -select count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 order by 1; +select count(s) from aggfns where cfloat8 > 0; count ------- - 49288 + 99508 (1 row) -select s, count(s) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by s order by 1; +select s, count(s) from aggfns where cfloat8 > 0 group by s order by count(s), s limit 10; s | count ---+------- - 0 | 4928 - 1 | 4929 - 2 | 4928 - 3 | 4928 - 4 | 4929 - 5 | 4929 - 6 | 4929 - 7 | 4929 - 8 | 4929 - 9 | 4930 -(10 rows) - -select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; + 8 | 9788 + 7 | 9873 + 9 | 9879 + 0 | 9881 + 3 | 9902 + 1 | 9959 + 6 | 10004 + 5 | 10009 + 4 | 10038 + 2 | 10175 +(10 rows) + +select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by count(s), ss limit 10; ss | count ----+------- - 0 | 9943 - 3 | 9934 - 4 | 9932 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 - 11 | 19896 | 8 -(10 rows) - -select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 4928 - 3 | 4925 - 4 | 4922 - 5 | 4929 - 6 | 4929 - 7 | 4929 - 8 | 4929 - 9 | 4930 - 11 | 9864 - | 3 -(10 rows) - -select max(s) from aggfns where cfloat8 > 0 order by 1; + 8 | 9788 + 7 | 9873 + 9 | 9879 + 0 | 9881 + 3 | 9894 + 6 | 10004 + 5 | 10009 + 4 | 10026 + 11 | 20146 +(10 rows) + +select max(s) from aggfns where cfloat8 > 0; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(s) from aggfns where cfloat8 > 0 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -3450,28 +3024,28 @@ select s, max(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by max(s), ss limit 10; ss | max ----+----- 0 | 0 3 | 3 + | 3 4 | 4 + 11 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 4 - | 3 (10 rows) -select min(s) from aggfns where cfloat8 > 0 order by 1; +select min(s) from aggfns where cfloat8 > 0; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(s) from aggfns where cfloat8 > 0 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -3486,28 +3060,28 @@ select s, min(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by min(s), ss limit 10; ss | min ----+----- 0 | 0 + 11 | 1 3 | 3 + | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 1 - | 3 (10 rows) -select stddev(s) from aggfns where cfloat8 > 0 order by 1; +select stddev(s) from aggfns where cfloat8 > 0; stddev -------------------- - 2.8722957659869625 + 2.8656139545132202 (1 row) -select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -3522,7 +3096,7 @@ select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by stddev(s), ss limit 10; ss | stddev ----+------------------------ 0 | 0 @@ -3533,68 +3107,68 @@ select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 - 11 | 0.50331713731225271878 | 0 + 11 | 0.50352713246563412901 (10 rows) -select sum(s) from aggfns where cfloat8 > 0 order by 1; +select sum(s) from aggfns where cfloat8 > 0; sum -------- - 447443 + 446562 (1 row) -select s, sum(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 > 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by 1; + 1 | 9959 + 2 | 20350 + 3 | 29706 + 4 | 40152 + 5 | 50045 + 6 | 60024 + 7 | 69111 + 8 | 78304 + 9 | 88911 +(10 rows) + +select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by sum(s), ss limit 10; ss | sum ----+------- 0 | 0 - 3 | 29802 - 4 | 39728 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 - 11 | 29871 | 24 + 3 | 29682 + 11 | 30357 + 4 | 40104 + 5 | 50045 + 6 | 60024 + 7 | 69111 + 8 | 78304 + 9 | 88911 (10 rows) -select avg(ss) from aggfns where cfloat8 > 0 order by 1; +select avg(ss) from aggfns where cfloat8 > 0; avg -------------------- - 6.4010379996379071 + 6.4099195979899497 (1 row) -select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by avg(ss), s limit 10; s | avg ---+------------------------ 0 | 0.00000000000000000000 - 1 | 11.0000000000000000 - 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0077441416071608 + 4 | 4.0083682008368201 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by avg(ss), ss limit 10; ss | avg ----+------------------------ 0 | 0.00000000000000000000 @@ -3609,28 +3183,28 @@ select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; | (10 rows) -select max(ss) from aggfns where cfloat8 > 0 order by 1; +select max(ss) from aggfns where cfloat8 > 0; max ----- 11 (1 row) -select s, max(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 > 0 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 - 4 | 11 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by max(ss), ss limit 10; ss | max ----+----- 0 | 0 @@ -3645,18 +3219,16 @@ select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; | (10 rows) -select min(ss) from aggfns where cfloat8 > 0 order by 1; +select min(ss) from aggfns where cfloat8 > 0; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 > 0 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 4 | 4 5 | 5 @@ -3664,9 +3236,11 @@ select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by min(ss), ss limit 10; ss | min ----+----- 0 | 0 @@ -3681,28 +3255,28 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; | (10 rows) -select stddev(ss) from aggfns where cfloat8 > 0 order by 1; +select stddev(ss) from aggfns where cfloat8 > 0; stddev -------------------- - 3.3528295838273201 + 3.3546680341938823 (1 row) -select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by stddev(ss), s limit 10; s | stddev ---+------------------------ 0 | 0 1 | 0 2 | 0 3 | 0 - 4 | 0.23271112137690657933 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 + 4 | 0.24189503558873125235 (10 rows) -select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by stddev(ss), ss limit 10; ss | stddev ----+-------- 0 | 0 @@ -3717,1447 +3291,1273 @@ select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; | (10 rows) -select sum(ss) from aggfns where cfloat8 > 0 order by 1; +select sum(ss) from aggfns where cfloat8 > 0; sum -------- - 636404 + 637787 (1 row) -select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 109373 - 2 | 109362 - 3 | 29802 - 4 | 39849 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by 1; + 3 | 29682 + 4 | 40236 + 5 | 50045 + 6 | 60024 + 7 | 69111 + 8 | 78304 + 9 | 88911 + 1 | 109549 + 2 | 111925 +(10 rows) + +select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 - 3 | 29802 - 4 | 39728 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 - 11 | 218856 + 3 | 29682 + 4 | 40104 + 5 | 50045 + 6 | 60024 + 7 | 69111 + 8 | 78304 + 9 | 88911 + 11 | 221606 | (10 rows) -select max(t) from aggfns where cfloat8 > 0 order by 1; +select max(t) from aggfns where cfloat8 > 0; max -------- - 110000 + 109994 (1 row) -select s, max(t) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(t) from aggfns where cfloat8 > 0 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 19999 1 | 30000 - 2 | 39999 - 3 | 49998 + 2 | 40000 + 3 | 50000 4 | 60000 - 5 | 69999 + 5 | 70000 6 | 80000 - 7 | 89999 - 8 | 99998 - 9 | 110000 + 7 | 89997 + 8 | 100000 + 9 | 109994 (10 rows) -select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 19999 - 3 | 49998 + | 46332 + 3 | 50000 + 11 | 59192 4 | 60000 - 5 | 69999 + 5 | 70000 6 | 80000 - 7 | 89999 - 8 | 99998 - 9 | 110000 - 11 | 58135 - | 49491 + 7 | 89997 + 8 | 100000 + 9 | 109994 (10 rows) -select min(t) from aggfns where cfloat8 > 0 order by 1; +select min(t) from aggfns where cfloat8 > 0; min ----- 1 (1 row) -select s, min(t) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(t) from aggfns where cfloat8 > 0 group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 - 1 | 10001 - 2 | 20006 - 3 | 30005 - 4 | 40004 - 5 | 50003 - 6 | 60002 + 1 | 10003 + 2 | 20002 + 3 | 30003 + 4 | 40001 + 5 | 50002 + 6 | 60001 7 | 70001 - 8 | 80001 - 9 | 90001 + 8 | 80003 + 9 | 90002 (10 rows) -select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; +select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by min(t), ss limit 10; ss | min ----+------- 0 | 1 - 3 | 30005 - 4 | 40004 - 5 | 50003 - 6 | 60002 + 11 | 10003 + 3 | 30003 + | 30537 + 4 | 40001 + 5 | 50002 + 6 | 60001 7 | 70001 - 8 | 80001 - 9 | 90001 - 11 | 10001 - | 32643 + 8 | 80003 + 9 | 90002 (10 rows) -select count(*) from aggfns where cfloat8 <= 0 order by 1; +select count(*) from aggfns where cfloat8 <= 0; count -------- - 100570 -(1 row) - -select count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; - count -------- - 50140 + 100492 (1 row) -select s, count(*) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, count(*) from aggfns where cfloat8 <= 0 group by s order by count(*), s limit 10; s | count ---+------- - 0 | 5014 - 1 | 5014 - 2 | 5015 - 3 | 5015 - 4 | 5014 - 5 | 5013 - 6 | 5013 - 7 | 5014 - 8 | 5014 - 9 | 5014 -(10 rows) - -select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 10057 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 - 11 | 20123 - | 11 -(10 rows) - -select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; + 2 | 9825 + 4 | 9962 + 5 | 9991 + 6 | 9996 + 1 | 10041 + 3 | 10098 + 0 | 10119 + 9 | 10121 + 7 | 10127 + 8 | 10212 +(10 rows) + +select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by count(*), ss limit 10; ss | count ----+------- - 0 | 5014 - 3 | 5012 - 4 | 5010 - 5 | 5013 - 6 | 5013 - 7 | 5014 - 8 | 5014 - 9 | 5014 - 11 | 10033 - | 3 -(10 rows) - -select x, count(*) from aggfns where cfloat8 <= 0 group by x order by 1; - x | count -----+------- - 0 | 10057 - 11 | 20123 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 | 11 -(10 rows) - -select max(cdate) from aggfns where cfloat8 <= 0 order by 1; + 4 | 9955 + 5 | 9991 + 6 | 9996 + 3 | 10087 + 0 | 10119 + 9 | 10121 + 7 | 10127 + 8 | 10212 + 11 | 19873 +(10 rows) + +select max(cdate) from aggfns where cfloat8 <= 0; max ------------ - 03-04-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-05-2075 - 1 | 02-20-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-10-2185 - 5 | 08-28-2212 - 6 | 01-13-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-04-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by max(cdate), ss limit 10; ss | max ----+------------ - 0 | 10-05-2075 - 3 | 11-24-2157 - 4 | 04-10-2185 - 5 | 08-28-2212 - 6 | 01-13-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-04-2322 - 11 | 01-24-2183 - | 08-15-2153 -(10 rows) - -select min(cdate) from aggfns where cfloat8 <= 0 order by 1; + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns where cfloat8 <= 0; min ------------ - 01-04-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-04-2021 - 1 | 05-21-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 09-01-2212 - 8 | 01-17-2240 - 9 | 06-03-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by min(cdate), ss limit 10; ss | min ----+------------ - 0 | 01-04-2021 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 09-01-2212 - 8 | 01-17-2240 - 9 | 06-03-2267 - 11 | 05-21-2048 - | 08-11-2104 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - avg ------ - NaN + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns where cfloat8 <= 0; + avg +------------------- + 0.106185028347415 (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | avg ----+------------------- - 0 | 0.273710566446533 - 1 | NaN - 2 | Infinity - 3 | 0.271225418012403 - 4 | 0.274902188431565 - 5 | 0.278701234893647 - 6 | 0.279196201482741 - 7 | 0.281055561785383 - 8 | 0.276832673694496 - 9 | 0.276832673694496 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+------------------- - 0 | 0.273710566446533 - 3 | 0.281539709766287 - 4 | 0.290259015901558 - 5 | 0.278701234893647 - 6 | 0.279196201482741 - 7 | 0.281055561785383 - 8 | 0.276832673694496 - 9 | 0.276832673694496 - 11 | NaN - | -9.14947360483083 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - max ------ - NaN +select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat4), s limit 10; + s | avg +---+--------------------- + 1 | -0.369617656298752 + 5 | -0.238408898764696 + 6 | -0.140676149758002 + 9 | -0.0210546333041521 + 2 | 0.174820695098385 + 4 | 0.200448185895117 + 3 | 0.200936527140099 + 8 | 0.369675376818395 + 7 | 0.378335182597323 + 0 | 0.497406092427368 +(10 rows) + +select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+--------------------- + 5 | -0.238408898764696 + 6 | -0.140676149758002 + 11 | -0.101489562396578 + 9 | -0.0210546333041521 + 3 | 0.198087105455873 + 4 | 0.20291806567958 + 8 | 0.369675376818395 + 7 | 0.378335182597323 + 0 | 0.497406092427368 + | 2.81385621157559 +(10 rows) + +select max(cfloat4) from aggfns where cfloat8 <= 0; + max +--------- + 49.9997 (1 row) -select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; +select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by max(cfloat4), s limit 10; + s | max +---+--------- + 3 | 49.9831 + 5 | 49.9847 + 9 | 49.9899 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 + 2 | 49.9977 + 0 | 49.9995 + 8 | 49.9997 + 1 | 49.9997 +(10 rows) + +select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat4), ss limit 10; ss | max ----+--------- - 0 | 49.9977 - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 - 11 | NaN - | 48.478 -(10 rows) - -select min(cfloat4) from aggfns where cfloat8 <= 0 order by 1; + | 43.8334 + 3 | 49.9831 + 5 | 49.9847 + 9 | 49.9899 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 + 0 | 49.9995 + 8 | 49.9997 + 11 | 49.9997 +(10 rows) + +select min(cfloat4) from aggfns where cfloat8 <= 0; min ---------- - -49.9756 + -49.9995 (1 row) -select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by min(cfloat4), s limit 10; s | min ---+---------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 - 3 | -49.9756 - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; + 6 | -49.9995 + 7 | -49.9984 + 1 | -49.9974 + 0 | -49.9949 + 5 | -49.9942 + 2 | -49.9932 + 8 | -49.9837 + 9 | -49.9836 + 4 | -49.9742 + 3 | -49.974 +(10 rows) + +select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat4), ss limit 10; ss | min ----+---------- - 0 | -49.9756 - 3 | -49.9756 - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 - 11 | NaN - | -46.7478 -(10 rows) - -select stddev(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - stddev --------- - NaN + 6 | -49.9995 + 7 | -49.9984 + 11 | -49.9974 + 0 | -49.9949 + 5 | -49.9942 + 8 | -49.9837 + 9 | -49.9836 + 4 | -49.9742 + 3 | -49.974 + | -45.4083 +(10 rows) + +select stddev(cfloat4) from aggfns where cfloat8 <= 0; + stddev +------------------ + 28.9176238982259 (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8948722701767 - 1 | NaN - 2 | NaN - 3 | 28.8971947735823 - 4 | 28.8962786797298 - 5 | 28.8969485514879 - 6 | 28.898342825597 - 7 | 28.8981465590944 - 8 | 28.8998126918449 - 9 | 28.8998126918449 -(10 rows) - -select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; + 4 | 28.6443792572409 + 0 | 28.7188352112159 + 3 | 28.8001993440446 + 7 | 28.8445902712948 + 6 | 28.9280364258487 + 9 | 29.0050149205695 + 8 | 29.0137169777563 + 2 | 29.0305221043722 + 1 | 29.0393254603524 + 5 | 29.149709761256 +(10 rows) + +select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - 0 | 28.8948722701767 - 3 | 28.8951497341689 - 4 | 28.8918331282339 - 5 | 28.8969485514879 - 6 | 28.898342825597 - 7 | 28.8981465590944 - 8 | 28.8998126918449 - 9 | 28.8998126918449 - 11 | NaN - | 30.6521210689863 -(10 rows) - -select sum(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - sum ------ - NaN + 4 | 28.644441921671 + 0 | 28.7188352112159 + 3 | 28.7972864714779 + 7 | 28.8445902712948 + 6 | 28.9280364258488 + 9 | 29.0050149205695 + 8 | 29.0137169777563 + 11 | 29.0353370214802 + 5 | 29.1497097612561 + | 32.7733939400537 +(10 rows) + +select sum(cfloat4) from aggfns where cfloat8 <= 0; + sum +--------- + 10670.7 (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat4), s limit 10; s | sum ---+---------- - 0 | 2752.71 - 1 | NaN - 2 | Infinity - 3 | 2727.98 - 4 | 2764.69 - 5 | 2802.9 - 6 | 2807.6 - 7 | 2826.29 - 8 | 2784.11 - 9 | 2784.11 -(10 rows) - -select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; + 1 | -3711.33 + 5 | -2381.94 + 6 | -1406.2 + 9 | -213.094 + 2 | 1717.61 + 4 | 1996.86 + 3 | 2029.06 + 8 | 3775.12 + 7 | 3831.4 + 0 | 5033.25 +(10 rows) + +select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+---------- - 0 | 2752.71 - 3 | 2828.63 - 4 | 2916.81 - 5 | 2802.9 - 6 | 2807.6 - 7 | 2826.29 - 8 | 2784.11 - 9 | 2784.11 - 11 | NaN - | -100.644 -(10 rows) - -select avg(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + 5 | -2381.94 + 11 | -2016.9 + 6 | -1406.2 + 9 | -213.094 + | 30.9524 + 3 | 1998.1 + 4 | 2020.05 + 8 | 3775.12 + 7 | 3831.4 + 0 | 5033.25 +(10 rows) + +select avg(cfloat8) from aggfns where cfloat8 <= 0; avg ------------------- - -25.0059242142437 + -25.0742807687329 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------- - 0 | -25.0026878159296 - 1 | -25.0026878159296 - 2 | -25.0037259853644 - 3 | -25.0033035766331 - 4 | -25.0044243209649 - 5 | -25.0071564832908 - 6 | -25.0084381401581 - 7 | -25.0089627629465 - 8 | -25.0089281362381 - 9 | -25.0089281362381 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; + 6 | -25.2249493219802 + 7 | -25.1427599469014 + 5 | -25.1376795423819 + 3 | -25.1007961021779 + 0 | -25.0944548448943 + 9 | -25.0670826007257 + 1 | -25.048029068051 + 8 | -25.0124743296045 + 4 | -24.9766590364965 + 2 | -24.9353738049633 +(10 rows) + +select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat8), ss limit 10; ss | avg ----+------------------- - 0 | -25.0026878159296 - 3 | -25.0067336719196 - 4 | -24.9970119951125 - 5 | -25.0071564832908 - 6 | -25.0084381401581 - 7 | -25.0089627629465 - 8 | -25.0089281362381 - 9 | -25.0089281362381 - 11 | -25.0069089689736 - | -21.870379272679 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + | -25.7439222038639 + 6 | -25.2249493219802 + 7 | -25.1427599469014 + 5 | -25.1376795423819 + 3 | -25.1000947650986 + 0 | -25.0944548448943 + 9 | -25.0670826007257 + 8 | -25.0124743296045 + 11 | -24.9935950203669 + 4 | -24.9740905060663 +(10 rows) + +select max(cfloat8) from aggfns where cfloat8 <= 0; max ----------------------- - -0.000542588531970978 + -0.000587338581681252 (1 row) -select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by max(cfloat8), s limit 10; s | max ---+----------------------- - 0 | -0.000542588531970978 - 1 | -0.000542588531970978 - 2 | -0.000542588531970978 - 3 | -0.000542588531970978 - 4 | -0.000542588531970978 - 5 | -0.000542588531970978 - 6 | -0.000542588531970978 - 7 | -0.000542588531970978 - 8 | -0.000542588531970978 - 9 | -0.000542588531970978 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; + 4 | -0.015261210501194 + 6 | -0.00991490669548512 + 0 | -0.00547224190086126 + 7 | -0.00457693822681904 + 9 | -0.00377818942070007 + 3 | -0.00155717134475708 + 5 | -0.00140282791107893 + 1 | -0.00135276932269335 + 8 | -0.00127912499010563 + 2 | -0.000587338581681252 +(10 rows) + +select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat8), ss limit 10; ss | max ----+----------------------- - 0 | -0.000542588531970978 - 3 | -0.000542588531970978 - 4 | -0.000542588531970978 - 5 | -0.000542588531970978 - 6 | -0.000542588531970978 - 7 | -0.000542588531970978 - 8 | -0.000542588531970978 - 9 | -0.000542588531970978 - 11 | -0.000542588531970978 - | -4.53631093259901 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + | -3.40055420529097 + 4 | -0.015261210501194 + 6 | -0.00991490669548512 + 0 | -0.00547224190086126 + 7 | -0.00457693822681904 + 9 | -0.00377818942070007 + 3 | -0.00155717134475708 + 5 | -0.00140282791107893 + 8 | -0.00127912499010563 + 11 | -0.000587338581681252 +(10 rows) + +select min(cfloat8) from aggfns where cfloat8 <= 0; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 1 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + 2 | -49.9854512279853 +(10 rows) + +select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- - 0 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 - 11 | -49.9755693599582 - | -38.3512130472809 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 11 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + | -40.4587021796033 +(10 rows) + +select stddev(cfloat8) from aggfns where cfloat8 <= 0; stddev ------------------ - 14.4806777057013 + 14.4132133795776 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 14.4821730365752 - 1 | 14.4821730365752 - 2 | 14.4818272972739 - 3 | 14.4815478866618 - 4 | 14.48183169158 - 5 | 14.4805923063393 - 6 | 14.4807418968606 - 7 | 14.4812687827814 - 8 | 14.4805491499824 - 9 | 14.4805491499824 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; + 8 | 14.3287207237224 + 4 | 14.338825539003 + 2 | 14.3532302747139 + 6 | 14.4046796063746 + 5 | 14.4106499899109 + 1 | 14.4216091274813 + 7 | 14.4303638321788 + 9 | 14.4471294863496 + 3 | 14.484217665042 + 0 | 14.5136612753879 +(10 rows) + +select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - 0 | 14.4821730365752 - 3 | 14.485819356309 - 4 | 14.4810339821535 - 5 | 14.4805923063393 - 6 | 14.4807418968606 - 7 | 14.4812687827813 - 8 | 14.4805491499824 - 9 | 14.4805491499824 - 11 | 14.4820374611522 - | 9.77628724519737 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + | 13.2313932766119 + 8 | 14.3287207237224 + 4 | 14.3399291680111 + 11 | 14.3870105146555 + 6 | 14.4046796063746 + 5 | 14.4106499899109 + 7 | 14.4303638321788 + 9 | 14.4471294863496 + 3 | 14.4861084104713 + 0 | 14.5136612753879 +(10 rows) + +select sum(cfloat8) from aggfns where cfloat8 <= 0; sum ------------------- - -2514845.79822649 + -2519764.62301151 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------- - 0 | -251452.031364804 - 1 | -251452.031364804 - 2 | -251487.475960795 - 3 | -251483.227373776 - 4 | -251469.495395944 - 5 | -251496.972752456 - 6 | -251484.85393743 - 7 | -251490.12954419 - 8 | -251514.790266147 - 9 | -251514.790266147 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; + 8 | -255427.387853921 + 7 | -254620.729982271 + 0 | -253930.788575485 + 9 | -253703.943001945 + 3 | -253467.839039792 + 6 | -252148.593422514 + 1 | -251507.2598723 + 5 | -251150.556307938 + 4 | -248817.477321578 + 2 | -244990.047633764 +(10 rows) + +select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat8), ss limit 10; ss | sum ----+------------------- - 0 | -251452.031364804 - 3 | -251242.653201777 - 4 | -251194.973538886 - 5 | -251496.972752456 - 6 | -251484.85393743 - 7 | -251490.12954419 - 8 | -251514.790266147 - 9 | -251514.790266147 - 11 | -503214.029182657 - | -240.574171999469 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 <= 0 order by 1; - avg ------------------------ - -143.1624265950034836 + 11 | -496697.713839752 + 8 | -255427.387853921 + 7 | -254620.729982271 + 0 | -253930.788575485 + 9 | -253703.943001945 + 3 | -253184.65589555 + 6 | -252148.593422514 + 5 | -251150.556307938 + 4 | -248617.07098789 + | -283.183144242503 +(10 rows) + +select avg(cint2) from aggfns where cfloat8 <= 0; + avg +---------------------- + -32.8711290402908511 (1 row) -select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by avg(cint2), s limit 10; s | avg ---+----------------------- - 0 | -145.9491390464815368 - 1 | -146.0055732484076433 - 2 | -145.5036823248407643 - 3 | -144.9877599761170266 - 4 | -141.3792931806869089 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+------------------------ - 0 | -145.9491390464815368 - 3 | -143.3365212193664077 - 4 | -139.6013749128225565 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 - 11 | -146.6405192996418623 - | -1651.8181818181818182 -(10 rows) - -select count(cint2) from aggfns where cfloat8 <= 0 order by 1; + 3 | -195.8809712586719524 + 8 | -128.5279874522105676 + 2 | -123.2159959246051961 + 4 | -28.9879409104612602 + 7 | -19.0635438284415456 + 9 | -12.7132403836645901 + 6 | -3.6577550816060879 + 0 | 6.6666006927263731 + 1 | 31.0574277168494516 + 5 | 146.6757812500000000 +(10 rows) + +select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+----------------------- + 3 | -196.2831630122035916 + 8 | -128.5279874522105676 + 11 | -45.6090066492041104 + 4 | -28.2469831053901850 + 7 | -19.0635438284415456 + 9 | -12.7132403836645901 + 6 | -3.6577550816060879 + 0 | 6.6666006927263731 + 5 | 146.6757812500000000 + | 172.6363636363636364 +(10 rows) + +select count(cint2) from aggfns where cfloat8 <= 0; count -------- - 100470 -(1 row) - -select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; - count -------- - 50095 + 100395 (1 row) -select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 10047 - 1 | 10048 - 2 | 10048 - 3 | 10049 - 4 | 10045 - 5 | 10048 - 6 | 10046 - 7 | 10048 - 8 | 10044 - 9 | 10047 -(10 rows) - -select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by count(cint2), s limit 10; s | count ---+------- - 0 | 5010 - 1 | 5010 - 2 | 5011 - 3 | 5012 - 4 | 5008 - 5 | 5010 - 6 | 5007 - 7 | 5012 - 8 | 5006 - 9 | 5009 -(10 rows) - -select ss, count(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; + 2 | 9815 + 4 | 9951 + 5 | 9984 + 6 | 9987 + 1 | 10030 + 3 | 10090 + 0 | 10105 + 9 | 10113 + 7 | 10119 + 8 | 10201 +(10 rows) + +select ss, count(cint2) from aggfns where cfloat8 <= 0 group by ss order by count(cint2), ss limit 10; ss | count ----+------- - 0 | 10047 - 3 | 10038 - 4 | 10037 - 5 | 10048 - 6 | 10046 - 7 | 10048 - 8 | 10044 - 9 | 10047 - 11 | 20104 | 11 + 4 | 9944 + 5 | 9984 + 6 | 9987 + 3 | 10079 + 0 | 10105 + 9 | 10113 + 7 | 10119 + 8 | 10201 + 11 | 19852 +(10 rows) + +select max(cint2) from aggfns where cfloat8 <= 0; + max +------- + 16383 +(1 row) + +select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by max(cint2), s limit 10; + s | max +---+------- + 2 | 16375 + 9 | 16375 + 3 | 16380 + 0 | 16381 + 5 | 16381 + 7 | 16381 + 1 | 16382 + 8 | 16382 + 4 | 16383 + 6 | 16383 (10 rows) -select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 5010 - 3 | 5009 - 4 | 5004 - 5 | 5010 - 6 | 5007 - 7 | 5012 - 8 | 5006 - 9 | 5009 - 11 | 10025 - | 3 -(10 rows) - -select x, count(cint2) from aggfns where cfloat8 <= 0 group by x order by 1; - x | count +select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by max(cint2), ss limit 10; + ss | max ----+------- - 0 | 10047 - 11 | 20104 - 3 | 10038 - 4 | 10037 - 5 | 10048 - 6 | 10046 - 7 | 10048 - 8 | 10044 - 9 | 10047 - | 11 + | 10632 + 9 | 16375 + 3 | 16380 + 0 | 16381 + 5 | 16381 + 7 | 16381 + 8 | 16382 + 11 | 16382 + 4 | 16383 + 6 | 16383 (10 rows) -select max(cint2) from aggfns where cfloat8 <= 0 order by 1; +select min(cint2) from aggfns where cfloat8 <= 0; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16380 + 4 | -16379 + 1 | -16378 + 5 | -16374 + 9 | -16374 +(10 rows) + +select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16380 + 4 | -16379 + 5 | -16374 + 9 | -16374 + | -9099 +(10 rows) + +select stddev(cint2) from aggfns where cfloat8 <= 0; + stddev +------------------- + 9468.828025193727 +(1 row) + +select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by stddev(cint2), s limit 10; + s | stddev +---+------------------- + 3 | 9431.449699785939 + 6 | 9448.435617417508 + 0 | 9451.115288155243 + 9 | 9455.614886560824 + 8 | 9463.597928793709 + 2 | 9469.005892286076 + 4 | 9474.656350647745 + 5 | 9476.359682175140 + 7 | 9480.532843811240 + 1 | 9537.428149419877 +(10 rows) + +select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+------------------- + | 6505.198648353904 + 3 | 9434.362465275590 + 6 | 9448.435617417508 + 0 | 9451.115288155243 + 9 | 9455.614886560824 + 8 | 9463.597928793709 + 4 | 9473.486702235684 + 5 | 9476.359682175140 + 7 | 9480.532843811240 + 11 | 9504.295955675669 +(10 rows) + +select sum(cint2) from aggfns where cfloat8 <= 0; + sum +---------- + -3300097 +(1 row) + +select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 3 | -1976439 + 8 | -1311114 + 2 | -1209365 + 4 | -288459 + 7 | -192904 + 9 | -128569 + 6 | -36530 + 0 | 67366 + 1 | 311506 + 5 | 1464411 +(10 rows) + +select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 3 | -1978338 + 8 | -1311114 + 11 | -905430 + 4 | -280888 + 7 | -192904 + 9 | -128569 + 6 | -36530 + | 1899 + 0 | 67366 + 5 | 1464411 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 <= 0; + avg +---------------------- + -26.1579926760339131 +(1 row) + +select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by avg(cint4), s limit 10; + s | avg +---+------------------------ + 2 | -183.4400000000000000 + 7 | -172.7792041078305520 + 4 | -108.3184099578397912 + 9 | -87.4561802193459144 + 0 | -21.8140132424152584 + 8 | -17.1878182530356443 + 6 | 0.76360544217687074830 + 1 | 26.8885569166417687 + 3 | 137.3122400475341652 + 5 | 162.1092983685316785 +(10 rows) + +select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+------------------------ + 7 | -172.7792041078305520 + 4 | -109.1407332998493219 + 9 | -87.4561802193459144 + 11 | -76.7313440346198360 + 0 | -21.8140132424152584 + 8 | -17.1878182530356443 + 6 | 0.76360544217687074830 + 3 | 133.4929116684841876 + 5 | 162.1092983685316785 + | 3639.6363636363636364 +(10 rows) + +select max(cint4) from aggfns where cfloat8 <= 0; max ------- 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by max(cint4), s limit 10; s | max ---+------- + 5 | 16357 + 2 | 16376 + 7 | 16376 + 3 | 16379 + 6 | 16379 + 1 | 16381 + 9 | 16381 0 | 16383 - 1 | 16383 - 2 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 - 6 | 16383 - 7 | 16383 8 | 16383 - 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by max(cint4), ss limit 10; ss | max ----+------- + | 12486 + 5 | 16357 + 7 | 16376 + 3 | 16379 + 6 | 16379 + 9 | 16381 + 11 | 16381 0 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 - 6 | 16383 - 7 | 16383 8 | 16383 - 9 | 16383 - 11 | 16383 - | 10616 (10 rows) -select min(cint2) from aggfns where cfloat8 <= 0 order by 1; +select min(cint4) from aggfns where cfloat8 <= 0; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by min(cint4), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 + 0 | -16383 + 7 | -16383 + 1 | -16382 + 2 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16381 + 3 | -16379 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by min(cint4), ss limit 10; ss | min ----+-------- - 0 | -16375 - 3 | -16375 - 4 | -16375 + 0 | -16383 + 7 | -16383 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 11 | -16382 + 9 | -16381 + 3 | -16379 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 - 11 | -16375 - | -15206 + | -11573 (10 rows) -select stddev(cint2) from aggfns where cfloat8 <= 0 order by 1; +select stddev(cint4) from aggfns where cfloat8 <= 0; stddev ------------------- - 9537.532064200194 + 9450.360040184708 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by stddev(cint4), s limit 10; s | stddev ---+------------------- - 0 | 9538.832178541630 - 1 | 9537.717255354464 - 2 | 9540.157933140146 - 3 | 9535.281475740805 - 4 | 9537.335027198989 - 5 | 9538.686769657499 - 6 | 9537.494931550558 - 7 | 9538.995155888144 - 8 | 9537.123911034158 - 9 | 9537.962959664725 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; + 2 | 9359.751806276146 + 4 | 9416.548048818506 + 6 | 9419.427850127196 + 8 | 9428.883569195765 + 9 | 9443.762847438393 + 0 | 9444.372352979574 + 3 | 9484.296797827590 + 7 | 9486.697094022398 + 1 | 9501.054201574921 + 5 | 9513.457526639607 +(10 rows) + +select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint4), ss limit 10; ss | stddev ----+------------------- - 0 | 9538.832178541630 - 3 | 9535.623908566148 - 4 | 9537.357537825379 - 5 | 9538.686769657499 - 6 | 9537.494931550558 - 7 | 9538.995155888144 - 8 | 9537.123911034158 - 9 | 9537.962959664725 - 11 | 9538.688016316899 - | 9537.230025727405 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 <= 0 order by 1; - sum ------------ - -14383529 -(1 row) - -select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; - sum ------------ - -11419529 + | 8175.417839752624 + 4 | 9415.625139634959 + 6 | 9419.427850127196 + 8 | 9428.883569195765 + 11 | 9432.239512888477 + 9 | 9443.762847438393 + 0 | 9444.372352979574 + 3 | 9485.269059849581 + 7 | 9486.697094022398 + 5 | 9513.457526639607 +(10 rows) + +select sum(cint4) from aggfns where cfloat8 <= 0; + sum +---------- + -2628669 (1 row) -select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+---------- - 0 | -1466351 - 1 | -1467064 - 2 | -1462021 - 3 | -1456982 - 4 | -1420155 - 5 | -1402289 - 6 | -1424907 - 7 | -1451488 - 8 | -1380814 - 9 | -1451458 -(10 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by sum(cint4), s limit 10; s | sum ---+---------- - 0 | -1159786 - 1 | -1173264 - 2 | -1167568 - 3 | -1133852 - 4 | -1087309 - 5 | -1123689 - 6 | -1125479 - 7 | -1161075 - 8 | -1102312 - 9 | -1185195 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; + 2 | -1802298 + 7 | -1749735 + 4 | -1079068 + 9 | -885144 + 0 | -220736 + 8 | -175522 + 6 | 7633 + 1 | 269988 + 3 | 1386579 + 5 | 1619634 +(10 rows) + +select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by sum(cint4), ss limit 10; ss | sum ----+---------- - 0 | -1466351 - 3 | -1438812 - 4 | -1401179 - 5 | -1402289 - 6 | -1424907 - 7 | -1451488 - 8 | -1380814 - 9 | -1451458 - 11 | -2948061 - | -18170 -(10 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+---------- - 0 | -1159786 - 3 | -1145030 - 4 | -1072475 - 5 | -1123689 - 6 | -1125479 - 7 | -1161075 - 8 | -1102312 - 9 | -1185195 - 11 | -2355666 - | 11178 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 <= 0 order by 1; - avg ------------------------ - -2626106.025594113553 + 7 | -1749735 + 11 | -1524882 + 4 | -1086496 + 9 | -885144 + 0 | -220736 + 8 | -175522 + 6 | 7633 + | 40036 + 3 | 1346543 + 5 | 1619634 +(10 rows) + +select avg(cint8) from aggfns where cfloat8 <= 0; + avg +---------------------- + -32.2056880149663655 (1 row) -select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 0 | -2611631.507507208909 - 1 | -2611631.507507208909 - 2 | -2609754.938158679658 - 3 | -2572787.244482004375 - 4 | -2583154.535149647012 - 5 | -2738485.569155811872 - 6 | -2660373.598150357995 - 7 | -2578784.074681782021 - 8 | -2647231.455304762852 - 9 | -2647231.455304762852 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; + 8 | -175.3259890325107716 + 5 | -73.3032729456510860 + 7 | -67.4105855633455120 + 9 | -52.9631459341962257 + 4 | -36.5615338285484842 + 2 | -26.8270737913486005 + 6 | -11.9105642256902761 + 0 | -11.7269493032908390 + 1 | 44.7094910865451648 + 3 | 91.2747078629431571 +(10 rows) + +select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by avg(cint8), ss limit 10; ss | avg ----+----------------------- - 0 | -2611631.507507208909 - 3 | -2371975.736040609137 - 4 | -2420650.042193253060 - 5 | -2738485.569155811872 - 6 | -2660373.598150357995 - 7 | -2578784.074681782021 - 8 | -2647231.455304762852 - 9 | -2647231.455304762852 - 11 | -2691833.530040252447 - | -185986716.81818182 -(10 rows) - -select max(cint4) from aggfns where cfloat8 <= 0 order by 1; - max ------------- - 1073660631 + 8 | -175.3259890325107716 + 5 | -73.3032729456510860 + 7 | -67.4105855633455120 + 9 | -52.9631459341962257 + 4 | -35.5581115017579106 + 6 | -11.9105642256902761 + 0 | -11.7269493032908390 + 11 | 8.8113017662154682 + 3 | 87.4090413403390503 + | 3636.0909090909090909 +(10 rows) + +select max(cint8) from aggfns where cfloat8 <= 0; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 556763469 -(10 rows) - -select min(cint4) from aggfns where cfloat8 <= 0 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -888962001 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 <= 0 order by 1; - stddev ------------ - 618699699 -(1 row) +select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by max(cint8), s limit 10; + s | max +---+------- + 5 | 16363 + 6 | 16375 + 7 | 16375 + 2 | 16379 + 8 | 16380 + 9 | 16381 + 1 | 16382 + 3 | 16382 + 4 | 16382 + 0 | 16383 +(10 rows) -select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+----------- - 0 | 618765816 - 1 | 618765816 - 2 | 618735080 - 3 | 618695738 - 4 | 618725626 - 5 | 618719952 - 6 | 618701125 - 7 | 618716683 - 8 | 618723996 - 9 | 618723996 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 618765816 - 3 | 618865631 - 4 | 618722231 - 5 | 618719952 - 6 | 618701125 - 7 | 618716683 - 8 | 618723996 - 9 | 618723996 - 11 | 618736738 - | 415688814 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 <= 0 order by 1; - sum ---------------- - -264107482994 -(1 row) - -select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; - sum ----------------- - 26764915210806 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+-------------- - 0 | -26265178071 - 1 | -26265178071 - 2 | -26248915168 - 3 | -25877094105 - 4 | -25978785160 - 5 | -27540949369 - 6 | -26752716903 - 7 | -25932252655 - 8 | -26623206746 - 9 | -26623206746 -(10 rows) - -select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+--------------- - 0 | 2676782361278 - 1 | 2676782361278 - 2 | 2676798624181 - 3 | 2676798624181 - 4 | 2676696933126 - 5 | 2675895912591 - 6 | 2675895912591 - 7 | 2676421493860 - 8 | 2676421493860 - 9 | 2676421493860 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -26265178071 - 3 | -23831240220 - 4 | -24325112274 - 5 | -27540949369 - 6 | -26752716903 - 7 | -25932252655 - 8 | -26623206746 - 9 | -26623206746 - 11 | -54167766125 - | -2045853885 -(10 rows) - -select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+--------------- - 0 | 2676782361278 - 3 | 2676068232273 - 4 | 2675355890947 - 5 | 2675895912591 - 6 | 2675895912591 - 7 | 2676421493860 - 8 | 2676421493860 - 9 | 2676421493860 - 11 | 5354922027638 - | 730391908 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 <= 0 order by 1; - avg ----------------------- - 1589663.454419807100 +select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 12678 + 5 | 16363 + 6 | 16375 + 7 | 16375 + 8 | 16380 + 9 | 16381 + 3 | 16382 + 4 | 16382 + 11 | 16382 + 0 | 16383 +(10 rows) + +select min(cint8) from aggfns where cfloat8 <= 0; + min +-------- + -16383 (1 row) -select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | avg ----+---------------------- - 0 | 1609068.184846375659 - 1 | 1609068.184846375659 - 2 | 1561674.145953469875 - 3 | 1654097.121694173792 - 4 | 1574613.534354181167 - 5 | 1583685.317888038182 - 6 | 1613166.887529832936 - 7 | 1554490.104514717582 - 8 | 1568383.139206522820 - 9 | 1568383.139206522820 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+---------------------- - 0 | 1609068.184846375659 - 3 | 1911095.221857270827 - 4 | 1427463.756393671012 - 5 | 1583685.317888038182 - 6 | 1613166.887529832936 - 7 | 1554490.104514717582 - 8 | 1568383.139206522820 - 9 | 1568383.139206522820 - 11 | 1658849.193559608408 - | -233078622.18181818 -(10 rows) - -select max(cint8) from aggfns where cfloat8 <= 0 order by 1; - max ------------- - 1073660631 +select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 6 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 7 | -16381 + 2 | -16379 + 9 | -16377 + 1 | -16376 + 3 | -16375 +(10 rows) + +select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 7 | -16381 + 11 | -16379 + 9 | -16377 + 3 | -16375 + | -11918 +(10 rows) + +select sum(cint8) from aggfns where cfloat8 <= 0; + sum +---------- + -3236414 (1 row) -select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 989667573 -(10 rows) - -select min(cint8) from aggfns where cfloat8 <= 0 order by 1; - min -------------- - -1073053412 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | min ----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 - 11 | -1073053412 - | -796158533 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 <= 0 order by 1; - sum --------------- - 159872453611 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+------------- - 0 | 16182398735 - 1 | 16182398735 - 2 | 15707318560 - 3 | 16636908850 - 4 | 15835888315 - 5 | 15927123242 - 6 | 16222006221 - 7 | 15631952491 - 8 | 15773229231 - 9 | 15773229231 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------------- - 0 | 16182398735 - 3 | 19200773694 - 4 | 14344583288 - 5 | 15927123242 - 6 | 16222006221 - 7 | 15631952491 - 8 | 15773229231 - 9 | 15773229231 - 11 | 33381022322 - | -2563864844 -(10 rows) - -select max(cts) from aggfns where cfloat8 <= 0 order by 1; +select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -1790429 + 5 | -732373 + 7 | -682667 + 9 | -536040 + 4 | -364226 + 2 | -263576 + 6 | -119058 + 0 | -118665 + 1 | 448928 + 3 | 921692 +(10 rows) + +select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -1790429 + 5 | -732373 + 7 | -682667 + 9 | -536040 + 4 | -353981 + 6 | -119058 + 0 | -118665 + | 39997 + 11 | 175107 + 3 | 881695 +(10 rows) + +select max(cts) from aggfns where cfloat8 <= 0; max -------------------------- - Sat Jan 02 07:34:20 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:00 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:00 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:20 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:20 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by max(cts), ss limit 10; ss | max ----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:00 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:20 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:20 2021 - 11 | Fri Jan 01 17:27:33 2021 - | Fri Jan 01 14:28:19 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns where cfloat8 <= 0; min -------------------------- - Fri Jan 01 01:01:04 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:04 2021 - 1 | Fri Jan 01 03:47:43 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:45 2021 - 8 | Fri Jan 01 23:14:24 2021 - 9 | Sat Jan 02 02:01:03 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by min(cts), ss limit 10; ss | min ----+-------------------------- - 0 | Fri Jan 01 01:01:04 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:45 2021 - 8 | Fri Jan 01 23:14:24 2021 - 9 | Sat Jan 02 02:01:03 2021 - 11 | Fri Jan 01 03:47:43 2021 - | Fri Jan 01 09:29:58 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns where cfloat8 <= 0; max ------------------------------ - Sat Jan 02 07:34:20 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:00 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:00 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:20 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:20 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by max(ctstz), ss limit 10; ss | max ----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:00 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:20 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:20 2021 PST - 11 | Fri Jan 01 17:27:33 2021 PST - | Fri Jan 01 14:28:19 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 <= 0; min ------------------------------ - Fri Jan 01 01:01:04 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:04 2021 PST - 1 | Fri Jan 01 03:47:43 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:45 2021 PST - 8 | Fri Jan 01 23:14:24 2021 PST - 9 | Sat Jan 02 02:01:03 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by min(ctstz), ss limit 10; ss | min ----+------------------------------ - 0 | Fri Jan 01 01:01:04 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:45 2021 PST - 8 | Fri Jan 01 23:14:24 2021 PST - 9 | Sat Jan 02 02:01:03 2021 PST - 11 | Fri Jan 01 03:47:43 2021 PST - | Fri Jan 01 09:29:58 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns where cfloat8 <= 0; avg -------------------- - 4.4999204534155315 + 4.5121800740357441 (1 row) -select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 @@ -5172,100 +4572,64 @@ select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by avg(s), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 + 11 | 1.4954460826246666 3 | 3.0000000000000000 + | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 - 11 | 1.5010187347810963 - | 3.0000000000000000 (10 rows) -select count(s) from aggfns where cfloat8 <= 0 order by 1; +select count(s) from aggfns where cfloat8 <= 0; count -------- - 100570 + 100492 (1 row) -select count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 order by 1; - count -------- - 50140 -(1 row) - -select s, count(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, count(s) from aggfns where cfloat8 <= 0 group by s order by count(s), s limit 10; s | count ---+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 5014 - 1 | 5014 - 2 | 5015 - 3 | 5015 - 4 | 5014 - 5 | 5013 - 6 | 5013 - 7 | 5014 - 8 | 5014 - 9 | 5014 -(10 rows) - -select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; + 2 | 9825 + 4 | 9962 + 5 | 9991 + 6 | 9996 + 1 | 10041 + 3 | 10098 + 0 | 10119 + 9 | 10121 + 7 | 10127 + 8 | 10212 +(10 rows) + +select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by count(s), ss limit 10; ss | count ----+------- - 0 | 10057 - 3 | 10047 - 4 | 10049 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 - 11 | 20123 | 11 -(10 rows) - -select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 5014 - 3 | 5012 - 4 | 5010 - 5 | 5013 - 6 | 5013 - 7 | 5014 - 8 | 5014 - 9 | 5014 - 11 | 10033 - | 3 -(10 rows) - -select max(s) from aggfns where cfloat8 <= 0 order by 1; + 4 | 9955 + 5 | 9991 + 6 | 9996 + 3 | 10087 + 0 | 10119 + 9 | 10121 + 7 | 10127 + 8 | 10212 + 11 | 19873 +(10 rows) + +select max(s) from aggfns where cfloat8 <= 0; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(s) from aggfns where cfloat8 <= 0 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -5280,28 +4644,28 @@ select s, max(s) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by max(s), ss limit 10; ss | max ----+----- 0 | 0 3 | 3 + | 3 4 | 4 + 11 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 4 - | 3 (10 rows) -select min(s) from aggfns where cfloat8 <= 0 order by 1; +select min(s) from aggfns where cfloat8 <= 0; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(s) from aggfns where cfloat8 <= 0 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -5316,28 +4680,28 @@ select s, min(s) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by min(s), ss limit 10; ss | min ----+----- 0 | 0 + 11 | 1 3 | 3 + | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 1 - | 3 (10 rows) -select stddev(s) from aggfns where cfloat8 <= 0 order by 1; +select stddev(s) from aggfns where cfloat8 <= 0; stddev -------------------- - 2.8722956022845549 + 2.8788449199038282 (1 row) -select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -5352,7 +4716,7 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by stddev(s), ss limit 10; ss | stddev ----+------------------------ 0 | 0 @@ -5363,68 +4727,68 @@ select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by 1; 7 | 0 8 | 0 9 | 0 - 11 | 0.50239111765906328317 | 0 + 11 | 0.50210095387112910955 (10 rows) -select sum(s) from aggfns where cfloat8 <= 0 order by 1; +select sum(s) from aggfns where cfloat8 <= 0; sum -------- - 452557 + 453438 (1 row) -select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by 1; + 1 | 10041 + 2 | 19650 + 3 | 30294 + 4 | 39848 + 5 | 49955 + 6 | 59976 + 7 | 70889 + 8 | 81696 + 9 | 91089 +(10 rows) + +select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by sum(s), ss limit 10; ss | sum ----+------- 0 | 0 - 3 | 30141 - 4 | 40196 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 - 11 | 30205 | 33 + 11 | 29719 + 3 | 30261 + 4 | 39820 + 5 | 49955 + 6 | 59976 + 7 | 70889 + 8 | 81696 + 9 | 91089 (10 rows) -select avg(ss) from aggfns where cfloat8 <= 0 order by 1; +select avg(ss) from aggfns where cfloat8 <= 0; avg -------------------- - 6.4009387523742281 + 6.3921437883779023 (1 row) -select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 11.0000000000000000 - 2 | 11.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0055682609127971 + 4 | 4.0049186910258984 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by avg(ss), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 @@ -5439,28 +4803,28 @@ select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; | (10 rows) -select max(ss) from aggfns where cfloat8 <= 0 order by 1; +select max(ss) from aggfns where cfloat8 <= 0; max ----- 11 (1 row) -select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 - 4 | 11 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by max(ss), ss limit 10; ss | max ----+----- 0 | 0 @@ -5475,18 +4839,16 @@ select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; | (10 rows) -select min(ss) from aggfns where cfloat8 <= 0 order by 1; +select min(ss) from aggfns where cfloat8 <= 0; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 4 | 4 5 | 5 @@ -5494,9 +4856,11 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by min(ss), ss limit 10; ss | min ----+----- 0 | 0 @@ -5511,28 +4875,28 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; | (10 rows) -select stddev(ss) from aggfns where cfloat8 <= 0 order by 1; +select stddev(ss) from aggfns where cfloat8 <= 0; stddev -------------------- - 3.3528527058531930 + 3.3510077839151207 (1 row) -select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by stddev(ss), s limit 10; s | stddev ---+------------------------ 0 | 0 1 | 0 2 | 0 3 | 0 - 4 | 0.19735930141067535100 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 + 4 | 0.18549958974449259010 (10 rows) -select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by stddev(ss), ss limit 10; ss | stddev ----+-------- 0 | 0 @@ -5547,127 +4911,121 @@ select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; | (10 rows) -select sum(ss) from aggfns where cfloat8 <= 0 order by 1; +select sum(ss) from aggfns where cfloat8 <= 0; sum -------- - 643672 + 642289 (1 row) -select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 110627 - 2 | 110638 - 3 | 30141 - 4 | 40284 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; + 3 | 30261 + 4 | 39897 + 5 | 49955 + 6 | 59976 + 7 | 70889 + 8 | 81696 + 9 | 91089 + 2 | 108075 + 1 | 110451 +(10 rows) + +select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 - 3 | 30141 - 4 | 40196 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 - 11 | 221353 + 3 | 30261 + 4 | 39820 + 5 | 49955 + 6 | 59976 + 7 | 70889 + 8 | 81696 + 9 | 91089 + 11 | 218603 | (10 rows) -select max(t) from aggfns where cfloat8 <= 0 order by 1; +select max(t) from aggfns where cfloat8 <= 0; max -------- - 109999 + 110000 (1 row) -select s, max(t) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(t) from aggfns where cfloat8 <= 0 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 1 | 29999 - 2 | 40000 - 3 | 50000 + 2 | 39999 + 3 | 49996 4 | 59999 - 5 | 70000 + 5 | 69998 6 | 79999 7 | 90000 - 8 | 100000 - 9 | 109999 + 8 | 99999 + 9 | 110000 (10 rows) -select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 20000 - 3 | 50000 + | 49491 + 3 | 49996 + 11 | 54964 4 | 59999 - 5 | 70000 + 5 | 69998 6 | 79999 7 | 90000 - 8 | 100000 - 9 | 109999 - 11 | 59192 - | 48438 + 8 | 99999 + 9 | 110000 (10 rows) -select min(t) from aggfns where cfloat8 <= 0 order by 1; +select min(t) from aggfns where cfloat8 <= 0; min ----- - 3 + 8 (1 row) -select s, min(t) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(t) from aggfns where cfloat8 <= 0 group by s order by min(t), s limit 10; s | min ---+------- - 0 | 3 - 1 | 10002 + 0 | 8 + 1 | 10001 2 | 20001 3 | 30001 - 4 | 40001 + 4 | 40003 5 | 50001 - 6 | 60001 - 7 | 70004 - 8 | 80003 - 9 | 90002 + 6 | 60002 + 7 | 70005 + 8 | 80001 + 9 | 90001 (10 rows) -select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; +select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by min(t), ss limit 10; ss | min ----+------- - 0 | 3 + 0 | 8 + 11 | 10001 3 | 30001 - 4 | 40001 + | 32643 + 4 | 40003 5 | 50001 - 6 | 60001 - 7 | 70004 - 8 | 80003 - 9 | 90002 - 11 | 10002 - | 30537 + 6 | 60002 + 7 | 70005 + 8 | 80001 + 9 | 90001 (10 rows) -select count(*) from aggfns where cfloat8 < 1000 order by 1; +select count(*) from aggfns where cfloat8 < 1000; count -------- 200000 (1 row) -select count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; - count -------- - 99428 -(1 row) - -select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, count(*) from aggfns where cfloat8 < 1000 group by s order by count(*), s limit 10; s | count ---+------- 0 | 20000 @@ -5682,547 +5040,496 @@ select s, count(*) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) -select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; - s | count ----+------- - 0 | 9942 - 1 | 9943 - 2 | 9943 - 3 | 9943 - 4 | 9943 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 -(10 rows) - -select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by count(*), ss limit 10; ss | count ----+------- - 0 | 20000 + | 19 3 | 19981 4 | 19981 + 0 | 20000 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 11 | 40019 - | 19 -(10 rows) - -select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 9942 - 3 | 9937 - 4 | 9932 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 - 11 | 19897 - | 6 -(10 rows) - -select x, count(*) from aggfns where cfloat8 < 1000 group by x order by 1; - x | count -----+------- - 0 | 20000 - 11 | 40019 - 3 | 19981 - 4 | 19981 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - | 19 (10 rows) -select max(cdate) from aggfns where cfloat8 < 1000 order by 1; +select max(cdate) from aggfns where cfloat8 < 1000; max ------------ - 03-05-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 < 1000 group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by max(cdate), ss limit 10; ss | max ----+------------ - 0 | 10-05-2075 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 - 11 | 01-24-2183 - | 07-03-2156 -(10 rows) - -select min(cdate) from aggfns where cfloat8 < 1000 order by 1; + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns where cfloat8 < 1000; min ------------ - 01-02-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 < 1000 group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by min(cdate), ss limit 10; ss | min ----+------------ - 0 | 01-02-2021 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 - 11 | 05-20-2048 - | 08-11-2104 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 < 1000 order by 1; + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns where cfloat8 < 1000; avg ----- NaN (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.132126759885764 - 3 | -Infinity - 4 | -0.124977103379316 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 - 11 | NaN - | -5.91588952823689 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select s, avg(cfloat4) from aggfns where cfloat8 < 1000 group by s order by avg(cfloat4), s limit 10; + s | avg +---+---------------------- + 3 | -Infinity + 9 | -0.292700759558938 + 4 | -0.177721596086072 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 2 | Infinity + 1 | NaN +(10 rows) + +select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+---------------------- + 3 | -Infinity + | -1.39583652270468 + 9 | -0.292700759558938 + 4 | -0.169252917487522 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 11 | NaN +(10 rows) + +select max(cfloat4) from aggfns where cfloat8 < 1000; max ----- NaN (1 row) -select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by max(cfloat4), s limit 10; s | max ---+---------- - 0 | 49.9977 - 1 | NaN + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + 1 | NaN (10 rows) -select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by max(cfloat4), ss limit 10; ss | max ----+--------- - 0 | 49.9977 - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 + | 47.2047 + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 11 | NaN - | 48.478 (10 rows) -select min(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select min(cfloat4) from aggfns where cfloat8 < 1000; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 < 1000 group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; + 4 | -49.9999 + 6 | -49.9995 + 2 | -49.9991 + 7 | -49.9984 + 1 | -49.9974 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 +(10 rows) + +select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by min(cfloat4), ss limit 10; ss | min ----+----------- - 0 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 + 4 | -49.9999 + 6 | -49.9995 + 7 | -49.9984 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 + | -45.4083 11 | NaN - | -46.7478 (10 rows) -select stddev(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select stddev(cfloat4) from aggfns where cfloat8 < 1000; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8941380063426 + 0 | 28.7274163912974 + 7 | 28.7892027644317 + 4 | 28.8273136003882 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270615 1 | NaN 2 | NaN 3 | NaN - 4 | 28.8948189281653 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301629 - 8 | 28.8963276918371 - 9 | 28.8968307405967 (10 rows) -select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - 0 | 28.8941380063427 + 0 | 28.7274163912974 + 7 | 28.7892027644318 + 4 | 28.8220943927954 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270614 + | 30.6324072248673 3 | NaN - 4 | 28.89302954083 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301628 - 8 | 28.8963276918371 - 9 | 28.8968307405966 11 | NaN - | 27.2867943876683 (10 rows) -select sum(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select sum(cfloat4) from aggfns where cfloat8 < 1000; sum ----- NaN (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 < 1000 group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 + 9 | -5854.02 + 4 | -3554.43 + 6 | -122.193 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 2 | Infinity + 1 | NaN (10 rows) -select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+----------- - 0 | -2642.54 3 | -Infinity - 4 | -2497.17 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 + 9 | -5854.02 + 4 | -3381.84 + 6 | -122.193 + | -26.5209 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 11 | NaN - | -112.402 (10 rows) -select avg(cfloat8) from aggfns where cfloat8 < 1000 order by 1; +select avg(cfloat8) from aggfns where cfloat8 < 1000; avg -------------------- - -0.131776180773973 + -0.162669734027353 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.131261021163082 - 3 | -0.128550004763072 - 4 | -0.129264304572168 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 - 11 | -0.131587538323368 - | -4.30903203025656 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 < 1000 order by 1; - max ------------------ - 49.997744965367 +select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by avg(cfloat8), s limit 10; + s | avg +---+----------------------- + 8 | -0.607624531147303 + 7 | -0.454194548579399 + 9 | -0.448788876848994 + 3 | -0.364286396751413 + 0 | -0.306925132697215 + 1 | -0.0518103775125928 + 6 | -4.20950399711728e-05 + 5 | 0.0180876209540293 + 4 | 0.032399496253347 + 2 | 0.55648750109598 +(10 rows) + +select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+----------------------- + | -6.85744955032868 + 8 | -0.607624531147303 + 7 | -0.454194548579399 + 9 | -0.448788876848994 + 3 | -0.358112026103399 + 0 | -0.306925132697215 + 6 | -4.20950399711728e-05 + 5 | 0.0180876209540293 + 4 | 0.0258167200477049 + 11 | 0.25552084043733 +(10 rows) + +select max(cfloat8) from aggfns where cfloat8 < 1000; + max +------------------ + 49.9996809987351 (1 row) -select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; +select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 1 | 49.9971219105646 + 2 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - 0 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 - 11 | 49.997744965367 - | 49.2015035590157 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 < 1000 order by 1; + | 41.8287402018905 + 4 | 49.9951320933178 + 0 | 49.9965498689562 + 8 | 49.9969401862472 + 11 | 49.9983029672876 + 6 | 49.9984448775649 + 9 | 49.998860899359 + 5 | 49.9991805525497 + 3 | 49.9995571095496 + 7 | 49.9996809987351 +(10 rows) + +select min(cfloat8) from aggfns where cfloat8 < 1000; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 1 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + 2 | -49.9854512279853 +(10 rows) + +select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- - 0 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 - 11 | -49.9755693599582 - | -38.3512130472809 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 < 1000 order by 1; + 0 | -49.9994775978848 + 9 | -49.9993407865986 + 4 | -49.998479289934 + 11 | -49.9980724882334 + 8 | -49.9969880329445 + 7 | -49.9969201860949 + 5 | -49.9964643968269 + 6 | -49.9959305627272 + 3 | -49.9903481686488 + | -40.4587021796033 +(10 rows) + +select stddev(cfloat8) from aggfns where cfloat8 < 1000; stddev ----------------- - 28.894749851557 + 28.892061623641 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840889 - 5 | 28.8960532056264 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; + 8 | 28.785076111741 + 9 | 28.7991243564982 + 4 | 28.8027578036838 + 7 | 28.8638207913961 + 2 | 28.871977070659 + 3 | 28.8844659681246 + 1 | 28.9470128733139 + 0 | 28.965342556856 + 5 | 28.9663806098752 + 6 | 29.0218963292706 +(10 rows) + +select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - 0 | 28.893219634188 - 3 | 28.8988694216911 - 4 | 28.8937408619903 - 5 | 28.8960532056265 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 - 11 | 28.8954978116663 - | 24.556507133269 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 < 1000 order by 1; + | 27.2393448599587 + 8 | 28.7850761117411 + 9 | 28.7991243564982 + 4 | 28.8000379619243 + 7 | 28.863820791396 + 3 | 28.8859339629585 + 11 | 28.9120343325061 + 0 | 28.9653425568561 + 5 | 28.9663806098753 + 6 | 29.0218963292706 +(10 rows) + +select sum(cfloat8) from aggfns where cfloat8 < 1000; sum ------------------- - -26355.2361547947 + -32533.9468054706 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+------------------- - 0 | -2625.22042326164 - 3 | -2568.55764517095 - 4 | -2582.83006965648 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 - 11 | -5266.00169616286 - | -81.8716085748747 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 < 1000 order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by sum(cfloat8), s limit 10; + s | sum +---+-------------------- + 8 | -12152.4906229461 + 7 | -9083.89097158797 + 9 | -8975.77753697988 + 3 | -7285.72793502826 + 0 | -6138.50265394431 + 1 | -1036.20755025186 + 6 | -0.841900799423456 + 5 | 361.752419080585 + 4 | 647.98992506694 + 2 | 11129.7500219196 +(10 rows) + +select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+-------------------- + 8 | -12152.4906229461 + 7 | -9083.89097158797 + 9 | -8975.77753697988 + 3 | -7155.43639357202 + 0 | -6138.50265394431 + | -130.291541456245 + 6 | -0.841900799423456 + 5 | 361.752419080585 + 4 | 515.843883273192 + 11 | 10225.6885134615 +(10 rows) + +select avg(cint2) from aggfns where cfloat8 < 1000; avg ---------------------- - -42.1591712126520194 + -33.1461788699264301 (1 row) -select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -42.2972824182973825 - 3 | -42.6071034966436229 - 4 | -40.0837090471896604 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 - 11 | -42.9734623946374528 - | -335.0000000000000000 -(10 rows) - -select count(cint2) from aggfns where cfloat8 < 1000 order by 1; +select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 2 | -158.3178019118162254 + 8 | -129.4959711726139833 + 3 | -95.7656773935238477 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 4 | -28.7127771382813673 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 1 | 91.9493518842900756 + 5 | 110.0305290025524248 +(10 rows) + +select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -1368.1578947368421053 + 8 | -129.4959711726139833 + 3 | -94.5546037471195271 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 11 | -33.7550336409794652 + 4 | -27.5652740206392145 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 5 | 110.0305290025524248 +(10 rows) + +select count(cint2) from aggfns where cfloat8 < 1000; count -------- 199810 (1 row) -select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; - count -------- - 99342 -(1 row) - -select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by count(cint2), s limit 10; s | count ---+------- 0 | 19981 @@ -6237,757 +5544,640 @@ select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 19981 (10 rows) -select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; - s | count ----+------- - 0 | 9936 - 1 | 9935 - 2 | 9935 - 3 | 9934 - 4 | 9933 - 5 | 9933 - 6 | 9932 - 7 | 9936 - 8 | 9933 - 9 | 9935 -(10 rows) - -select ss, count(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, count(cint2) from aggfns where cfloat8 < 1000 group by ss order by count(cint2), ss limit 10; ss | count ----+------- - 0 | 19981 + | 19 3 | 19962 4 | 19962 + 0 | 19981 5 | 19981 6 | 19981 7 | 19981 8 | 19981 9 | 19981 11 | 39981 - | 19 -(10 rows) - -select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 9936 - 3 | 9928 - 4 | 9922 - 5 | 9933 - 6 | 9932 - 7 | 9936 - 8 | 9933 - 9 | 9935 - 11 | 19881 - | 6 -(10 rows) - -select x, count(cint2) from aggfns where cfloat8 < 1000 group by x order by 1; - x | count -----+------- - 0 | 19981 - 11 | 39981 - 3 | 19962 - 4 | 19962 - 5 | 19981 - 6 | 19981 - 7 | 19981 - 8 | 19981 - 9 | 19981 - | 19 (10 rows) -select max(cint2) from aggfns where cfloat8 < 1000 order by 1; +select max(cint2) from aggfns where cfloat8 < 1000; max ------- 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 < 1000 group by s order by max(cint2), s limit 10; s | max ---+------- + 3 | 16380 + 2 | 16381 + 5 | 16381 + 7 | 16381 + 8 | 16382 0 | 16383 1 | 16383 - 2 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by max(cint2), ss limit 10; ss | max ----+------- + | 16362 + 3 | 16380 + 5 | 16381 + 7 | 16381 + 8 | 16382 0 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 9 | 16383 11 | 16383 - | 13720 (10 rows) -select min(cint2) from aggfns where cfloat8 < 1000 order by 1; +select min(cint2) from aggfns where cfloat8 < 1000; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 < 1000 group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by min(cint2), ss limit 10; ss | min ----+-------- - 0 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 9 | -16375 - 11 | -16375 - | -15206 + | -16100 (10 rows) -select stddev(cint2) from aggfns where cfloat8 < 1000 order by 1; +select stddev(cint2) from aggfns where cfloat8 < 1000; stddev ------------------- - 9467.689085960139 + 9475.597346265432 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cint2) from aggfns where cfloat8 < 1000 group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; + 9 | 9450.322790943425 + 2 | 9458.737760855119 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9473.424234931108 + 8 | 9477.586839536066 + 4 | 9483.720025499142 + 0 | 9484.907423282680 + 1 | 9528.039076724276 +(10 rows) + +select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+------------------- - 0 | 9468.854793575036 - 3 | 9466.351508971864 - 4 | 9469.021659499615 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 - 11 | 9467.946206136906 - | 9796.780548277639 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 < 1000 order by 1; + | 8413.549166956554 + 9 | 9450.322790943425 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9474.482349111595 + 8 | 9477.586839536066 + 4 | 9483.611454519949 + 0 | 9484.907423282680 + 11 | 9494.206429493352 +(10 rows) + +select sum(cint2) from aggfns where cfloat8 < 1000; sum ---------- - -8423824 + -6622938 (1 row) -select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; - sum ------------ - -17618159 +select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 2 | -3163348 + 8 | -2587459 + 3 | -1913494 + 6 | -1220352 + 7 | -1116329 + 4 | -573710 + 9 | -435575 + 0 | 351569 + 1 | 1837240 + 5 | 2198520 +(10 rows) + +select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 8 | -2587459 + 3 | -1887499 + 11 | -1349560 + 6 | -1220352 + 7 | -1116329 + 4 | -550258 + 9 | -435575 + | -25995 + 0 | 351569 + 5 | 2198520 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 < 1000; + avg +--------------------- + -4.9369150000000000 +(1 row) + +select s, avg(cint4) from aggfns where cfloat8 < 1000 group by s order by avg(cint4), s limit 10; + s | avg +---+----------------------- + 9 | -102.4283000000000000 + 2 | -101.3952000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 4 | 6.6530500000000000 + 0 | 27.7536500000000000 + 3 | 70.4102500000000000 + 1 | 71.5608500000000000 + 5 | 103.1069000000000000 +(10 rows) + +select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 9 | -102.4283000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 11 | -16.4247732327144606 + 4 | 9.6930584054852110 + 0 | 27.7536500000000000 + 3 | 68.3874180471447875 + 5 | 103.1069000000000000 + | 2197.6842105263157895 +(10 rows) + +select max(cint4) from aggfns where cfloat8 < 1000; + max +------- + 16383 +(1 row) + +select s, max(cint4) from aggfns where cfloat8 < 1000 group by s order by max(cint4), s limit 10; + s | max +---+------- + 3 | 16379 + 5 | 16379 + 7 | 16379 + 2 | 16381 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 +(10 rows) + +select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + +select min(cint4) from aggfns where cfloat8 < 1000; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfns where cfloat8 < 1000 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 + | -15907 +(10 rows) + +select stddev(cint4) from aggfns where cfloat8 < 1000; + stddev +------------------- + 9450.334382392243 +(1 row) + +select s, stddev(cint4) from aggfns where cfloat8 < 1000 group by s order by stddev(cint4), s limit 10; + s | stddev +---+------------------- + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 2 | 9440.675087350597 + 4 | 9443.098516157448 + 8 | 9450.281544631633 + 1 | 9459.538662433945 + 3 | 9474.762271621918 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + | 9361.317298404296 + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 4 | 9442.480718256247 + 8 | 9450.281544631633 + 11 | 9450.690059613938 + 3 | 9474.873657491443 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select sum(cint4) from aggfns where cfloat8 < 1000; + sum +--------- + -987383 (1 row) -select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by sum(cint4), s limit 10; s | sum ---+---------- - 0 | -1788968 - 1 | -1806454 - 2 | -1747433 - 3 | -1738178 - 4 | -1717456 - 5 | -1788759 - 6 | -1746163 - 7 | -1731851 - 8 | -1741688 - 9 | -1811209 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+---------- - 0 | -845142 - 3 | -850523 - 4 | -800151 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 - 11 | -1718122 - | -6365 -(10 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; + 9 | -2048566 + 2 | -2027904 + 6 | -1063133 + 7 | -852243 + 8 | -585231 + 4 | 133061 + 0 | 555073 + 3 | 1408205 + 1 | 1431217 + 5 | 2062138 +(10 rows) + +select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by sum(cint4), ss limit 10; ss | sum ----+---------- - 0 | -1788968 - 3 | -1737816 - 4 | -1696920 - 5 | -1788759 - 6 | -1746163 - 7 | -1731851 - 8 | -1741688 - 9 | -1811209 - 11 | -3574423 - | -362 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 < 1000 order by 1; - avg ------------------------ - -2833327.786810000000 + 9 | -2048566 + 6 | -1063133 + 7 | -852243 + 11 | -657303 + 8 | -585231 + | 41756 + 4 | 193677 + 0 | 555073 + 3 | 1366449 + 5 | 2062138 +(10 rows) + +select avg(cint8) from aggfns where cfloat8 < 1000; + avg +---------------------- + -12.1026800000000000 (1 row) -select s, avg(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(cint8) from aggfns where cfloat8 < 1000 group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 1 | -25.4401500000000000 + 4 | -19.5071500000000000 + 2 | -2.4691500000000000 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 39.9743500000000000 + 9 | 61.7467500000000000 +(10 rows) + +select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by avg(cint8), ss limit 10; ss | avg ----+----------------------- - 0 | -2919248.121000000000 - 3 | -2682566.613082428307 - 4 | -2753845.761523447275 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 - 11 | -2846001.238586671331 - | -146005017.57894737 -(10 rows) - -select max(cint4) from aggfns where cfloat8 < 1000 order by 1; - max ------------- - 1073660631 + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 4 | -17.0811771182623492 + 11 | -15.1685449411529523 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 37.6662329212752115 + 9 | 61.7467500000000000 + | 2467.2631578947368421 +(10 rows) + +select max(cint8) from aggfns where cfloat8 < 1000; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 978482473 -(10 rows) - -select min(cint4) from aggfns where cfloat8 < 1000 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -960881516 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 < 1000 order by 1; - stddev ------------ - 620480022 -(1 row) +select s, max(cint8) from aggfns where cfloat8 < 1000 group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16379 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 5 | 16383 +(10 rows) -select s, stddev(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+----------- - 0 | 620497458 - 3 | 620502162 - 4 | 620460588 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 - 11 | 620490348 - | 569369090 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 < 1000 order by 1; - sum ---------------- - -566665557362 -(1 row) - -select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; - sum ----------------- - 53436167838463 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+--------------- - 0 | 5342690615367 - 1 | 5343370718252 - 2 | 5343352005654 - 3 | 5343352005654 - 4 | 5344281595944 - 5 | 5343480575409 - 6 | 5343480575409 - 7 | 5344006156678 - 8 | 5344006156678 - 9 | 5344147433418 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+--------------- - 0 | -58384962420 - 3 | -53600363496 - 4 | -55024592161 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 - 11 | -113894123567 - | -2774095334 -(10 rows) - -select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+---------------- - 0 | 5342690615367 - 3 | 5340469357420 - 4 | 5338771617836 - 5 | 5343480575409 - 6 | 5343480575409 - 7 | 5344006156678 - 8 | 5344006156678 - 9 | 5344147433418 - 11 | 10692232702014 - | 2882648234 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 < 1000 order by 1; - avg ------------------------ - -2823388.766060000000 +select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 4 | 16383 + 5 | 16383 + 11 | 16383 +(10 rows) + +select min(cint8) from aggfns where cfloat8 < 1000; + min +-------- + -16383 (1 row) -select s, avg(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2836378.364750000000 - 3 | -2653999.743206045743 - 4 | -3009394.583854661929 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 - 11 | -2748620.862390364577 - | -127121035.31578947 -(10 rows) - -select max(cint8) from aggfns where cfloat8 < 1000 order by 1; - max ------------- - 1073660631 +select s, min(cint8) from aggfns where cfloat8 < 1000 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 2 | -16379 + 3 | -16378 +(10 rows) + +select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 3 | -16378 + | -14174 +(10 rows) + +select sum(cint8) from aggfns where cfloat8 < 1000; + sum +---------- + -2420536 (1 row) -select s, max(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 - 11 | 1073660631 - | 989667573 -(10 rows) - -select min(cint8) from aggfns where cfloat8 < 1000 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 - 11 | -1073184428 - | -796158533 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 < 1000 order by 1; - sum ---------------- - -564677753212 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+--------------- - 0 | -56727567295 - 3 | -53029568869 - 4 | -60130713180 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 - 11 | -109997058292 - | -2415299671 -(10 rows) - -select max(cts) from aggfns where cfloat8 < 1000 order by 1; +select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -2369740 + 5 | -1633911 + 1 | -508803 + 4 | -390143 + 2 | -49383 + 7 | -47127 + 6 | 238113 + 0 | 306036 + 3 | 799487 + 9 | 1234935 +(10 rows) + +select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -2369740 + 5 | -1633911 + 11 | -607030 + 4 | -341299 + 7 | -47127 + | 46878 + 6 | 238113 + 0 | 306036 + 3 | 752609 + 9 | 1234935 +(10 rows) + +select max(cts) from aggfns where cfloat8 < 1000; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 < 1000 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by max(cts), ss limit 10; ss | max ----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 - 11 | Fri Jan 01 17:27:33 2021 - | Fri Jan 01 14:45:52 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns where cfloat8 < 1000; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 < 1000 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by min(cts), ss limit 10; ss | min ----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 - 11 | Fri Jan 01 03:47:42 2021 - | Fri Jan 01 09:29:58 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns where cfloat8 < 1000; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 < 1000 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by max(ctstz), ss limit 10; ss | max ----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST - 11 | Fri Jan 01 17:27:33 2021 PST - | Fri Jan 01 14:45:52 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 < 1000; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 < 1000 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by min(ctstz), ss limit 10; ss | min ----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST - 11 | Fri Jan 01 03:47:42 2021 PST - | Fri Jan 01 09:29:58 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns where cfloat8 < 1000; avg -------------------- 4.5000000000000000 (1 row) -select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 @@ -7002,34 +6192,28 @@ select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by avg(s), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 + 11 | 1.5011869362053025 3 | 3.0000000000000000 + | 3.0000000000000000 4 | 4.0000000000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 - 11 | 1.5011869362053025 - | 3.0000000000000000 (10 rows) -select count(s) from aggfns where cfloat8 < 1000 order by 1; +select count(s) from aggfns where cfloat8 < 1000; count -------- 200000 (1 row) -select count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 order by 1; - count -------- - 99428 -(1 row) - -select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, count(s) from aggfns where cfloat8 < 1000 group by s order by count(s), s limit 10; s | count ---+------- 0 | 20000 @@ -7044,58 +6228,28 @@ select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) -select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by s order by 1; - s | count ----+------- - 0 | 9942 - 1 | 9943 - 2 | 9943 - 3 | 9943 - 4 | 9943 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 -(10 rows) - -select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by count(s), ss limit 10; ss | count ----+------- - 0 | 20000 + | 19 3 | 19981 4 | 19981 + 0 | 20000 5 | 20000 6 | 20000 7 | 20000 8 | 20000 9 | 20000 11 | 40019 - | 19 (10 rows) -select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 9942 - 3 | 9937 - 4 | 9932 - 5 | 9942 - 6 | 9942 - 7 | 9943 - 8 | 9943 - 9 | 9944 - 11 | 19897 - | 6 -(10 rows) - -select max(s) from aggfns where cfloat8 < 1000 order by 1; +select max(s) from aggfns where cfloat8 < 1000; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(s) from aggfns where cfloat8 < 1000 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -7110,28 +6264,28 @@ select s, max(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by max(s), ss limit 10; ss | max ----+----- 0 | 0 3 | 3 + | 3 4 | 4 + 11 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 4 - | 3 (10 rows) -select min(s) from aggfns where cfloat8 < 1000 order by 1; +select min(s) from aggfns where cfloat8 < 1000; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(s) from aggfns where cfloat8 < 1000 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -7146,28 +6300,28 @@ select s, min(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by min(s), ss limit 10; ss | min ----+----- 0 | 0 + 11 | 1 3 | 3 + | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 - 11 | 1 - | 3 (10 rows) -select stddev(s) from aggfns where cfloat8 < 1000 order by 1; +select stddev(s) from aggfns where cfloat8 < 1000; stddev -------------------- 2.8722885039992502 (1 row) -select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -7182,7 +6336,7 @@ select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by stddev(s), ss limit 10; ss | stddev ----+------------------------ 0 | 0 @@ -7193,17 +6347,17 @@ select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by 1; 7 | 0 8 | 0 9 | 0 - 11 | 0.50284545977155885187 | 0 + 11 | 0.50284545977155885187 (10 rows) -select sum(s) from aggfns where cfloat8 < 1000 order by 1; +select sum(s) from aggfns where cfloat8 < 1000; sum -------- 900000 (1 row) -select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by sum(s), s limit 10; s | sum ---+-------- 0 | 0 @@ -7218,33 +6372,31 @@ select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 180000 (10 rows) -select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by sum(s), ss limit 10; ss | sum ----+-------- 0 | 0 + | 57 3 | 59943 + 11 | 60076 4 | 79924 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 - 11 | 60076 - | 57 (10 rows) -select avg(ss) from aggfns where cfloat8 < 1000 order by 1; +select avg(ss) from aggfns where cfloat8 < 1000; avg -------------------- 6.4009880938689175 (1 row) -select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 11.0000000000000000 - 2 | 11.0000000000000000 3 | 3.0000000000000000 4 | 4.0066500000000000 5 | 5.0000000000000000 @@ -7252,9 +6404,11 @@ select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by avg(ss), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 @@ -7269,28 +6423,28 @@ select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select max(ss) from aggfns where cfloat8 < 1000 order by 1; +select max(ss) from aggfns where cfloat8 < 1000; max ----- 11 (1 row) -select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 - 4 | 11 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by max(ss), ss limit 10; ss | max ----+----- 0 | 0 @@ -7305,18 +6459,16 @@ select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select min(ss) from aggfns where cfloat8 < 1000 order by 1; +select min(ss) from aggfns where cfloat8 < 1000; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 11 - 2 | 11 3 | 3 4 | 4 5 | 5 @@ -7324,9 +6476,11 @@ select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by min(ss), ss limit 10; ss | min ----+----- 0 | 0 @@ -7341,28 +6495,28 @@ select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select stddev(ss) from aggfns where cfloat8 < 1000 order by 1; +select stddev(ss) from aggfns where cfloat8 < 1000; stddev -------------------- 3.3528328280068652 (1 row) -select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by stddev(ss), s limit 10; s | stddev ---+------------------------ 0 | 0 1 | 0 2 | 0 3 | 0 - 4 | 0.21565737387148452722 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 + 4 | 0.21565737387148452722 (10 rows) -select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by stddev(ss), ss limit 10; ss | stddev ----+-------- 0 | 0 @@ -7377,18 +6531,16 @@ select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select sum(ss) from aggfns where cfloat8 < 1000 order by 1; +select sum(ss) from aggfns where cfloat8 < 1000; sum --------- 1280076 (1 row) -select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 220000 - 2 | 220000 3 | 59943 4 | 80133 5 | 100000 @@ -7396,9 +6548,11 @@ select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by 1; 7 | 140000 8 | 160000 9 | 180000 + 1 | 220000 + 2 | 220000 (10 rows) -select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 @@ -7413,13 +6567,13 @@ select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; | (10 rows) -select max(t) from aggfns where cfloat8 < 1000 order by 1; +select max(t) from aggfns where cfloat8 < 1000; max -------- 110000 (1 row) -select s, max(t) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(t) from aggfns where cfloat8 < 1000 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 @@ -7434,28 +6588,28 @@ select s, max(t) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 110000 (10 rows) -select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 20000 + | 49491 3 | 50000 + 11 | 59192 4 | 60000 5 | 70000 6 | 80000 7 | 90000 8 | 100000 9 | 110000 - 11 | 59192 - | 49491 (10 rows) -select min(t) from aggfns where cfloat8 < 1000 order by 1; +select min(t) from aggfns where cfloat8 < 1000; min ----- 1 (1 row) -select s, min(t) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(t) from aggfns where cfloat8 < 1000 group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 @@ -7470,832 +6624,742 @@ select s, min(t) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 90001 (10 rows) -select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; +select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by min(t), ss limit 10; ss | min ----+------- 0 | 1 + 11 | 10001 3 | 30001 + | 30537 4 | 40001 5 | 50001 6 | 60001 7 | 70001 8 | 80001 9 | 90001 - 11 | 10001 - | 30537 (10 rows) -select count(*) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; +select count(*) from aggfns where cfloat8 > 1000; count ------- 0 (1 row) -select s, count(*) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select s, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, count(*) from aggfns where cfloat8 > 1000 group by s order by count(*), s limit 10; s | count ---+------- (0 rows) -select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select ss, count(*) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by count(*), ss limit 10; ss | count ----+------- (0 rows) -select x, count(*) from aggfns where cfloat8 > 1000 group by x order by 1; - x | count ----+------- -(0 rows) - -select max(cdate) from aggfns where cfloat8 > 1000 order by 1; +select max(cdate) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cdate) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 > 1000 group by s order by max(cdate), s limit 10; s | max ---+----- (0 rows) -select ss, max(cdate) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cdate) from aggfns where cfloat8 > 1000 group by ss order by max(cdate), ss limit 10; ss | max ----+----- (0 rows) -select min(cdate) from aggfns where cfloat8 > 1000 order by 1; +select min(cdate) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cdate) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 > 1000 group by s order by min(cdate), s limit 10; s | min ---+----- (0 rows) -select ss, min(cdate) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cdate) from aggfns where cfloat8 > 1000 group by ss order by min(cdate), ss limit 10; ss | min ----+----- (0 rows) -select avg(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select avg(cfloat4) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cfloat4) from aggfns where cfloat8 > 1000 group by s order by avg(cfloat4), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by avg(cfloat4), ss limit 10; ss | avg ----+----- (0 rows) -select max(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select max(cfloat4) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 > 1000 group by s order by max(cfloat4), s limit 10; s | max ---+----- (0 rows) -select ss, max(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by max(cfloat4), ss limit 10; ss | max ----+----- (0 rows) -select min(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select min(cfloat4) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 > 1000 group by s order by min(cfloat4), s limit 10; s | min ---+----- (0 rows) -select ss, min(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by min(cfloat4), ss limit 10; ss | min ----+----- (0 rows) -select stddev(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cfloat4) from aggfns where cfloat8 > 1000; stddev -------- (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select sum(cfloat4) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 > 1000 group by s order by sum(cfloat4), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+----- (0 rows) -select avg(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select avg(cfloat8) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 > 1000 group by s order by avg(cfloat8), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by avg(cfloat8), ss limit 10; ss | avg ----+----- (0 rows) -select max(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select max(cfloat8) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cfloat8) from aggfns where cfloat8 > 1000 group by s order by max(cfloat8), s limit 10; s | max ---+----- (0 rows) -select ss, max(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by max(cfloat8), ss limit 10; ss | max ----+----- (0 rows) -select min(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select min(cfloat8) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 > 1000 group by s order by min(cfloat8), s limit 10; s | min ---+----- (0 rows) -select ss, min(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by min(cfloat8), ss limit 10; ss | min ----+----- (0 rows) -select stddev(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cfloat8) from aggfns where cfloat8 > 1000; stddev -------- (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select sum(cfloat8) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 > 1000 group by s order by sum(cfloat8), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by sum(cfloat8), ss limit 10; ss | sum ----+----- (0 rows) -select avg(cint2) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint2) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint2) from aggfns where cfloat8 > 1000 group by s order by avg(cint2), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(cint2) from aggfns where cfloat8 > 1000 group by ss order by avg(cint2), ss limit 10; ss | avg ----+----- (0 rows) -select count(cint2) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; +select count(cint2) from aggfns where cfloat8 > 1000; count ------- 0 (1 row) -select s, count(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select s, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, count(cint2) from aggfns where cfloat8 > 1000 group by s order by count(cint2), s limit 10; s | count ---+------- (0 rows) -select ss, count(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select ss, count(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, count(cint2) from aggfns where cfloat8 > 1000 group by ss order by count(cint2), ss limit 10; ss | count ----+------- (0 rows) -select x, count(cint2) from aggfns where cfloat8 > 1000 group by x order by 1; - x | count ----+------- -(0 rows) - -select max(cint2) from aggfns where cfloat8 > 1000 order by 1; +select max(cint2) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 > 1000 group by s order by max(cint2), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cint2) from aggfns where cfloat8 > 1000 group by ss order by max(cint2), ss limit 10; ss | max ----+----- (0 rows) -select min(cint2) from aggfns where cfloat8 > 1000 order by 1; +select min(cint2) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 > 1000 group by s order by min(cint2), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cint2) from aggfns where cfloat8 > 1000 group by ss order by min(cint2), ss limit 10; ss | min ----+----- (0 rows) -select stddev(cint2) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cint2) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cint2) from aggfns where cfloat8 > 1000 group by s order by stddev(cint2), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(cint2) from aggfns where cfloat8 > 1000 group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(cint2) from aggfns where cfloat8 > 1000 order by 1; - sum ------ - -(1 row) - -select sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint2) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; - s | sum ----+----- -(0 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by sum(cint2), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(cint2) from aggfns where cfloat8 > 1000 group by ss order by sum(cint2), ss limit 10; ss | sum ----+----- (0 rows) -select avg(cint4) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint4) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint4) from aggfns where cfloat8 > 1000 group by s order by avg(cint4), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(cint4) from aggfns where cfloat8 > 1000 group by ss order by avg(cint4), ss limit 10; ss | avg ----+----- (0 rows) -select max(cint4) from aggfns where cfloat8 > 1000 order by 1; +select max(cint4) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint4) from aggfns where cfloat8 > 1000 group by s order by max(cint4), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cint4) from aggfns where cfloat8 > 1000 group by ss order by max(cint4), ss limit 10; ss | max ----+----- (0 rows) -select min(cint4) from aggfns where cfloat8 > 1000 order by 1; +select min(cint4) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint4) from aggfns where cfloat8 > 1000 group by s order by min(cint4), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cint4) from aggfns where cfloat8 > 1000 group by ss order by min(cint4), ss limit 10; ss | min ----+----- (0 rows) -select stddev(cint4) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cint4) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cint4) from aggfns where cfloat8 > 1000 group by s order by stddev(cint4), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(cint4) from aggfns where cfloat8 > 1000 group by ss order by stddev(cint4), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(cint4) from aggfns where cfloat8 > 1000 order by 1; - sum ------ - -(1 row) - -select sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint4) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; - s | sum ----+----- -(0 rows) - -select s, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by sum(cint4), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select ss, sum(cint4) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(cint4) from aggfns where cfloat8 > 1000 group by ss order by sum(cint4), ss limit 10; ss | sum ----+----- (0 rows) -select avg(cint8) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint8) from aggfns where cfloat8 > 1000; avg ----- (0 rows) -select s, avg(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint8) from aggfns where cfloat8 > 1000 group by s order by avg(cint8), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(cint8) from aggfns where cfloat8 > 1000 group by ss order by avg(cint8), ss limit 10; ss | avg ----+----- (0 rows) -select max(cint8) from aggfns where cfloat8 > 1000 order by 1; +select max(cint8) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint8) from aggfns where cfloat8 > 1000 group by s order by max(cint8), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cint8) from aggfns where cfloat8 > 1000 group by ss order by max(cint8), ss limit 10; ss | max ----+----- (0 rows) -select min(cint8) from aggfns where cfloat8 > 1000 order by 1; +select min(cint8) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint8) from aggfns where cfloat8 > 1000 group by s order by min(cint8), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cint8) from aggfns where cfloat8 > 1000 group by ss order by min(cint8), ss limit 10; ss | min ----+----- (0 rows) -select sum(cint8) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint8) from aggfns where cfloat8 > 1000; sum ----- (0 rows) -select s, sum(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint8) from aggfns where cfloat8 > 1000 group by s order by sum(cint8), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(cint8) from aggfns where cfloat8 > 1000 group by ss order by sum(cint8), ss limit 10; ss | sum ----+----- (0 rows) -select max(cts) from aggfns where cfloat8 > 1000 order by 1; +select max(cts) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cts) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 > 1000 group by s order by max(cts), s limit 10; s | max ---+----- (0 rows) -select ss, max(cts) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(cts) from aggfns where cfloat8 > 1000 group by ss order by max(cts), ss limit 10; ss | max ----+----- (0 rows) -select min(cts) from aggfns where cfloat8 > 1000 order by 1; +select min(cts) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cts) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 > 1000 group by s order by min(cts), s limit 10; s | min ---+----- (0 rows) -select ss, min(cts) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(cts) from aggfns where cfloat8 > 1000 group by ss order by min(cts), ss limit 10; ss | min ----+----- (0 rows) -select max(ctstz) from aggfns where cfloat8 > 1000 order by 1; +select max(ctstz) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(ctstz) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 > 1000 group by s order by max(ctstz), s limit 10; s | max ---+----- (0 rows) -select ss, max(ctstz) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(ctstz) from aggfns where cfloat8 > 1000 group by ss order by max(ctstz), ss limit 10; ss | max ----+----- (0 rows) -select min(ctstz) from aggfns where cfloat8 > 1000 order by 1; +select min(ctstz) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(ctstz) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 > 1000 group by s order by min(ctstz), s limit 10; s | min ---+----- (0 rows) -select ss, min(ctstz) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(ctstz) from aggfns where cfloat8 > 1000 group by ss order by min(ctstz), ss limit 10; ss | min ----+----- (0 rows) -select avg(s) from aggfns where cfloat8 > 1000 order by 1; +select avg(s) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 > 1000 group by s order by avg(s), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(s) from aggfns where cfloat8 > 1000 group by ss order by avg(s), ss limit 10; ss | avg ----+----- (0 rows) -select count(s) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 order by 1; +select count(s) from aggfns where cfloat8 > 1000; count ------- 0 (1 row) -select s, count(s) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select s, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, count(s) from aggfns where cfloat8 > 1000 group by s order by count(s), s limit 10; s | count ---+------- (0 rows) -select ss, count(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, count(s) from aggfns where cfloat8 > 1000 group by ss order by count(s), ss limit 10; ss | count ----+------- (0 rows) -select ss, count(s) filter (where cint4 > 0) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select max(s) from aggfns where cfloat8 > 1000 order by 1; +select max(s) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(s) from aggfns where cfloat8 > 1000 group by s order by max(s), s limit 10; s | max ---+----- (0 rows) -select ss, max(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(s) from aggfns where cfloat8 > 1000 group by ss order by max(s), ss limit 10; ss | max ----+----- (0 rows) -select min(s) from aggfns where cfloat8 > 1000 order by 1; +select min(s) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(s) from aggfns where cfloat8 > 1000 group by s order by min(s), s limit 10; s | min ---+----- (0 rows) -select ss, min(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(s) from aggfns where cfloat8 > 1000 group by ss order by min(s), ss limit 10; ss | min ----+----- (0 rows) -select stddev(s) from aggfns where cfloat8 > 1000 order by 1; +select stddev(s) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 > 1000 group by s order by stddev(s), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(s) from aggfns where cfloat8 > 1000 group by ss order by stddev(s), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(s) from aggfns where cfloat8 > 1000 order by 1; +select sum(s) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 > 1000 group by s order by sum(s), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(s) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(s) from aggfns where cfloat8 > 1000 group by ss order by sum(s), ss limit 10; ss | sum ----+----- (0 rows) -select avg(ss) from aggfns where cfloat8 > 1000 order by 1; +select avg(ss) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 > 1000 group by s order by avg(ss), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by avg(ss), ss limit 10; ss | avg ----+----- (0 rows) -select max(ss) from aggfns where cfloat8 > 1000 order by 1; +select max(ss) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 > 1000 group by s order by max(ss), s limit 10; s | max ---+----- (0 rows) -select ss, max(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(ss) from aggfns where cfloat8 > 1000 group by ss order by max(ss), ss limit 10; ss | max ----+----- (0 rows) -select min(ss) from aggfns where cfloat8 > 1000 order by 1; +select min(ss) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 > 1000 group by s order by min(ss), s limit 10; s | min ---+----- (0 rows) -select ss, min(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(ss) from aggfns where cfloat8 > 1000 group by ss order by min(ss), ss limit 10; ss | min ----+----- (0 rows) -select stddev(ss) from aggfns where cfloat8 > 1000 order by 1; +select stddev(ss) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(ss) from aggfns where cfloat8 > 1000 group by s order by stddev(ss), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, stddev(ss) from aggfns where cfloat8 > 1000 group by ss order by stddev(ss), ss limit 10; ss | stddev ----+-------- (0 rows) -select sum(ss) from aggfns where cfloat8 > 1000 order by 1; +select sum(ss) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 > 1000 group by s order by sum(ss), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, sum(ss) from aggfns where cfloat8 > 1000 group by ss order by sum(ss), ss limit 10; ss | sum ----+----- (0 rows) -select max(t) from aggfns where cfloat8 > 1000 order by 1; +select max(t) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(t) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(t) from aggfns where cfloat8 > 1000 group by s order by max(t), s limit 10; s | max ---+----- (0 rows) -select ss, max(t) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, max(t) from aggfns where cfloat8 > 1000 group by ss order by max(t), ss limit 10; ss | max ----+----- (0 rows) -select min(t) from aggfns where cfloat8 > 1000 order by 1; +select min(t) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(t) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(t) from aggfns where cfloat8 > 1000 group by s order by min(t), s limit 10; s | min ---+----- (0 rows) -select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by 1; +select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by min(t), ss limit 10; ss | min ----+----- (0 rows) -select avg(cint2) from aggfns where cint2 is null order by 1; +select avg(cint2) from aggfns where cint2 is null; avg ----- (1 row) -select s, avg(cint2) from aggfns where cint2 is null group by s order by 1; +select s, avg(cint2) from aggfns where cint2 is null group by s order by avg(cint2), s limit 10; s | avg ---+----- 0 | @@ -8310,7 +7374,7 @@ select s, avg(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; +select ss, avg(cint2) from aggfns where cint2 is null group by ss order by avg(cint2), ss limit 10; ss | avg ----+----- 0 | @@ -8324,34 +7388,13 @@ select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) -select count(cint2) from aggfns where cint2 is null order by 1; - count -------- - 0 -(1 row) - -select count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null order by 1; +select count(cint2) from aggfns where cint2 is null; count ------- 0 (1 row) -select s, count(cint2) from aggfns where cint2 is null group by s order by 1; - s | count ----+------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select s, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by s order by 1; +select s, count(cint2) from aggfns where cint2 is null group by s order by count(cint2), s limit 10; s | count ---+------- 0 | 0 @@ -8366,21 +7409,7 @@ select s, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null 9 | 0 (10 rows) -select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | count -----+------- - 0 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 - 11 | 0 -(9 rows) - -select ss, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by ss order by 1; +select ss, count(cint2) from aggfns where cint2 is null group by ss order by count(cint2), ss limit 10; ss | count ----+------- 0 | 0 @@ -8394,27 +7423,13 @@ select ss, count(cint2) filter (where cint4 > 0) from aggfns where cint2 is null 11 | 0 (9 rows) -select x, count(cint2) from aggfns where cint2 is null group by x order by 1; - x | count -----+------- - 0 | 0 - 11 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(9 rows) - -select max(cint2) from aggfns where cint2 is null order by 1; +select max(cint2) from aggfns where cint2 is null; max ----- (1 row) -select s, max(cint2) from aggfns where cint2 is null group by s order by 1; +select s, max(cint2) from aggfns where cint2 is null group by s order by max(cint2), s limit 10; s | max ---+----- 0 | @@ -8429,7 +7444,7 @@ select s, max(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; +select ss, max(cint2) from aggfns where cint2 is null group by ss order by max(cint2), ss limit 10; ss | max ----+----- 0 | @@ -8443,13 +7458,13 @@ select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) -select min(cint2) from aggfns where cint2 is null order by 1; +select min(cint2) from aggfns where cint2 is null; min ----- (1 row) -select s, min(cint2) from aggfns where cint2 is null group by s order by 1; +select s, min(cint2) from aggfns where cint2 is null group by s order by min(cint2), s limit 10; s | min ---+----- 0 | @@ -8464,7 +7479,7 @@ select s, min(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; +select ss, min(cint2) from aggfns where cint2 is null group by ss order by min(cint2), ss limit 10; ss | min ----+----- 0 | @@ -8478,13 +7493,13 @@ select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) -select stddev(cint2) from aggfns where cint2 is null order by 1; +select stddev(cint2) from aggfns where cint2 is null; stddev -------- (1 row) -select s, stddev(cint2) from aggfns where cint2 is null group by s order by 1; +select s, stddev(cint2) from aggfns where cint2 is null group by s order by stddev(cint2), s limit 10; s | stddev ---+-------- 0 | @@ -8499,7 +7514,7 @@ select s, stddev(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; +select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+-------- 0 | @@ -8513,34 +7528,13 @@ select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; 11 | (9 rows) -select sum(cint2) from aggfns where cint2 is null order by 1; +select sum(cint2) from aggfns where cint2 is null; sum ----- (1 row) -select sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null order by 1; - sum ------ - -(1 row) - -select s, sum(cint2) from aggfns where cint2 is null group by s order by 1; - s | sum ----+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select s, sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by s order by 1; +select s, sum(cint2) from aggfns where cint2 is null group by s order by sum(cint2), s limit 10; s | sum ---+----- 0 | @@ -8555,21 +7549,7 @@ select s, sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null gr 9 | (10 rows) -select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | sum -----+----- - 0 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | - 11 | -(9 rows) - -select ss, sum(cint2) filter (where cint4 > 0) from aggfns where cint2 is null group by ss order by 1; +select ss, sum(cint2) from aggfns where cint2 is null group by ss order by sum(cint2), ss limit 10; ss | sum ----+----- 0 | @@ -8589,16 +7569,16 @@ order by count(*) desc, cint2 limit 10 ; count | count | min | cint2 -------+-------+----------+-------- - 190 | 0 | -49.6472 | - 60 | 60 | -13.3701 | -11208 - 60 | 60 | -48.5206 | 1924 - 50 | 50 | -44.7573 | -11714 - 50 | 50 | -22.1541 | -11331 - 50 | 50 | -35.9287 | -6252 - 50 | 50 | -9.84793 | -120 - 50 | 50 | -36.2595 | 15467 - 50 | 50 | -30.1285 | 15889 - 40 | 40 | -33.4605 | -15975 + 190 | 0 | -49.6644 | + 19 | 19 | -49.5299 | -8743 + 17 | 17 | -48.5497 | -12921 + 17 | 17 | -48.5697 | -701 + 17 | 17 | -47.2641 | 525 + 16 | 16 | -42.41 | -10234 + 16 | 16 | -47.2083 | -4609 + 16 | 16 | -49.9555 | -4261 + 16 | 16 | -35.1643 | -296 + 16 | 16 | -45.4426 | 1373 (10 rows) select s, count(*) from edges group by 1 order by 1; diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out new file mode 100644 index 00000000000..867387e79cc --- /dev/null +++ b/tsl/test/expected/vector_agg_grouping.out @@ -0,0 +1,372 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +----------------------- + (1,public,agggroup,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into agggroup select * from source where s = 1; +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 1 +(1 row) + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze agggroup; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0']) with ordinality as condition(condition, n), + unnest(array[ + 'x', + 'ss, x', + 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec +select x, count(*) from agggroup group by x order by count(*), x limit 10; + x | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select ss, x, count(*) from agggroup group by ss, x order by count(*), ss, x limit 10; + ss | x | count +----+----+------- + | | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 + 8 | 8 | 20000 + 9 | 9 | 20000 + 11 | 11 | 40019 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +----+---+----+---+--------+--------+-------+------- + 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 + 2 | 0 | 0 | 0 | -5373 | 1096 | -6638 | 1 + 3 | 0 | 0 | 0 | -7109 | -15920 | 13672 | 1 + 4 | 0 | 0 | 0 | -4927 | 14299 | -8187 | 1 + 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 + 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 + 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 + 8 | 0 | 0 | 0 | -12705 | -10427 | 876 | 1 + 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 + 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 +(10 rows) + +select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; + x | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + +select ss, x, count(cint2) from agggroup group by ss, x order by count(cint2), ss, x limit 10; + ss | x | count +----+----+------- + | | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 + 8 | 8 | 19981 + 9 | 9 | 19981 + 11 | 11 | 39981 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +-------+---+----+---+-------+--------+--------+------- + 1051 | 0 | 0 | 0 | | -8612 | 14327 | 0 + 2102 | 0 | 0 | 0 | | 11069 | 16047 | 0 + 3153 | 0 | 0 | 0 | | 6192 | 12700 | 0 + 4204 | 0 | 0 | 0 | | 4165 | -10102 | 0 + 5255 | 0 | 0 | 0 | | 16314 | 13418 | 0 + 6306 | 0 | 0 | 0 | | 701 | -3029 | 0 + 7357 | 0 | 0 | 0 | | 1115 | 4913 | 0 + 8408 | 0 | 0 | 0 | | 15553 | 1743 | 0 + 9459 | 0 | 0 | 0 | | -14640 | 11933 | 0 + 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 +(10 rows) + +select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; + x | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 11 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + +select ss, x, min(cint2) from agggroup group by ss, x order by min(cint2), ss, x limit 10; + ss | x | min +----+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 7 | 7 | -16382 + 8 | 8 | -16382 + 11 | 11 | -16382 + 3 | 3 | -16381 + 9 | 9 | -16375 + | | -16100 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | min +-------+---+----+----+--------+--------+--------+-------- + 6194 | 0 | 0 | 0 | -16383 | -13372 | 11094 | -16383 + 17044 | 0 | 0 | 0 | -16383 | -10318 | 6326 | -16383 + 53843 | 4 | 4 | 4 | -16383 | -9008 | 4390 | -16383 + 60530 | 5 | 5 | 5 | -16383 | 6729 | 6717 | -16383 + 73208 | 6 | 6 | 6 | -16383 | -3043 | -1794 | -16383 + 74870 | 6 | 6 | 6 | -16383 | -16190 | 13646 | -16383 + 22836 | 2 | 11 | 11 | -16382 | -3080 | -15609 | -16382 + 29858 | 2 | 11 | 11 | -16382 | -14012 | -9888 | -16382 + 31516 | 2 | 11 | 11 | -16382 | 6193 | 206 | -16382 + 76781 | 7 | 7 | 7 | -16382 | 9938 | 6519 | -16382 +(10 rows) + +select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; + x | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, x, count(*) from agggroup where cint2 > 0 group by ss, x order by count(*), ss, x limit 10; + ss | x | count +----+----+------- + | | 7 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 + 5 | 5 | 10110 + 11 | 11 | 19973 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +----+---+----+---+-------+--------+-------+------- + 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 + 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 + 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 + 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 + 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 + 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 + 14 | 0 | 0 | 0 | 4669 | -13766 | -398 | 1 + 15 | 0 | 0 | 0 | 15101 | -13009 | 14045 | 1 + 19 | 0 | 0 | 0 | 7684 | -16257 | 4566 | 1 + 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 +(10 rows) + +select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; + x | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select ss, x, count(cint2) from agggroup where cint2 > 0 group by ss, x order by count(cint2), ss, x limit 10; + ss | x | count +----+----+------- + | | 7 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 + 5 | 5 | 10110 + 11 | 11 | 19973 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +----+---+----+---+-------+--------+-------+------- + 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 + 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 + 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 + 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 + 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 + 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 + 14 | 0 | 0 | 0 | 4669 | -13766 | -398 | 1 + 15 | 0 | 0 | 0 | 15101 | -13009 | 14045 | 1 + 19 | 0 | 0 | 0 | 7684 | -16257 | 4566 | 1 + 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 +(10 rows) + +select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; + x | min +----+------ + 11 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 3667 +(10 rows) + +select ss, x, min(cint2) from agggroup where cint2 > 0 group by ss, x order by min(cint2), ss, x limit 10; + ss | x | min +----+----+------ + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 11 | 11 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 + | | 3667 +(10 rows) + +select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | min +-------+---+----+----+-------+--------+--------+----- + 11611 | 1 | 11 | 11 | 1 | -12025 | -2210 | 1 + 28649 | 2 | 11 | 11 | 1 | -1493 | -1043 | 1 + 28786 | 1 | 11 | 11 | 1 | -4190 | -2827 | 1 + 41774 | 3 | 3 | 3 | 1 | 1863 | 7650 | 1 + 41779 | 3 | 3 | 3 | 1 | 14078 | 9929 | 1 + 51152 | 5 | 5 | 5 | 1 | 9242 | -9798 | 1 + 70932 | 7 | 7 | 7 | 1 | -10344 | -13684 | 1 + 86957 | 7 | 7 | 7 | 1 | 15656 | 12597 | 1 + 89689 | 8 | 8 | 8 | 1 | 11189 | -5168 | 1 + 22147 | 1 | 11 | 11 | 2 | -9569 | 9760 | 2 +(10 rows) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 6d0fbc412ac..018f033252f 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -102,6 +102,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) recompress_chunk_segmentwise.sql feature_flags.sql vector_agg_default.sql + vector_agg_filter.sql + vector_agg_grouping.sql vector_agg_segmentby.sql) endif(CMAKE_BUILD_TYPE MATCHES Debug) diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql new file mode 100644 index 00000000000..513bcc231fa --- /dev/null +++ b/tsl/test/sql/vector_agg_filter.sql @@ -0,0 +1,107 @@ + +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into aggfilter select * from source where s = 1; + +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; + +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; +vacuum freeze analyze aggfilter; + + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's', + 'ss']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 074572a7a31..479cd49a7c8 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -20,19 +20,20 @@ create table aggfns(t int, s int, select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); create view source as -select s * 10000::int + t as t, +select s * 10000 + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end as cint2, - (mix(s + t + 2) * 32767 * 65536)::int4 as cint4, - (mix(s + t + 3) * 32767 * 65536)::int8 as cint8, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end as cfloat4, - (mix(s + t + 5) * 100)::float8 as cfloat8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t) as cts, - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t) as ctstz, - '2021-01-01'::date + interval '1 day' * (s * 10000::int + t) as cdate + else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, + (mix(s + t * 1039) * 100)::float8 as cfloat8, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) @@ -86,16 +87,17 @@ vacuum freeze analyze edges; set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +-- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s)%s from aggfns%s%s order by 1;', + format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, grouping || ', ', function, variable, - ' filter (where ' || agg_filter || ')', ' where ' || condition, - ' group by ' || grouping ) + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) from unnest(array[ 'explain (costs off) ', @@ -130,11 +132,7 @@ from unnest(array[ null, 's', - 'ss', - 'x']) with ordinality as grouping(grouping, n), - unnest(array[ - null, - 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -143,12 +141,8 @@ where -- This is not vectorized yet and (variable != 'cint8' or function != 'stddev') and (function != 'count' or variable in ('cint2', 's', '*')) - and (agg_filter is null or (function = 'count') or (function = 'sum' and variable in ('cint2', 'cint4'))) and (condition is distinct from 'cint2 is null' or variable = 'cint2') - -- No need to test the aggregate functions themselves again for string - -- grouping. - and (grouping is distinct from 'x' or (function = 'count' and variable in ('cint2', '*') and agg_filter is null)) -order by explain, condition.n, variable, function, grouping.n, agg_filter.n +order by explain, condition.n, variable, function, grouping.n \gexec diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql new file mode 100644 index 00000000000..cdc0d94ebc7 --- /dev/null +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -0,0 +1,100 @@ + +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into agggroup select * from source where s = 1; + +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('agggroup') x; + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; + +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; +vacuum freeze analyze agggroup; + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0']) with ordinality as condition(condition, n), + unnest(array[ + 'x', + 'ss, x', + 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec + +reset timescaledb.debug_require_vector_agg; From 9746d795a121bd53e4d52bb337b5049f4045260f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sun, 27 Oct 2024 12:21:39 +0100 Subject: [PATCH 071/242] explain and cleanups --- .../nodes/decompress_chunk/compressed_batch.c | 2 - tsl/src/nodes/vector_agg/exec.c | 6 +- tsl/src/nodes/vector_agg/grouping_policy.h | 2 + .../nodes/vector_agg/grouping_policy_batch.c | 7 + .../nodes/vector_agg/grouping_policy_hash.c | 25 +- .../nodes/vector_agg/grouping_policy_hash.h | 1 + tsl/src/nodes/vector_agg/hash_serialized.c | 1 + .../nodes/vector_agg/hash_single_fixed_2.c | 1 + .../nodes/vector_agg/hash_single_fixed_4.c | 1 + .../nodes/vector_agg/hash_single_fixed_8.c | 1 + tsl/src/nodes/vector_agg/hash_single_text.c | 1 + .../vector_agg/hash_table_functions_impl.c | 2 + tsl/test/expected/vector_agg_filter.out | 992 +++++++++++++++++- tsl/test/expected/vector_agg_grouping.out | 401 +++++++ tsl/test/expected/vectorized_aggregation.out | 322 +++++- tsl/test/sql/vector_agg_filter.sql | 3 +- tsl/test/sql/vector_agg_grouping.sql | 5 + 17 files changed, 1701 insertions(+), 72 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index d7614baa15d..8e9e8a03f59 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -345,8 +345,6 @@ compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_ var->varattno); Assert(column_description != NULL); Assert(column_description->typid == var->vartype); - Ensure(column_description->type == COMPRESSED_COLUMN, - "only compressed columns are supported in vectorized quals"); CompressedColumnValues *column_values = &batch_state->compressed_columns[column_index]; diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index ae6861e7d30..c5fc7b15f59 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -346,7 +346,11 @@ vector_agg_exec(CustomScanState *node) static void vector_agg_explain(CustomScanState *node, List *ancestors, ExplainState *es) { - /* No additional output is needed. */ + VectorAggState *state = (VectorAggState *) node; + if (es->verbose || es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyText("Grouping Policy", state->grouping->gp_explain(state->grouping), es); + } } static struct CustomExecMethods exec_methods = { diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 00f153423ce..c32447952cb 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -37,6 +37,8 @@ typedef struct GroupingPolicy bool (*gp_do_emit)(GroupingPolicy *gp, TupleTableSlot *aggregated_slot); void (*gp_destroy)(GroupingPolicy *gp); + + char *(*gp_explain)(GroupingPolicy *gp); } GroupingPolicy; extern GroupingPolicy *create_grouping_policy_batch(List *agg_defs, List *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 405cc53534d..b1b77e2c35b 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -259,9 +259,16 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return true; } +static char * +gp_batch_explain(GroupingPolicy *gp) +{ + return "entire batch"; +} + static const GroupingPolicy grouping_policy_batch_functions = { .gp_reset = gp_batch_reset, .gp_add_batch = gp_batch_add_batch, .gp_should_emit = gp_batch_should_emit, .gp_do_emit = gp_batch_do_emit, + .gp_explain = gp_batch_explain, }; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d38ddebb2ab..d0eaf5fd244 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -254,6 +254,9 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con start_row, end_row); + /* + * Process the aggregate function states. + */ const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; for (int i = 0; i < num_fns; i++) { @@ -270,8 +273,10 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con /* * Initialize the aggregate function states for the newly added keys. */ - agg_def->func.agg_init(agg_def->func.state_bytes * first_uninitialized_state_index + - (char *) list_nth(policy->per_agg_states, i), + void *first_uninitialized_state = + agg_def->func.state_bytes * first_uninitialized_state_index + + (char *) list_nth(policy->per_agg_states, i); + agg_def->func.agg_init(first_uninitialized_state, next_unused_key_index - first_uninitialized_state_index); } @@ -363,11 +368,17 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) ; const int start_row = start_word * 64 + pg_rightmost_one_pos64(filter[start_word]); + Assert(start_row <= n); + /* * The bits for past-the-end rows must be set to zero, so this * calculation should yield no more than n. */ - int end_row = (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; + Assert(end_word > start_word); + const int end_row = + (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; + Assert(end_row <= n); + add_one_range(policy, batch_state, start_row, end_row); stat_range_rows += end_row - start_row; @@ -461,9 +472,17 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return true; } +static char * +gp_hash_explain(GroupingPolicy *gp) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + return psprintf("hashed with %s key", policy->functions.explain_name); +} + static const GroupingPolicy grouping_policy_hash_functions = { .gp_reset = gp_hash_reset, .gp_add_batch = gp_hash_add_batch, .gp_should_emit = gp_hash_should_emit, .gp_do_emit = gp_hash_do_emit, + .gp_explain = gp_hash_explain, }; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 309e54560e1..ea985d1fc01 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -17,6 +17,7 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; typedef struct { + char *explain_name; void *(*create)(MemoryContext context, uint32 initial_rows, void *data); void (*reset)(void *table); uint32 (*get_num_keys)(void *table); diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index fa6dc62c03f..34afad37148 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -232,6 +232,7 @@ serialized_destroy_key(BytesView key) pfree((void *) key.data); } +#define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index d00e50f12dd..3799d4dae9b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -16,6 +16,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 #define KEY_BYTES 2 #define KEY_HASH hash64 diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index 928ef31e1da..e4982c9e11b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -16,6 +16,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 #define KEY_BYTES 4 #define KEY_HASH hash64 diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index b8646766caa..f191cbfe9ff 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -16,6 +16,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 #define KEY_BYTES 8 #define KEY_HASH hash64 diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index a91610714e7..511d94f83ac 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -95,6 +95,7 @@ single_text_destroy_key(BytesView key) /* Noop. */ } +#define EXPLAIN_NAME "single text" #define KEY_VARIANT single_text #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 20c668f7d98..69da80f8ffa 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -206,8 +206,10 @@ HashTableFunctions FUNCTION_NAME(functions) = { .get_num_keys = FUNCTION_NAME(get_num_keys), .get_size_bytes = FUNCTION_NAME(get_size_bytes), .fill_offsets = FUNCTION_NAME(fill_offsets), + .explain_name = EXPLAIN_NAME, }; +#undef EXPLAIN_NAME #undef KEY_VARIANT #undef KEY_BYTES #undef KEY_HASH diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out index 0cc68d15e4d..ed82b625827 100644 --- a/tsl/test/expected/vector_agg_filter.out +++ b/tsl/test/expected/vector_agg_filter.out @@ -100,7 +100,8 @@ from null, 'cint2 < 0', 'ss > 1000', - 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -131,6 +132,12 @@ select count(*) filter (where cint4 > 0) from aggfilter; 100038 (1 row) +select count(*) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + select s, count(*) from aggfilter group by s order by count(*), s limit 10; s | count ---+------- @@ -191,6 +198,21 @@ select s, count(*) filter (where cint4 > 0) from aggfilter group by s order by c 9 | 9961 (10 rows) +select s, count(*) filter (where s != 5) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + select ss, count(*) from aggfilter group by ss order by count(*), ss limit 10; ss | count ----+------- @@ -251,6 +273,21 @@ select ss, count(*) filter (where cint4 > 0) from aggfilter group by ss order by 11 | 19938 (10 rows) +select ss, count(*) filter (where s != 5) from aggfilter group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select count(cint2) from aggfilter; count -------- @@ -275,6 +312,12 @@ select count(cint2) filter (where cint4 > 0) from aggfilter; 99946 (1 row) +select count(cint2) filter (where s != 5) from aggfilter; + count +-------- + 179829 +(1 row) + select s, count(cint2) from aggfilter group by s order by count(cint2), s limit 10; s | count ---+------- @@ -335,6 +378,21 @@ select s, count(cint2) filter (where cint4 > 0) from aggfilter group by s order 9 | 9952 (10 rows) +select s, count(cint2) filter (where s != 5) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 0 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + select ss, count(cint2) from aggfilter group by ss order by count(cint2), ss limit 10; ss | count ----+------- @@ -395,6 +453,21 @@ select ss, count(cint2) filter (where cint4 > 0) from aggfilter group by ss orde 11 | 19917 (10 rows) +select ss, count(cint2) filter (where s != 5) from aggfilter group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 0 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + select min(cint2) from aggfilter; min -------- @@ -419,6 +492,12 @@ select min(cint2) filter (where cint4 > 0) from aggfilter; -16383 (1 row) +select min(cint2) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + select s, min(cint2) from aggfilter group by s order by min(cint2), s limit 10; s | min ---+-------- @@ -479,6 +558,21 @@ select s, min(cint2) filter (where cint4 > 0) from aggfilter group by s order by 9 | -16375 (10 rows) +select s, min(cint2) filter (where s != 5) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + select ss, min(cint2) from aggfilter group by ss order by min(cint2), ss limit 10; ss | min ----+-------- @@ -539,6 +633,21 @@ select ss, min(cint2) filter (where cint4 > 0) from aggfilter group by ss order | -16100 (10 rows) +select ss, min(cint2) filter (where s != 5) from aggfilter group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + select count(cint4) from aggfilter; count -------- @@ -563,6 +672,12 @@ select count(cint4) filter (where cint4 > 0) from aggfilter; 100038 (1 row) +select count(cint4) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + select s, count(cint4) from aggfilter group by s order by count(cint4), s limit 10; s | count ---+------- @@ -623,6 +738,21 @@ select s, count(cint4) filter (where cint4 > 0) from aggfilter group by s order 9 | 9961 (10 rows) +select s, count(cint4) filter (where s != 5) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + select ss, count(cint4) from aggfilter group by ss order by count(cint4), ss limit 10; ss | count ----+------- @@ -683,6 +813,21 @@ select ss, count(cint4) filter (where cint4 > 0) from aggfilter group by ss orde 11 | 19938 (10 rows) +select ss, count(cint4) filter (where s != 5) from aggfilter group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select min(cint4) from aggfilter; min -------- @@ -707,6 +852,12 @@ select min(cint4) filter (where cint4 > 0) from aggfilter; 1 (1 row) +select min(cint4) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + select s, min(cint4) from aggfilter group by s order by min(cint4), s limit 10; s | min ---+-------- @@ -767,6 +918,21 @@ select s, min(cint4) filter (where cint4 > 0) from aggfilter group by s order by 5 | 2 (10 rows) +select s, min(cint4) filter (where s != 5) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | +(10 rows) + select ss, min(cint4) from aggfilter group by ss order by min(cint4), ss limit 10; ss | min ----+-------- @@ -827,6 +993,21 @@ select ss, min(cint4) filter (where cint4 > 0) from aggfilter group by ss order | 4132 (10 rows) +select ss, min(cint4) filter (where s != 5) from aggfilter group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | + | -15907 +(10 rows) + select count(s) from aggfilter; count -------- @@ -851,6 +1032,12 @@ select count(s) filter (where cint4 > 0) from aggfilter; 100038 (1 row) +select count(s) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + select s, count(s) from aggfilter group by s order by count(s), s limit 10; s | count ---+------- @@ -911,6 +1098,21 @@ select s, count(s) filter (where cint4 > 0) from aggfilter group by s order by c 9 | 9961 (10 rows) +select s, count(s) filter (where s != 5) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + select ss, count(s) from aggfilter group by ss order by count(s), ss limit 10; ss | count ----+------- @@ -971,6 +1173,21 @@ select ss, count(s) filter (where cint4 > 0) from aggfilter group by ss order by 11 | 19938 (10 rows) +select ss, count(s) filter (where s != 5) from aggfilter group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select min(s) from aggfilter; min ----- @@ -995,6 +1212,12 @@ select min(s) filter (where cint4 > 0) from aggfilter; 0 (1 row) +select min(s) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + select s, min(s) from aggfilter group by s order by min(s), s limit 10; s | min ---+----- @@ -1055,6 +1278,21 @@ select s, min(s) filter (where cint4 > 0) from aggfilter group by s order by min 9 | 9 (10 rows) +select s, min(s) filter (where s != 5) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select ss, min(s) from aggfilter group by ss order by min(s), ss limit 10; ss | min ----+----- @@ -1115,6 +1353,21 @@ select ss, min(s) filter (where cint4 > 0) from aggfilter group by ss order by m 9 | 9 (10 rows) +select ss, min(s) filter (where s != 5) from aggfilter group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select count(ss) from aggfilter; count -------- @@ -1139,6 +1392,12 @@ select count(ss) filter (where cint4 > 0) from aggfilter; 100027 (1 row) +select count(ss) filter (where s != 5) from aggfilter; + count +-------- + 179981 +(1 row) + select s, count(ss) from aggfilter group by s order by count(ss), s limit 10; s | count ---+------- @@ -1199,6 +1458,21 @@ select s, count(ss) filter (where cint4 > 0) from aggfilter group by s order by 9 | 9961 (10 rows) +select s, count(ss) filter (where s != 5) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + select ss, count(ss) from aggfilter group by ss order by count(ss), ss limit 10; ss | count ----+------- @@ -1259,6 +1533,21 @@ select ss, count(ss) filter (where cint4 > 0) from aggfilter group by ss order b 11 | 19938 (10 rows) +select ss, count(ss) filter (where s != 5) from aggfilter group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select min(ss) from aggfilter; min ----- @@ -1283,7 +1572,13 @@ select min(ss) filter (where cint4 > 0) from aggfilter; 0 (1 row) -select s, min(ss) from aggfilter group by s order by min(ss), s limit 10; +select min(ss) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 @@ -1343,6 +1638,21 @@ select s, min(ss) filter (where cint4 > 0) from aggfilter group by s order by mi 2 | 11 (10 rows) +select s, min(ss) filter (where s != 5) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + select ss, min(ss) from aggfilter group by ss order by min(ss), ss limit 10; ss | min ----+----- @@ -1403,6 +1713,21 @@ select ss, min(ss) filter (where cint4 > 0) from aggfilter group by ss order by | (10 rows) +select ss, min(ss) filter (where s != 5) from aggfilter group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select count(*) from aggfilter where cint2 > 0; count ------- @@ -1427,6 +1752,12 @@ select count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0; 49817 (1 row) +select count(*) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + select s, count(*) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; s | count ---+------- @@ -1487,6 +1818,21 @@ select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 group 5 | 5167 (10 rows) +select s, count(*) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + select ss, count(*) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; ss | count ----+------- @@ -1547,6 +1893,21 @@ select ss, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 grou 11 | 9990 (10 rows) +select ss, count(*) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 0 + 11 | 19973 +(10 rows) + select count(cint2) from aggfilter where cint2 > 0; count ------- @@ -1571,6 +1932,12 @@ select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; 49817 (1 row) +select count(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + select s, count(cint2) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; s | count ---+------- @@ -1631,6 +1998,21 @@ select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 g 5 | 5167 (10 rows) +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + select ss, count(cint2) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; ss | count ----+------- @@ -1691,6 +2073,21 @@ select ss, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 11 | 9990 (10 rows) +select ss, count(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 0 + 11 | 19973 +(10 rows) + select min(cint2) from aggfilter where cint2 > 0; min ----- @@ -1715,6 +2112,12 @@ select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; 1 (1 row) +select min(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + select s, min(cint2) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; s | min ---+----- @@ -1775,6 +2178,21 @@ select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 gro 4 | 4 (10 rows) +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + select ss, min(cint2) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; ss | min ----+------ @@ -1835,6 +2253,21 @@ select ss, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 gr | 3667 (10 rows) +select ss, min(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+------ + 3 | 1 + 5 | + 7 | 1 + 8 | 1 + 11 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 3667 +(10 rows) + select count(cint4) from aggfilter where cint2 > 0; count ------- @@ -1859,6 +2292,12 @@ select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; 49817 (1 row) +select count(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + select s, count(cint4) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; s | count ---+------- @@ -1919,6 +2358,21 @@ select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 g 5 | 5167 (10 rows) +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + select ss, count(cint4) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; ss | count ----+------- @@ -1979,6 +2433,21 @@ select ss, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 11 | 9990 (10 rows) +select ss, count(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 0 + 11 | 19973 +(10 rows) + select min(cint4) from aggfilter where cint2 > 0; min -------- @@ -2003,6 +2472,12 @@ select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; 1 (1 row) +select min(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + select s, min(cint4) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; s | min ---+-------- @@ -2063,6 +2538,21 @@ select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 gro 5 | 2 (10 rows) +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | +(10 rows) + select ss, min(cint4) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; ss | min ----+-------- @@ -2123,6 +2613,21 @@ select ss, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 gr | 4132 (10 rows) +select ss, min(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 11 | -16382 + 8 | -16377 + 5 | + | -11573 +(10 rows) + select count(s) from aggfilter where cint2 > 0; count ------- @@ -2147,6 +2652,12 @@ select count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; 49817 (1 row) +select count(s) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + select s, count(s) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; s | count ---+------- @@ -2207,6 +2718,21 @@ select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group 5 | 5167 (10 rows) +select s, count(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + select ss, count(s) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; ss | count ----+------- @@ -2267,6 +2793,21 @@ select ss, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 grou 11 | 9990 (10 rows) +select ss, count(s) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 0 + 11 | 19973 +(10 rows) + select min(s) from aggfilter where cint2 > 0; min ----- @@ -2291,6 +2832,12 @@ select min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; 0 (1 row) +select min(s) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + select s, min(s) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; s | min ---+----- @@ -2351,6 +2898,21 @@ select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group b 9 | 9 (10 rows) +select s, min(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select ss, min(s) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; ss | min ----+----- @@ -2411,18 +2973,33 @@ select ss, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group 9 | 9 (10 rows) -select count(ss) from aggfilter where cint2 > 0; - count -------- - 99657 -(1 row) - -select count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; - count -------- - 0 -(1 row) - +select ss, min(s) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 > 0; + count +------- + 99657 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + select count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; count ------- @@ -2435,6 +3012,12 @@ select count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; 49813 (1 row) +select count(ss) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89547 +(1 row) + select s, count(ss) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; s | count ---+------- @@ -2495,6 +3078,21 @@ select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 grou 5 | 5167 (10 rows) +select s, count(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + select ss, count(ss) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; ss | count ----+------- @@ -2555,6 +3153,21 @@ select ss, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 gro 11 | 9990 (10 rows) +select ss, count(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by count(ss), ss limit 10; + ss | count +----+------- + | 0 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 0 + 11 | 19973 +(10 rows) + select min(ss) from aggfilter where cint2 > 0; min ----- @@ -2579,6 +3192,12 @@ select min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; 0 (1 row) +select min(ss) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + select s, min(ss) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; s | min ---+----- @@ -2639,6 +3258,21 @@ select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group 2 | 11 (10 rows) +select s, min(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + select ss, min(ss) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; ss | min ----+----- @@ -2699,6 +3333,21 @@ select ss, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group | (10 rows) +select ss, min(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select count(*) from aggfilter where cint2 is null; count ------- @@ -2723,6 +3372,12 @@ select count(*) filter (where cint4 > 0) from aggfilter where cint2 is null; 92 (1 row) +select count(*) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + select s, count(*) from aggfilter where cint2 is null group by s order by count(*), s limit 10; s | count ---+------- @@ -2783,6 +3438,21 @@ select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null g 9 | 9 (10 rows) +select s, count(*) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + select ss, count(*) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; ss | count ----+------- @@ -2839,6 +3509,20 @@ select ss, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null 11 | 21 (9 rows) +select ss, count(*) filter (where s != 5) from aggfilter where cint2 is null group by ss order by count(*), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select count(cint2) from aggfilter where cint2 is null; count ------- @@ -2863,6 +3547,12 @@ select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; 0 (1 row) +select count(cint2) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + select s, count(cint2) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; s | count ---+------- @@ -2923,6 +3613,21 @@ select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is nu 9 | 0 (10 rows) +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + select ss, count(cint2) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; ss | count ----+------- @@ -2979,6 +3684,20 @@ select ss, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is n 11 | 0 (9 rows) +select ss, count(cint2) filter (where s != 5) from aggfilter where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + select min(cint2) from aggfilter where cint2 is null; min ----- @@ -3003,6 +3722,12 @@ select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; (1 row) +select min(cint2) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + +(1 row) + select s, min(cint2) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; s | min ---+----- @@ -3063,6 +3788,21 @@ select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null 9 | (10 rows) +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + select ss, min(cint2) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; ss | min ----+----- @@ -3119,6 +3859,20 @@ select ss, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is nul 11 | (9 rows) +select ss, min(cint2) filter (where s != 5) from aggfilter where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + select count(cint4) from aggfilter where cint2 is null; count ------- @@ -3143,6 +3897,12 @@ select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; 92 (1 row) +select count(cint4) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + select s, count(cint4) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; s | count ---+------- @@ -3203,6 +3963,21 @@ select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is nu 9 | 9 (10 rows) +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + select ss, count(cint4) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; ss | count ----+------- @@ -3259,6 +4034,20 @@ select ss, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is n 11 | 21 (9 rows) +select ss, count(cint4) filter (where s != 5) from aggfilter where cint2 is null group by ss order by count(cint4), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select min(cint4) from aggfilter where cint2 is null; min -------- @@ -3283,6 +4072,12 @@ select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; 473 (1 row) +select min(cint4) filter (where s != 5) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + select s, min(cint4) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; s | min ---+-------- @@ -3343,6 +4138,21 @@ select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null 3 | 473 (10 rows) +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + select ss, min(cint4) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; ss | min ----+-------- @@ -3399,6 +4209,20 @@ select ss, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is nul 3 | 473 (9 rows) +select ss, min(cint4) filter (where s != 5) from aggfilter where cint2 is null group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | + 11 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 3 | -9908 +(9 rows) + select count(s) from aggfilter where cint2 is null; count ------- @@ -3423,6 +4247,12 @@ select count(s) filter (where cint4 > 0) from aggfilter where cint2 is null; 92 (1 row) +select count(s) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + select s, count(s) from aggfilter where cint2 is null group by s order by count(s), s limit 10; s | count ---+------- @@ -3483,6 +4313,21 @@ select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null g 9 | 9 (10 rows) +select s, count(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + select ss, count(s) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; ss | count ----+------- @@ -3539,6 +4384,20 @@ select ss, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null 11 | 21 (9 rows) +select ss, count(s) filter (where s != 5) from aggfilter where cint2 is null group by ss order by count(s), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select min(s) from aggfilter where cint2 is null; min ----- @@ -3563,6 +4422,12 @@ select min(s) filter (where cint4 > 0) from aggfilter where cint2 is null; 0 (1 row) +select min(s) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + select s, min(s) from aggfilter where cint2 is null group by s order by min(s), s limit 10; s | min ---+----- @@ -3623,6 +4488,21 @@ select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null gro 9 | 9 (10 rows) +select s, min(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select ss, min(s) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; ss | min ----+----- @@ -3679,6 +4559,20 @@ select ss, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null gr 9 | 9 (9 rows) +select ss, min(s) filter (where s != 5) from aggfilter where cint2 is null group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(9 rows) + select count(ss) from aggfilter where cint2 is null; count ------- @@ -3703,6 +4597,12 @@ select count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; 92 (1 row) +select count(ss) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + select s, count(ss) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; s | count ---+------- @@ -3763,6 +4663,21 @@ select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null 9 | 9 (10 rows) +select s, count(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + select ss, count(ss) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; ss | count ----+------- @@ -3819,6 +4734,20 @@ select ss, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null 11 | 21 (9 rows) +select ss, count(ss) filter (where s != 5) from aggfilter where cint2 is null group by ss order by count(ss), ss limit 10; + ss | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + select min(ss) from aggfilter where cint2 is null; min ----- @@ -3843,6 +4772,12 @@ select min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; 0 (1 row) +select min(ss) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + select s, min(ss) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; s | min ---+----- @@ -3903,6 +4838,21 @@ select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null gr 2 | 11 (10 rows) +select s, min(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + select ss, min(ss) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; ss | min ----+----- @@ -3959,3 +4909,17 @@ select ss, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null g 11 | 11 (9 rows) +select ss, min(ss) filter (where s != 5) from aggfilter where cint2 is null group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 +(9 rows) + diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index 867387e79cc..2c8c9fc111d 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -90,6 +90,11 @@ from null, 'cint2 > 0']) with ordinality as condition(condition, n), unnest(array[ + null, + 's', + 'cint2', + 'cint4', + 'cint8', 'x', 'ss, x', 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) @@ -99,6 +104,72 @@ where and (variable != '*' or function = 'count') order by explain, condition.n, variable, function, grouping.n \gexec +select count(*) from agggroup; + count +-------- + 200000 +(1 row) + +select s, count(*) from agggroup group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select cint2, count(*) from agggroup group by cint2 order by count(*), cint2 limit 10; + cint2 | count +--------+------- + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 + -15615 | 1 +(10 rows) + +select cint4, count(*) from agggroup group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 + -15760 | 1 +(10 rows) + +select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + select x, count(*) from agggroup group by x order by count(*), x limit 10; x | count ----+------- @@ -144,6 +215,72 @@ select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup group by t, s, s 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 (10 rows) +select count(cint2) from agggroup; + count +-------- + 199810 +(1 row) + +select s, count(cint2) from agggroup group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select cint2, count(cint2) from agggroup group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +--------+------- + | 0 + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + 8426 | 0 + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 +(10 rows) + +select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; x | count ----+------- @@ -189,6 +326,72 @@ select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup group by t, 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 (10 rows) +select min(cint2) from agggroup; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from agggroup group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select cint2, min(cint2) from agggroup group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +--------+-------- + -16383 | -16383 + -16382 | -16382 + -16381 | -16381 + -16380 | -16380 + -16379 | -16379 + -16378 | -16378 + -16377 | -16377 + -16376 | -16376 + -16375 | -16375 + -16374 | -16374 +(10 rows) + +select cint4, min(cint2) from agggroup group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+-------- + -16190 | -16383 + -13372 | -16383 + -10318 | -16383 + -9008 | -16383 + -3043 | -16383 + 6729 | -16383 + -14012 | -16382 + -8606 | -16382 + -3080 | -16382 + 2223 | -16382 +(10 rows) + +select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+-------- + -1794 | -16383 + 4390 | -16383 + 6326 | -16383 + 6717 | -16383 + 11094 | -16383 + 13646 | -16383 + -15609 | -16382 + -10357 | -16382 + -9888 | -16382 + 206 | -16382 +(10 rows) + select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; x | min ----+-------- @@ -234,6 +437,72 @@ select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup group by t, s, 76781 | 7 | 7 | 7 | -16382 | 9938 | 6519 | -16382 (10 rows) +select count(*) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select s, count(*) from agggroup where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select cint2, count(*) from agggroup where cint2 > 0 group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(*) from agggroup where cint2 > 0 group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; x | count ----+------- @@ -279,6 +548,72 @@ select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 (10 rows) +select count(cint2) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select s, count(cint2) from agggroup where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select cint2, count(cint2) from agggroup where cint2 > 0 group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup where cint2 > 0 group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; x | count ----+------- @@ -324,6 +659,72 @@ select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 (10 rows) +select min(cint2) from agggroup where cint2 > 0; + min +----- + 1 +(1 row) + +select s, min(cint2) from agggroup where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select cint2, min(cint2) from agggroup where cint2 > 0 group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 +(10 rows) + +select cint4, min(cint2) from agggroup where cint2 > 0 group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -12025 | 1 + -10344 | 1 + -4190 | 1 + -1493 | 1 + 1863 | 1 + 9242 | 1 + 11189 | 1 + 14078 | 1 + 15656 | 1 + -11410 | 2 +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -13684 | 1 + -9798 | 1 + -5168 | 1 + -2827 | 1 + -2210 | 1 + -1043 | 1 + 7650 | 1 + 9929 | 1 + 12597 | 1 + -13639 | 2 +(10 rows) + select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; x | min ----+------ diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index c25c51c8a6c..7dc56fc69ee 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -59,18 +59,21 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -103,7 +106,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(52 rows) +(55 rows) -- Vectorization possible - filter on segment_by :EXPLAIN @@ -115,6 +118,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Index Scan using compress_hyper_2_11_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_11_chunk @@ -122,6 +126,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Index Cond: (compress_hyper_2_11_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Index Scan using compress_hyper_2_12_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_12_chunk @@ -129,6 +134,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Index Cond: (compress_hyper_2_12_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Index Scan using compress_hyper_2_13_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_13_chunk @@ -169,7 +175,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; -> Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.segment_by_value > 0) -(59 rows) +(62 rows) -- Vectorization not possible due to a used filter :EXPLAIN @@ -181,6 +187,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) @@ -189,6 +196,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v Index Cond: (compress_hyper_2_11_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) @@ -197,6 +205,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v Index Cond: (compress_hyper_2_12_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) @@ -238,7 +247,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v -> Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: ((_hyper_1_10_chunk.segment_by_value > 0) AND (_hyper_1_10_chunk.int_value > 0)) -(62 rows) +(65 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; @@ -252,6 +261,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) @@ -259,6 +269,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) @@ -266,6 +277,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) @@ -306,7 +318,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.int_value > 0) -(62 rows) +(65 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; @@ -320,6 +332,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.float_value > '0'::double precision) @@ -327,6 +340,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.float_value > '0'::double precision) @@ -334,6 +348,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.float_value > '0'::double precision) @@ -374,7 +389,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.float_value > '0'::double precision) -(62 rows) +(65 rows) -- Vectorization not possible due grouping :EXPLAIN @@ -390,18 +405,21 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -441,7 +459,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; Group Key: _hyper_1_10_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.float_value, _hyper_1_10_chunk.segment_by_value -(60 rows) +(63 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; @@ -456,18 +474,21 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.int_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.int_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.int_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -507,7 +528,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Group Key: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value -(60 rows) +(63 rows) -- Vectorization possible with grouping by a segmentby column. :EXPLAIN @@ -523,18 +544,21 @@ SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value, _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value, _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value, _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -574,7 +598,7 @@ SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value, _hyper_1_10_chunk.int_value -(60 rows) +(63 rows) :EXPLAIN SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; @@ -592,18 +616,21 @@ SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_b -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -643,7 +670,7 @@ SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_b Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(63 rows) +(66 rows) SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; sum | segment_by_value @@ -777,18 +804,21 @@ SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_b -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -828,7 +858,7 @@ SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_b Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(63 rows) +(66 rows) SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; segment_by_value | sum @@ -965,18 +995,21 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -1009,7 +1042,7 @@ SELECT sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -(52 rows) +(55 rows) -- Vectorized aggregation possible SELECT sum(float_value) FROM testtable; @@ -1030,18 +1063,21 @@ SELECT sum(float_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.float_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.float_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.float_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -1074,7 +1110,7 @@ SELECT sum(float_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.float_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.float_value -(52 rows) +(55 rows) --- -- Tests with all chunks compressed @@ -1116,65 +1152,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk Output: compress_hyper_2_20_chunk._ts_meta_count, compress_hyper_2_20_chunk.segment_by_value, compress_hyper_2_20_chunk._ts_meta_min_1, compress_hyper_2_20_chunk._ts_meta_max_1, compress_hyper_2_20_chunk."time", compress_hyper_2_20_chunk.int_value, compress_hyper_2_20_chunk.float_value -(66 rows) +(76 rows) -- Vectorized aggregation possible SELECT sum(int_value) FROM testtable; @@ -1195,65 +1241,75 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk Output: compress_hyper_2_20_chunk._ts_meta_count, compress_hyper_2_20_chunk.segment_by_value, compress_hyper_2_20_chunk._ts_meta_min_1, compress_hyper_2_20_chunk._ts_meta_max_1, compress_hyper_2_20_chunk."time", compress_hyper_2_20_chunk.int_value, compress_hyper_2_20_chunk.float_value -(66 rows) +(76 rows) --- -- Tests with some chunks are partially compressed @@ -1279,60 +1335,70 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1341,7 +1407,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) -- Vectorized aggregation possible SELECT sum(int_value) FROM testtable; @@ -1362,60 +1428,70 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1424,7 +1500,7 @@ SELECT sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -(70 rows) +(80 rows) --Vectorized aggregation not possible for expression SELECT sum(abs(int_value)) FROM testtable; @@ -1679,60 +1755,70 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1741,7 +1827,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -1763,60 +1849,70 @@ SELECT sum(int_value), sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1825,7 +1921,7 @@ SELECT sum(int_value), sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -(70 rows) +(80 rows) -- Using the same sum function multiple times is supported by vectorization :EXPLAIN @@ -1840,60 +1936,70 @@ SELECT sum(segment_by_value), sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1902,7 +2008,7 @@ SELECT sum(segment_by_value), sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) -- Performing a sum on multiple columns is supported. :EXPLAIN @@ -1917,60 +2023,70 @@ SELECT sum(int_value), sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)), (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)), (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)), (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)), (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value, _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)), (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value, _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)), (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value, _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)), (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value, _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)), (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value, _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)), (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value, _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)), (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1979,7 +2095,7 @@ SELECT sum(int_value), sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value), PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) SELECT sum(int_value), sum(segment_by_value) FROM testtable; sum | sum @@ -2250,6 +2366,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_41_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_41_chunk Output: _hyper_1_41_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_51_chunk @@ -2257,6 +2374,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_51_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_42_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_42_chunk Output: _hyper_1_42_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_52_chunk @@ -2264,6 +2382,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_52_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_43_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_43_chunk Output: _hyper_1_43_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_53_chunk @@ -2271,6 +2390,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_53_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_44_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_44_chunk Output: _hyper_1_44_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_54_chunk @@ -2278,6 +2398,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_54_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_45_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_45_chunk Output: _hyper_1_45_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_55_chunk @@ -2285,6 +2406,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_55_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_46_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_46_chunk Output: _hyper_1_46_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_56_chunk @@ -2292,6 +2414,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_56_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_47_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_47_chunk Output: _hyper_1_47_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_57_chunk @@ -2299,6 +2422,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_57_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_48_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_48_chunk Output: _hyper_1_48_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_58_chunk @@ -2306,6 +2430,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_58_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_49_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_49_chunk Output: _hyper_1_49_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_59_chunk @@ -2313,12 +2438,13 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_59_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_50_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_50_chunk Output: _hyper_1_50_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_60_chunk Output: compress_hyper_2_60_chunk._ts_meta_count, compress_hyper_2_60_chunk.segment_by_value, compress_hyper_2_60_chunk._ts_meta_min_1, compress_hyper_2_60_chunk._ts_meta_max_1, compress_hyper_2_60_chunk."time", compress_hyper_2_60_chunk.int_value, compress_hyper_2_60_chunk.float_value Filter: (compress_hyper_2_60_chunk.segment_by_value > 5) -(76 rows) +(86 rows) SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; sum @@ -2367,65 +2493,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_41_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_41_chunk Output: _hyper_1_41_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_51_chunk Output: compress_hyper_2_51_chunk._ts_meta_count, compress_hyper_2_51_chunk.segment_by_value, compress_hyper_2_51_chunk._ts_meta_min_1, compress_hyper_2_51_chunk._ts_meta_max_1, compress_hyper_2_51_chunk."time", compress_hyper_2_51_chunk.int_value, compress_hyper_2_51_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_42_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_42_chunk Output: _hyper_1_42_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_52_chunk Output: compress_hyper_2_52_chunk._ts_meta_count, compress_hyper_2_52_chunk.segment_by_value, compress_hyper_2_52_chunk._ts_meta_min_1, compress_hyper_2_52_chunk._ts_meta_max_1, compress_hyper_2_52_chunk."time", compress_hyper_2_52_chunk.int_value, compress_hyper_2_52_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_43_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_43_chunk Output: _hyper_1_43_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_53_chunk Output: compress_hyper_2_53_chunk._ts_meta_count, compress_hyper_2_53_chunk.segment_by_value, compress_hyper_2_53_chunk._ts_meta_min_1, compress_hyper_2_53_chunk._ts_meta_max_1, compress_hyper_2_53_chunk."time", compress_hyper_2_53_chunk.int_value, compress_hyper_2_53_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_44_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_44_chunk Output: _hyper_1_44_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_54_chunk Output: compress_hyper_2_54_chunk._ts_meta_count, compress_hyper_2_54_chunk.segment_by_value, compress_hyper_2_54_chunk._ts_meta_min_1, compress_hyper_2_54_chunk._ts_meta_max_1, compress_hyper_2_54_chunk."time", compress_hyper_2_54_chunk.int_value, compress_hyper_2_54_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_45_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_45_chunk Output: _hyper_1_45_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_55_chunk Output: compress_hyper_2_55_chunk._ts_meta_count, compress_hyper_2_55_chunk.segment_by_value, compress_hyper_2_55_chunk._ts_meta_min_1, compress_hyper_2_55_chunk._ts_meta_max_1, compress_hyper_2_55_chunk."time", compress_hyper_2_55_chunk.int_value, compress_hyper_2_55_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_46_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_46_chunk Output: _hyper_1_46_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_56_chunk Output: compress_hyper_2_56_chunk._ts_meta_count, compress_hyper_2_56_chunk.segment_by_value, compress_hyper_2_56_chunk._ts_meta_min_1, compress_hyper_2_56_chunk._ts_meta_max_1, compress_hyper_2_56_chunk."time", compress_hyper_2_56_chunk.int_value, compress_hyper_2_56_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_47_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_47_chunk Output: _hyper_1_47_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_57_chunk Output: compress_hyper_2_57_chunk._ts_meta_count, compress_hyper_2_57_chunk.segment_by_value, compress_hyper_2_57_chunk._ts_meta_min_1, compress_hyper_2_57_chunk._ts_meta_max_1, compress_hyper_2_57_chunk."time", compress_hyper_2_57_chunk.int_value, compress_hyper_2_57_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_48_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_48_chunk Output: _hyper_1_48_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_58_chunk Output: compress_hyper_2_58_chunk._ts_meta_count, compress_hyper_2_58_chunk.segment_by_value, compress_hyper_2_58_chunk._ts_meta_min_1, compress_hyper_2_58_chunk._ts_meta_max_1, compress_hyper_2_58_chunk."time", compress_hyper_2_58_chunk.int_value, compress_hyper_2_58_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_49_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_49_chunk Output: _hyper_1_49_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_59_chunk Output: compress_hyper_2_59_chunk._ts_meta_count, compress_hyper_2_59_chunk.segment_by_value, compress_hyper_2_59_chunk._ts_meta_min_1, compress_hyper_2_59_chunk._ts_meta_max_1, compress_hyper_2_59_chunk."time", compress_hyper_2_59_chunk.int_value, compress_hyper_2_59_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_50_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_50_chunk Output: _hyper_1_50_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_60_chunk Output: compress_hyper_2_60_chunk._ts_meta_count, compress_hyper_2_60_chunk.segment_by_value, compress_hyper_2_60_chunk._ts_meta_min_1, compress_hyper_2_60_chunk._ts_meta_max_1, compress_hyper_2_60_chunk."time", compress_hyper_2_60_chunk.int_value, compress_hyper_2_60_chunk.float_value -(66 rows) +(76 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -2552,65 +2688,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_82_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_83_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_84_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_85_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_86_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_87_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_88_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_89_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_90_chunk.segment_by_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) :EXPLAIN SELECT sum(int_value) FROM testtable; @@ -2624,65 +2770,75 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_81_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_82_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_83_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_84_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_85_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_86_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_87_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_88_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_89_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_90_chunk.int_value)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -2707,67 +2863,77 @@ SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testta Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) Workers Planned: 2 -> Parallel Append - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999))) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) SET timescaledb.enable_vectorized_aggregation = OFF; SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; @@ -2843,59 +3009,68 @@ SELECT sum(segment_by_value1) FROM testtable2; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk Output: compress_hyper_4_110_chunk._ts_meta_count, compress_hyper_4_110_chunk.segment_by_value1, compress_hyper_4_110_chunk.segment_by_value2, compress_hyper_4_110_chunk._ts_meta_min_1, compress_hyper_4_110_chunk._ts_meta_max_1, compress_hyper_4_110_chunk."time", compress_hyper_4_110_chunk.int_value, compress_hyper_4_110_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk Output: compress_hyper_4_111_chunk._ts_meta_count, compress_hyper_4_111_chunk.segment_by_value1, compress_hyper_4_111_chunk.segment_by_value2, compress_hyper_4_111_chunk._ts_meta_min_1, compress_hyper_4_111_chunk._ts_meta_max_1, compress_hyper_4_111_chunk."time", compress_hyper_4_111_chunk.int_value, compress_hyper_4_111_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk Output: compress_hyper_4_112_chunk._ts_meta_count, compress_hyper_4_112_chunk.segment_by_value1, compress_hyper_4_112_chunk.segment_by_value2, compress_hyper_4_112_chunk._ts_meta_min_1, compress_hyper_4_112_chunk._ts_meta_max_1, compress_hyper_4_112_chunk."time", compress_hyper_4_112_chunk.int_value, compress_hyper_4_112_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk Output: compress_hyper_4_113_chunk._ts_meta_count, compress_hyper_4_113_chunk.segment_by_value1, compress_hyper_4_113_chunk.segment_by_value2, compress_hyper_4_113_chunk._ts_meta_min_1, compress_hyper_4_113_chunk._ts_meta_max_1, compress_hyper_4_113_chunk."time", compress_hyper_4_113_chunk.int_value, compress_hyper_4_113_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk Output: compress_hyper_4_114_chunk._ts_meta_count, compress_hyper_4_114_chunk.segment_by_value1, compress_hyper_4_114_chunk.segment_by_value2, compress_hyper_4_114_chunk._ts_meta_min_1, compress_hyper_4_114_chunk._ts_meta_max_1, compress_hyper_4_114_chunk."time", compress_hyper_4_114_chunk.int_value, compress_hyper_4_114_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk Output: compress_hyper_4_115_chunk._ts_meta_count, compress_hyper_4_115_chunk.segment_by_value1, compress_hyper_4_115_chunk.segment_by_value2, compress_hyper_4_115_chunk._ts_meta_min_1, compress_hyper_4_115_chunk._ts_meta_max_1, compress_hyper_4_115_chunk."time", compress_hyper_4_115_chunk.int_value, compress_hyper_4_115_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk Output: compress_hyper_4_116_chunk._ts_meta_count, compress_hyper_4_116_chunk.segment_by_value1, compress_hyper_4_116_chunk.segment_by_value2, compress_hyper_4_116_chunk._ts_meta_min_1, compress_hyper_4_116_chunk._ts_meta_max_1, compress_hyper_4_116_chunk."time", compress_hyper_4_116_chunk.int_value, compress_hyper_4_116_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk Output: compress_hyper_4_117_chunk._ts_meta_count, compress_hyper_4_117_chunk.segment_by_value1, compress_hyper_4_117_chunk.segment_by_value2, compress_hyper_4_117_chunk._ts_meta_min_1, compress_hyper_4_117_chunk._ts_meta_max_1, compress_hyper_4_117_chunk."time", compress_hyper_4_117_chunk.int_value, compress_hyper_4_117_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value -(60 rows) +(69 rows) SELECT sum(segment_by_value1) FROM testtable2; sum @@ -2915,59 +3090,68 @@ SELECT sum(segment_by_value2) FROM testtable2; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk Output: compress_hyper_4_110_chunk._ts_meta_count, compress_hyper_4_110_chunk.segment_by_value1, compress_hyper_4_110_chunk.segment_by_value2, compress_hyper_4_110_chunk._ts_meta_min_1, compress_hyper_4_110_chunk._ts_meta_max_1, compress_hyper_4_110_chunk."time", compress_hyper_4_110_chunk.int_value, compress_hyper_4_110_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk Output: compress_hyper_4_111_chunk._ts_meta_count, compress_hyper_4_111_chunk.segment_by_value1, compress_hyper_4_111_chunk.segment_by_value2, compress_hyper_4_111_chunk._ts_meta_min_1, compress_hyper_4_111_chunk._ts_meta_max_1, compress_hyper_4_111_chunk."time", compress_hyper_4_111_chunk.int_value, compress_hyper_4_111_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk Output: compress_hyper_4_112_chunk._ts_meta_count, compress_hyper_4_112_chunk.segment_by_value1, compress_hyper_4_112_chunk.segment_by_value2, compress_hyper_4_112_chunk._ts_meta_min_1, compress_hyper_4_112_chunk._ts_meta_max_1, compress_hyper_4_112_chunk."time", compress_hyper_4_112_chunk.int_value, compress_hyper_4_112_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk Output: compress_hyper_4_113_chunk._ts_meta_count, compress_hyper_4_113_chunk.segment_by_value1, compress_hyper_4_113_chunk.segment_by_value2, compress_hyper_4_113_chunk._ts_meta_min_1, compress_hyper_4_113_chunk._ts_meta_max_1, compress_hyper_4_113_chunk."time", compress_hyper_4_113_chunk.int_value, compress_hyper_4_113_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk Output: compress_hyper_4_114_chunk._ts_meta_count, compress_hyper_4_114_chunk.segment_by_value1, compress_hyper_4_114_chunk.segment_by_value2, compress_hyper_4_114_chunk._ts_meta_min_1, compress_hyper_4_114_chunk._ts_meta_max_1, compress_hyper_4_114_chunk."time", compress_hyper_4_114_chunk.int_value, compress_hyper_4_114_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk Output: compress_hyper_4_115_chunk._ts_meta_count, compress_hyper_4_115_chunk.segment_by_value1, compress_hyper_4_115_chunk.segment_by_value2, compress_hyper_4_115_chunk._ts_meta_min_1, compress_hyper_4_115_chunk._ts_meta_max_1, compress_hyper_4_115_chunk."time", compress_hyper_4_115_chunk.int_value, compress_hyper_4_115_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk Output: compress_hyper_4_116_chunk._ts_meta_count, compress_hyper_4_116_chunk.segment_by_value1, compress_hyper_4_116_chunk.segment_by_value2, compress_hyper_4_116_chunk._ts_meta_min_1, compress_hyper_4_116_chunk._ts_meta_max_1, compress_hyper_4_116_chunk."time", compress_hyper_4_116_chunk.int_value, compress_hyper_4_116_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk Output: compress_hyper_4_117_chunk._ts_meta_count, compress_hyper_4_117_chunk.segment_by_value1, compress_hyper_4_117_chunk.segment_by_value2, compress_hyper_4_117_chunk._ts_meta_min_1, compress_hyper_4_117_chunk._ts_meta_max_1, compress_hyper_4_117_chunk."time", compress_hyper_4_117_chunk.int_value, compress_hyper_4_117_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value2)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value -(60 rows) +(69 rows) SELECT sum(segment_by_value2) FROM testtable2; sum @@ -2988,6 +3172,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -2995,6 +3180,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_110_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3002,6 +3188,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_111_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3009,6 +3196,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_112_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3016,6 +3204,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_113_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3023,6 +3212,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_114_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3030,6 +3220,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_115_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3037,6 +3228,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_116_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3044,12 +3236,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_117_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: (compress_hyper_4_118_chunk.segment_by_value1 > 0) -(69 rows) +(78 rows) :EXPLAIN SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND segment_by_value2 > 0; @@ -3063,6 +3256,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -3070,6 +3264,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_110_chunk.segment_by_value1 > 0) AND (compress_hyper_4_110_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3077,6 +3272,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_111_chunk.segment_by_value1 > 0) AND (compress_hyper_4_111_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3084,6 +3280,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_112_chunk.segment_by_value1 > 0) AND (compress_hyper_4_112_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3091,6 +3288,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_113_chunk.segment_by_value1 > 0) AND (compress_hyper_4_113_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3098,6 +3296,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_114_chunk.segment_by_value1 > 0) AND (compress_hyper_4_114_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3105,6 +3304,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_115_chunk.segment_by_value1 > 0) AND (compress_hyper_4_115_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3112,6 +3312,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_116_chunk.segment_by_value1 > 0) AND (compress_hyper_4_116_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3119,12 +3320,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_117_chunk.segment_by_value1 > 0) AND (compress_hyper_4_117_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: ((compress_hyper_4_118_chunk.segment_by_value1 > 0) AND (compress_hyper_4_118_chunk.segment_by_value2 > 0)) -(69 rows) +(78 rows) :EXPLAIN SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND segment_by_value2 > 0 AND 2>1; @@ -3138,6 +3340,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -3145,6 +3348,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_110_chunk.segment_by_value1 > 0) AND (compress_hyper_4_110_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3152,6 +3356,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_111_chunk.segment_by_value1 > 0) AND (compress_hyper_4_111_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3159,6 +3364,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_112_chunk.segment_by_value1 > 0) AND (compress_hyper_4_112_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3166,6 +3372,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_113_chunk.segment_by_value1 > 0) AND (compress_hyper_4_113_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3173,6 +3380,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_114_chunk.segment_by_value1 > 0) AND (compress_hyper_4_114_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3180,6 +3388,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_115_chunk.segment_by_value1 > 0) AND (compress_hyper_4_115_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3187,6 +3396,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_116_chunk.segment_by_value1 > 0) AND (compress_hyper_4_116_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3194,12 +3404,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_117_chunk.segment_by_value1 > 0) AND (compress_hyper_4_117_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: ((compress_hyper_4_118_chunk.segment_by_value1 > 0) AND (compress_hyper_4_118_chunk.segment_by_value2 > 0)) -(69 rows) +(78 rows) -- Vectorization not possible filter on segment_by and compressed value -- Disable parallel worker to get deterministic query plans on i386 @@ -3213,6 +3424,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_101_chunk.int_value > 1000) @@ -3221,6 +3433,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_110_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_102_chunk.int_value > 1000) @@ -3229,6 +3442,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_111_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_103_chunk.int_value > 1000) @@ -3237,6 +3451,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_112_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_104_chunk.int_value > 1000) @@ -3245,6 +3460,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_113_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_105_chunk.int_value > 1000) @@ -3253,6 +3469,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_114_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_106_chunk.int_value > 1000) @@ -3261,6 +3478,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_115_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_107_chunk.int_value > 1000) @@ -3269,6 +3487,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_116_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_108_chunk.int_value > 1000) @@ -3277,12 +3496,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_117_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: entire batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_109_chunk.int_value > 1000) -> Index Scan using compress_hyper_4_118_chunk_segment_by_value1_segment_by_val_idx on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Index Cond: (compress_hyper_4_118_chunk.segment_by_value1 > 1000) -(75 rows) +(84 rows) RESET max_parallel_workers_per_gather; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index 513bcc231fa..1b82ace15f6 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -98,7 +98,8 @@ from null, 'cint2 < 0', 'ss > 1000', - 'cint4 > 0']) with ordinality as agg_filter(agg_filter, n) + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) where true and (explain is null /* or condition is null and grouping = 's' */) diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index cdc0d94ebc7..1a5d0caa476 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -87,6 +87,11 @@ from null, 'cint2 > 0']) with ordinality as condition(condition, n), unnest(array[ + null, + 's', + 'cint2', + 'cint4', + 'cint8', 'x', 'ss, x', 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) From 411e933fed215bf8eb1c9a815408b3199cf4c734 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:34:00 +0100 Subject: [PATCH 072/242] review comments -- vector agg defs array --- tsl/src/nodes/vector_agg/exec.c | 45 +++++++++++++++---- tsl/src/nodes/vector_agg/exec.h | 5 ++- tsl/src/nodes/vector_agg/grouping_policy.h | 8 +++- .../nodes/vector_agg/grouping_policy_batch.c | 40 ++++++++++------- .../nodes/vector_agg/grouping_policy_hash.c | 41 +++++++++-------- .../nodes/vector_agg/grouping_policy_hash.h | 11 +++-- 6 files changed, 95 insertions(+), 55 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index c5fc7b15f59..b29ad93411c 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -80,15 +80,35 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) */ List *aggregated_tlist = castNode(CustomScan, vector_agg_state->custom.ss.ps.plan)->custom_scan_tlist; - const int naggs = list_length(aggregated_tlist); - for (int i = 0; i < naggs; i++) + const int tlist_length = list_length(aggregated_tlist); + + int agg_functions_counter = 0; + for (int i = 0; i < tlist_length; i++) + { + TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + if (IsA(tlentry->expr, Aggref)) + { + agg_functions_counter++; + } + else + { + /* This is a grouping column. */ + Assert(IsA(tlentry->expr, Var)); + } + } + + vector_agg_state->num_agg_defs = agg_functions_counter; + vector_agg_state->agg_defs = + palloc0(sizeof(*vector_agg_state->agg_defs) * vector_agg_state->num_agg_defs); + + agg_functions_counter = 0; + for (int i = 0; i < tlist_length; i++) { TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { /* This is an aggregate function. */ - VectorAggDef *def = palloc0(sizeof(VectorAggDef)); - vector_agg_state->agg_defs = lappend(vector_agg_state->agg_defs, def); + VectorAggDef *def = &vector_agg_state->agg_defs[agg_functions_counter++]; def->output_offset = i; Aggref *aggref = castNode(Aggref, tlentry->expr); @@ -165,7 +185,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) * Per-batch grouping. */ vector_agg_state->grouping = - create_grouping_policy_batch(vector_agg_state->agg_defs, + create_grouping_policy_batch(vector_agg_state->num_agg_defs, + vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); } else @@ -174,7 +195,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) * Hash grouping. */ vector_agg_state->grouping = - create_grouping_policy_hash(vector_agg_state->agg_defs, + create_grouping_policy_hash(vector_agg_state->num_agg_defs, + vector_agg_state->agg_defs, vector_agg_state->output_grouping_columns); } } @@ -291,10 +313,14 @@ vector_agg_exec(CustomScanState *node) dcontext->ps->instrument->tuplecount += not_filtered_rows; } - const int naggs = list_length(vector_agg_state->agg_defs); + /* + * Compute the vectorized filters for the aggregate function FILTER + * clauses. + */ + const int naggs = vector_agg_state->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(vector_agg_state->agg_defs, i); + VectorAggDef *agg_def = &vector_agg_state->agg_defs[i]; if (agg_def->filter_clauses == NIL) { continue; @@ -315,6 +341,9 @@ vector_agg_exec(CustomScanState *node) agg_def->filter_result = vqstate->vector_qual_result; } + /* + * Finally, pass the compressed batch to the grouping policy. + */ grouping->gp_add_batch(grouping, batch_state); } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 1920f243119..487a3d3a774 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -13,7 +13,7 @@ #include "function/functions.h" #include "grouping_policy.h" -typedef struct +typedef struct VectorAggDef { VectorAggFunctions func; int input_offset; @@ -37,7 +37,8 @@ typedef struct { CustomScanState custom; - List *agg_defs; + int num_agg_defs; + VectorAggDef *agg_defs; List *output_grouping_columns; diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index c32447952cb..6dfae8d0884 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -11,6 +11,8 @@ typedef struct GroupingPolicy GroupingPolicy; typedef struct TupleTableSlot TupleTableSlot; +typedef struct VectorAggDef VectorAggDef; + /* * This is a common interface for grouping policies which define how the rows * are grouped for aggregation -- e.g. there can be an implementation for no @@ -41,6 +43,8 @@ typedef struct GroupingPolicy char *(*gp_explain)(GroupingPolicy *gp); } GroupingPolicy; -extern GroupingPolicy *create_grouping_policy_batch(List *agg_defs, List *grouping_columns); +extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, + List *grouping_columns); -extern GroupingPolicy *create_grouping_policy_hash(List *agg_defs, List *grouping_columns); +extern GroupingPolicy *create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, + List *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index b1b77e2c35b..68cccf10231 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -23,8 +23,12 @@ typedef struct { GroupingPolicy funcs; - List *agg_defs; - List *agg_states; + + int num_agg_defs; + VectorAggDef *agg_defs; + + void **agg_states; + List *output_grouping_columns; Datum *output_grouping_values; bool *output_grouping_isnull; @@ -44,20 +48,24 @@ typedef struct static const GroupingPolicy grouping_policy_batch_functions; GroupingPolicy * -create_grouping_policy_batch(List *agg_defs, List *output_grouping_columns) +create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, + List *output_grouping_columns) { GroupingPolicyBatch *policy = palloc0(sizeof(GroupingPolicyBatch)); policy->funcs = grouping_policy_batch_functions; policy->output_grouping_columns = output_grouping_columns; + policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - ListCell *lc; - foreach (lc, agg_defs) + + policy->agg_states = palloc(sizeof(*policy->agg_states) * policy->num_agg_defs); + for (int i = 0; i < policy->num_agg_defs; i++) { - VectorAggDef *agg_def = lfirst(lc); - policy->agg_states = lappend(policy->agg_states, palloc0(agg_def->func.state_bytes)); + VectorAggDef *agg_def = &policy->agg_defs[i]; + policy->agg_states[i] = palloc0(agg_def->func.state_bytes); } + policy->output_grouping_values = (Datum *) palloc0(MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum)) + MAXALIGN(list_length(output_grouping_columns) * sizeof(bool))); @@ -75,11 +83,11 @@ gp_batch_reset(GroupingPolicy *obj) MemoryContextReset(policy->agg_extra_mctx); - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; agg_def->func.agg_init(agg_state, 1); } @@ -178,11 +186,11 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) policy->num_tmp_filter_words = (num_words * 2 + 1); } - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; compute_single_aggregate(policy, batch_state, agg_def, agg_state, policy->agg_extra_mctx); } @@ -230,11 +238,11 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return false; } - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; agg_def->func.agg_emit(agg_state, &aggregated_slot->tts_values[agg_def->output_offset], &aggregated_slot->tts_isnull[agg_def->output_offset]); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index d0eaf5fd244..ba1333db1d6 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -40,22 +40,23 @@ extern HashTableFunctions serialized_functions; static const GroupingPolicy grouping_policy_hash_functions; GroupingPolicy * -create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) +create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, List *output_grouping_columns) { GroupingPolicyHash *policy = palloc0(sizeof(GroupingPolicyHash)); policy->funcs = grouping_policy_hash_functions; policy->output_grouping_columns = output_grouping_columns; - policy->agg_defs = agg_defs; policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; - ListCell *lc; - foreach (lc, agg_defs) + + policy->num_agg_defs = num_agg_defs; + policy->agg_defs = agg_defs; + policy->per_agg_states = palloc(sizeof(*policy->per_agg_states) * policy->num_agg_defs); + for (int i = 0; i < policy->num_agg_defs; i++) { - VectorAggDef *agg_def = lfirst(lc); - policy->per_agg_states = - lappend(policy->per_agg_states, - palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); + VectorAggDef *agg_def = &policy->agg_defs[i]; + policy->per_agg_states[i] = + palloc(agg_def->func.state_bytes * policy->allocated_aggstate_rows); } policy->num_allocated_keys = policy->allocated_aggstate_rows; @@ -216,8 +217,7 @@ static void add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, const int start_row, const int end_row) { - const int num_fns = list_length(policy->agg_defs); - Assert(list_length(policy->per_agg_states) == num_fns); + const int num_fns = policy->num_agg_defs; Assert(start_row < end_row); Assert(end_row <= batch_state->total_batch_rows); @@ -260,14 +260,13 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; for (int i = 0; i < num_fns; i++) { - VectorAggDef *agg_def = list_nth(policy->agg_defs, i); + VectorAggDef *agg_def = &policy->agg_defs[i]; if (next_unused_key_index > first_uninitialized_state_index) { if (next_unused_key_index > policy->allocated_aggstate_rows) { - lfirst(list_nth_cell(policy->per_agg_states, i)) = - repalloc(list_nth(policy->per_agg_states, i), - new_aggstate_rows * agg_def->func.state_bytes); + policy->per_agg_states[i] = repalloc(policy->per_agg_states[i], + new_aggstate_rows * agg_def->func.state_bytes); } /* @@ -275,7 +274,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con */ void *first_uninitialized_state = agg_def->func.state_bytes * first_uninitialized_state_index + - (char *) list_nth(policy->per_agg_states, i); + (char *) policy->per_agg_states[i]; agg_def->func.agg_init(first_uninitialized_state, next_unused_key_index - first_uninitialized_state_index); } @@ -288,7 +287,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con start_row, end_row, agg_def, - list_nth(policy->per_agg_states, i), + policy->per_agg_states[i], policy->offsets, policy->agg_extra_mctx); } @@ -379,9 +378,9 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; Assert(end_row <= n); - add_one_range(policy, batch_state, start_row, end_row); - stat_range_rows += end_row - start_row; + + add_one_range(policy, batch_state, start_row, end_row); } policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - stat_range_rows; } @@ -443,11 +442,11 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return false; } - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_states = list_nth(policy->per_agg_states, i); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_states = policy->per_agg_states[i]; void *agg_state = current_key * agg_def->func.state_bytes + (char *) agg_states; agg_def->func.agg_emit(agg_state, &aggregated_slot->tts_values[agg_def->output_offset], diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index ea985d1fc01..22a2ae28da4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -11,8 +11,6 @@ #include "grouping_policy.h" -typedef struct DecompressBatchState DecompressBatchState; - typedef struct GroupingPolicyHash GroupingPolicyHash; typedef struct @@ -36,7 +34,8 @@ typedef struct GroupingPolicyHash */ GroupingPolicy funcs; - List *agg_defs; + int num_agg_defs; + VectorAggDef *agg_defs; List *output_grouping_columns; /* @@ -75,11 +74,11 @@ typedef struct GroupingPolicyHash uint64 num_allocated_offsets; /* - * Storage of aggregate function states, each List entry is the array of + * Storage of aggregate function states, each entry is the array of * states for the respective function from agg_defs. The state index 0 is - * invalid, and the state index 1 is reserved for a null key. + * invalid. */ - List *per_agg_states; + void **per_agg_states; uint64 allocated_aggstate_rows; uint64 num_allocated_keys; From aca0dca899f1aa2302643dcebd419777bc295adf Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:50:39 +0100 Subject: [PATCH 073/242] review comments -- GroupingColumn array --- tsl/src/nodes/vector_agg/exec.c | 22 +++++++----- tsl/src/nodes/vector_agg/exec.h | 5 +-- tsl/src/nodes/vector_agg/grouping_policy.h | 8 +++-- .../nodes/vector_agg/grouping_policy_batch.c | 35 +++++++++++-------- .../nodes/vector_agg/grouping_policy_hash.c | 27 +++++++------- .../nodes/vector_agg/grouping_policy_hash.h | 10 +++--- tsl/src/nodes/vector_agg/hash_serialized.c | 6 ++-- tsl/src/nodes/vector_agg/hash_single_text.c | 4 +-- .../vector_agg/hash_table_functions_impl.c | 4 +-- .../nodes/vector_agg/single_fixed_key_impl.c | 4 +-- 10 files changed, 72 insertions(+), 53 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index b29ad93411c..c346a92deca 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -83,6 +83,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) const int tlist_length = list_length(aggregated_tlist); int agg_functions_counter = 0; + int grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); @@ -94,6 +95,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) { /* This is a grouping column. */ Assert(IsA(tlentry->expr, Var)); + grouping_column_counter++; } } @@ -101,7 +103,12 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) vector_agg_state->agg_defs = palloc0(sizeof(*vector_agg_state->agg_defs) * vector_agg_state->num_agg_defs); + vector_agg_state->num_grouping_columns = grouping_column_counter; + vector_agg_state->grouping_columns = palloc0(sizeof(*vector_agg_state->grouping_columns) * + vector_agg_state->num_grouping_columns); + agg_functions_counter = 0; + grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); @@ -145,9 +152,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) /* This is a grouping column. */ Assert(IsA(tlentry->expr, Var)); - GroupingColumn *col = palloc0(sizeof(GroupingColumn)); - vector_agg_state->output_grouping_columns = - lappend(vector_agg_state->output_grouping_columns, col); + GroupingColumn *col = &vector_agg_state->grouping_columns[grouping_column_counter++]; col->output_offset = i; Var *var = castNode(Var, tlentry->expr); @@ -165,10 +170,9 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } bool all_segmentby = true; - for (int i = 0; i < list_length(vector_agg_state->output_grouping_columns); i++) + for (int i = 0; i < vector_agg_state->num_grouping_columns; i++) { - GroupingColumn *col = - (GroupingColumn *) list_nth(vector_agg_state->output_grouping_columns, i); + GroupingColumn *col = &vector_agg_state->grouping_columns[i]; DecompressContext *dcontext = &decompress_state->decompress_context; CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; // if (desc->type == COMPRESSED_COLUMN && desc->by_value && desc->value_bytes > 0 && @@ -187,7 +191,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) vector_agg_state->grouping = create_grouping_policy_batch(vector_agg_state->num_agg_defs, vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns); + vector_agg_state->num_grouping_columns, + vector_agg_state->grouping_columns); } else { @@ -197,7 +202,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) vector_agg_state->grouping = create_grouping_policy_hash(vector_agg_state->num_agg_defs, vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns); + vector_agg_state->num_grouping_columns, + vector_agg_state->grouping_columns); } } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 487a3d3a774..4e85e3fddd1 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -22,7 +22,7 @@ typedef struct VectorAggDef uint64 *filter_result; } VectorAggDef; -typedef struct +typedef struct GroupingColumn { int input_offset; int output_offset; @@ -40,7 +40,8 @@ typedef struct int num_agg_defs; VectorAggDef *agg_defs; - List *output_grouping_columns; + int num_grouping_columns; + GroupingColumn *grouping_columns; /* * We can't call the underlying scan after it has ended, or it will be diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 6dfae8d0884..68a23b038e5 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -13,6 +13,8 @@ typedef struct TupleTableSlot TupleTableSlot; typedef struct VectorAggDef VectorAggDef; +typedef struct GroupingColumn GroupingColumn; + /* * This is a common interface for grouping policies which define how the rows * are grouped for aggregation -- e.g. there can be an implementation for no @@ -44,7 +46,9 @@ typedef struct GroupingPolicy } GroupingPolicy; extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, - List *grouping_columns); + int num_grouping_columns, + GroupingColumn *grouping_columns); extern GroupingPolicy *create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, - List *grouping_columns); + int num_grouping_columns, + GroupingColumn *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 68cccf10231..b076ea71485 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -29,7 +29,9 @@ typedef struct void **agg_states; - List *output_grouping_columns; + int num_grouping_columns; + GroupingColumn *grouping_columns; + Datum *output_grouping_values; bool *output_grouping_isnull; bool have_results; @@ -48,14 +50,18 @@ typedef struct static const GroupingPolicy grouping_policy_batch_functions; GroupingPolicy * -create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, - List *output_grouping_columns) +create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, + GroupingColumn *output_grouping_columns) { GroupingPolicyBatch *policy = palloc0(sizeof(GroupingPolicyBatch)); policy->funcs = grouping_policy_batch_functions; - policy->output_grouping_columns = output_grouping_columns; + + policy->num_grouping_columns = num_grouping_columns; + policy->grouping_columns = output_grouping_columns; + policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; + policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); @@ -67,11 +73,10 @@ create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, } policy->output_grouping_values = - (Datum *) palloc0(MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum)) + - MAXALIGN(list_length(output_grouping_columns) * sizeof(bool))); - policy->output_grouping_isnull = - (bool *) ((char *) policy->output_grouping_values + - MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum))); + (Datum *) palloc0(MAXALIGN(num_grouping_columns * sizeof(Datum)) + + MAXALIGN(num_grouping_columns * sizeof(bool))); + policy->output_grouping_isnull = (bool *) ((char *) policy->output_grouping_values + + MAXALIGN(num_grouping_columns * sizeof(Datum))); return &policy->funcs; } @@ -91,7 +96,7 @@ gp_batch_reset(GroupingPolicy *obj) agg_def->func.agg_init(agg_state, 1); } - const int ngrp = list_length(policy->output_grouping_columns); + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { policy->output_grouping_values[i] = 0; @@ -194,10 +199,10 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) compute_single_aggregate(policy, batch_state, agg_def, agg_state, policy->agg_extra_mctx); } - const int ngrp = list_length(policy->output_grouping_columns); + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { - GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + GroupingColumn *col = &policy->grouping_columns[i]; Assert(col->input_offset >= 0); Assert(col->output_offset >= 0); @@ -225,7 +230,7 @@ gp_batch_should_emit(GroupingPolicy *gp) * If we're grouping by segmentby columns, we have to output partials for * every batch. */ - return policy->output_grouping_columns != NIL && policy->have_results; + return policy->num_grouping_columns > 0 && policy->have_results; } static bool @@ -248,10 +253,10 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) &aggregated_slot->tts_isnull[agg_def->output_offset]); } - const int ngrp = list_length(policy->output_grouping_columns); + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { - GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + GroupingColumn *col = &policy->grouping_columns[i]; Assert(col->input_offset >= 0); Assert(col->output_offset >= 0); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index ba1333db1d6..dbd978d6d1f 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -40,17 +40,22 @@ extern HashTableFunctions serialized_functions; static const GroupingPolicy grouping_policy_hash_functions; GroupingPolicy * -create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, List *output_grouping_columns) +create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, + GroupingColumn *grouping_columns) { GroupingPolicyHash *policy = palloc0(sizeof(GroupingPolicyHash)); policy->funcs = grouping_policy_hash_functions; - policy->output_grouping_columns = output_grouping_columns; + + policy->num_grouping_columns = num_grouping_columns; + policy->grouping_columns = grouping_columns; + policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; + policy->per_agg_states = palloc(sizeof(*policy->per_agg_states) * policy->num_agg_defs); for (int i = 0; i < policy->num_agg_defs; i++) { @@ -60,14 +65,13 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, List *outp } policy->num_allocated_keys = policy->allocated_aggstate_rows; - policy->output_keys = - palloc((sizeof(uint64) + list_length(policy->output_grouping_columns) * sizeof(Datum)) * - policy->num_allocated_keys); + policy->output_keys = palloc((sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * + policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; - if (list_length(policy->output_grouping_columns) == 1) + if (num_grouping_columns == 1) { - GroupingColumn *g = linitial(policy->output_grouping_columns); + GroupingColumn *g = &policy->grouping_columns[0]; switch (g->value_bytes) { case 8: @@ -238,8 +242,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con policy->num_allocated_keys = num_possible_keys; policy->output_keys = repalloc(policy->output_keys, - (sizeof(uint64) + - list_length(policy->output_grouping_columns) * sizeof(Datum)) * + (sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * num_possible_keys); } @@ -453,10 +456,10 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) &aggregated_slot->tts_isnull[agg_def->output_offset]); } - const int num_keys = list_length(policy->output_grouping_columns); - for (int i = 0; i < num_keys; i++) + const int num_key_columns = policy->num_grouping_columns; + for (int i = 0; i < num_key_columns; i++) { - GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + GroupingColumn *col = &policy->grouping_columns[i]; aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[i]; aggregated_slot->tts_isnull[col->output_offset] = diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 22a2ae28da4..a568cc48f42 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -36,7 +36,9 @@ typedef struct GroupingPolicyHash int num_agg_defs; VectorAggDef *agg_defs; - List *output_grouping_columns; + + int num_grouping_columns; + GroupingColumn *grouping_columns; /* * The hash table we use for grouping. @@ -101,10 +103,8 @@ typedef struct GroupingPolicyHash static inline uint64 * gp_hash_key_validity_bitmap(GroupingPolicyHash *policy, int key_index) { - return ( - uint64 *) ((char *) policy->output_keys + - (sizeof(uint64) + sizeof(Datum) * list_length(policy->output_grouping_columns)) * - key_index); + return (uint64 *) ((char *) policy->output_keys + + (sizeof(uint64) + sizeof(Datum) * policy->num_grouping_columns) * key_index); } static inline Datum * diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 34afad37148..98eccf7b70c 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -29,12 +29,12 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re uint64 *restrict serialized_key_validity_word; - const int num_columns = list_length(policy->output_grouping_columns); + const int num_columns = policy->num_grouping_columns; Assert(num_columns <= 64); size_t num_bytes = 0; for (int i = 0; i < num_columns; i++) { - const GroupingColumn *def = list_nth(policy->output_grouping_columns, i); + const GroupingColumn *def = &policy->grouping_columns[i]; num_bytes = att_align_nominal(num_bytes, def->typalign); if (def->by_value) { @@ -88,7 +88,7 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re uint32 offset = 0; for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = list_nth(policy->output_grouping_columns, column_index); + const GroupingColumn *def = &policy->grouping_columns[column_index]; offset = att_align_nominal(offset, def->typalign); const CompressedColumnValues *column_values = diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 511d94f83ac..5f2ff2338fc 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -32,12 +32,12 @@ static pg_attribute_always_inline void single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, int row, int next_key_index, BytesView *restrict key, bool *restrict valid) { - if (list_length(policy->output_grouping_columns) != 1) + if (policy->num_grouping_columns != 1) { pg_unreachable(); } - GroupingColumn *g = linitial(policy->output_grouping_columns); + GroupingColumn *g = &policy->grouping_columns[0]; CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; if (unlikely(column.decompression_type == DT_Scalar)) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 69da80f8ffa..aa7022c4eb9 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -147,9 +147,9 @@ FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, uint32 next_unused_state_index, int start_row, int end_row) { - if (list_length(policy->output_grouping_columns) == 1) + if (policy->num_grouping_columns == 1) { - GroupingColumn *g = linitial(policy->output_grouping_columns); + GroupingColumn *g = &policy->grouping_columns[0]; CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; if (unlikely(column.decompression_type == DT_Scalar)) diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 263b762c840..fe8ff76bed8 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -13,12 +13,12 @@ FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, int row, int next_key_index, CTYPE *restrict key, bool *restrict valid) { - if (list_length(policy->output_grouping_columns) != 1) + if (policy->num_grouping_columns != 1) { pg_unreachable(); } - GroupingColumn *g = linitial(policy->output_grouping_columns); + GroupingColumn *g = &policy->grouping_columns[0]; CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; if (unlikely(column.decompression_type == DT_Scalar)) From 49e9396d6466dcfd955df00daec3d0f69f5f77e6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:26:31 +0100 Subject: [PATCH 074/242] assorted review fixes --- .../nodes/vector_agg/grouping_policy_hash.c | 103 +++++++++--------- .../nodes/vector_agg/grouping_policy_hash.h | 100 ++++++++++++----- tsl/src/nodes/vector_agg/hash_serialized.c | 10 +- tsl/src/nodes/vector_agg/hash_single_text.c | 10 +- .../vector_agg/hash_table_functions_impl.c | 90 ++++++++------- .../nodes/vector_agg/single_fixed_key_impl.c | 10 +- 6 files changed, 185 insertions(+), 138 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index dbd978d6d1f..ef14722abb6 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -51,7 +51,7 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; + policy->num_agg_state_rows = TARGET_COMPRESSED_BATCH_SIZE; policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; @@ -60,13 +60,9 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr for (int i = 0; i < policy->num_agg_defs; i++) { VectorAggDef *agg_def = &policy->agg_defs[i]; - policy->per_agg_states[i] = - palloc(agg_def->func.state_bytes * policy->allocated_aggstate_rows); + policy->per_agg_states[i] = palloc(agg_def->func.state_bytes * policy->num_agg_state_rows); } - policy->num_allocated_keys = policy->allocated_aggstate_rows; - policy->output_keys = palloc((sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * - policy->num_allocated_keys); policy->key_body_mctx = policy->agg_extra_mctx; if (num_grouping_columns == 1) @@ -98,11 +94,7 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr } policy->table = - policy->functions.create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); - policy->null_key_index = 0; - policy->next_unused_key_index = 1; - - policy->returning_results = false; + policy->functions.create(CurrentMemoryContext, policy->num_agg_state_rows, NULL); return &policy->funcs; } @@ -119,7 +111,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->functions.reset(policy->table); policy->null_key_index = 0; - policy->next_unused_key_index = 1; + policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; policy->stat_input_total_rows = 0; @@ -230,43 +222,24 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * Remember which aggregation states have already existed, and which we * have to initialize. State index zero is invalid. */ - const uint32 first_uninitialized_state_index = policy->next_unused_key_index; - - /* - * Allocate enough storage for keys, given that each bach row might be - * a separate new key. - */ - const uint32 num_possible_keys = first_uninitialized_state_index + (end_row - start_row); - if (num_possible_keys > policy->num_allocated_keys) - { - policy->num_allocated_keys = num_possible_keys; - policy->output_keys = - repalloc(policy->output_keys, - (sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * - num_possible_keys); - } + const uint32 first_initialized_key_index = policy->last_used_key_index; /* * Match rows to aggregation states using a hash table. */ - Assert((size_t) end_row <= policy->num_allocated_offsets); - uint32 next_unused_key_index = policy->next_unused_key_index; - next_unused_key_index = policy->functions.fill_offsets(policy, - batch_state, - next_unused_key_index, - start_row, - end_row); + Assert((size_t) end_row <= policy->num_key_index_for_row); + policy->functions.fill_offsets(policy, batch_state, start_row, end_row); /* * Process the aggregate function states. */ - const uint64 new_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; + const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; for (int i = 0; i < num_fns; i++) { VectorAggDef *agg_def = &policy->agg_defs[i]; - if (next_unused_key_index > first_uninitialized_state_index) + if (policy->last_used_key_index > first_initialized_key_index) { - if (next_unused_key_index > policy->allocated_aggstate_rows) + if (policy->last_used_key_index >= policy->num_agg_state_rows) { policy->per_agg_states[i] = repalloc(policy->per_agg_states[i], new_aggstate_rows * agg_def->func.state_bytes); @@ -276,10 +249,10 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * Initialize the aggregate function states for the newly added keys. */ void *first_uninitialized_state = - agg_def->func.state_bytes * first_uninitialized_state_index + + agg_def->func.state_bytes * (first_initialized_key_index + 1) + (char *) policy->per_agg_states[i]; agg_def->func.agg_init(first_uninitialized_state, - next_unused_key_index - first_uninitialized_state_index); + policy->last_used_key_index - first_initialized_key_index); } /* @@ -291,20 +264,18 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con end_row, agg_def, policy->per_agg_states[i], - policy->offsets, + policy->key_index_for_row, policy->agg_extra_mctx); } /* * Record the newly allocated number of rows in case we had to reallocate. */ - if (next_unused_key_index > policy->allocated_aggstate_rows) + if (policy->last_used_key_index >= policy->num_agg_state_rows) { - Assert(new_aggstate_rows >= policy->allocated_aggstate_rows); - policy->allocated_aggstate_rows = new_aggstate_rows; + Assert(new_aggstate_rows > policy->num_agg_state_rows); + policy->num_agg_state_rows = new_aggstate_rows; } - - policy->next_unused_key_index = next_unused_key_index; } static void @@ -318,14 +289,42 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Initialize the array for storing the aggregate state offsets corresponding - * to a given batch row. + * to a given batch row. We don't need the offsets for the previous batch + * that are currently stored there, so we don't need to use repalloc. */ - if ((size_t) n > policy->num_allocated_offsets) + if ((size_t) n > policy->num_key_index_for_row) { - policy->num_allocated_offsets = n; - policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + if (policy->key_index_for_row != NULL) + { + pfree(policy->key_index_for_row); + } + policy->num_key_index_for_row = n; + policy->key_index_for_row = + palloc(sizeof(policy->key_index_for_row[0]) * policy->num_key_index_for_row); + } + memset(policy->key_index_for_row, 0, n * sizeof(policy->key_index_for_row[0])); + + /* + * Allocate enough storage for keys, given that each row of the new + * compressed batch might turn out to be a new grouping key. + * We do this here to avoid allocations in the hot loop that fills the hash + * table. + */ + const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; + if (num_possible_keys > policy->num_output_keys) + { + policy->num_output_keys = num_possible_keys * 2 + 1; + const size_t new_bytes = (sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * + policy->num_output_keys; + if (policy->output_keys == NULL) + { + policy->output_keys = palloc(new_bytes); + } + else + { + policy->output_keys = repalloc(policy->output_keys, new_bytes); + } } - memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); /* * Allocate the temporary filter array for computing the combined results of @@ -417,7 +416,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) policy->returning_results = true; policy->last_returned_key = 1; - const float keys = policy->next_unused_key_index - 1; + const float keys = policy->last_used_key_index; if (keys > 0) { DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " @@ -438,7 +437,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) } const uint32 current_key = policy->last_returned_key; - const uint32 keys_end = policy->next_unused_key_index; + const uint32 keys_end = policy->last_used_key_index + 1; if (current_key >= keys_end) { policy->returning_results = false; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index a568cc48f42..aca32d38e63 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -20,12 +20,36 @@ typedef struct void (*reset)(void *table); uint32 (*get_num_keys)(void *table); uint64 (*get_size_bytes)(void *table); - uint32 (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - uint32 next_unused_state_index, int start_row, int end_row); + void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int start_row, int end_row); } HashTableFunctions; /* * Hash grouping policy. + * + * The grouping and aggregation is performed as follows: + * + * 0) The grouping policy keeps track of the unique grouping keys seen in + * the input rows, and the states of aggregate functions for each key. This + * spans multiple input compressed batches, and is reset after the partial + * aggregation results are emitted. + * + * 1) For each row of the new compressed batch, we obtain an integer index that + * uniquely identifies its grouping key. This is done by matching the row's + * grouping columns to the hash table recording the unique grouping keys and + * their respective indexes. It is performed in bulk for all rows of the batch, + * to improve memory locality. + * + * 2) The key indexes are used to locate the aggregate function states + * corresponding to a given row, and update it. This is done in bulk for all + * rows of the batch, and for each aggregate function separately, to generate + * simpler and potentially vectorizable code, and improve memory locality. + * + * 3) After the input have ended, or if the memory limit is reached, the partial + * results are emitted into the output slot. This is done in the order of unique + * grouping key indexes, thereby preserving the incoming key order. This + * guarantees that this policy works correctly even in a Partial GroupAggregate + * node, even though it's not optimal performance-wise. */ typedef struct GroupingPolicyHash { @@ -41,55 +65,79 @@ typedef struct GroupingPolicyHash GroupingColumn *grouping_columns; /* - * The hash table we use for grouping. + * The hash table we use for grouping. It matches each grouping key to its + * unique integer index. */ void *table; HashTableFunctions functions; /* - * Whether we are in the mode of returning the partial aggregation results. - * Track the last returned aggregate state offset if we are. + * The last used index of an unique grouping key. Key index 0 is invalid. */ - bool returning_results; - uint32 last_returned_key; + uint32 last_used_key_index; /* * In single-column grouping, we store the null key outside of the hash - * table, and it has a reserved aggregate state index 1. We also reset this - * flag after we output the null key during iteration. + * table, and its index is given by this value. Key index 0 is invalid. + * This is done to avoid having an "is null" flag in the hash table entries, + * to reduce the hash table size. */ uint32 null_key_index; /* - * A memory context for aggregate functions to allocate additional data, - * i.e. if they store strings or float8 datum on 32-bit systems. Valid until - * the grouping policy is reset. + * Temporary storage of unique key indexes corresponding to a given row of + * the compressed batch that is currently being aggregated. We keep it in + * the policy because it is potentially too big to keep on stack, and we + * don't want to reallocate it each batch. */ - MemoryContext agg_extra_mctx; + uint32 *restrict key_index_for_row; + uint64 num_key_index_for_row; /* - * Temporary storage of aggregate state offsets for a given batch. We keep - * it in the policy because it is potentially too big to keep on stack, and - * we don't want to reallocate it each batch. + * The temporary filter bitmap we use to combine the results of the + * vectorized filters in WHERE, validity of the aggregate function argument, + * and the aggregate FILTER clause. It is then used by the aggregate + * function implementation to filter out the rows that don't pass. */ - uint32 *restrict offsets; - uint64 num_allocated_offsets; + uint64 *tmp_filter; + uint64 num_tmp_filter_words; /* - * Storage of aggregate function states, each entry is the array of - * states for the respective function from agg_defs. The state index 0 is - * invalid. + * Aggregate function states. Each element is an array of states for the + * respective function from agg_defs. These arrays are indexed by the unique + * grouping key indexes. The state index 0 is invalid, so the corresponding + * states are unused. + * The states of each aggregate function are stored separately and + * contiguously, to achieve better memory locality when updating them. */ void **per_agg_states; - uint64 allocated_aggstate_rows; + uint64 num_agg_state_rows; - uint64 num_allocated_keys; + /* + * A memory context for aggregate functions to allocate additional data, + * i.e. if they store strings or float8 datum on 32-bit systems. Valid until + * the grouping policy is reset. + */ + MemoryContext agg_extra_mctx; + + /* + * For each unique grouping key, we store the values of the grouping columns + * in Postgres format (i.e. Datum/isnull). They are used when emitting the + * partial aggregation results. The details of this are managed by the + * hashing strategy. + * + * FIXME + */ void *restrict output_keys; + uint64 num_output_keys; MemoryContext key_body_mctx; - uint32 next_unused_key_index; - uint64 *tmp_filter; - uint64 num_tmp_filter_words; + /* + * Whether we are in the mode of returning the partial aggregation results. + * If we are, track the index of the last returned grouping key. + */ + bool returning_results; + uint32 last_returned_key; /* * Some statistics for debugging. diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 98eccf7b70c..d4329a4d46d 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -20,7 +20,7 @@ static pg_attribute_always_inline void serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - int row, int next_key_index, BytesView *restrict key, bool *restrict valid) + int row, BytesView *restrict key, bool *restrict valid) { // if (list_length(policy->output_grouping_columns) == 1) // { @@ -78,8 +78,10 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re num_bytes = att_align_nominal(num_bytes, TYPALIGN_DOUBLE); num_bytes += sizeof(*serialized_key_validity_word); - uint64 *restrict output_key_validity_word = gp_hash_key_validity_bitmap(policy, next_key_index); - Datum *restrict output_key_datums = gp_hash_output_keys(policy, next_key_index); + uint64 *restrict output_key_validity_word = + gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1); + Datum *restrict output_key_datums = + gp_hash_output_keys(policy, policy->last_used_key_index + 1); uint8 *restrict serialized_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); serialized_key_validity_word = (uint64 *) &( (char *) serialized_key_storage)[num_bytes - sizeof(*serialized_key_validity_word)]; @@ -220,7 +222,7 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re } static pg_attribute_always_inline BytesView -serialized_store_key(GroupingPolicyHash *restrict policy, BytesView key, uint32 key_index) +serialized_store_key(GroupingPolicyHash *restrict policy, BytesView key) { /* Noop, all done in get_key. */ return key; diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 5f2ff2338fc..5ede4904820 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -30,7 +30,7 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) static pg_attribute_always_inline void single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - int row, int next_key_index, BytesView *restrict key, bool *restrict valid) + int row, BytesView *restrict key, bool *restrict valid) { if (policy->num_grouping_columns != 1) { @@ -63,12 +63,12 @@ single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *r pg_unreachable(); } - gp_hash_key_validity_bitmap(policy, next_key_index)[0] = *valid; + gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1)[0] = *valid; DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", policy, row, - next_key_index, + policy->last_used_key_index + 1, key->len); for (size_t i = 0; i < key->len; i++) { @@ -78,14 +78,14 @@ single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *r } static pg_attribute_always_inline BytesView -single_text_store_key(GroupingPolicyHash *restrict policy, BytesView key, uint32 key_index) +single_text_store_key(GroupingPolicyHash *restrict policy, BytesView key) { const int total_bytes = key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), key.data, key.len); key.data = (uint8 *) VARDATA(stored); - gp_hash_output_keys(policy, key_index)[0] = PointerGetDatum(stored); + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); return key; } diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index aa7022c4eb9..3a11e1d0226 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -9,16 +9,25 @@ #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) /* - * For the hash table, use the generic Datum key that is mapped to the aggregate - * state index. + * The hash table maps the value of the grouping key to its unique index. + * We don't store any extra information here, because we're accessing the memory + * of the hash table randomly, and want it to be as small as possible to fit the + * caches. */ typedef struct { CTYPE key; + #ifdef STORE_HASH + /* + * We store hash for non-POD types, because it's slow to recalculate it + * on inserts for the existing values. + */ uint32 hash; #endif - uint32 agg_state_index; + + /* Key index 0 is invalid. */ + uint32 key_index; } FUNCTION_NAME(entry); #define SH_PREFIX KEY_VARIANT @@ -30,7 +39,7 @@ typedef struct #define SH_SCOPE static inline #define SH_DECLARE #define SH_DEFINE -#define SH_ENTRY_EMPTY(entry) ((entry)->agg_state_index == 0) +#define SH_ENTRY_EMPTY(entry) ((entry)->key_index == 0) #ifdef STORE_HASH #define SH_GET_HASH(tb, entry) entry->hash #define SH_STORE_HASH @@ -54,24 +63,24 @@ FUNCTION_NAME(get_size_bytes)(void *table) } /* - * Fill the aggregation state offsets for all rows using a hash table. + * Fill the unique key indexes for all rows using a hash table. */ -static pg_attribute_always_inline uint32 +static pg_attribute_always_inline void FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - uint32 next_unused_state_index, int start_row, int end_row) + int start_row, int end_row) { - uint32 *restrict offsets = policy->offsets; - Assert((size_t) end_row <= policy->num_allocated_offsets); + uint32 *restrict indexes = policy->key_index_for_row; + Assert((size_t) end_row <= policy->num_key_index_for_row); struct FUNCTION_NAME(hash) *restrict table = policy->table; - CTYPE last_key; - uint32 last_key_index = 0; + CTYPE previous_key; + uint32 previous_key_index = 0; for (int row = start_row; row < end_row; row++) { bool key_valid = false; CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(policy, batch_state, row, next_unused_state_index, &key, &key_valid); + FUNCTION_NAME(get_key)(policy, batch_state, row, &key, &key_valid); if (!arrow_row_is_valid(batch_state->vector_qual_result, row)) { @@ -86,26 +95,26 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r /* The key is null. */ if (policy->null_key_index == 0) { - policy->null_key_index = next_unused_state_index++; + policy->null_key_index = ++policy->last_used_key_index; } - offsets[row] = policy->null_key_index; + indexes[row] = policy->null_key_index; DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); FUNCTION_NAME(destroy_key)(key); continue; } - if (likely(last_key_index != 0) && KEY_EQUAL(key, last_key)) + if (likely(previous_key_index != 0) && KEY_EQUAL(key, previous_key)) { /* * In real data sets, we often see consecutive rows with the * same key, so checking for this case improves performance. */ - offsets[row] = last_key_index; + indexes[row] = previous_key_index; FUNCTION_NAME(destroy_key)(key); #ifndef NDEBUG policy->stat_consecutive_keys++; #endif - DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, last_key_index); + DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; } @@ -119,33 +128,30 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r /* * New key, have to store it persistently. */ - const int index = next_unused_state_index++; - entry->key = FUNCTION_NAME(store_key)(policy, key, index); - entry->agg_state_index = index; + const int index = ++policy->last_used_key_index; + entry->key = FUNCTION_NAME(store_key)(policy, key); + entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } else { - DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->agg_state_index); + DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); FUNCTION_NAME(destroy_key)(key); } - offsets[row] = entry->agg_state_index; + indexes[row] = entry->key_index; - last_key_index = entry->agg_state_index; - last_key = entry->key; + previous_key_index = entry->key_index; + previous_key = entry->key; } - - return next_unused_state_index; } /* * Nudge the compiler to generate separate implementations for different key * decompression types. */ -static pg_attribute_always_inline uint32 +static pg_attribute_always_inline void FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, - uint32 next_unused_state_index, int start_row, int end_row) + DecompressBatchState *restrict batch_state, int start_row, int end_row) { if (policy->num_grouping_columns == 1) { @@ -154,27 +160,23 @@ FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, if (unlikely(column.decompression_type == DT_Scalar)) { - return FUNCTION_NAME( - impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); } else if (column.decompression_type == DT_ArrowText) { - return FUNCTION_NAME( - impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); } else if (column.decompression_type == DT_ArrowTextDict) { - return FUNCTION_NAME( - impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); } else { - return FUNCTION_NAME( - impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); } } - return FUNCTION_NAME(impl)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); } /* @@ -182,22 +184,18 @@ FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, * where the entire batch matches and the key has no null values, and the * unimportant corner case when we have a scalar column. */ -static uint32 +static void FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - uint32 next_unused_state_index, int start_row, int end_row) + int start_row, int end_row) { if (batch_state->vector_qual_result == NULL) { - next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(dispatch_type)(policy, batch_state, start_row, end_row); } else { - next_unused_state_index = FUNCTION_NAME( - dispatch_type)(policy, batch_state, next_unused_state_index, start_row, end_row); + FUNCTION_NAME(dispatch_type)(policy, batch_state, start_row, end_row); } - - return next_unused_state_index; } HashTableFunctions FUNCTION_NAME(functions) = { diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index fe8ff76bed8..1a738b67ecf 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -10,8 +10,8 @@ static pg_attribute_always_inline void FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int row, int next_key_index, - CTYPE *restrict key, bool *restrict valid) + DecompressBatchState *restrict batch_state, int row, CTYPE *restrict key, + bool *restrict valid) { if (policy->num_grouping_columns != 1) { @@ -38,12 +38,12 @@ FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, pg_unreachable(); } - gp_hash_output_keys(policy, next_key_index)[0] = CTYPE_TO_DATUM(*key); - gp_hash_key_validity_bitmap(policy, next_key_index)[0] = *valid; + gp_hash_output_keys(policy, policy->last_used_key_index + 1)[0] = CTYPE_TO_DATUM(*key); + gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1)[0] = *valid; } static pg_attribute_always_inline CTYPE -FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key, uint32 key_index) +FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key) { return key; } From b57057176204c562da5e6173d582c57a170677ef Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:50:08 +0100 Subject: [PATCH 075/242] try to generate specializations -- bad --- tsl/src/nodes/vector_agg/bytes_view.h | 6 +-- tsl/src/nodes/vector_agg/hash_serialized.c | 4 +- .../nodes/vector_agg/hash_single_fixed_2.c | 1 + .../nodes/vector_agg/hash_single_fixed_4.c | 1 + .../nodes/vector_agg/hash_single_fixed_8.c | 1 + tsl/src/nodes/vector_agg/hash_single_text.c | 32 +++++++--------- .../vector_agg/hash_table_functions_impl.c | 37 +++++++++++++------ .../nodes/vector_agg/single_fixed_key_impl.c | 24 +++++------- 8 files changed, 58 insertions(+), 48 deletions(-) diff --git a/tsl/src/nodes/vector_agg/bytes_view.h b/tsl/src/nodes/vector_agg/bytes_view.h index 1930186b51b..28696bb1654 100644 --- a/tsl/src/nodes/vector_agg/bytes_view.h +++ b/tsl/src/nodes/vector_agg/bytes_view.h @@ -18,7 +18,7 @@ typedef struct BytesView static pg_attribute_always_inline uint32 hash_bytes_view(BytesView view) { - uint32 valll = -1; - COMP_CRC32C(valll, view.data, view.len); - return valll; + uint32 val = -1; + COMP_CRC32C(val, view.data, view.len); + return val; } diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index d4329a4d46d..cd47c1a83f0 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,7 +19,9 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, +serialized_get_key(GroupingPolicyHash *restrict policy, +DecompressBatchState *restrict batch_state, + CompressedColumnValues *single_key_column, int row, BytesView *restrict key, bool *restrict valid) { // if (list_length(policy->output_grouping_columns) == 1) diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 3799d4dae9b..0022fa2593d 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -21,6 +21,7 @@ #define KEY_BYTES 2 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b +#define CHECK_PREVIOUS_KEY #define CTYPE int16 #define DATUM_TO_CTYPE DatumGetInt16 #define CTYPE_TO_DATUM Int16GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index e4982c9e11b..57bd2c278ce 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -21,6 +21,7 @@ #define KEY_BYTES 4 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b +#define CHECK_PREVIOUS_KEY #define CTYPE int32 #define DATUM_TO_CTYPE DatumGetInt32 #define CTYPE_TO_DATUM Int32GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index f191cbfe9ff..89e52168a08 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -21,6 +21,7 @@ #define KEY_BYTES 8 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b +#define CHECK_PREVIOUS_KEY #define CTYPE int64 #define DATUM_TO_CTYPE DatumGetInt64 #define CTYPE_TO_DATUM Int64GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 5ede4904820..80fd83121dc 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -30,33 +30,28 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) static pg_attribute_always_inline void single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + CompressedColumnValues *single_key_column, int row, BytesView *restrict key, bool *restrict valid) { - if (policy->num_grouping_columns != 1) - { - pg_unreachable(); - } - - GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + Assert(policy->num_grouping_columns == 1); - if (unlikely(column.decompression_type == DT_Scalar)) + if (unlikely(single_key_column->decompression_type == DT_Scalar)) { /* Already stored. */ - key->len = VARSIZE_ANY_EXHDR(*column.output_value); - key->data = (const uint8 *) VARDATA_ANY(*column.output_value); - *valid = !*column.output_isnull; + key->len = VARSIZE_ANY_EXHDR(*single_key_column->output_value); + key->data = (const uint8 *) VARDATA_ANY(*single_key_column->output_value); + *valid = !*single_key_column->output_isnull; } - else if (column.decompression_type == DT_ArrowText) + else if (single_key_column->decompression_type == DT_ArrowText) { - *key = get_bytes_view(&column, row); - *valid = arrow_row_is_valid(column.buffers[0], row); + *key = get_bytes_view(single_key_column, row); + *valid = arrow_row_is_valid(single_key_column->buffers[0], row); } - else if (column.decompression_type == DT_ArrowTextDict) + else if (single_key_column->decompression_type == DT_ArrowTextDict) { - const int16 index = ((int16 *) column.buffers[3])[row]; - *key = get_bytes_view(&column, index); - *valid = arrow_row_is_valid(column.buffers[0], row); + const int16 index = ((int16 *) single_key_column->buffers[3])[row]; + *key = get_bytes_view(single_key_column, index); + *valid = arrow_row_is_valid(single_key_column->buffers[0], row); } else { @@ -100,5 +95,6 @@ single_text_destroy_key(BytesView key) #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define STORE_HASH +#define CHECK_PREVIOUS_KEY #define CTYPE BytesView #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 3a11e1d0226..daac0520ffb 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -67,6 +67,7 @@ FUNCTION_NAME(get_size_bytes)(void *table) */ static pg_attribute_always_inline void FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + CompressedColumnValues *single_key_column, int start_row, int end_row) { uint32 *restrict indexes = policy->key_index_for_row; @@ -74,13 +75,15 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r struct FUNCTION_NAME(hash) *restrict table = policy->table; +#ifdef CHECK_PREVIOUS_KEY CTYPE previous_key; uint32 previous_key_index = 0; +#endif for (int row = start_row; row < end_row; row++) { bool key_valid = false; CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(policy, batch_state, row, &key, &key_valid); + FUNCTION_NAME(get_key)(policy, batch_state, single_key_column, row, &key, &key_valid); if (!arrow_row_is_valid(batch_state->vector_qual_result, row)) { @@ -103,11 +106,14 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r continue; } +#ifdef CHECK_PREVIOUS_KEY if (likely(previous_key_index != 0) && KEY_EQUAL(key, previous_key)) { /* * In real data sets, we often see consecutive rows with the - * same key, so checking for this case improves performance. + * same value of a grouping column, so checking for this case + * improves performance. For multi-column keys, this is unlikely and + * so this check is disabled. */ indexes[row] = previous_key_index; FUNCTION_NAME(destroy_key)(key); @@ -117,6 +123,7 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; } +#endif /* * Find the key using the hash table. @@ -140,8 +147,10 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r } indexes[row] = entry->key_index; +#ifdef CHECK_PREVIOUS_KEY previous_key_index = entry->key_index; previous_key = entry->key; +#endif } } @@ -156,27 +165,29 @@ FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, if (policy->num_grouping_columns == 1) { GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + CompressedColumnValues *restrict single_key_column = &batch_state->compressed_columns[g->input_offset]; - if (unlikely(column.decompression_type == DT_Scalar)) + if (unlikely(single_key_column->decompression_type == DT_Scalar)) { - FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); } - else if (column.decompression_type == DT_ArrowText) + else if (single_key_column->decompression_type == DT_ArrowText) { - FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); } - else if (column.decompression_type == DT_ArrowTextDict) + else if (single_key_column->decompression_type == DT_ArrowTextDict) { - FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); } else { - FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); + FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); } } - - FUNCTION_NAME(impl)(policy, batch_state, start_row, end_row); + else + { + FUNCTION_NAME(impl)(policy, batch_state, NULL, start_row, end_row); + } } /* @@ -212,6 +223,8 @@ HashTableFunctions FUNCTION_NAME(functions) = { #undef KEY_BYTES #undef KEY_HASH #undef KEY_EQUAL +#undef STORE_HASH +#undef CHECK_PREVIOUS_KEY #undef CTYPE #undef DATUM_TO_CTYPE #undef CTYPE_TO_DATUM diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 1a738b67ecf..cad35f3b4e0 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -10,26 +10,22 @@ static pg_attribute_always_inline void FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int row, CTYPE *restrict key, + DecompressBatchState *restrict batch_state, + CompressedColumnValues *single_key_column, + int row, CTYPE *restrict key, bool *restrict valid) { - if (policy->num_grouping_columns != 1) - { - pg_unreachable(); - } - - GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues column = batch_state->compressed_columns[g->input_offset]; + Assert(policy->num_grouping_columns == 1); - if (unlikely(column.decompression_type == DT_Scalar)) + if (unlikely(single_key_column->decompression_type == DT_Scalar)) { - *key = DATUM_TO_CTYPE(*column.output_value); - *valid = !*column.output_isnull; + *key = DATUM_TO_CTYPE(*single_key_column->output_value); + *valid = !*single_key_column->output_isnull; } - else if (column.decompression_type == sizeof(CTYPE)) + else if (single_key_column->decompression_type == sizeof(CTYPE)) { - const CTYPE *values = column.buffers[1]; - const uint64 *key_validity = column.buffers[0]; + const CTYPE *values = single_key_column->buffers[1]; + const uint64 *key_validity = single_key_column->buffers[0]; *valid = arrow_row_is_valid(key_validity, row); *key = values[row]; } From 3aff8a98d3c6688cf7871c39bf05c790ef8bc8ed Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:06:08 +0100 Subject: [PATCH 076/242] specializations --- .../function/agg_many_vector_helper.c | 13 +- .../nodes/vector_agg/grouping_policy_hash.c | 12 +- .../nodes/vector_agg/grouping_policy_hash.h | 12 +- tsl/src/nodes/vector_agg/hash_serialized.c | 6 +- tsl/src/nodes/vector_agg/hash_single_text.c | 28 ++--- .../vector_agg/hash_table_functions_impl.c | 111 ++++++++++-------- .../nodes/vector_agg/single_fixed_key_impl.c | 19 ++- 7 files changed, 114 insertions(+), 87 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index aae48bb2230..192fad35017 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -31,6 +31,15 @@ FUNCTION_NAME(many_vector_impl)(void *restrict agg_states, const uint32 *offsets MemoryContextSwitchTo(old); } +static pg_noinline void +FUNCTION_NAME(many_vector_all_valid)(void *restrict agg_states, const uint32 *offsets, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + FUNCTION_NAME(many_vector_impl) + (agg_states, offsets, NULL, start_row, end_row, vector, agg_extra_mctx); +} + static void FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, int start_row, int end_row, const ArrowArray *vector, @@ -38,8 +47,8 @@ FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, con { if (filter == NULL) { - FUNCTION_NAME(many_vector_impl) - (agg_states, offsets, NULL, start_row, end_row, vector, agg_extra_mctx); + FUNCTION_NAME(many_vector_all_valid) + (agg_states, offsets, start_row, end_row, vector, agg_extra_mctx); } else { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index ef14722abb6..b1d7e6a6e1e 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -59,7 +59,7 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->per_agg_states = palloc(sizeof(*policy->per_agg_states) * policy->num_agg_defs); for (int i = 0; i < policy->num_agg_defs; i++) { - VectorAggDef *agg_def = &policy->agg_defs[i]; + const VectorAggDef *agg_def = &policy->agg_defs[i]; policy->per_agg_states[i] = palloc(agg_def->func.state_bytes * policy->num_agg_state_rows); } @@ -67,7 +67,7 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr if (num_grouping_columns == 1) { - GroupingColumn *g = &policy->grouping_columns[0]; + const GroupingColumn *g = &policy->grouping_columns[0]; switch (g->value_bytes) { case 8: @@ -121,7 +121,7 @@ gp_hash_reset(GroupingPolicy *obj) static void compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState *batch_state, - int start_row, int end_row, VectorAggDef *agg_def, void *agg_states, + int start_row, int end_row, const VectorAggDef *agg_def, void *agg_states, const uint32 *offsets, MemoryContext agg_extra_mctx) { const ArrowArray *arg_arrow = NULL; @@ -236,7 +236,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; for (int i = 0; i < num_fns; i++) { - VectorAggDef *agg_def = &policy->agg_defs[i]; + const VectorAggDef *agg_def = &policy->agg_defs[i]; if (policy->last_used_key_index > first_initialized_key_index) { if (policy->last_used_key_index >= policy->num_agg_state_rows) @@ -447,7 +447,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = &policy->agg_defs[i]; + const VectorAggDef *agg_def = &policy->agg_defs[i]; void *agg_states = policy->per_agg_states[i]; void *agg_state = current_key * agg_def->func.state_bytes + (char *) agg_states; agg_def->func.agg_emit(agg_state, @@ -458,7 +458,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) const int num_key_columns = policy->num_grouping_columns; for (int i = 0; i < num_key_columns; i++) { - GroupingColumn *col = &policy->grouping_columns[i]; + const GroupingColumn *col = &policy->grouping_columns[i]; aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[i]; aggregated_slot->tts_isnull[col->output_offset] = diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index aca32d38e63..ea858b836ee 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -11,6 +11,8 @@ #include "grouping_policy.h" +#include "nodes/decompress_chunk/compressed_batch.h" + typedef struct GroupingPolicyHash GroupingPolicyHash; typedef struct @@ -59,10 +61,10 @@ typedef struct GroupingPolicyHash GroupingPolicy funcs; int num_agg_defs; - VectorAggDef *agg_defs; + const VectorAggDef *restrict agg_defs; int num_grouping_columns; - GroupingColumn *grouping_columns; + const GroupingColumn *restrict grouping_columns; /* * The hash table we use for grouping. It matches each grouping key to its @@ -166,3 +168,9 @@ gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) #ifndef DEBUG_PRINT #define DEBUG_PRINT(...) #endif + +typedef struct HashingConfig +{ + const uint64 *restrict batch_filter; + CompressedColumnValues single_key; +} HashingConfig; diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index cd47c1a83f0..024b7706d22 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,10 +19,8 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(GroupingPolicyHash *restrict policy, -DecompressBatchState *restrict batch_state, - CompressedColumnValues *single_key_column, - int row, BytesView *restrict key, bool *restrict valid) +serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, + HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) { // if (list_length(policy->output_grouping_columns) == 1) // { diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 80fd83121dc..15290bed7b8 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -30,35 +30,35 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) static pg_attribute_always_inline void single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - CompressedColumnValues *single_key_column, - int row, BytesView *restrict key, bool *restrict valid) + HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) { Assert(policy->num_grouping_columns == 1); - if (unlikely(single_key_column->decompression_type == DT_Scalar)) + if (unlikely(config.single_key.decompression_type == DT_Scalar)) { /* Already stored. */ - key->len = VARSIZE_ANY_EXHDR(*single_key_column->output_value); - key->data = (const uint8 *) VARDATA_ANY(*single_key_column->output_value); - *valid = !*single_key_column->output_isnull; + key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); + key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); + *valid = !*config.single_key.output_isnull; } - else if (single_key_column->decompression_type == DT_ArrowText) + else if (config.single_key.decompression_type == DT_ArrowText) { - *key = get_bytes_view(single_key_column, row); - *valid = arrow_row_is_valid(single_key_column->buffers[0], row); + *key = get_bytes_view(&config.single_key, row); + *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } - else if (single_key_column->decompression_type == DT_ArrowTextDict) + else if (config.single_key.decompression_type == DT_ArrowTextDict) { - const int16 index = ((int16 *) single_key_column->buffers[3])[row]; - *key = get_bytes_view(single_key_column, index); - *valid = arrow_row_is_valid(single_key_column->buffers[0], row); + const int16 index = ((int16 *) config.single_key.buffers[3])[row]; + *key = get_bytes_view(&config.single_key, index); + *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } else { pg_unreachable(); } - gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1)[0] = *valid; + *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1) = + *valid; DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", policy, diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index daac0520ffb..40b022532a8 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -66,9 +66,9 @@ FUNCTION_NAME(get_size_bytes)(void *table) * Fill the unique key indexes for all rows using a hash table. */ static pg_attribute_always_inline void -FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - CompressedColumnValues *single_key_column, - int start_row, int end_row) +FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, + DecompressBatchState *restrict batch_state, HashingConfig config, + int start_row, int end_row) { uint32 *restrict indexes = policy->key_index_for_row; Assert((size_t) end_row <= policy->num_key_index_for_row); @@ -81,18 +81,17 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r #endif for (int row = start_row; row < end_row; row++) { - bool key_valid = false; - CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(policy, batch_state, single_key_column, row, &key, &key_valid); - - if (!arrow_row_is_valid(batch_state->vector_qual_result, row)) + if (!arrow_row_is_valid(config.batch_filter, row)) { - DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); /* The row doesn't pass the filter. */ - FUNCTION_NAME(destroy_key)(key); + DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); continue; } + bool key_valid = false; + CTYPE key = { 0 }; + FUNCTION_NAME(get_key)(policy, batch_state, config, row, &key, &key_valid); + if (unlikely(!key_valid)) { /* The key is null. */ @@ -155,57 +154,73 @@ FUNCTION_NAME(impl)(GroupingPolicyHash *restrict policy, DecompressBatchState *r } /* - * Nudge the compiler to generate separate implementations for different key - * decompression types. + * For some configurations of hashing, we want to generate dedicated + * implementations that will be more efficient. For example, for 2-byte keys + * when all the batch and key rows are valid. */ -static pg_attribute_always_inline void -FUNCTION_NAME(dispatch_type)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, int start_row, int end_row) -{ - if (policy->num_grouping_columns == 1) - { - GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues *restrict single_key_column = &batch_state->compressed_columns[g->input_offset]; - - if (unlikely(single_key_column->decompression_type == DT_Scalar)) - { - FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); - } - else if (single_key_column->decompression_type == DT_ArrowText) - { - FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); - } - else if (single_key_column->decompression_type == DT_ArrowTextDict) - { - FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); - } - else - { - FUNCTION_NAME(impl)(policy, batch_state, single_key_column, start_row, end_row); - } - } - else - { - FUNCTION_NAME(impl)(policy, batch_state, NULL, start_row, end_row); +#define APPLY_FOR_SPECIALIZATIONS(X) \ + X(fixed_all_valid, \ + config.batch_filter == NULL && config.single_key.decompression_type == sizeof(CTYPE) && \ + config.single_key.buffers[0] == NULL) \ + X(text_all_valid, \ + config.batch_filter == NULL && config.single_key.decompression_type == DT_ArrowText && \ + config.single_key.buffers[0] == NULL) \ + X(text_dict_all_valid, \ + config.batch_filter == NULL && config.single_key.decompression_type == DT_ArrowTextDict && \ + config.single_key.buffers[0] == NULL) \ + X(no_batch_filter, config.batch_filter == NULL) + +#define DEFINE(NAME, CONDITION) \ + static pg_noinline void FUNCTION_NAME(NAME)(GroupingPolicyHash *restrict policy, \ + DecompressBatchState *restrict batch_state, \ + HashingConfig config, \ + int start_row, \ + int end_row) \ + { \ + if (!(CONDITION)) \ + { \ + pg_unreachable(); \ + } \ + \ + FUNCTION_NAME(fill_offsets_impl)(policy, batch_state, config, start_row, end_row); \ } -} + +APPLY_FOR_SPECIALIZATIONS(DEFINE) + +#undef DEFINE /* - * Nudge the compiler to generate separate implementation for the important case - * where the entire batch matches and the key has no null values, and the - * unimportant corner case when we have a scalar column. + * In some special cases we call a more efficient specialization of the grouping + * function. */ static void FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row) { - if (batch_state->vector_qual_result == NULL) + HashingConfig config = { + .batch_filter = batch_state->vector_qual_result, + }; + + if (policy->num_grouping_columns == 1) { - FUNCTION_NAME(dispatch_type)(policy, batch_state, start_row, end_row); + const GroupingColumn *g = &policy->grouping_columns[0]; + CompressedColumnValues *restrict single_key_column = + &batch_state->compressed_columns[g->input_offset]; + + config.single_key = *single_key_column; } + +#define DISPATCH(NAME, CONDITION) \ + if (CONDITION) \ + { \ + FUNCTION_NAME(NAME)(policy, batch_state, config, start_row, end_row); \ + } \ else + + APPLY_FOR_SPECIALIZATIONS(DISPATCH) { - FUNCTION_NAME(dispatch_type)(policy, batch_state, start_row, end_row); + /* Use a generic implementation if no specializations matched. */ + FUNCTION_NAME(fill_offsets_impl)(policy, batch_state, config, start_row, end_row); } } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index cad35f3b4e0..ba5b9bf974a 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -10,23 +10,20 @@ static pg_attribute_always_inline void FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, - CompressedColumnValues *single_key_column, - int row, CTYPE *restrict key, - bool *restrict valid) + DecompressBatchState *restrict batch_state, HashingConfig config, int row, + CTYPE *restrict key, bool *restrict valid) { Assert(policy->num_grouping_columns == 1); - if (unlikely(single_key_column->decompression_type == DT_Scalar)) + if (unlikely(config.single_key.decompression_type == DT_Scalar)) { - *key = DATUM_TO_CTYPE(*single_key_column->output_value); - *valid = !*single_key_column->output_isnull; + *key = DATUM_TO_CTYPE(*config.single_key.output_value); + *valid = !*config.single_key.output_isnull; } - else if (single_key_column->decompression_type == sizeof(CTYPE)) + else if (config.single_key.decompression_type == sizeof(CTYPE)) { - const CTYPE *values = single_key_column->buffers[1]; - const uint64 *key_validity = single_key_column->buffers[0]; - *valid = arrow_row_is_valid(key_validity, row); + const CTYPE *values = config.single_key.buffers[1]; + *valid = arrow_row_is_valid(config.single_key.buffers[0], row); *key = values[row]; } else From 2da859191e516604cc478f5123ab468c1e285d9d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:06:18 +0100 Subject: [PATCH 077/242] benchmark specializations (2024-10-29 no. 1) From 71b0e81853d3c5e780634c79a6b249143bb48bcf Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:43:03 +0100 Subject: [PATCH 078/242] more specializations --- .../vector_agg/hash_table_functions_impl.c | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 40b022532a8..001b1668164 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -158,17 +158,26 @@ FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, * implementations that will be more efficient. For example, for 2-byte keys * when all the batch and key rows are valid. */ -#define APPLY_FOR_SPECIALIZATIONS(X) \ - X(fixed_all_valid, \ - config.batch_filter == NULL && config.single_key.decompression_type == sizeof(CTYPE) && \ - config.single_key.buffers[0] == NULL) \ - X(text_all_valid, \ - config.batch_filter == NULL && config.single_key.decompression_type == DT_ArrowText && \ - config.single_key.buffers[0] == NULL) \ - X(text_dict_all_valid, \ - config.batch_filter == NULL && config.single_key.decompression_type == DT_ArrowTextDict && \ - config.single_key.buffers[0] == NULL) \ - X(no_batch_filter, config.batch_filter == NULL) +#define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ + X(NAME##_all, (COND) && (config.batch_filter == NULL)) \ + X(NAME##_filter, (COND) && (config.batch_filter != NULL)) + +#define APPLY_FOR_TYPE(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_fixed, \ + (COND) && (config.single_key.decompression_type == sizeof(CTYPE))) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_text, \ + (COND) && (config.single_key.decompression_type == DT_ArrowText)) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_dict, \ + (COND) && (config.single_key.decompression_type == DT_ArrowTextDict)) + +#define APPLY_FOR_VALIDITY(X, NAME, COND) \ + APPLY_FOR_TYPE(X, NAME, (COND) && (config.single_key.buffers[0] == NULL)) \ + APPLY_FOR_TYPE(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, , true) #define DEFINE(NAME, CONDITION) \ static pg_noinline void FUNCTION_NAME(NAME)(GroupingPolicyHash *restrict policy, \ From 4a1cce3e9fa0028dd2c782a70a3e3826846eb1e6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:59:25 +0100 Subject: [PATCH 079/242] optimizations --- tsl/src/nodes/vector_agg/exec.c | 19 ++- tsl/src/nodes/vector_agg/exec.h | 2 +- .../nodes/vector_agg/grouping_policy_hash.h | 15 +- tsl/src/nodes/vector_agg/hash_serialized.c | 147 ++++++++++++------ .../nodes/vector_agg/hash_single_fixed_2.c | 1 - .../nodes/vector_agg/hash_single_fixed_4.c | 1 - .../nodes/vector_agg/hash_single_fixed_8.c | 1 - tsl/src/nodes/vector_agg/hash_single_text.c | 5 +- .../vector_agg/hash_table_functions_impl.c | 69 ++++---- .../nodes/vector_agg/single_fixed_key_impl.c | 6 +- 10 files changed, 170 insertions(+), 96 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index c346a92deca..40b1a3e9482 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -165,7 +165,24 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) col->typid = desc->typid; col->value_bytes = desc->value_bytes; col->by_value = desc->by_value; - col->typalign = desc->typalign; + switch (desc->typalign) + { + case TYPALIGN_CHAR: + col->alignment_bytes = 1; + break; + case TYPALIGN_SHORT: + col->alignment_bytes = ALIGNOF_SHORT; + break; + case TYPALIGN_INT: + col->alignment_bytes = ALIGNOF_INT; + break; + case TYPALIGN_DOUBLE: + col->alignment_bytes = ALIGNOF_DOUBLE; + break; + default: + Assert(false); + col->alignment_bytes = 1; + } } } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 4e85e3fddd1..20bbd852395 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -30,7 +30,7 @@ typedef struct GroupingColumn Oid typid; int16 value_bytes; bool by_value; - char typalign; + int8 alignment_bytes; } GroupingColumn; typedef struct diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index ea858b836ee..7bf3f024acc 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -73,6 +73,13 @@ typedef struct GroupingPolicyHash void *table; HashTableFunctions functions; + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; + /* * The last used index of an unique grouping key. Key index 0 is invalid. */ @@ -171,6 +178,12 @@ gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) typedef struct HashingConfig { - const uint64 *restrict batch_filter; + const uint64 *batch_filter; CompressedColumnValues single_key; + + int num_grouping_columns; + const GroupingColumn *grouping_columns; + const CompressedColumnValues *compressed_columns; + + GroupingPolicyHash *policy; } HashingConfig; diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 024b7706d22..3ac7818623c 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,82 +19,121 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) +serialized_get_key(HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) { - // if (list_length(policy->output_grouping_columns) == 1) - // { - // pg_unreachable(); - // } + GroupingPolicyHash *policy = config.policy; uint64 *restrict serialized_key_validity_word; - const int num_columns = policy->num_grouping_columns; + const int num_columns = config.num_grouping_columns; Assert(num_columns <= 64); + + /* + * Loop through the grouping columns to determine the length of the key. We + * need that to allocate memory to store it. + */ size_t num_bytes = 0; - for (int i = 0; i < num_columns; i++) + for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = &policy->grouping_columns[i]; - num_bytes = att_align_nominal(num_bytes, def->typalign); - if (def->by_value) + const GroupingColumn *def = &config.grouping_columns[column_index]; + const CompressedColumnValues *column_values = &config.compressed_columns[def->input_offset]; + + num_bytes = TYPEALIGN(def->alignment_bytes, num_bytes); + + if (column_values->decompression_type > 0) { - num_bytes += def->value_bytes; + Assert(def->by_value); + num_bytes += column_values->decompression_type; } - else + else if (unlikely(column_values->decompression_type == DT_Scalar)) { - const CompressedColumnValues *column = - &batch_state->compressed_columns[def->input_offset]; - if (unlikely(column->decompression_type == DT_Scalar)) + if (def->by_value) { - num_bytes += (*column->output_isnull) ? 0 : VARSIZE_ANY(*column->output_value); + num_bytes += def->value_bytes; } - else if (column->decompression_type == DT_ArrowText) + else { - if (arrow_row_is_valid(column->buffers[0], row)) - { - const uint32 start = ((uint32 *) column->buffers[1])[row]; - const int32 value_bytes = ((uint32 *) column->buffers[1])[row + 1] - start; - num_bytes += value_bytes + VARHDRSZ; - } + num_bytes += + (*column_values->output_isnull) ? 0 : VARSIZE_ANY(*column_values->output_value); } - else if (column->decompression_type == DT_ArrowTextDict) + } + else if (column_values->decompression_type == DT_ArrowText) + { + if (arrow_row_is_valid(column_values->buffers[0], row)) { - if (arrow_row_is_valid(column->buffers[0], row)) - { - const int16 index = ((int16 *) column->buffers[3])[row]; - const uint32 start = ((uint32 *) column->buffers[1])[index]; - const int32 value_bytes = ((uint32 *) column->buffers[1])[index + 1] - start; - num_bytes += value_bytes + VARHDRSZ; - } + const uint32 start = ((uint32 *) column_values->buffers[1])[row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[row + 1] - start; + num_bytes += value_bytes + VARHDRSZ; } - else + } + else if (column_values->decompression_type == DT_ArrowTextDict) + { + if (arrow_row_is_valid(column_values->buffers[0], row)) { - pg_unreachable(); + const int16 index = ((int16 *) column_values->buffers[3])[row]; + const uint32 start = ((uint32 *) column_values->buffers[1])[index]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[index + 1] - start; + num_bytes += value_bytes + VARHDRSZ; } } + else + { + pg_unreachable(); + } } - /* The optional null bitmap. */ - num_bytes = att_align_nominal(num_bytes, TYPALIGN_DOUBLE); + /* + * The key can have a null bitmap if any values are null, we always allocate + * the storage for it. + */ + num_bytes = TYPEALIGN(ALIGNOF_DOUBLE, num_bytes); num_bytes += sizeof(*serialized_key_validity_word); + /* + * Use temporary storage for the new key, reallocate if it's too small. + */ + if (num_bytes > policy->num_tmp_key_storage_bytes) + { + if (policy->tmp_key_storage != NULL) + { + policy->key_body_mctx->methods->free_p(policy->key_body_mctx, policy->tmp_key_storage); + } + policy->tmp_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); + policy->num_tmp_key_storage_bytes = num_bytes; + } + uint8 *restrict serialized_key_storage = policy->tmp_key_storage; + + /* + * Have to memset the key with zeros, so that the alignment bytes are zeroed + * out. + */ + memset(serialized_key_storage, 0, num_bytes); + + serialized_key_validity_word = (uint64 *) &( + (char *) serialized_key_storage)[num_bytes - sizeof(*serialized_key_validity_word)]; + *serialized_key_validity_word = ~0ULL; + + /* + * We will also fill the output key values in Postgres format. They can go + * straight into the next unused key space, if this key is discarded they + * will just be overwritten later. + */ uint64 *restrict output_key_validity_word = gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1); Datum *restrict output_key_datums = gp_hash_output_keys(policy, policy->last_used_key_index + 1); - uint8 *restrict serialized_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); - serialized_key_validity_word = (uint64 *) &( - (char *) serialized_key_storage)[num_bytes - sizeof(*serialized_key_validity_word)]; - *serialized_key_validity_word = ~0ULL; + /* + * Loop through the grouping columns again and build the actual key. + */ uint32 offset = 0; for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = &policy->grouping_columns[column_index]; - offset = att_align_nominal(offset, def->typalign); + const GroupingColumn *def = &config.grouping_columns[column_index]; + const CompressedColumnValues *column_values = &config.compressed_columns[def->input_offset]; + + offset = TYPEALIGN(def->alignment_bytes, offset); - const CompressedColumnValues *column_values = - &batch_state->compressed_columns[def->input_offset]; if (column_values->decompression_type > 0) { Assert(offset <= UINT_MAX - column_values->decompression_type); @@ -199,12 +238,12 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re } } - Assert((void *) &serialized_key_storage[att_align_nominal(offset, TYPALIGN_DOUBLE)] == + Assert((void *) &serialized_key_storage[TYPEALIGN(ALIGNOF_DOUBLE, offset)] == (void *) serialized_key_validity_word); if (*serialized_key_validity_word != ~0ULL) { - offset = att_align_nominal(offset, TYPALIGN_DOUBLE) + sizeof(*serialized_key_validity_word); + offset = TYPEALIGN(ALIGNOF_DOUBLE, offset) + sizeof(*serialized_key_validity_word); Assert(offset == num_bytes); } @@ -218,20 +257,32 @@ serialized_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *re // fprintf(stderr, "\n"); *key = (BytesView){ .data = serialized_key_storage, .len = offset }; + + /* + * The multi-column key is always considered non-null, and the null flags + * for the individual columns are stored in a bitmap that is part of the + * key. + */ *valid = true; } static pg_attribute_always_inline BytesView serialized_store_key(GroupingPolicyHash *restrict policy, BytesView key) { - /* Noop, all done in get_key. */ + /* + * We will store this key so we have to consume the temporary storage that + * was used for it. The subsequent keys will need to allocate new memory. + */ + Assert(policy->tmp_key_storage == key.data); + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; return key; } static pg_attribute_always_inline void serialized_destroy_key(BytesView key) { - pfree((void *) key.data); + /* Noop, the memory will be reused by the subsequent key. */ } #define EXPLAIN_NAME "serialized" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 0022fa2593d..3799d4dae9b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -21,7 +21,6 @@ #define KEY_BYTES 2 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CHECK_PREVIOUS_KEY #define CTYPE int16 #define DATUM_TO_CTYPE DatumGetInt16 #define CTYPE_TO_DATUM Int16GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index 57bd2c278ce..e4982c9e11b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -21,7 +21,6 @@ #define KEY_BYTES 4 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CHECK_PREVIOUS_KEY #define CTYPE int32 #define DATUM_TO_CTYPE DatumGetInt32 #define CTYPE_TO_DATUM Int32GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index 89e52168a08..f191cbfe9ff 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -21,7 +21,6 @@ #define KEY_BYTES 8 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CHECK_PREVIOUS_KEY #define CTYPE int64 #define DATUM_TO_CTYPE DatumGetInt64 #define CTYPE_TO_DATUM Int64GetDatum diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 15290bed7b8..bdc0028a589 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -29,9 +29,9 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(GroupingPolicyHash *restrict policy, DecompressBatchState *restrict batch_state, - HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) +single_text_get_key(HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) { + GroupingPolicyHash *policy = config.policy; Assert(policy->num_grouping_columns == 1); if (unlikely(config.single_key.decompression_type == DT_Scalar)) @@ -95,6 +95,5 @@ single_text_destroy_key(BytesView key) #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define STORE_HASH -#define CHECK_PREVIOUS_KEY #define CTYPE BytesView #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 001b1668164..19d0de2506c 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -66,19 +66,19 @@ FUNCTION_NAME(get_size_bytes)(void *table) * Fill the unique key indexes for all rows using a hash table. */ static pg_attribute_always_inline void -FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, HashingConfig config, - int start_row, int end_row) +FUNCTION_NAME(fill_offsets_impl)( + + HashingConfig config, int start_row, int end_row) { + GroupingPolicyHash *policy = config.policy; + uint32 *restrict indexes = policy->key_index_for_row; Assert((size_t) end_row <= policy->num_key_index_for_row); struct FUNCTION_NAME(hash) *restrict table = policy->table; -#ifdef CHECK_PREVIOUS_KEY CTYPE previous_key; uint32 previous_key_index = 0; -#endif for (int row = start_row; row < end_row; row++) { if (!arrow_row_is_valid(config.batch_filter, row)) @@ -90,7 +90,7 @@ FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, bool key_valid = false; CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(policy, batch_state, config, row, &key, &key_valid); + FUNCTION_NAME(get_key)(config, row, &key, &key_valid); if (unlikely(!key_valid)) { @@ -105,24 +105,22 @@ FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, continue; } -#ifdef CHECK_PREVIOUS_KEY if (likely(previous_key_index != 0) && KEY_EQUAL(key, previous_key)) { /* * In real data sets, we often see consecutive rows with the * same value of a grouping column, so checking for this case - * improves performance. For multi-column keys, this is unlikely and - * so this check is disabled. + * improves performance. For multi-column keys, this is unlikely, + * but we currently often have suboptimal plans that use this policy + * as a GroupAggregate, so we still use this as an easy optimization + * for that case. */ indexes[row] = previous_key_index; FUNCTION_NAME(destroy_key)(key); -#ifndef NDEBUG policy->stat_consecutive_keys++; -#endif DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; } -#endif /* * Find the key using the hash table. @@ -146,10 +144,8 @@ FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, } indexes[row] = entry->key_index; -#ifdef CHECK_PREVIOUS_KEY previous_key_index = entry->key_index; previous_key = entry->key; -#endif } } @@ -162,36 +158,35 @@ FUNCTION_NAME(fill_offsets_impl)(GroupingPolicyHash *restrict policy, X(NAME##_all, (COND) && (config.batch_filter == NULL)) \ X(NAME##_filter, (COND) && (config.batch_filter != NULL)) +#define APPLY_FOR_VALIDITY(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && (config.single_key.buffers[0] == NULL)) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + #define APPLY_FOR_TYPE(X, NAME, COND) \ + APPLY_FOR_VALIDITY(X, \ + NAME##_fixed, \ + (COND) && (config.single_key.decompression_type == sizeof(CTYPE))) \ + APPLY_FOR_VALIDITY(X, \ + NAME##_text, \ + (COND) && (config.single_key.decompression_type == DT_ArrowText)) \ + APPLY_FOR_VALIDITY(X, \ + NAME##_dict, \ + (COND) && (config.single_key.decompression_type == DT_ArrowTextDict)) \ APPLY_FOR_BATCH_FILTER(X, \ - NAME##_fixed, \ - (COND) && (config.single_key.decompression_type == sizeof(CTYPE))) \ - APPLY_FOR_BATCH_FILTER(X, \ - NAME##_text, \ - (COND) && (config.single_key.decompression_type == DT_ArrowText)) \ - APPLY_FOR_BATCH_FILTER(X, \ - NAME##_dict, \ - (COND) && (config.single_key.decompression_type == DT_ArrowTextDict)) - -#define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_TYPE(X, NAME, (COND) && (config.single_key.buffers[0] == NULL)) \ - APPLY_FOR_TYPE(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + NAME##_multi, \ + (COND) && (config.single_key.decompression_type == DT_Invalid)) -#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, , true) +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, , true) #define DEFINE(NAME, CONDITION) \ - static pg_noinline void FUNCTION_NAME(NAME)(GroupingPolicyHash *restrict policy, \ - DecompressBatchState *restrict batch_state, \ - HashingConfig config, \ - int start_row, \ - int end_row) \ + static pg_noinline void FUNCTION_NAME(NAME)(HashingConfig config, int start_row, int end_row) \ { \ if (!(CONDITION)) \ { \ pg_unreachable(); \ } \ \ - FUNCTION_NAME(fill_offsets_impl)(policy, batch_state, config, start_row, end_row); \ + FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); \ } APPLY_FOR_SPECIALIZATIONS(DEFINE) @@ -207,7 +202,11 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba int start_row, int end_row) { HashingConfig config = { + .policy = policy, .batch_filter = batch_state->vector_qual_result, + .num_grouping_columns = policy->num_grouping_columns, + .grouping_columns = policy->grouping_columns, + .compressed_columns = batch_state->compressed_columns, }; if (policy->num_grouping_columns == 1) @@ -222,14 +221,14 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba #define DISPATCH(NAME, CONDITION) \ if (CONDITION) \ { \ - FUNCTION_NAME(NAME)(policy, batch_state, config, start_row, end_row); \ + FUNCTION_NAME(NAME)(config, start_row, end_row); \ } \ else APPLY_FOR_SPECIALIZATIONS(DISPATCH) { /* Use a generic implementation if no specializations matched. */ - FUNCTION_NAME(fill_offsets_impl)(policy, batch_state, config, start_row, end_row); + FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); } } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index ba5b9bf974a..0ff68ee60f1 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -9,11 +9,9 @@ #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(GroupingPolicyHash *restrict policy, - DecompressBatchState *restrict batch_state, HashingConfig config, int row, - CTYPE *restrict key, bool *restrict valid) +FUNCTION_NAME(get_key)(HashingConfig config, int row, CTYPE *restrict key, bool *restrict valid) { - Assert(policy->num_grouping_columns == 1); + GroupingPolicyHash *policy = config.policy; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { From 8ec6eb768f591c4fde6312e7dbb211ed03934a59 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:59:37 +0100 Subject: [PATCH 080/242] benchmark more optimizations (2024-10-29 no. 2) From c2d1b7f635264e3fa2231bf7efe646802b463329 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:02:53 +0100 Subject: [PATCH 081/242] benchmark more optimizations (2024-10-29 no. 3) --- tsl/src/nodes/vector_agg/hash_serialized.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 3ac7818623c..1eabe621927 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -96,7 +96,7 @@ serialized_get_key(HashingConfig config, int row, BytesView *restrict key, bool { if (policy->tmp_key_storage != NULL) { - policy->key_body_mctx->methods->free_p(policy->key_body_mctx, policy->tmp_key_storage); + pfree(policy->tmp_key_storage); } policy->tmp_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); policy->num_tmp_key_storage_bytes = num_bytes; From 25dc4cd2b2aa7172014fdc3af8479f28d071663d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:40:53 +0100 Subject: [PATCH 082/242] Refactor vectorized grouping to prepare for hash grouping This commit has various assorted refactorings and cosmetic changes: * Various cosmetic things I don't know where to put. * The definitions of aggregate functions and grouping columns in the vector agg node are now typed arrays and not lists. * The aggegate function implementation always work with at most one filter bitmap. This reduces the amount of code and will help to support the aggregate FILTER clauses. * Parts of the aggregate function implementations are restructured and renamed in a way that will make it easier to support hash grouping. * EXPLAIN output is added for vector agg node that mentions the grouping policy that is being used. --- .../compression/algorithms/deltadelta_impl.c | 12 +- tsl/src/compression/arrow_c_data_interface.h | 27 +- tsl/src/nodes/decompress_chunk/planner.c | 19 +- tsl/src/nodes/vector_agg/exec.c | 73 ++++- tsl/src/nodes/vector_agg/exec.h | 12 +- ...agg_const_helper.c => agg_scalar_helper.c} | 16 +- .../function/agg_vector_validity_helper.c | 40 +-- .../function/float48_accum_single.c | 79 ++++-- tsl/src/nodes/vector_agg/function/functions.c | 30 +- tsl/src/nodes/vector_agg/function/functions.h | 16 +- .../vector_agg/function/int128_accum_single.c | 34 ++- .../function/int24_avg_accum_single.c | 20 +- .../function/int24_avg_accum_templates.c | 11 +- .../vector_agg/function/int24_sum_single.c | 20 +- .../vector_agg/function/int24_sum_templates.c | 11 +- .../function/minmax_arithmetic_single.c | 37 ++- .../vector_agg/function/minmax_templates.c | 11 +- .../vector_agg/function/sum_float_single.c | 24 +- .../vector_agg/function/sum_float_templates.c | 11 +- tsl/src/nodes/vector_agg/grouping_policy.h | 19 +- .../nodes/vector_agg/grouping_policy_batch.c | 169 ++++++++---- tsl/src/nodes/vector_agg/plan.c | 45 +-- tsl/test/expected/vectorized_aggregation.out | 260 ++++++++++++++++-- 23 files changed, 719 insertions(+), 277 deletions(-) rename tsl/src/nodes/vector_agg/function/{agg_const_helper.c => agg_scalar_helper.c} (60%) diff --git a/tsl/src/compression/algorithms/deltadelta_impl.c b/tsl/src/compression/algorithms/deltadelta_impl.c index 6e036a5722b..3100c8a8822 100644 --- a/tsl/src/compression/algorithms/deltadelta_impl.c +++ b/tsl/src/compression/algorithms/deltadelta_impl.c @@ -44,12 +44,12 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Pad the number of elements to multiple of 64 bytes if needed, so that we * can work in 64-byte blocks. */ +#define INNER_LOOP_SIZE_LOG2 3 +#define INNER_LOOP_SIZE (1 << INNER_LOOP_SIZE_LOG2) const uint32 n_total = has_nulls ? nulls.num_elements : num_deltas; - const uint32 n_total_padded = - ((n_total * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_total_padded = pad_to_multiple(INNER_LOOP_SIZE, n_total); const uint32 n_notnull = num_deltas; - const uint32 n_notnull_padded = - ((n_notnull * sizeof(ELEMENT_TYPE) + 63) / 64) * 64 / sizeof(ELEMENT_TYPE); + const uint32 n_notnull_padded = pad_to_multiple(INNER_LOOP_SIZE, n_notnull); Assert(n_total_padded >= n_total); Assert(n_notnull_padded >= n_notnull); Assert(n_total >= n_notnull); @@ -57,7 +57,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory /* * We need additional padding at the end of buffer, because the code that - * converts the elements to postres Datum always reads in 8 bytes. + * converts the elements to postgres Datum always reads in 8 bytes. */ const int buffer_bytes = n_total_padded * sizeof(ELEMENT_TYPE) + 8; ELEMENT_TYPE *restrict decompressed_values = MemoryContextAlloc(dest_mctx, buffer_bytes); @@ -75,7 +75,6 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory * Also tried zig-zag decoding in a separate loop, seems to be slightly * slower, around the noise threshold. */ -#define INNER_LOOP_SIZE 8 Assert(n_notnull_padded % INNER_LOOP_SIZE == 0); for (uint32 outer = 0; outer < n_notnull_padded; outer += INNER_LOOP_SIZE) { @@ -86,6 +85,7 @@ FUNCTION_NAME(delta_delta_decompress_all, ELEMENT_TYPE)(Datum compressed, Memory decompressed_values[outer + inner] = current_element; } } +#undef INNER_LOOP_SIZE_LOG2 #undef INNER_LOOP_SIZE uint64 *restrict validity_bitmap = NULL; diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index a0362f85328..467a6237f3c 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -182,6 +182,31 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) Assert(arrow_row_is_valid(bitmap, row_number) == value); } +/* + * AND two optional arrow validity bitmaps into the given storage. + */ +static inline uint64 * +arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, + const uint64 *filter2) +{ + if (filter1 == NULL) + { + return filter2; + } + + if (filter2 == NULL) + { + return filter1; + } + + for (size_t i = 0; i < num_words; i++) + { + storage[i] = filter1[i] & filter2[i]; + } + + return storage; +} + /* Increase the `source_value` to be an even multiple of `pad_to`. */ static inline uint64 pad_to_multiple(uint64 pad_to, uint64 source_value) @@ -190,7 +215,7 @@ pad_to_multiple(uint64 pad_to, uint64 source_value) } static inline size_t -arrow_num_valid(uint64 *bitmap, size_t total_rows) +arrow_num_valid(const uint64 *bitmap, size_t total_rows) { if (bitmap == NULL) { diff --git a/tsl/src/nodes/decompress_chunk/planner.c b/tsl/src/nodes/decompress_chunk/planner.c index c1f7648c9e3..d3b68cd5283 100644 --- a/tsl/src/nodes/decompress_chunk/planner.c +++ b/tsl/src/nodes/decompress_chunk/planner.c @@ -887,8 +887,12 @@ static void find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *path, List *qual_list, List **vectorized, List **nonvectorized) { - ListCell *lc; + VectorQualInfo vqi = { + .vector_attrs = build_vector_attrs_array(context->uncompressed_attno_info, path->info), + .rti = path->info->chunk_rel->relid, + }; + ListCell *lc; foreach (lc, qual_list) { Node *source_qual = lfirst(lc); @@ -901,14 +905,7 @@ find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *pat */ Node *transformed_comparison = (Node *) ts_transform_cross_datatype_comparison((Expr *) source_qual); - VectorQualInfoDecompressChunk vqidc = { - .vqinfo = { - .vector_attrs = build_vector_attrs_array(context->uncompressed_attno_info, path->info), - .rti = path->info->chunk_rel->relid, - }, - .colinfo = context->uncompressed_attno_info, - }; - Node *vectorized_qual = vector_qual_make(transformed_comparison, &vqidc.vqinfo); + Node *vectorized_qual = vector_qual_make(transformed_comparison, &vqi); if (vectorized_qual) { *vectorized = lappend(*vectorized, vectorized_qual); @@ -917,9 +914,9 @@ find_vectorized_quals(DecompressionMapContext *context, DecompressChunkPath *pat { *nonvectorized = lappend(*nonvectorized, source_qual); } - - pfree(vqidc.vqinfo.vector_attrs); } + + pfree(vqi.vector_attrs); } /* diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 7e8e59de1cd..0ca647b6cba 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -47,7 +47,8 @@ get_input_offset(DecompressChunkState *decompress_state, Var *var) Assert(value_column_description->type == COMPRESSED_COLUMN || value_column_description->type == SEGMENTBY_COLUMN); - return value_column_description - dcontext->compressed_chunk_columns; + const int index = value_column_description - dcontext->compressed_chunk_columns; + return index; } static void @@ -76,21 +77,60 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) */ List *aggregated_tlist = castNode(CustomScan, vector_agg_state->custom.ss.ps.plan)->custom_scan_tlist; - const int naggs = list_length(aggregated_tlist); - for (int i = 0; i < naggs; i++) + const int tlist_length = list_length(aggregated_tlist); + + /* + * First, count how many grouping columns and aggregate functions we have. + */ + int agg_functions_counter = 0; + int grouping_column_counter = 0; + for (int i = 0; i < tlist_length; i++) + { + TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + if (IsA(tlentry->expr, Aggref)) + { + agg_functions_counter++; + } + else + { + /* This is a grouping column. */ + Assert(IsA(tlentry->expr, Var)); + grouping_column_counter++; + } + } + Assert(agg_functions_counter + grouping_column_counter == tlist_length); + + /* + * Allocate the storage for definitions of aggregate function and grouping + * columns. + */ + vector_agg_state->num_agg_defs = agg_functions_counter; + vector_agg_state->agg_defs = + palloc0(sizeof(*vector_agg_state->agg_defs) * vector_agg_state->num_agg_defs); + + vector_agg_state->num_grouping_columns = grouping_column_counter; + vector_agg_state->grouping_columns = palloc0(sizeof(*vector_agg_state->grouping_columns) * + vector_agg_state->num_grouping_columns); + + /* + * Loop through the aggregated targetlist again and fill the definitions. + */ + agg_functions_counter = 0; + grouping_column_counter = 0; + for (int i = 0; i < tlist_length; i++) { TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { /* This is an aggregate function. */ - VectorAggDef *def = palloc0(sizeof(VectorAggDef)); - vector_agg_state->agg_defs = lappend(vector_agg_state->agg_defs, def); + VectorAggDef *def = &vector_agg_state->agg_defs[agg_functions_counter++]; def->output_offset = i; Aggref *aggref = castNode(Aggref, tlentry->expr); + VectorAggFunctions *func = get_vector_aggregate(aggref->aggfnoid); Assert(func != NULL); - def->func = func; + def->func = *func; if (list_length(aggref->args) > 0) { @@ -112,9 +152,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) /* This is a grouping column. */ Assert(IsA(tlentry->expr, Var)); - GroupingColumn *col = palloc0(sizeof(GroupingColumn)); - vector_agg_state->output_grouping_columns = - lappend(vector_agg_state->output_grouping_columns, col); + GroupingColumn *col = &vector_agg_state->grouping_columns[grouping_column_counter++]; col->output_offset = i; Var *var = castNode(Var, tlentry->expr); @@ -122,11 +160,14 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } } - List *grouping_column_offsets = linitial(cscan->custom_private); + /* + * Currently the only grouping policy we use is per-batch grouping. + */ vector_agg_state->grouping = - create_grouping_policy_batch(vector_agg_state->agg_defs, - vector_agg_state->output_grouping_columns, - /* partial_per_batch = */ grouping_column_offsets != NIL); + create_grouping_policy_batch(vector_agg_state->num_agg_defs, + vector_agg_state->agg_defs, + vector_agg_state->num_grouping_columns, + vector_agg_state->grouping_columns); } static void @@ -272,7 +313,11 @@ vector_agg_exec(CustomScanState *node) static void vector_agg_explain(CustomScanState *node, List *ancestors, ExplainState *es) { - /* No additional output is needed. */ + VectorAggState *state = (VectorAggState *) node; + if (es->verbose || es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyText("Grouping Policy", state->grouping->gp_explain(state->grouping), es); + } } static struct CustomExecMethods exec_methods = { diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index d886b927d31..26f832b3548 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -13,14 +13,14 @@ #include "function/functions.h" #include "grouping_policy.h" -typedef struct +typedef struct VectorAggDef { - VectorAggFunctions *func; + VectorAggFunctions func; int input_offset; int output_offset; } VectorAggDef; -typedef struct +typedef struct GroupingColumn { int input_offset; int output_offset; @@ -30,9 +30,11 @@ typedef struct { CustomScanState custom; - List *agg_defs; + int num_agg_defs; + VectorAggDef *agg_defs; - List *output_grouping_columns; + int num_grouping_columns; + GroupingColumn *grouping_columns; /* * We can't call the underlying scan after it has ended, or it will be diff --git a/tsl/src/nodes/vector_agg/function/agg_const_helper.c b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c similarity index 60% rename from tsl/src/nodes/vector_agg/function/agg_const_helper.c rename to tsl/src/nodes/vector_agg/function/agg_scalar_helper.c index a1abe481aec..0d81abfcf65 100644 --- a/tsl/src/nodes/vector_agg/function/agg_const_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_scalar_helper.c @@ -11,14 +11,20 @@ * implementation otherwise. */ static void -FUNCTION_NAME(const)(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +FUNCTION_NAME(scalar)(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { - const uint64 valid = constisnull ? 0 : 1; - const CTYPE value = valid ? DATUM_TO_CTYPE(constvalue) : 0; + if (constisnull) + { + return; + } + + const CTYPE value = DATUM_TO_CTYPE(constvalue); + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); for (int i = 0; i < n; i++) { - FUNCTION_NAME(vector_impl)(agg_state, 1, &value, &valid, NULL, agg_extra_mctx); + FUNCTION_NAME(one)(agg_state, value); } + MemoryContextSwitchTo(old); } diff --git a/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c b/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c index ac3a95055a0..9dc1cfe853c 100644 --- a/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_vector_validity_helper.c @@ -11,62 +11,40 @@ */ static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl_arrow)(void *agg_state, const ArrowArray *vector, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl_arrow)(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { const int n = vector->length; const CTYPE *values = vector->buffers[1]; - FUNCTION_NAME(vector_impl)(agg_state, n, values, valid1, valid2, agg_extra_mctx); + FUNCTION_NAME(vector_impl)(agg_state, n, values, filter, agg_extra_mctx); } static pg_noinline void FUNCTION_NAME(vector_all_valid)(void *agg_state, const ArrowArray *vector, MemoryContext agg_extra_mctx) { - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, NULL, NULL, agg_extra_mctx); + FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, NULL, agg_extra_mctx); } static pg_noinline void -FUNCTION_NAME(vector_one_validity)(void *agg_state, const ArrowArray *vector, const uint64 *valid, +FUNCTION_NAME(vector_one_validity)(void *agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx) { - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, valid, NULL, agg_extra_mctx); -} - -static pg_noinline void -FUNCTION_NAME(vector_two_validity)(void *agg_state, const ArrowArray *vector, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) -{ - FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, valid1, valid2, agg_extra_mctx); + FUNCTION_NAME(vector_impl_arrow)(agg_state, vector, filter, agg_extra_mctx); } static void FUNCTION_NAME(vector)(void *agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx) { - const uint64 *row_validity = vector->buffers[0]; - - if (row_validity == NULL && filter == NULL) + if (filter == NULL) { /* All rows are valid and we don't have to check any validity bitmaps. */ FUNCTION_NAME(vector_all_valid)(agg_state, vector, agg_extra_mctx); } - else if (row_validity != NULL && filter == NULL) - { - /* Have to check only one bitmap -- row validity bitmap. */ - FUNCTION_NAME(vector_one_validity)(agg_state, vector, row_validity, agg_extra_mctx); - } - else if (filter != NULL && row_validity == NULL) - { - /* Have to check only one bitmap -- results of the vectorized filter. */ - FUNCTION_NAME(vector_one_validity)(agg_state, vector, filter, agg_extra_mctx); - } else { - /* - * Have to check both the row validity bitmap and the results of the - * vectorized filter. - */ - FUNCTION_NAME(vector_two_validity)(agg_state, vector, row_validity, filter, agg_extra_mctx); + /* Have to check only one combined validity bitmap. */ + FUNCTION_NAME(vector_one_validity)(agg_state, vector, filter, agg_extra_mctx); } } diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index fb63bc61fb3..fed87b958d4 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -55,10 +55,13 @@ typedef struct } FUNCTION_NAME(state); static void -FUNCTION_NAME(init)(void *agg_state) +FUNCTION_NAME(init)(void *restrict agg_states, int n) { - FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - *state = (FUNCTION_NAME(state)){ 0 }; + FUNCTION_NAME(state) *states = (FUNCTION_NAME(state) *) agg_states; + for (int i = 0; i < n; i++) + { + states[i] = (FUNCTION_NAME(state)){ 0 }; + } } static void @@ -96,8 +99,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) * Youngs-Cramer update for rows after the first. */ static pg_attribute_always_inline void -FUNCTION_NAME(update)(const uint64 *valid1, const uint64 *valid2, const CTYPE *values, int row, - double *N, double *Sx +FUNCTION_NAME(update)(const uint64 *filter, const CTYPE *values, int row, double *N, double *Sx #ifdef NEED_SXX , double *Sxx @@ -105,7 +107,7 @@ FUNCTION_NAME(update)(const uint64 *valid1, const uint64 *valid2, const CTYPE *v ) { const CTYPE newval = values[row]; - if (!arrow_row_both_valid(valid1, valid2, row)) + if (!arrow_row_is_valid(filter, row)) { return; } @@ -182,20 +184,19 @@ FUNCTION_NAME(combine)(double *inout_N, double *inout_Sx, } #ifdef NEED_SXX -#define UPDATE(valid1, valid2, values, row, N, Sx, Sxx) \ - FUNCTION_NAME(update)(valid1, valid2, values, row, N, Sx, Sxx) +#define UPDATE(filter, values, row, N, Sx, Sxx) \ + FUNCTION_NAME(update)(filter, values, row, N, Sx, Sxx) #define COMBINE(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) \ FUNCTION_NAME(combine)(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) #else -#define UPDATE(valid1, valid2, values, row, N, Sx, Sxx) \ - FUNCTION_NAME(update)(valid1, valid2, values, row, N, Sx) +#define UPDATE(filter, values, row, N, Sx, Sxx) FUNCTION_NAME(update)(filter, values, row, N, Sx) #define COMBINE(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2) \ FUNCTION_NAME(combine)(inout_N, inout_Sx, N2, Sx2) #endif static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { /* * Vector registers can be up to 512 bits wide. @@ -225,7 +226,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (; row < n; row++) { const CTYPE newval = values[row]; - if (arrow_row_both_valid(valid1, valid2, row)) + if (arrow_row_is_valid(filter, row)) { Narray[inner] = 1; Sxarray[inner] = newval; @@ -243,7 +244,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (size_t inner = row % UNROLL_SIZE; inner > 0 && inner < UNROLL_SIZE && row < n; inner++, row++) { - UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); + UPDATE(filter, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } #endif @@ -255,13 +256,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const { for (size_t inner = 0; inner < UNROLL_SIZE; inner++) { - UPDATE(valid1, - valid2, - values, - row + inner, - &Narray[inner], - &Sxarray[inner], - &Sxxarray[inner]); + UPDATE(filter, values, row + inner, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } } @@ -271,7 +266,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const for (; row < n; row++) { const size_t inner = row % UNROLL_SIZE; - UPDATE(valid1, valid2, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); + UPDATE(filter, values, row, &Narray[inner], &Sxarray[inner], &Sxxarray[inner]); } /* @@ -290,14 +285,42 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const COMBINE(&state->N, &state->Sx, &state->Sxx, Narray[0], Sxarray[0], Sxxarray[0]); } -#include "agg_const_helper.c" +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + /* + * This code follows the Postgres float8_accum() transition function, see + * the comments there. + */ + const double newN = state->N + 1.0; + const double newSx = state->Sx + value; +#ifdef NEED_SXX + if (state->N > 0.0) + { + const double tmp = value * newN - newSx; + state->Sxx += tmp * tmp / (state->N * newN); + } + else + { + state->Sxx = 0 * value; + } +#endif + + state->N = newN; + state->Sx = newSx; +} + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" -VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), - .agg_init = FUNCTION_NAME(init), - .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), - .agg_vector = FUNCTION_NAME(vector) }; +VectorAggFunctions FUNCTION_NAME(argdef) = { + .state_bytes = sizeof(FUNCTION_NAME(state)), + .agg_init = FUNCTION_NAME(init), + .agg_emit = FUNCTION_NAME(emit), + .agg_scalar = FUNCTION_NAME(scalar), + .agg_vector = FUNCTION_NAME(vector), +}; #undef UPDATE #undef COMBINE diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 6cbb7dccf0d..1cd08e7cd25 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -27,10 +27,13 @@ typedef struct } CountState; static void -count_init(void *agg_state) +count_init(void *restrict agg_states, int n) { - CountState *state = (CountState *) agg_state; - state->count = 0; + CountState *states = (CountState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].count = 0; + } } static void @@ -42,8 +45,8 @@ count_emit(void *agg_state, Datum *out_result, bool *out_isnull) } static void -count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; state->count += n; @@ -52,7 +55,7 @@ count_star_const(void *agg_state, Datum constvalue, bool constisnull, int n, VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, - .agg_const = count_star_const, + .agg_scalar = count_star_scalar, .agg_emit = count_emit, }; @@ -60,8 +63,8 @@ VectorAggFunctions count_star_agg = { * Aggregate function count(x). */ static void -count_any_const(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx) +count_any_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx) { if (constisnull) { @@ -78,23 +81,20 @@ count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter { CountState *state = (CountState *) agg_state; const int n = vector->length; - const uint64 *restrict validity = (uint64 *) vector->buffers[0]; /* First, process the full words. */ for (int i = 0; i < n / 64; i++) { - const uint64 validity_word = validity ? validity[i] : ~0ULL; const uint64 filter_word = filter ? filter[i] : ~0ULL; - const uint64 resulting_word = validity_word & filter_word; #ifdef HAVE__BUILTIN_POPCOUNT - state->count += __builtin_popcountll(resulting_word); + state->count += __builtin_popcountll(filter_word); #else /* * Unfortunately, we have to have this fallback for Windows. */ for (uint16 i = 0; i < 64; i++) { - const bool this_bit = (resulting_word >> i) & 1; + const bool this_bit = (filter_word >> i) & 1; state->count += this_bit; } #endif @@ -106,7 +106,7 @@ count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter */ for (int i = 64 * (n / 64); i < n; i++) { - state->count += arrow_row_is_valid(validity, i) * arrow_row_is_valid(filter, i); + state->count += arrow_row_is_valid(filter, i); } } @@ -114,7 +114,7 @@ VectorAggFunctions count_any_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, .agg_emit = count_emit, - .agg_const = count_any_const, + .agg_scalar = count_any_scalar, .agg_vector = count_any_vector, }; diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 773bffe584c..2d150659276 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -16,19 +16,19 @@ typedef struct /* Size of the aggregate function state. */ size_t state_bytes; - /* Initialize the aggregate function state pointed to by agg_value and agg_isnull. */ - void (*agg_init)(void *agg_state); + /* Initialize the aggregate function states. */ + void (*agg_init)(void *restrict agg_states, int n); /* Aggregate a given arrow array. */ - void (*agg_vector)(void *agg_state, const ArrowArray *vector, const uint64 *filter, + void (*agg_vector)(void *restrict agg_state, const ArrowArray *vector, const uint64 *filter, MemoryContext agg_extra_mctx); - /* Aggregate a constant (like segmentby or column with default value). */ - void (*agg_const)(void *agg_state, Datum constvalue, bool constisnull, int n, - MemoryContext agg_extra_mctx); + /* Aggregate a scalar value, like segmentby or column with default value. */ + void (*agg_scalar)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, + MemoryContext agg_extra_mctx); - /* Emit a partial result. */ - void (*agg_emit)(void *agg_state, Datum *out_result, bool *out_isnull); + /* Emit a partial aggregation result. */ + void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; VectorAggFunctions *get_vector_aggregate(Oid aggfnoid); diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index e50a743c901..d94ead56cd3 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -25,14 +25,17 @@ typedef struct } FUNCTION_NAME(state); static void -FUNCTION_NAME(init)(void *agg_state) +FUNCTION_NAME(init)(void *restrict agg_states, int n) { - FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - state->N = 0; - state->sumX = 0; + FUNCTION_NAME(state) *states = (FUNCTION_NAME(state) *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].N = 0; + states[i].sumX = 0; #ifdef NEED_SUMX2 - state->sumX2 = 0; + states[i].sumX2 = 0; #endif + } } static void @@ -69,8 +72,8 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) } static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { int64 N = 0; int128 sumX = 0; @@ -79,7 +82,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #endif for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); const CTYPE value = values[row]; N += row_ok; sumX += value * row_ok; @@ -96,14 +99,25 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #endif } -#include "agg_const_helper.c" +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->N++; + state->sumX += value; +#ifdef NEED_SUMX2 + state->sumX2 += ((int128) value) * ((int128) value); +#endif +} + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FUNCTION_NAME(state)), .agg_init = FUNCTION_NAME(init), .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), }; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 551730c1912..9fbf950330a 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -11,14 +11,14 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { int64 batch_count = 0; int64 batch_sum = 0; for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); batch_count += row_ok; batch_sum += values[row] * row_ok; } @@ -28,14 +28,24 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->sum += batch_sum; } -#include "agg_const_helper.c" +typedef Int24AvgAccumState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->count++; + state->sum += value; +} + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24AvgAccumState), .agg_init = int24_avg_accum_init, .agg_emit = int24_avg_accum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), }; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c index 0841eb79cc1..518a7491aab 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c @@ -27,11 +27,14 @@ typedef struct } Int24AvgAccumState; static void -int24_avg_accum_init(void *agg_state) +int24_avg_accum_init(void *restrict agg_states, int n) { - Int24AvgAccumState *state = (Int24AvgAccumState *) agg_state; - state->count = 0; - state->sum = 0; + Int24AvgAccumState *states = (Int24AvgAccumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].count = 0; + states[i].sum = 0; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index e84c873aed2..81b6e11c339 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -11,8 +11,8 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { Int24SumState *state = (Int24SumState *) agg_state; @@ -37,7 +37,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui bool have_result = false; for (int row = 0; row < n; row++) { - const bool row_ok = arrow_row_both_valid(valid1, valid2, row); + const bool row_ok = arrow_row_is_valid(filter, row); batch_sum += values[row] * row_ok; have_result |= row_ok; } @@ -51,14 +51,24 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->isnull &= !have_result; } -#include "agg_const_helper.c" +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + Int24SumState *state = (Int24SumState *) agg_state; + state->result += value; + state->isnull = false; +} + +typedef Int24SumState FUNCTION_NAME(state); + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(Int24SumState), .agg_init = int_sum_init, .agg_emit = int_sum_emit, - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c index 5e87f3c9a32..8b250cc91cc 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c @@ -28,11 +28,14 @@ typedef struct } Int24SumState; static void -int_sum_init(void *agg_state) +int_sum_init(void *restrict agg_states, int n) { - Int24SumState *state = (Int24SumState *) agg_state; - state->result = 0; - state->isnull = true; + Int24SumState *states = (Int24SumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].result = 0; + states[i].isnull = true; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index f21521f12bd..22d8cf588d4 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -10,8 +10,8 @@ case PG_AGG_OID_HELPER(AGG_NAME, PG_TYPE): return &FUNCTION_NAME(argdef); #else static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { MinMaxState *state = (MinMaxState *) agg_state; @@ -20,7 +20,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui for (int row = 0; row < n; row++) { const CTYPE new_value = values[row]; - const bool new_value_ok = arrow_row_both_valid(valid1, valid2, row); + const bool new_value_ok = arrow_row_is_valid(filter, row); /* * Note that we have to properly handle NaNs and Infinities for floats. @@ -41,14 +41,33 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui MemoryContextSwitchTo(old); } -#include "agg_const_helper.c" +typedef MinMaxState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + if (!state->isvalid || PREDICATE(DATUM_TO_CTYPE(state->value), value) || isnan((double) value)) + { + /* + * Note that float8 Datum is by-reference on 32-bit systems, and this + * function is called in the extra aggregate data memory context. + */ + state->value = CTYPE_TO_DATUM(value); + state->isvalid = true; + } +} + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" -VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(MinMaxState), - .agg_init = minmax_init, - .agg_emit = minmax_emit, - .agg_const = FUNCTION_NAME(const), - .agg_vector = FUNCTION_NAME(vector) }; +VectorAggFunctions FUNCTION_NAME(argdef) = { + .state_bytes = sizeof(MinMaxState), + .agg_init = minmax_init, + .agg_emit = minmax_emit, + .agg_scalar = FUNCTION_NAME(scalar), + .agg_vector = FUNCTION_NAME(vector), +}; #endif #undef PG_TYPE diff --git a/tsl/src/nodes/vector_agg/function/minmax_templates.c b/tsl/src/nodes/vector_agg/function/minmax_templates.c index be79cc3c1db..0775f6bd1f2 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_templates.c +++ b/tsl/src/nodes/vector_agg/function/minmax_templates.c @@ -26,11 +26,14 @@ typedef struct } MinMaxState; static void -minmax_init(void *agg_state) +minmax_init(void *restrict agg_states, int n) { - MinMaxState *state = (MinMaxState *) agg_state; - state->isvalid = false; - state->value = 0; + MinMaxState *states = (MinMaxState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].isvalid = false; + states[i].value = 0; + } } static void diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 59a5cfe1fc7..3b0447e867d 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -21,8 +21,8 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) } static pg_attribute_always_inline void -FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *valid1, - const uint64 *valid2, MemoryContext agg_extra_mctx) +FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const uint64 *filter, + MemoryContext agg_extra_mctx) { /* * Vector registers can be up to 512 bits wide. @@ -46,15 +46,15 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui * infinities and NaNs. */ #define INNER_LOOP \ - const bool valid = arrow_row_both_valid(valid1, valid2, row); \ + const bool row_valid = arrow_row_is_valid(filter, row); \ union \ { \ CTYPE f; \ MASKTYPE m; \ } u = { .f = values[row] }; \ - u.m &= valid ? ~(MASKTYPE) 0 : (MASKTYPE) 0; \ + u.m &= row_valid ? ~(MASKTYPE) 0 : (MASKTYPE) 0; \ *dest += u.f; \ - *have_result |= valid; + *have_result |= row_valid; INNER_LOOP } @@ -80,14 +80,24 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui state->result += sum_accu[0]; } -#include "agg_const_helper.c" +typedef FloatSumState FUNCTION_NAME(state); + +static pg_attribute_always_inline void +FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) +{ + FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; + state->isnull = false; + state->result += value; +} + +#include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" VectorAggFunctions FUNCTION_NAME(argdef) = { .state_bytes = sizeof(FloatSumState), .agg_init = float_sum_init, .agg_emit = FUNCTION_NAME(emit), - .agg_const = FUNCTION_NAME(const), + .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), }; diff --git a/tsl/src/nodes/vector_agg/function/sum_float_templates.c b/tsl/src/nodes/vector_agg/function/sum_float_templates.c index b24e3e3d812..f2b22523b34 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_templates.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_templates.c @@ -23,11 +23,14 @@ typedef struct } FloatSumState; static void -float_sum_init(void *agg_state) +float_sum_init(void *restrict agg_states, int n) { - FloatSumState *state = (FloatSumState *) agg_state; - state->result = 0; - state->isnull = true; + FloatSumState *states = (FloatSumState *) agg_states; + for (int i = 0; i < n; i++) + { + states[i].result = 0; + states[i].isnull = true; + } } #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 108584f19ef..98bcbbed315 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -9,6 +9,12 @@ typedef struct DecompressBatchState DecompressBatchState; typedef struct GroupingPolicy GroupingPolicy; +typedef struct TupleTableSlot TupleTableSlot; + +typedef struct VectorAggDef VectorAggDef; + +typedef struct GroupingColumn GroupingColumn; + /* * This is a common interface for grouping policies which define how the rows * are grouped for aggregation -- e.g. there can be an implementation for no @@ -34,8 +40,17 @@ typedef struct GroupingPolicy */ bool (*gp_do_emit)(GroupingPolicy *gp, TupleTableSlot *aggregated_slot); + /* + * Destroy the grouping policy. + */ void (*gp_destroy)(GroupingPolicy *gp); + + /* + * Description of this grouping policy for the EXPLAIN output. + */ + char *(*gp_explain)(GroupingPolicy *gp); } GroupingPolicy; -extern GroupingPolicy *create_grouping_policy_batch(List *agg_defs, List *grouping_columns, - bool partial_per_batch); +extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, + int num_grouping_columns, + GroupingColumn *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index ee42a5b6e1e..805aeeda487 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -23,18 +23,32 @@ typedef struct { GroupingPolicy funcs; - List *agg_defs; - List *agg_states; - List *output_grouping_columns; + + int num_agg_defs; + VectorAggDef *agg_defs; + + /* + * Temporary storage for combined bitmap of batch filter and aggregate + * argument validity. + */ + uint64 *tmp_filter; + uint64 num_tmp_filter_words; + + void **agg_states; + + int num_grouping_columns; + GroupingColumn *grouping_columns; + Datum *output_grouping_values; bool *output_grouping_isnull; - bool partial_per_batch; bool have_results; /* * A memory context for aggregate functions to allocate additional data, - * i.e. if they store strings or float8 datum on 32-bit systems. Valid until - * the grouping policy is reset. + * i.e. if they store strings or float8 datum on 32-bit systems, or they + * have variable-length state like the exact distinct function or the + * statistical sketches. + * Valid until the grouping policy is reset. */ MemoryContext agg_extra_mctx; } GroupingPolicyBatch; @@ -42,27 +56,33 @@ typedef struct static const GroupingPolicy grouping_policy_batch_functions; GroupingPolicy * -create_grouping_policy_batch(List *agg_defs, List *output_grouping_columns, bool partial_per_batch) +create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, + GroupingColumn *output_grouping_columns) { GroupingPolicyBatch *policy = palloc0(sizeof(GroupingPolicyBatch)); - policy->partial_per_batch = partial_per_batch; policy->funcs = grouping_policy_batch_functions; - policy->output_grouping_columns = output_grouping_columns; + + policy->num_grouping_columns = num_grouping_columns; + policy->grouping_columns = output_grouping_columns; + + policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; + policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - ListCell *lc; - foreach (lc, agg_defs) + + policy->agg_states = palloc(sizeof(*policy->agg_states) * policy->num_agg_defs); + for (int i = 0; i < policy->num_agg_defs; i++) { - VectorAggDef *def = lfirst(lc); - policy->agg_states = lappend(policy->agg_states, palloc0(def->func->state_bytes)); + VectorAggDef *agg_def = &policy->agg_defs[i]; + policy->agg_states[i] = palloc0(agg_def->func.state_bytes); } + policy->output_grouping_values = - (Datum *) palloc0(MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum)) + - MAXALIGN(list_length(output_grouping_columns) * sizeof(bool))); - policy->output_grouping_isnull = - (bool *) ((char *) policy->output_grouping_values + - MAXALIGN(list_length(output_grouping_columns) * sizeof(Datum))); + (Datum *) palloc0(MAXALIGN(num_grouping_columns * sizeof(Datum)) + + MAXALIGN(num_grouping_columns * sizeof(bool))); + policy->output_grouping_isnull = (bool *) ((char *) policy->output_grouping_values + + MAXALIGN(num_grouping_columns * sizeof(Datum))); return &policy->funcs; } @@ -74,15 +94,15 @@ gp_batch_reset(GroupingPolicy *obj) MemoryContextReset(policy->agg_extra_mctx); - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); - agg_def->func->agg_init(agg_state); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; + agg_def->func.agg_init(agg_state, 1); } - const int ngrp = list_length(policy->output_grouping_columns); + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { policy->output_grouping_values[i] = 0; @@ -93,10 +113,11 @@ gp_batch_reset(GroupingPolicy *obj) } static void -compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_def, void *agg_state, - MemoryContext agg_extra_mctx) +compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batch_state, + VectorAggDef *agg_def, void *agg_state, MemoryContext agg_extra_mctx) { ArrowArray *arg_arrow = NULL; + const uint64 *arg_validity_bitmap = NULL; Datum arg_datum = 0; bool arg_isnull = true; @@ -113,6 +134,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de if (values->arrow != NULL) { arg_arrow = values->arrow; + arg_validity_bitmap = values->buffers[0]; } else { @@ -122,16 +144,22 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de } } + /* + * Compute the unified validity bitmap. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + const uint64 *filter = arrow_combine_validity(num_words, + policy->tmp_filter, + batch_state->vector_qual_result, + arg_validity_bitmap); + /* * Now call the function. */ if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func->agg_vector(agg_state, - arg_arrow, - batch_state->vector_qual_result, - agg_extra_mctx); + agg_def->func.agg_vector(agg_state, arg_arrow, filter, agg_extra_mctx); } else { @@ -139,16 +167,18 @@ compute_single_aggregate(DecompressBatchState *batch_state, VectorAggDef *agg_de * Scalar argument, or count(*). Have to also count the valid rows in * the batch. */ - const int n = - arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows); + const int n = arrow_num_valid(filter, batch_state->total_batch_rows); /* * The batches that are fully filtered out by vectorized quals should * have been skipped by the caller. */ - Assert(n > 0); + // Assert(n > 0); - agg_def->func->agg_const(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + if (n > 0) + { + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + } } } @@ -156,18 +186,42 @@ static void gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) { GroupingPolicyBatch *policy = (GroupingPolicyBatch *) gp; - const int naggs = list_length(policy->agg_defs); + + /* + * Allocate the temporary filter array for computing the combined results of + * batch filter and column validity. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + if (num_words > policy->num_tmp_filter_words) + { + const size_t new_words = num_words * 2 + 1; + if (policy->tmp_filter != NULL) + { + pfree(policy->tmp_filter); + } + + policy->tmp_filter = palloc(sizeof(*policy->tmp_filter) * new_words); + policy->num_tmp_filter_words = new_words; + } + + /* + * Compute the aggregates. + */ + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); - compute_single_aggregate(batch_state, agg_def, agg_state, policy->agg_extra_mctx); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; + compute_single_aggregate(policy, batch_state, agg_def, agg_state, policy->agg_extra_mctx); } - const int ngrp = list_length(policy->output_grouping_columns); + /* + * Save the values of the grouping columns. + */ + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { - GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + GroupingColumn *col = &policy->grouping_columns[i]; Assert(col->input_offset >= 0); Assert(col->output_offset >= 0); @@ -180,7 +234,6 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * means we're grouping by segmentby, and these values will be valid * until the next call to the vector agg node. */ - Assert(policy->partial_per_batch); policy->output_grouping_values[i] = *values->output_value; policy->output_grouping_isnull[i] = *values->output_isnull; } @@ -192,7 +245,12 @@ static bool gp_batch_should_emit(GroupingPolicy *gp) { GroupingPolicyBatch *policy = (GroupingPolicyBatch *) gp; - return policy->partial_per_batch && policy->have_results; + + /* + * If we're grouping by segmentby columns, we have to output partials for + * every batch. + */ + return policy->num_grouping_columns > 0 && policy->have_results; } static bool @@ -205,20 +263,20 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return false; } - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_state = (void *) list_nth(policy->agg_states, i); - agg_def->func->agg_emit(agg_state, - &aggregated_slot->tts_values[agg_def->output_offset], - &aggregated_slot->tts_isnull[agg_def->output_offset]); + VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_state = policy->agg_states[i]; + agg_def->func.agg_emit(agg_state, + &aggregated_slot->tts_values[agg_def->output_offset], + &aggregated_slot->tts_isnull[agg_def->output_offset]); } - const int ngrp = list_length(policy->output_grouping_columns); + const int ngrp = policy->num_grouping_columns; for (int i = 0; i < ngrp; i++) { - GroupingColumn *col = list_nth(policy->output_grouping_columns, i); + GroupingColumn *col = &policy->grouping_columns[i]; Assert(col->input_offset >= 0); Assert(col->output_offset >= 0); @@ -234,9 +292,22 @@ gp_batch_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) return true; } +static char * +gp_batch_explain(GroupingPolicy *gp) +{ + GroupingPolicyBatch *policy = (GroupingPolicyBatch *) gp; + + /* + * If we're grouping by segmentby columns, we have to output partials for + * every batch. + */ + return policy->num_grouping_columns > 0 ? "per compressed batch" : "all compressed batches"; +} + static const GroupingPolicy grouping_policy_batch_functions = { .gp_reset = gp_batch_reset, .gp_add_batch = gp_batch_add_batch, .gp_should_emit = gp_batch_should_emit, .gp_do_emit = gp_batch_do_emit, + .gp_explain = gp_batch_explain, }; diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index ac150b7ea99..bd0a236de58 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -117,9 +117,9 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) static Plan * vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) { - CustomScan *custom = (CustomScan *) makeNode(CustomScan); - custom->custom_plans = list_make1(decompress_chunk); - custom->methods = &scan_methods; + CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); + vector_agg->custom_plans = list_make1(decompress_chunk); + vector_agg->methods = &scan_methods; /* * Note that this is being called from the post-planning hook, and therefore @@ -127,42 +127,43 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) * the previous planning stages, and they contain special varnos referencing * the scan targetlists. */ - custom->custom_scan_tlist = resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); - custom->scan.plan.targetlist = - build_trivial_custom_output_targetlist(custom->custom_scan_tlist); + vector_agg->custom_scan_tlist = + resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); + vector_agg->scan.plan.targetlist = + build_trivial_custom_output_targetlist(vector_agg->custom_scan_tlist); /* * Copy the costs from the normal aggregation node, so that they show up in * the EXPLAIN output. They are not used for any other purposes, because * this hook is called after the planning is finished. */ - custom->scan.plan.plan_rows = agg->plan.plan_rows; - custom->scan.plan.plan_width = agg->plan.plan_width; - custom->scan.plan.startup_cost = agg->plan.startup_cost; - custom->scan.plan.total_cost = agg->plan.total_cost; + vector_agg->scan.plan.plan_rows = agg->plan.plan_rows; + vector_agg->scan.plan.plan_width = agg->plan.plan_width; + vector_agg->scan.plan.startup_cost = agg->plan.startup_cost; + vector_agg->scan.plan.total_cost = agg->plan.total_cost; - custom->scan.plan.parallel_aware = false; - custom->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; - custom->scan.plan.async_capable = false; + vector_agg->scan.plan.parallel_aware = false; + vector_agg->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; + vector_agg->scan.plan.async_capable = false; - custom->scan.plan.plan_node_id = agg->plan.plan_node_id; + vector_agg->scan.plan.plan_node_id = agg->plan.plan_node_id; Assert(agg->plan.qual == NIL); - custom->scan.plan.initPlan = agg->plan.initPlan; + vector_agg->scan.plan.initPlan = agg->plan.initPlan; - custom->scan.plan.extParam = bms_copy(agg->plan.extParam); - custom->scan.plan.allParam = bms_copy(agg->plan.allParam); + vector_agg->scan.plan.extParam = bms_copy(agg->plan.extParam); + vector_agg->scan.plan.allParam = bms_copy(agg->plan.allParam); - List *grouping_col_offsets = NIL; + List *grouping_child_output_offsets = NIL; for (int i = 0; i < agg->numCols; i++) { - grouping_col_offsets = - lappend_int(grouping_col_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); + grouping_child_output_offsets = + lappend_int(grouping_child_output_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); } - custom->custom_private = list_make1(grouping_col_offsets); + vector_agg->custom_private = list_make1(grouping_child_output_offsets); - return (Plan *) custom; + return (Plan *) vector_agg; } /* diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 12ed14e3e84..54a712d8c12 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -59,18 +59,21 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -103,7 +106,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(52 rows) +(55 rows) -- Vectorization possible - filter on segment_by :EXPLAIN @@ -115,6 +118,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Index Scan using compress_hyper_2_11_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_11_chunk @@ -122,6 +126,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Index Cond: (compress_hyper_2_11_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Index Scan using compress_hyper_2_12_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_12_chunk @@ -129,6 +134,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Index Cond: (compress_hyper_2_12_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Index Scan using compress_hyper_2_13_chunk_segment_by_value__ts_meta_min_1___idx on _timescaledb_internal.compress_hyper_2_13_chunk @@ -169,7 +175,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; -> Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.segment_by_value > 0) -(59 rows) +(62 rows) -- Vectorization not possible due to a used filter :EXPLAIN @@ -181,6 +187,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) @@ -189,6 +196,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v Index Cond: (compress_hyper_2_11_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) @@ -197,6 +205,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v Index Cond: (compress_hyper_2_12_chunk.segment_by_value > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) @@ -238,7 +247,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_v -> Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: ((_hyper_1_10_chunk.segment_by_value > 0) AND (_hyper_1_10_chunk.int_value > 0)) -(62 rows) +(65 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; @@ -252,6 +261,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.int_value > 0) @@ -259,6 +269,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.int_value > 0) @@ -266,6 +277,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.int_value > 0) @@ -306,7 +318,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.int_value > 0) -(62 rows) +(65 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; @@ -320,6 +332,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value Vectorized Filter: (_hyper_1_1_chunk.float_value > '0'::double precision) @@ -327,6 +340,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value Vectorized Filter: (_hyper_1_2_chunk.float_value > '0'::double precision) @@ -334,6 +348,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value Vectorized Filter: (_hyper_1_3_chunk.float_value > '0'::double precision) @@ -374,7 +389,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value Filter: (_hyper_1_10_chunk.float_value > '0'::double precision) -(62 rows) +(65 rows) -- Vectorization not possible due grouping :EXPLAIN @@ -529,18 +544,21 @@ SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value, _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value, _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value, _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -580,7 +598,7 @@ SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value, _hyper_1_10_chunk.int_value -(60 rows) +(63 rows) :EXPLAIN SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; @@ -598,18 +616,21 @@ SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_b -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -649,7 +670,7 @@ SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_b Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(63 rows) +(66 rows) SELECT sum(segment_by_value), segment_by_value FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; sum | segment_by_value @@ -783,18 +804,21 @@ SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_b -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.segment_by_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.segment_by_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.segment_by_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: per compressed batch -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -834,7 +858,7 @@ SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_b Group Key: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -(63 rows) +(66 rows) SELECT segment_by_value, sum(segment_by_value) FROM testtable GROUP BY segment_by_value ORDER BY 1, 2; segment_by_value | sum @@ -971,18 +995,21 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -1015,7 +1042,7 @@ SELECT sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -(52 rows) +(55 rows) -- Vectorized aggregation possible SELECT sum(float_value) FROM testtable; @@ -1036,18 +1063,21 @@ SELECT sum(float_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.float_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.float_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.float_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -1080,7 +1110,7 @@ SELECT sum(float_value) FROM testtable; Output: PARTIAL sum(_hyper_1_10_chunk.float_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.float_value -(52 rows) +(55 rows) --- -- Tests with all chunks compressed @@ -1122,65 +1152,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk Output: compress_hyper_2_20_chunk._ts_meta_count, compress_hyper_2_20_chunk.segment_by_value, compress_hyper_2_20_chunk._ts_meta_min_1, compress_hyper_2_20_chunk._ts_meta_max_1, compress_hyper_2_20_chunk."time", compress_hyper_2_20_chunk.int_value, compress_hyper_2_20_chunk.float_value -(66 rows) +(76 rows) -- Vectorized aggregation possible SELECT sum(int_value) FROM testtable; @@ -1201,65 +1241,75 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk Output: compress_hyper_2_20_chunk._ts_meta_count, compress_hyper_2_20_chunk.segment_by_value, compress_hyper_2_20_chunk._ts_meta_min_1, compress_hyper_2_20_chunk._ts_meta_max_1, compress_hyper_2_20_chunk."time", compress_hyper_2_20_chunk.int_value, compress_hyper_2_20_chunk.float_value -(66 rows) +(76 rows) --- -- Tests with some chunks are partially compressed @@ -1285,60 +1335,70 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1347,7 +1407,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) -- Vectorized aggregation possible SELECT sum(int_value) FROM testtable; @@ -1368,60 +1428,70 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1430,7 +1500,7 @@ SELECT sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -(70 rows) +(80 rows) --Vectorized aggregation not possible for expression SELECT sum(abs(int_value)) FROM testtable; @@ -1685,60 +1755,70 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1747,7 +1827,7 @@ SELECT sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -1769,60 +1849,70 @@ SELECT sum(int_value), sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1831,7 +1921,7 @@ SELECT sum(int_value), sum(int_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value -(70 rows) +(80 rows) -- Using the same sum function multiple times is supported by vectorization :EXPLAIN @@ -1846,60 +1936,70 @@ SELECT sum(segment_by_value), sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1908,7 +2008,7 @@ SELECT sum(segment_by_value), sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) -- Performing a sum on multiple columns is supported. :EXPLAIN @@ -1923,60 +2023,70 @@ SELECT sum(int_value), sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_1_chunk.int_value)), (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_2_chunk.int_value)), (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_3_chunk.int_value)), (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_4_chunk.int_value)), (PARTIAL sum(_hyper_1_4_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_4_chunk Output: _hyper_1_4_chunk.int_value, _hyper_1_4_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_14_chunk Output: compress_hyper_2_14_chunk._ts_meta_count, compress_hyper_2_14_chunk.segment_by_value, compress_hyper_2_14_chunk._ts_meta_min_1, compress_hyper_2_14_chunk._ts_meta_max_1, compress_hyper_2_14_chunk."time", compress_hyper_2_14_chunk.int_value, compress_hyper_2_14_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_5_chunk.int_value)), (PARTIAL sum(_hyper_1_5_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_5_chunk Output: _hyper_1_5_chunk.int_value, _hyper_1_5_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_15_chunk Output: compress_hyper_2_15_chunk._ts_meta_count, compress_hyper_2_15_chunk.segment_by_value, compress_hyper_2_15_chunk._ts_meta_min_1, compress_hyper_2_15_chunk._ts_meta_max_1, compress_hyper_2_15_chunk."time", compress_hyper_2_15_chunk.int_value, compress_hyper_2_15_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_6_chunk.int_value)), (PARTIAL sum(_hyper_1_6_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_6_chunk Output: _hyper_1_6_chunk.int_value, _hyper_1_6_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_16_chunk Output: compress_hyper_2_16_chunk._ts_meta_count, compress_hyper_2_16_chunk.segment_by_value, compress_hyper_2_16_chunk._ts_meta_min_1, compress_hyper_2_16_chunk._ts_meta_max_1, compress_hyper_2_16_chunk."time", compress_hyper_2_16_chunk.int_value, compress_hyper_2_16_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_7_chunk.int_value)), (PARTIAL sum(_hyper_1_7_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_7_chunk Output: _hyper_1_7_chunk.int_value, _hyper_1_7_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_17_chunk Output: compress_hyper_2_17_chunk._ts_meta_count, compress_hyper_2_17_chunk.segment_by_value, compress_hyper_2_17_chunk._ts_meta_min_1, compress_hyper_2_17_chunk._ts_meta_max_1, compress_hyper_2_17_chunk."time", compress_hyper_2_17_chunk.int_value, compress_hyper_2_17_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_8_chunk.int_value)), (PARTIAL sum(_hyper_1_8_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_8_chunk Output: _hyper_1_8_chunk.int_value, _hyper_1_8_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_18_chunk Output: compress_hyper_2_18_chunk._ts_meta_count, compress_hyper_2_18_chunk.segment_by_value, compress_hyper_2_18_chunk._ts_meta_min_1, compress_hyper_2_18_chunk._ts_meta_max_1, compress_hyper_2_18_chunk."time", compress_hyper_2_18_chunk.int_value, compress_hyper_2_18_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_9_chunk.int_value)), (PARTIAL sum(_hyper_1_9_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_9_chunk Output: _hyper_1_9_chunk.int_value, _hyper_1_9_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_19_chunk Output: compress_hyper_2_19_chunk._ts_meta_count, compress_hyper_2_19_chunk.segment_by_value, compress_hyper_2_19_chunk._ts_meta_min_1, compress_hyper_2_19_chunk._ts_meta_max_1, compress_hyper_2_19_chunk."time", compress_hyper_2_19_chunk.int_value, compress_hyper_2_19_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_10_chunk.int_value)), (PARTIAL sum(_hyper_1_10_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_20_chunk @@ -1985,7 +2095,7 @@ SELECT sum(int_value), sum(segment_by_value) FROM testtable; Output: PARTIAL sum(_hyper_1_1_chunk.int_value), PARTIAL sum(_hyper_1_1_chunk.segment_by_value) -> Parallel Seq Scan on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -(70 rows) +(80 rows) SELECT sum(int_value), sum(segment_by_value) FROM testtable; sum | sum @@ -2256,6 +2366,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_41_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_41_chunk Output: _hyper_1_41_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_51_chunk @@ -2263,6 +2374,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_51_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_42_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_42_chunk Output: _hyper_1_42_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_52_chunk @@ -2270,6 +2382,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_52_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_43_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_43_chunk Output: _hyper_1_43_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_53_chunk @@ -2277,6 +2390,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_53_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_44_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_44_chunk Output: _hyper_1_44_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_54_chunk @@ -2284,6 +2398,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_54_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_45_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_45_chunk Output: _hyper_1_45_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_55_chunk @@ -2291,6 +2406,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_55_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_46_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_46_chunk Output: _hyper_1_46_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_56_chunk @@ -2298,6 +2414,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_56_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_47_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_47_chunk Output: _hyper_1_47_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_57_chunk @@ -2305,6 +2422,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_57_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_48_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_48_chunk Output: _hyper_1_48_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_58_chunk @@ -2312,6 +2430,7 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_58_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_49_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_49_chunk Output: _hyper_1_49_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_59_chunk @@ -2319,12 +2438,13 @@ SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; Filter: (compress_hyper_2_59_chunk.segment_by_value > 5) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_50_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_50_chunk Output: _hyper_1_50_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_60_chunk Output: compress_hyper_2_60_chunk._ts_meta_count, compress_hyper_2_60_chunk.segment_by_value, compress_hyper_2_60_chunk._ts_meta_min_1, compress_hyper_2_60_chunk._ts_meta_max_1, compress_hyper_2_60_chunk."time", compress_hyper_2_60_chunk.int_value, compress_hyper_2_60_chunk.float_value Filter: (compress_hyper_2_60_chunk.segment_by_value > 5) -(76 rows) +(86 rows) SELECT sum(int_value) FROM testtable WHERE segment_by_value > 5; sum @@ -2373,65 +2493,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_41_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_41_chunk Output: _hyper_1_41_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_51_chunk Output: compress_hyper_2_51_chunk._ts_meta_count, compress_hyper_2_51_chunk.segment_by_value, compress_hyper_2_51_chunk._ts_meta_min_1, compress_hyper_2_51_chunk._ts_meta_max_1, compress_hyper_2_51_chunk."time", compress_hyper_2_51_chunk.int_value, compress_hyper_2_51_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_42_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_42_chunk Output: _hyper_1_42_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_52_chunk Output: compress_hyper_2_52_chunk._ts_meta_count, compress_hyper_2_52_chunk.segment_by_value, compress_hyper_2_52_chunk._ts_meta_min_1, compress_hyper_2_52_chunk._ts_meta_max_1, compress_hyper_2_52_chunk."time", compress_hyper_2_52_chunk.int_value, compress_hyper_2_52_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_43_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_43_chunk Output: _hyper_1_43_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_53_chunk Output: compress_hyper_2_53_chunk._ts_meta_count, compress_hyper_2_53_chunk.segment_by_value, compress_hyper_2_53_chunk._ts_meta_min_1, compress_hyper_2_53_chunk._ts_meta_max_1, compress_hyper_2_53_chunk."time", compress_hyper_2_53_chunk.int_value, compress_hyper_2_53_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_44_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_44_chunk Output: _hyper_1_44_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_54_chunk Output: compress_hyper_2_54_chunk._ts_meta_count, compress_hyper_2_54_chunk.segment_by_value, compress_hyper_2_54_chunk._ts_meta_min_1, compress_hyper_2_54_chunk._ts_meta_max_1, compress_hyper_2_54_chunk."time", compress_hyper_2_54_chunk.int_value, compress_hyper_2_54_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_45_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_45_chunk Output: _hyper_1_45_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_55_chunk Output: compress_hyper_2_55_chunk._ts_meta_count, compress_hyper_2_55_chunk.segment_by_value, compress_hyper_2_55_chunk._ts_meta_min_1, compress_hyper_2_55_chunk._ts_meta_max_1, compress_hyper_2_55_chunk."time", compress_hyper_2_55_chunk.int_value, compress_hyper_2_55_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_46_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_46_chunk Output: _hyper_1_46_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_56_chunk Output: compress_hyper_2_56_chunk._ts_meta_count, compress_hyper_2_56_chunk.segment_by_value, compress_hyper_2_56_chunk._ts_meta_min_1, compress_hyper_2_56_chunk._ts_meta_max_1, compress_hyper_2_56_chunk."time", compress_hyper_2_56_chunk.int_value, compress_hyper_2_56_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_47_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_47_chunk Output: _hyper_1_47_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_57_chunk Output: compress_hyper_2_57_chunk._ts_meta_count, compress_hyper_2_57_chunk.segment_by_value, compress_hyper_2_57_chunk._ts_meta_min_1, compress_hyper_2_57_chunk._ts_meta_max_1, compress_hyper_2_57_chunk."time", compress_hyper_2_57_chunk.int_value, compress_hyper_2_57_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_48_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_48_chunk Output: _hyper_1_48_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_58_chunk Output: compress_hyper_2_58_chunk._ts_meta_count, compress_hyper_2_58_chunk.segment_by_value, compress_hyper_2_58_chunk._ts_meta_min_1, compress_hyper_2_58_chunk._ts_meta_max_1, compress_hyper_2_58_chunk."time", compress_hyper_2_58_chunk.int_value, compress_hyper_2_58_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_49_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_49_chunk Output: _hyper_1_49_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_59_chunk Output: compress_hyper_2_59_chunk._ts_meta_count, compress_hyper_2_59_chunk.segment_by_value, compress_hyper_2_59_chunk._ts_meta_min_1, compress_hyper_2_59_chunk._ts_meta_max_1, compress_hyper_2_59_chunk."time", compress_hyper_2_59_chunk.int_value, compress_hyper_2_59_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_50_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_50_chunk Output: _hyper_1_50_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_60_chunk Output: compress_hyper_2_60_chunk._ts_meta_count, compress_hyper_2_60_chunk.segment_by_value, compress_hyper_2_60_chunk._ts_meta_min_1, compress_hyper_2_60_chunk._ts_meta_max_1, compress_hyper_2_60_chunk."time", compress_hyper_2_60_chunk.int_value, compress_hyper_2_60_chunk.float_value -(66 rows) +(76 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -2558,65 +2688,75 @@ SELECT sum(segment_by_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_82_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_83_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_84_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_85_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_86_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_87_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_88_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_89_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_90_chunk.segment_by_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) :EXPLAIN SELECT sum(int_value) FROM testtable; @@ -2630,65 +2770,75 @@ SELECT sum(int_value) FROM testtable; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_81_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_82_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_83_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_84_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_85_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_86_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_87_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_88_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_89_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_1_90_chunk.int_value)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) SELECT sum(segment_by_value) FROM testtable; sum @@ -2849,59 +2999,68 @@ SELECT sum(segment_by_value1) FROM testtable2; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk Output: compress_hyper_4_110_chunk._ts_meta_count, compress_hyper_4_110_chunk.segment_by_value1, compress_hyper_4_110_chunk.segment_by_value2, compress_hyper_4_110_chunk._ts_meta_min_1, compress_hyper_4_110_chunk._ts_meta_max_1, compress_hyper_4_110_chunk."time", compress_hyper_4_110_chunk.int_value, compress_hyper_4_110_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk Output: compress_hyper_4_111_chunk._ts_meta_count, compress_hyper_4_111_chunk.segment_by_value1, compress_hyper_4_111_chunk.segment_by_value2, compress_hyper_4_111_chunk._ts_meta_min_1, compress_hyper_4_111_chunk._ts_meta_max_1, compress_hyper_4_111_chunk."time", compress_hyper_4_111_chunk.int_value, compress_hyper_4_111_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk Output: compress_hyper_4_112_chunk._ts_meta_count, compress_hyper_4_112_chunk.segment_by_value1, compress_hyper_4_112_chunk.segment_by_value2, compress_hyper_4_112_chunk._ts_meta_min_1, compress_hyper_4_112_chunk._ts_meta_max_1, compress_hyper_4_112_chunk."time", compress_hyper_4_112_chunk.int_value, compress_hyper_4_112_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk Output: compress_hyper_4_113_chunk._ts_meta_count, compress_hyper_4_113_chunk.segment_by_value1, compress_hyper_4_113_chunk.segment_by_value2, compress_hyper_4_113_chunk._ts_meta_min_1, compress_hyper_4_113_chunk._ts_meta_max_1, compress_hyper_4_113_chunk."time", compress_hyper_4_113_chunk.int_value, compress_hyper_4_113_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk Output: compress_hyper_4_114_chunk._ts_meta_count, compress_hyper_4_114_chunk.segment_by_value1, compress_hyper_4_114_chunk.segment_by_value2, compress_hyper_4_114_chunk._ts_meta_min_1, compress_hyper_4_114_chunk._ts_meta_max_1, compress_hyper_4_114_chunk."time", compress_hyper_4_114_chunk.int_value, compress_hyper_4_114_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk Output: compress_hyper_4_115_chunk._ts_meta_count, compress_hyper_4_115_chunk.segment_by_value1, compress_hyper_4_115_chunk.segment_by_value2, compress_hyper_4_115_chunk._ts_meta_min_1, compress_hyper_4_115_chunk._ts_meta_max_1, compress_hyper_4_115_chunk."time", compress_hyper_4_115_chunk.int_value, compress_hyper_4_115_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk Output: compress_hyper_4_116_chunk._ts_meta_count, compress_hyper_4_116_chunk.segment_by_value1, compress_hyper_4_116_chunk.segment_by_value2, compress_hyper_4_116_chunk._ts_meta_min_1, compress_hyper_4_116_chunk._ts_meta_max_1, compress_hyper_4_116_chunk."time", compress_hyper_4_116_chunk.int_value, compress_hyper_4_116_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk Output: compress_hyper_4_117_chunk._ts_meta_count, compress_hyper_4_117_chunk.segment_by_value1, compress_hyper_4_117_chunk.segment_by_value2, compress_hyper_4_117_chunk._ts_meta_min_1, compress_hyper_4_117_chunk._ts_meta_max_1, compress_hyper_4_117_chunk."time", compress_hyper_4_117_chunk.int_value, compress_hyper_4_117_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value -(60 rows) +(69 rows) SELECT sum(segment_by_value1) FROM testtable2; sum @@ -2921,59 +3080,68 @@ SELECT sum(segment_by_value2) FROM testtable2; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk Output: compress_hyper_4_110_chunk._ts_meta_count, compress_hyper_4_110_chunk.segment_by_value1, compress_hyper_4_110_chunk.segment_by_value2, compress_hyper_4_110_chunk._ts_meta_min_1, compress_hyper_4_110_chunk._ts_meta_max_1, compress_hyper_4_110_chunk."time", compress_hyper_4_110_chunk.int_value, compress_hyper_4_110_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk Output: compress_hyper_4_111_chunk._ts_meta_count, compress_hyper_4_111_chunk.segment_by_value1, compress_hyper_4_111_chunk.segment_by_value2, compress_hyper_4_111_chunk._ts_meta_min_1, compress_hyper_4_111_chunk._ts_meta_max_1, compress_hyper_4_111_chunk."time", compress_hyper_4_111_chunk.int_value, compress_hyper_4_111_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk Output: compress_hyper_4_112_chunk._ts_meta_count, compress_hyper_4_112_chunk.segment_by_value1, compress_hyper_4_112_chunk.segment_by_value2, compress_hyper_4_112_chunk._ts_meta_min_1, compress_hyper_4_112_chunk._ts_meta_max_1, compress_hyper_4_112_chunk."time", compress_hyper_4_112_chunk.int_value, compress_hyper_4_112_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk Output: compress_hyper_4_113_chunk._ts_meta_count, compress_hyper_4_113_chunk.segment_by_value1, compress_hyper_4_113_chunk.segment_by_value2, compress_hyper_4_113_chunk._ts_meta_min_1, compress_hyper_4_113_chunk._ts_meta_max_1, compress_hyper_4_113_chunk."time", compress_hyper_4_113_chunk.int_value, compress_hyper_4_113_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk Output: compress_hyper_4_114_chunk._ts_meta_count, compress_hyper_4_114_chunk.segment_by_value1, compress_hyper_4_114_chunk.segment_by_value2, compress_hyper_4_114_chunk._ts_meta_min_1, compress_hyper_4_114_chunk._ts_meta_max_1, compress_hyper_4_114_chunk."time", compress_hyper_4_114_chunk.int_value, compress_hyper_4_114_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk Output: compress_hyper_4_115_chunk._ts_meta_count, compress_hyper_4_115_chunk.segment_by_value1, compress_hyper_4_115_chunk.segment_by_value2, compress_hyper_4_115_chunk._ts_meta_min_1, compress_hyper_4_115_chunk._ts_meta_max_1, compress_hyper_4_115_chunk."time", compress_hyper_4_115_chunk.int_value, compress_hyper_4_115_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk Output: compress_hyper_4_116_chunk._ts_meta_count, compress_hyper_4_116_chunk.segment_by_value1, compress_hyper_4_116_chunk.segment_by_value2, compress_hyper_4_116_chunk._ts_meta_min_1, compress_hyper_4_116_chunk._ts_meta_max_1, compress_hyper_4_116_chunk."time", compress_hyper_4_116_chunk.int_value, compress_hyper_4_116_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk Output: compress_hyper_4_117_chunk._ts_meta_count, compress_hyper_4_117_chunk.segment_by_value1, compress_hyper_4_117_chunk.segment_by_value2, compress_hyper_4_117_chunk._ts_meta_min_1, compress_hyper_4_117_chunk._ts_meta_max_1, compress_hyper_4_117_chunk."time", compress_hyper_4_117_chunk.int_value, compress_hyper_4_117_chunk.float_value -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value2)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value2 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value -(60 rows) +(69 rows) SELECT sum(segment_by_value2) FROM testtable2; sum @@ -2994,6 +3162,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -3001,6 +3170,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_110_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3008,6 +3178,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_111_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3015,6 +3186,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_112_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3022,6 +3194,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_113_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3029,6 +3202,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_114_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3036,6 +3210,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_115_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3043,6 +3218,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_116_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3050,12 +3226,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0; Filter: (compress_hyper_4_117_chunk.segment_by_value1 > 0) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: (compress_hyper_4_118_chunk.segment_by_value1 > 0) -(69 rows) +(78 rows) :EXPLAIN SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND segment_by_value2 > 0; @@ -3069,6 +3246,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -3076,6 +3254,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_110_chunk.segment_by_value1 > 0) AND (compress_hyper_4_110_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3083,6 +3262,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_111_chunk.segment_by_value1 > 0) AND (compress_hyper_4_111_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3090,6 +3270,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_112_chunk.segment_by_value1 > 0) AND (compress_hyper_4_112_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3097,6 +3278,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_113_chunk.segment_by_value1 > 0) AND (compress_hyper_4_113_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3104,6 +3286,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_114_chunk.segment_by_value1 > 0) AND (compress_hyper_4_114_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3111,6 +3294,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_115_chunk.segment_by_value1 > 0) AND (compress_hyper_4_115_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3118,6 +3302,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_116_chunk.segment_by_value1 > 0) AND (compress_hyper_4_116_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3125,12 +3310,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_117_chunk.segment_by_value1 > 0) AND (compress_hyper_4_117_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: ((compress_hyper_4_118_chunk.segment_by_value1 > 0) AND (compress_hyper_4_118_chunk.segment_by_value2 > 0)) -(69 rows) +(78 rows) :EXPLAIN SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND segment_by_value2 > 0 AND 2>1; @@ -3144,6 +3330,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se -> Parallel Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_110_chunk @@ -3151,6 +3338,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_110_chunk.segment_by_value1 > 0) AND (compress_hyper_4_110_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_111_chunk @@ -3158,6 +3346,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_111_chunk.segment_by_value1 > 0) AND (compress_hyper_4_111_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_112_chunk @@ -3165,6 +3354,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_112_chunk.segment_by_value1 > 0) AND (compress_hyper_4_112_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_113_chunk @@ -3172,6 +3362,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_113_chunk.segment_by_value1 > 0) AND (compress_hyper_4_113_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_114_chunk @@ -3179,6 +3370,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_114_chunk.segment_by_value1 > 0) AND (compress_hyper_4_114_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_115_chunk @@ -3186,6 +3378,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_115_chunk.segment_by_value1 > 0) AND (compress_hyper_4_115_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_116_chunk @@ -3193,6 +3386,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_116_chunk.segment_by_value1 > 0) AND (compress_hyper_4_116_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_117_chunk @@ -3200,12 +3394,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 0 AND se Filter: ((compress_hyper_4_117_chunk.segment_by_value1 > 0) AND (compress_hyper_4_117_chunk.segment_by_value2 > 0)) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Filter: ((compress_hyper_4_118_chunk.segment_by_value1 > 0) AND (compress_hyper_4_118_chunk.segment_by_value2 > 0)) -(69 rows) +(78 rows) -- Vectorization not possible filter on segment_by and compressed value -- Disable parallel worker to get deterministic query plans on i386 @@ -3219,6 +3414,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND -> Append -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_101_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_101_chunk Output: _hyper_3_101_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_101_chunk.int_value > 1000) @@ -3227,6 +3423,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_110_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_102_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_102_chunk Output: _hyper_3_102_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_102_chunk.int_value > 1000) @@ -3235,6 +3432,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_111_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_103_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_103_chunk Output: _hyper_3_103_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_103_chunk.int_value > 1000) @@ -3243,6 +3441,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_112_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_104_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_104_chunk Output: _hyper_3_104_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_104_chunk.int_value > 1000) @@ -3251,6 +3450,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_113_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_105_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_105_chunk Output: _hyper_3_105_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_105_chunk.int_value > 1000) @@ -3259,6 +3459,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_114_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_106_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_106_chunk Output: _hyper_3_106_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_106_chunk.int_value > 1000) @@ -3267,6 +3468,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_115_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_107_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_107_chunk Output: _hyper_3_107_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_107_chunk.int_value > 1000) @@ -3275,6 +3477,7 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_116_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_108_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_108_chunk Output: _hyper_3_108_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_108_chunk.int_value > 1000) @@ -3283,12 +3486,13 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND Index Cond: (compress_hyper_4_117_chunk.segment_by_value1 > 1000) -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_3_109_chunk.segment_by_value1)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_109_chunk Output: _hyper_3_109_chunk.segment_by_value1 Vectorized Filter: (_hyper_3_109_chunk.int_value > 1000) -> Index Scan using compress_hyper_4_118_chunk_segment_by_value1_segment_by_val_idx on _timescaledb_internal.compress_hyper_4_118_chunk Output: compress_hyper_4_118_chunk._ts_meta_count, compress_hyper_4_118_chunk.segment_by_value1, compress_hyper_4_118_chunk.segment_by_value2, compress_hyper_4_118_chunk._ts_meta_min_1, compress_hyper_4_118_chunk._ts_meta_max_1, compress_hyper_4_118_chunk."time", compress_hyper_4_118_chunk.int_value, compress_hyper_4_118_chunk.float_value Index Cond: (compress_hyper_4_118_chunk.segment_by_value1 > 1000) -(75 rows) +(84 rows) RESET max_parallel_workers_per_gather; From 9df52d3f81560c729cdbd5ab0ffea9b61ab7ba35 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:48:54 +0100 Subject: [PATCH 083/242] const --- tsl/src/compression/arrow_c_data_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 467a6237f3c..a4fb8e3e9a6 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -185,7 +185,7 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) /* * AND two optional arrow validity bitmaps into the given storage. */ -static inline uint64 * +static inline const uint64 * arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, const uint64 *filter2) { From ae8b5132311991da7d7df1adfa3ecd1b7c1d4e55 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:58:00 +0100 Subject: [PATCH 084/242] forgotten reset --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index b1d7e6a6e1e..676130265ba 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -110,6 +110,13 @@ gp_hash_reset(GroupingPolicy *obj) policy->functions.reset(policy->table); + /* + * Have to reset this because it's in the key body context which is also + * reset here. + */ + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + policy->null_key_index = 0; policy->last_used_key_index = 0; From ac5bf2e3a01064d880ee2e5e14283471d05fa2d3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 13:58:06 +0100 Subject: [PATCH 085/242] benchmark more optimizations (2024-10-29 no. 4) From 78ec5b26c573df3cabbbb21468347ed6e08ec2e8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:09:17 +0100 Subject: [PATCH 086/242] reference REL_16_3 transparent_decompression-* --- tsl/test/expected/transparent_decompression-16.out | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/transparent_decompression-16.out b/tsl/test/expected/transparent_decompression-16.out index 06cfa51fb3a..5c2faab1770 100644 --- a/tsl/test/expected/transparent_decompression-16.out +++ b/tsl/test/expected/transparent_decompression-16.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); From 09ea9af7856ae9e50d315c1b8ea9838a5289ebe4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:10:04 +0100 Subject: [PATCH 087/242] reference REL_15_7 transparent_decompression-* --- tsl/test/expected/transparent_decompression-15.out | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/transparent_decompression-15.out b/tsl/test/expected/transparent_decompression-15.out index 8deee3b0a4e..f330b95b376 100644 --- a/tsl/test/expected/transparent_decompression-15.out +++ b/tsl/test/expected/transparent_decompression-15.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); From 533eff6a5d1661fe6260843fd06707c5c56c10af Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:10:54 +0100 Subject: [PATCH 088/242] reference REL_14_11 transparent_decompression-* --- tsl/test/expected/transparent_decompression-14.out | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/transparent_decompression-14.out b/tsl/test/expected/transparent_decompression-14.out index a7f2cd44508..94a13465842 100644 --- a/tsl/test/expected/transparent_decompression-14.out +++ b/tsl/test/expected/transparent_decompression-14.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); From 1cf81585f0b5d47daaf83914856690eab3eee669 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:11:45 +0100 Subject: [PATCH 089/242] reference REL_17_0-6-g4e0864af16 transparent_decompression-* --- tsl/test/expected/transparent_decompression-17.out | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/transparent_decompression-17.out b/tsl/test/expected/transparent_decompression-17.out index 06cfa51fb3a..5c2faab1770 100644 --- a/tsl/test/expected/transparent_decompression-17.out +++ b/tsl/test/expected/transparent_decompression-17.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); From 3c337431be6c83ede2c32bc1e0b54262c2a14d04 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:35:34 +0100 Subject: [PATCH 090/242] clean up the combine function --- tsl/src/compression/arrow_c_data_interface.h | 59 ++++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index f114ef8f574..35048ca878a 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -182,36 +182,71 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) Assert(arrow_row_is_valid(bitmap, row_number) == value); } +/* + * Combine the validity bitmaps into the given storage. + */ static inline const uint64 * arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, const uint64 *filter2, const uint64 *filter3) { - if (filter1 == NULL && filter2 == NULL && filter3 == NULL) + /* + * Any and all of the filters can be null. For simplicity, move the non-null + * filters to the front. + */ + const uint64 *tmp; +#define SWAP(X, Y) \ + tmp = (X); \ + (X) = (Y); \ + (Y) = tmp; + + if (filter2 == NULL) { - return NULL; + SWAP(filter2, filter3); } - for (size_t i = 0; i < num_words; i++) + if (filter1 == NULL) { - uint64 word = ~0; - if (filter1 != NULL) + SWAP(filter1, filter2); + + if (filter2 == NULL) { - word &= filter1[i]; + SWAP(filter2, filter3); } - if (filter2 != NULL) + } +#undef SWAP + + Assert(filter2 == NULL || filter1 != NULL); + Assert(filter3 == NULL || filter2 != NULL); + + if (filter2 == NULL) + { + /* Either have one non-null filter, or all of them are null. */ + return filter1; + } + + if (filter3 == NULL) + { + /* Have two non-null filters. */ + for (size_t i = 0; i < num_words; i++) { - word &= filter2[i]; + storage[i] = filter1[i] & filter2[i]; } - if (filter3 != NULL) + } + else + { + /* Have three non-null filters. */ + for (size_t i = 0; i < num_words; i++) { - word &= filter3[i]; + storage[i] = filter1[i] & filter2[i] & filter3[i]; } - storage[i] = word; } return storage; } -/* Increase the `source_value` to be an even multiple of `pad_to`. */ + +/* + * Increase the `source_value` to be an even multiple of `pad_to`. + */ static inline uint64 pad_to_multiple(uint64 pad_to, uint64 source_value) { From 29fd889ef4f01c2eda92aa5e390bbcf6cc4ef6b4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:39:20 +0100 Subject: [PATCH 091/242] refs --- tsl/test/expected/agg_partials_pushdown.out | 22 +++++++++++++++------ tsl/test/expected/compression.out | 6 ++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tsl/test/expected/agg_partials_pushdown.out b/tsl/test/expected/agg_partials_pushdown.out index f5585540ac9..4839d002561 100644 --- a/tsl/test/expected/agg_partials_pushdown.out +++ b/tsl/test/expected/agg_partials_pushdown.out @@ -40,6 +40,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Append (actual rows=2 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -49,6 +50,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((compress_hyper_2_3_chunk._ts_meta_max_1 >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (compress_hyper_2_3_chunk._ts_meta_min_1 <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -56,7 +58,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk (actual rows=5 loops=1) Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.device_id, compress_hyper_2_4_chunk.filter_1, compress_hyper_2_4_chunk.filler_2, compress_hyper_2_4_chunk.filler_3, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk."time", compress_hyper_2_4_chunk.v0, compress_hyper_2_4_chunk.v1, compress_hyper_2_4_chunk.v2, compress_hyper_2_4_chunk.v3 Filter: ((compress_hyper_2_4_chunk._ts_meta_max_1 >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (compress_hyper_2_4_chunk._ts_meta_min_1 <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -(21 rows) +(23 rows) -- Create partially compressed chunk INSERT INTO testtable(time,device_id,v0,v1,v2,v3) @@ -79,6 +81,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Append (actual rows=4 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -93,6 +96,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -105,7 +109,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -(31 rows) +(33 rows) -- Same query using chunk append SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= '2000-01-01 00:00:00+0'::text::timestamptz AND time <= '2000-02-01 00:00:00+0'; @@ -127,6 +131,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -141,6 +146,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -153,7 +159,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -(35 rows) +(37 rows) -- Perform chunk append startup chunk exclusion - issue 6282 :PREFIX @@ -169,6 +175,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 2 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -183,7 +190,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) Rows Removed by Filter: 15 -(23 rows) +(24 rows) -- Force plain / sorted aggregation SET enable_hashagg = OFF; @@ -206,6 +213,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -220,6 +228,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -232,7 +241,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -(35 rows) +(37 rows) RESET enable_hashagg; -- Check chunk exclusion for index scans @@ -256,6 +265,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 2 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -269,7 +279,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Index Scan using _hyper_1_2_chunk_testtable_time_idx on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Index Cond: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) -(22 rows) +(23 rows) RESET enable_seqscan; -- Check Append Node under ChunkAppend diff --git a/tsl/test/expected/compression.out b/tsl/test/expected/compression.out index 826c4f31946..82dc8215fab 100644 --- a/tsl/test/expected/compression.out +++ b/tsl/test/expected/compression.out @@ -1808,11 +1808,12 @@ SELECT sum(cpu) FROM f_sensor_data; Workers Planned: 4 -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_37_73_chunk.cpu)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_37_73_chunk Output: _hyper_37_73_chunk.cpu -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_38_74_chunk Output: compress_hyper_38_74_chunk._ts_meta_count, compress_hyper_38_74_chunk.sensor_id, compress_hyper_38_74_chunk._ts_meta_min_1, compress_hyper_38_74_chunk._ts_meta_max_1, compress_hyper_38_74_chunk."time", compress_hyper_38_74_chunk.cpu, compress_hyper_38_74_chunk.temperature -(11 rows) +(12 rows) -- Encourage use of Index Scan SET enable_seqscan = false; @@ -1863,11 +1864,12 @@ SELECT sum(cpu) FROM f_sensor_data; Output: _hyper_37_73_chunk.cpu -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_37_73_chunk.cpu)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_37_73_chunk Output: _hyper_37_73_chunk.cpu -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_38_74_chunk Output: compress_hyper_38_74_chunk._ts_meta_count, compress_hyper_38_74_chunk.sensor_id, compress_hyper_38_74_chunk._ts_meta_min_1, compress_hyper_38_74_chunk._ts_meta_max_1, compress_hyper_38_74_chunk."time", compress_hyper_38_74_chunk.cpu, compress_hyper_38_74_chunk.temperature -(16 rows) +(17 rows) :explain SELECT * FROM f_sensor_data WHERE sensor_id > 100; From 2554bc4805626388b845b3f76a1bdaf0994a3008 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:49:14 +0100 Subject: [PATCH 092/242] dict --- .../nodes/vector_agg/grouping_policy_hash.c | 45 ++++ .../nodes/vector_agg/grouping_policy_hash.h | 15 ++ tsl/src/nodes/vector_agg/hash_serialized.c | 4 +- tsl/src/nodes/vector_agg/hash_single_text.c | 223 +++++++++++++++++- .../vector_agg/hash_table_functions_impl.c | 27 ++- .../nodes/vector_agg/single_fixed_key_impl.c | 4 +- 6 files changed, 309 insertions(+), 9 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 3f4af495bd5..58fc714abfc 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -345,6 +345,51 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) policy->num_tmp_filter_words = (num_words * 2 + 1); } + if (policy->functions.prepare_for_batch) + { + /* + * Remember which aggregation states have already existed, and which we + * have to initialize. State index zero is invalid. + */ + const uint32 first_initialized_key_index = policy->last_used_key_index; + + policy->functions.prepare_for_batch(policy, batch_state); + + if (policy->last_used_key_index > first_initialized_key_index) + { + const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; + const int num_fns = policy->num_agg_defs; + for (int i = 0; i < num_fns; i++) + { + const VectorAggDef *agg_def = &policy->agg_defs[i]; + if (policy->last_used_key_index >= policy->num_agg_state_rows) + { + policy->per_agg_states[i] = + repalloc(policy->per_agg_states[i], + new_aggstate_rows * agg_def->func.state_bytes); + } + + /* + * Initialize the aggregate function states for the newly added keys. + */ + void *first_uninitialized_state = + agg_def->func.state_bytes * (first_initialized_key_index + 1) + + (char *) policy->per_agg_states[i]; + agg_def->func.agg_init(first_uninitialized_state, + policy->last_used_key_index - first_initialized_key_index); + } + + /* + * Record the newly allocated number of rows in case we had to reallocate. + */ + if (policy->last_used_key_index >= policy->num_agg_state_rows) + { + Assert(new_aggstate_rows > policy->num_agg_state_rows); + policy->num_agg_state_rows = new_aggstate_rows; + } + } + } + const uint64_t *restrict filter = batch_state->vector_qual_result; if (filter == NULL) { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 7bf3f024acc..a13d8ec5f6b 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -22,6 +22,7 @@ typedef struct void (*reset)(void *table); uint32 (*get_num_keys)(void *table); uint64 (*get_size_bytes)(void *table); + void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row); } HashTableFunctions; @@ -102,6 +103,15 @@ typedef struct GroupingPolicyHash uint32 *restrict key_index_for_row; uint64 num_key_index_for_row; + /* + * For single text key that uses dictionary encoding, in some cases we first + * calculate the key indexes for the dictionary entries, and then translate + * it to the actual rows. + */ + uint32 *restrict key_index_for_dict; + uint64 num_key_index_for_dict; + bool use_key_index_for_dict; + /* * The temporary filter bitmap we use to combine the results of the * vectorized filters in WHERE, validity of the aggregate function argument, @@ -186,4 +196,9 @@ typedef struct HashingConfig const CompressedColumnValues *compressed_columns; GroupingPolicyHash *policy; + + void (*get_key)(struct HashingConfig config, int row, void *restrict key, + bool *restrict key_valid); + + uint32 *restrict result_key_indexes; } HashingConfig; diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 1eabe621927..904a0d867f0 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,10 +19,12 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) +serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = config.policy; + BytesView *restrict key = (BytesView *) key_ptr; + uint64 *restrict serialized_key_validity_word; const int num_columns = config.num_grouping_columns; diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index bdc0028a589..22ebf61fd2f 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -29,11 +29,13 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(HashingConfig config, int row, BytesView *restrict key, bool *restrict valid) +single_text_get_key(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = config.policy; Assert(policy->num_grouping_columns == 1); + BytesView *restrict key = (BytesView *) key_ptr; + if (unlikely(config.single_key.decompression_type == DT_Scalar)) { /* Already stored. */ @@ -90,10 +92,229 @@ single_text_destroy_key(BytesView key) /* Noop. */ } +static pg_attribute_always_inline void single_text_fill_offsets_impl(HashingConfig config, + int start_row, int end_row); + +static pg_attribute_always_inline void +single_text_get_key_dict(HashingConfig config, int row, void *restrict key_ptr, + bool *restrict valid) +{ + GroupingPolicyHash *policy = config.policy; + Assert(policy->num_grouping_columns == 1); + + BytesView *restrict key = (BytesView *) key_ptr; + + if (config.single_key.decompression_type == DT_ArrowTextDict) + { + *key = get_bytes_view(&config.single_key, row); + *valid = true; + } + else + { + pg_unreachable(); + } + + *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1) = true; +} + +static void +single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + policy->use_key_index_for_dict = false; + + if (policy->num_grouping_columns != 1) + { + return; + } + + const GroupingColumn *g = &policy->grouping_columns[0]; + CompressedColumnValues *restrict single_key_column = + &batch_state->compressed_columns[g->input_offset]; + if (single_key_column->decompression_type != DT_ArrowTextDict) + { + return; + } + + const int dict_rows = single_key_column->arrow->dictionary->length; + if ((size_t) dict_rows > + arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) + { + return; + } + + /* + * Initialize the array for storing the aggregate state offsets corresponding + * to a given batch row. We don't need the offsets for the previous batch + * that are currently stored there, so we don't need to use repalloc. + */ + if ((size_t) dict_rows > policy->num_key_index_for_dict) + { + if (policy->key_index_for_dict != NULL) + { + pfree(policy->key_index_for_dict); + } + policy->num_key_index_for_dict = dict_rows; + policy->key_index_for_dict = + palloc(sizeof(policy->key_index_for_dict[0]) * policy->num_key_index_for_dict); + } + + /* + * Compute key indexes for the dictionary entries. + */ + HashingConfig config = { + .policy = policy, + .batch_filter = NULL, + .single_key = *single_key_column, + .num_grouping_columns = policy->num_grouping_columns, + .grouping_columns = policy->grouping_columns, + .compressed_columns = batch_state->compressed_columns, + .get_key = single_text_get_key_dict, + .result_key_indexes = policy->key_index_for_dict, + }; + + Assert((size_t) dict_rows <= policy->num_key_index_for_dict); + + bool have_null_key = false; + if (batch_state->vector_qual_result != NULL) + { + const uint64 *row_filter = batch_state->vector_qual_result; + uint64 *restrict dict_filter = policy->tmp_filter; + const size_t dict_words = (dict_rows + 63) / 64; + memset(dict_filter, 0, sizeof(*dict_filter) * dict_words); + + const int n = batch_state->total_batch_rows; + for (int i = 0; i < n; i++) + { + const int16 index = ((int16 *) config.single_key.buffers[3])[i]; + const bool batch_row_valid = arrow_row_is_valid(row_filter, i); + + const size_t qword_index = index / 64; + Assert(qword_index < dict_words); + const size_t bit_index = index % 64; + const uint64 mask = (batch_row_valid ? 1ull : 0ull) << bit_index; + dict_filter[qword_index] |= mask; + } + + config.batch_filter = dict_filter; + + if (config.single_key.arrow->null_count > 0) + { + Assert(config.single_key.buffers[0] != NULL); + const size_t batch_words = (n + 63) / 64; + for (size_t i = 0; i < batch_words; i++) + { + have_null_key |= + (row_filter[i] & (~((uint64 *) config.single_key.buffers[0])[i])) != 0; + } + } + } + else + { + if (config.single_key.arrow->null_count > 0) + { + have_null_key = true; + } + } + + single_text_fill_offsets_impl(config, 0, dict_rows); + + /* + * The dictionary doesn't store nulls, so add the null key separately if we + * have one. + */ + if (have_null_key && policy->null_key_index == 0) + { + policy->null_key_index = ++policy->last_used_key_index; + gp_hash_output_keys(policy, policy->null_key_index)[0] = PointerGetDatum(NULL); + *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->null_key_index) = false; + } + + policy->use_key_index_for_dict = true; + + DEBUG_PRINT("computed the dict offsets\n"); +} + +static pg_attribute_always_inline void +single_text_offsets_translate_impl(HashingConfig config, int start_row, int end_row) +{ + GroupingPolicyHash *policy = config.policy; + Assert(policy->use_key_index_for_dict); + + uint32 *restrict indexes_for_rows = config.result_key_indexes; + uint32 *restrict indexes_for_dict = policy->key_index_for_dict; + + for (int row = start_row; row < end_row; row++) + { + bool passes = arrow_row_is_valid(config.batch_filter, row); + bool row_valid = arrow_row_is_valid(config.single_key.buffers[0], row); + const int16 dict_index = ((int16 *) config.single_key.buffers[3])[row]; + + if (!passes) + { + continue; + } + + if (row_valid) + { + indexes_for_rows[row] = indexes_for_dict[dict_index]; + } + else + { + indexes_for_rows[row] = policy->null_key_index; + } + + Assert(indexes_for_rows[row] != 0); + } +} + +#define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ + X(NAME##_all, (COND) && (config.batch_filter == NULL)) \ + X(NAME##_filter, (COND) && (config.batch_filter != NULL)) + +#define APPLY_FOR_VALIDITY(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && (config.single_key.buffers[0] == NULL)) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, single_text_offsets_translate, true) + +#define DEFINE(NAME, CONDITION) \ + static pg_noinline void NAME(HashingConfig config, int start_row, int end_row) \ + { \ + if (!(CONDITION)) \ + { \ + pg_unreachable(); \ + } \ + \ + single_text_offsets_translate_impl(config, start_row, end_row); \ + } + +APPLY_FOR_SPECIALIZATIONS(DEFINE) + +#undef DEFINE + +static void +single_text_offsets_translate(HashingConfig config, int start_row, int end_row) +{ +#define DISPATCH(NAME, CONDITION) \ + if (CONDITION) \ + { \ + NAME(config, start_row, end_row); \ + } \ + else + + APPLY_FOR_SPECIALIZATIONS(DISPATCH) { pg_unreachable(); } +#undef DISPATCH +} + +#undef APPLY_FOR_SPECIALIZATIONS +#undef APPLY_FOR_VALIDITY +#undef APPLY_FOR_BATCH_FILTER + #define EXPLAIN_NAME "single text" #define KEY_VARIANT single_text #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define STORE_HASH #define CTYPE BytesView +#define HAVE_PREPARE_FUNCTION #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 19d0de2506c..77729fa2a6f 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -72,8 +72,7 @@ FUNCTION_NAME(fill_offsets_impl)( { GroupingPolicyHash *policy = config.policy; - uint32 *restrict indexes = policy->key_index_for_row; - Assert((size_t) end_row <= policy->num_key_index_for_row); + uint32 *restrict indexes = config.result_key_indexes; struct FUNCTION_NAME(hash) *restrict table = policy->table; @@ -90,7 +89,7 @@ FUNCTION_NAME(fill_offsets_impl)( bool key_valid = false; CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(config, row, &key, &key_valid); + config.get_key(config, row, &key, &key_valid); if (unlikely(!key_valid)) { @@ -207,8 +206,12 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba .num_grouping_columns = policy->num_grouping_columns, .grouping_columns = policy->grouping_columns, .compressed_columns = batch_state->compressed_columns, + .get_key = FUNCTION_NAME(get_key), + .result_key_indexes = policy->key_index_for_row, }; + Assert((size_t) end_row <= policy->num_key_index_for_row); + if (policy->num_grouping_columns == 1) { const GroupingColumn *g = &policy->grouping_columns[0]; @@ -219,13 +222,22 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba } #define DISPATCH(NAME, CONDITION) \ - if (CONDITION) \ + else if (CONDITION) \ { \ FUNCTION_NAME(NAME)(config, start_row, end_row); \ - } \ - else + } + if (false) + { + } +#ifdef HAVE_PREPARE_FUNCTION + else if (policy->use_key_index_for_dict) + { + single_text_offsets_translate(config, start_row, end_row); + } +#endif APPLY_FOR_SPECIALIZATIONS(DISPATCH) + else { /* Use a generic implementation if no specializations matched. */ FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); @@ -239,6 +251,9 @@ HashTableFunctions FUNCTION_NAME(functions) = { .get_size_bytes = FUNCTION_NAME(get_size_bytes), .fill_offsets = FUNCTION_NAME(fill_offsets), .explain_name = EXPLAIN_NAME, +#ifdef HAVE_PREPARE_FUNCTION + .prepare_for_batch = FUNCTION_NAME(prepare_for_batch), +#endif }; #undef EXPLAIN_NAME diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 0ff68ee60f1..966eb47158c 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -9,10 +9,12 @@ #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(HashingConfig config, int row, CTYPE *restrict key, bool *restrict valid) +FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = config.policy; + CTYPE *restrict key = (CTYPE *) key_ptr; + if (unlikely(config.single_key.decompression_type == DT_Scalar)) { *key = DATUM_TO_CTYPE(*config.single_key.output_value); From 7708193d34063e5c129cab3bf2d752fb553836cf Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:49:23 +0100 Subject: [PATCH 093/242] benchmark dict (2024-10-29 no. 5) From bb6c1c6a7d7b2c2138c6b38cd506aa76666e4876 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:51:09 +0100 Subject: [PATCH 094/242] benchmark vector agg refactoring (2024-10-29 no. 6) From 06b45931199383138364d055445051c5b3d1a8a3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:26:18 +0100 Subject: [PATCH 095/242] crazier dict --- .../nodes/vector_agg/grouping_policy_hash.h | 3 - tsl/src/nodes/vector_agg/hash_single_text.c | 107 +++++++++--------- .../vector_agg/hash_table_functions_impl.c | 43 ++++--- 3 files changed, 81 insertions(+), 72 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index a13d8ec5f6b..6d4d50e7168 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -197,8 +197,5 @@ typedef struct HashingConfig GroupingPolicyHash *policy; - void (*get_key)(struct HashingConfig config, int row, void *restrict key, - bool *restrict key_valid); - uint32 *restrict result_key_indexes; } HashingConfig; diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 22ebf61fd2f..4882a0f8355 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -92,30 +92,8 @@ single_text_destroy_key(BytesView key) /* Noop. */ } -static pg_attribute_always_inline void single_text_fill_offsets_impl(HashingConfig config, - int start_row, int end_row); - -static pg_attribute_always_inline void -single_text_get_key_dict(HashingConfig config, int row, void *restrict key_ptr, - bool *restrict valid) -{ - GroupingPolicyHash *policy = config.policy; - Assert(policy->num_grouping_columns == 1); - - BytesView *restrict key = (BytesView *) key_ptr; - - if (config.single_key.decompression_type == DT_ArrowTextDict) - { - *key = get_bytes_view(&config.single_key, row); - *valid = true; - } - else - { - pg_unreachable(); - } - - *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1) = true; -} +static pg_attribute_always_inline void single_text_dispatch_for_config(HashingConfig config, + int start_row, int end_row); static void single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) @@ -168,7 +146,6 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * .num_grouping_columns = policy->num_grouping_columns, .grouping_columns = policy->grouping_columns, .compressed_columns = batch_state->compressed_columns, - .get_key = single_text_get_key_dict, .result_key_indexes = policy->key_index_for_dict, }; @@ -182,25 +159,55 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * const size_t dict_words = (dict_rows + 63) / 64; memset(dict_filter, 0, sizeof(*dict_filter) * dict_words); - const int n = batch_state->total_batch_rows; - for (int i = 0; i < n; i++) + bool *restrict tmp = (bool *) policy->key_index_for_dict; + Assert(sizeof(*tmp) <= sizeof(*policy->key_index_for_dict)); + memset(tmp, 0, sizeof(*tmp) * dict_rows); + + const int batch_rows = batch_state->total_batch_rows; + int outer; + for (outer = 0; outer < batch_rows / 64; outer++) { - const int16 index = ((int16 *) config.single_key.buffers[3])[i]; - const bool batch_row_valid = arrow_row_is_valid(row_filter, i); - - const size_t qword_index = index / 64; - Assert(qword_index < dict_words); - const size_t bit_index = index % 64; - const uint64 mask = (batch_row_valid ? 1ull : 0ull) << bit_index; - dict_filter[qword_index] |= mask; +#define INNER_LOOP(INNER_MAX) \ + const uint64 word = row_filter[outer]; \ + for (int inner = 0; inner < INNER_MAX; inner++) \ + { \ + const int16 index = ((int16 *) config.single_key.buffers[3])[outer * 64 + inner]; \ + tmp[index] |= (word & (1ull << inner)); \ + } + + INNER_LOOP(64) } + if (batch_rows % 64) + { + INNER_LOOP(batch_rows % 64) + } +#undef INNER_LOOP + + for (outer = 0; outer < dict_rows / 64; outer++) + { +#define INNER_LOOP(INNER_MAX) \ + uint64 word = 0; \ + for (int inner = 0; inner < INNER_MAX; inner++) \ + { \ + word |= (tmp[outer * 64 + inner] ? 1ull : 0ull) << inner; \ + } \ + dict_filter[outer] = word; + + INNER_LOOP(64) + } + if (dict_rows % 64) + { + INNER_LOOP(dict_rows % 64) + } +#undef INNER_LOOP + config.batch_filter = dict_filter; if (config.single_key.arrow->null_count > 0) { Assert(config.single_key.buffers[0] != NULL); - const size_t batch_words = (n + 63) / 64; + const size_t batch_words = (batch_rows + 63) / 64; for (size_t i = 0; i < batch_words; i++) { have_null_key |= @@ -212,11 +219,19 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * { if (config.single_key.arrow->null_count > 0) { + Assert(config.single_key.buffers[0] != NULL); have_null_key = true; } } - single_text_fill_offsets_impl(config, 0, dict_rows); + /* + * Build offsets for the array entries as normal non-nullable text values. + */ + Assert(config.single_key.decompression_type = DT_ArrowTextDict); + config.single_key.decompression_type = DT_ArrowText; + config.single_key.buffers[0] = NULL; + memset(policy->key_index_for_dict, 0, sizeof(*policy->key_index_for_dict) * dict_rows); + single_text_dispatch_for_config(config, 0, dict_rows); /* * The dictionary doesn't store nulls, so add the null key separately if we @@ -245,15 +260,9 @@ single_text_offsets_translate_impl(HashingConfig config, int start_row, int end_ for (int row = start_row; row < end_row; row++) { - bool passes = arrow_row_is_valid(config.batch_filter, row); - bool row_valid = arrow_row_is_valid(config.single_key.buffers[0], row); + const bool row_valid = arrow_row_is_valid(config.single_key.buffers[0], row); const int16 dict_index = ((int16 *) config.single_key.buffers[3])[row]; - if (!passes) - { - continue; - } - if (row_valid) { indexes_for_rows[row] = indexes_for_dict[dict_index]; @@ -263,17 +272,13 @@ single_text_offsets_translate_impl(HashingConfig config, int start_row, int end_ indexes_for_rows[row] = policy->null_key_index; } - Assert(indexes_for_rows[row] != 0); + Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(config.batch_filter, row)); } } -#define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME##_all, (COND) && (config.batch_filter == NULL)) \ - X(NAME##_filter, (COND) && (config.batch_filter != NULL)) - #define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && (config.single_key.buffers[0] == NULL)) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + X(NAME##_notnull, (COND) && (config.single_key.buffers[0] == NULL)) \ + X(NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) #define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, single_text_offsets_translate, true) diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 77729fa2a6f..344b7b379a6 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -89,7 +89,7 @@ FUNCTION_NAME(fill_offsets_impl)( bool key_valid = false; CTYPE key = { 0 }; - config.get_key(config, row, &key, &key_valid); + FUNCTION_NAME(get_key)(config, row, &key, &key_valid); if (unlikely(!key_valid)) { @@ -192,6 +192,26 @@ APPLY_FOR_SPECIALIZATIONS(DEFINE) #undef DEFINE +static void +FUNCTION_NAME(dispatch_for_config)(HashingConfig config, int start_row, int end_row) +{ +#define DISPATCH(NAME, CONDITION) \ + if (CONDITION) \ + { \ + FUNCTION_NAME(NAME)(config, start_row, end_row); \ + } \ + else + + APPLY_FOR_SPECIALIZATIONS(DISPATCH) + { + /* Use a generic implementation if no specializations matched. */ + FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); + } +#undef DISPATCH +} + +#undef APPLY_FOR_SPECIALIZATIONS + /* * In some special cases we call a more efficient specialization of the grouping * function. @@ -206,7 +226,6 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba .num_grouping_columns = policy->num_grouping_columns, .grouping_columns = policy->grouping_columns, .compressed_columns = batch_state->compressed_columns, - .get_key = FUNCTION_NAME(get_key), .result_key_indexes = policy->key_index_for_row, }; @@ -221,27 +240,15 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba config.single_key = *single_key_column; } -#define DISPATCH(NAME, CONDITION) \ - else if (CONDITION) \ - { \ - FUNCTION_NAME(NAME)(config, start_row, end_row); \ - } - - if (false) - { - } #ifdef HAVE_PREPARE_FUNCTION - else if (policy->use_key_index_for_dict) + if (policy->use_key_index_for_dict) { single_text_offsets_translate(config, start_row, end_row); + return; } #endif - APPLY_FOR_SPECIALIZATIONS(DISPATCH) - else - { - /* Use a generic implementation if no specializations matched. */ - FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); - } + + FUNCTION_NAME(dispatch_for_config)(config, start_row, end_row); } HashTableFunctions FUNCTION_NAME(functions) = { From 90ec0683d38db5fa5d0478f61ab0877e9345a809 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:26:26 +0100 Subject: [PATCH 096/242] benchmark dict (2024-10-29 no. 7) From 794fb93817fc1c9f996281ce030d39c9d91a3a66 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 30 Oct 2024 13:36:52 +0100 Subject: [PATCH 097/242] to revert * datum key in serialized policy * specializaations for no scalar in serialized policy --- tsl/src/compression/arrow_c_data_interface.h | 3 +- .../nodes/decompress_chunk/compressed_batch.c | 3 + tsl/src/nodes/vector_agg/bytes_view.h | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 22 +- .../nodes/vector_agg/grouping_policy_hash.h | 83 +- tsl/src/nodes/vector_agg/hash_serialized.c | 274 +-- tsl/src/nodes/vector_agg/hash_single_text.c | 54 +- .../vector_agg/hash_table_functions_impl.c | 42 +- tsl/test/expected/vector_agg_grouping.out | 1679 ++++++++++++++--- tsl/test/sql/vector_agg_grouping.sql | 17 +- 10 files changed, 1723 insertions(+), 456 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 35048ca878a..077217b14af 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -176,8 +176,9 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) const size_t qword_index = row_number / 64; const size_t bit_index = row_number % 64; const uint64 mask = 1ull << bit_index; + const uint64 new_bit = (value ? 1ull : 0ull) << bit_index; - bitmap[qword_index] = (bitmap[qword_index] & ~mask) | ((-(uint64) value) & mask); + bitmap[qword_index] = (bitmap[qword_index] & ~mask) | new_bit; Assert(arrow_row_is_valid(bitmap, row_number) == value); } diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index 8e9e8a03f59..6a4664b1db5 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -253,6 +253,8 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state column_values->decompression_type = value_bytes; column_values->buffers[0] = arrow->buffers[0]; column_values->buffers[1] = arrow->buffers[1]; + column_values->buffers[2] = NULL; + column_values->buffers[3] = NULL; } else { @@ -278,6 +280,7 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state column_values->buffers[0] = arrow->buffers[0]; column_values->buffers[1] = arrow->buffers[1]; column_values->buffers[2] = arrow->buffers[2]; + column_values->buffers[3] = NULL; } else { diff --git a/tsl/src/nodes/vector_agg/bytes_view.h b/tsl/src/nodes/vector_agg/bytes_view.h index 28696bb1654..f7149c52568 100644 --- a/tsl/src/nodes/vector_agg/bytes_view.h +++ b/tsl/src/nodes/vector_agg/bytes_view.h @@ -11,8 +11,8 @@ typedef struct BytesView { - uint32 len; const uint8 *data; + uint32 len; } BytesView; static pg_attribute_always_inline uint32 diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 58fc714abfc..da96f9f1123 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -63,6 +63,8 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->per_agg_states[i] = palloc(agg_def->func.state_bytes * policy->num_agg_state_rows); } + policy->grouping_column_values = palloc(sizeof(CompressedColumnValues) * num_grouping_columns); + policy->key_body_mctx = policy->agg_extra_mctx; if (num_grouping_columns == 1) @@ -322,8 +324,8 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) if (num_possible_keys > policy->num_output_keys) { policy->num_output_keys = num_possible_keys * 2 + 1; - const size_t new_bytes = (sizeof(uint64) + policy->num_grouping_columns * sizeof(Datum)) * - policy->num_output_keys; + const size_t new_bytes = (char *) gp_hash_output_keys(policy, policy->num_output_keys) - + (char *) policy->output_keys; if (policy->output_keys == NULL) { policy->output_keys = palloc(new_bytes); @@ -345,6 +347,20 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) policy->num_tmp_filter_words = (num_words * 2 + 1); } + /* + * Arrange the input compressed columns in the order of grouping columns. + */ + for (int i = 0; i < policy->num_grouping_columns; i++) + { + const GroupingColumn *def = &policy->grouping_columns[i]; + const CompressedColumnValues *values = &batch_state->compressed_columns[def->input_offset]; + policy->grouping_column_values[i] = *values; + } + + /* + * Call the per-batch initialization function of the hashing strategy, if + * it has one. + */ if (policy->functions.prepare_for_batch) { /* @@ -515,7 +531,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[i]; aggregated_slot->tts_isnull[col->output_offset] = - !arrow_row_is_valid(gp_hash_key_validity_bitmap(policy, current_key), i); + !byte_bitmap_row_is_valid(gp_hash_key_validity_bitmap(policy, current_key), i); } DEBUG_PRINT("%p: output key index %d valid %lx\n", diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 6d4d50e7168..cf47b530850 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -67,6 +67,8 @@ typedef struct GroupingPolicyHash int num_grouping_columns; const GroupingColumn *restrict grouping_columns; + CompressedColumnValues *restrict grouping_column_values; + /* * The hash table we use for grouping. It matches each grouping key to its * unique integer index. @@ -167,21 +169,55 @@ typedef struct GroupingPolicyHash uint64 stat_consecutive_keys; } GroupingPolicyHash; -static inline uint64 * -gp_hash_key_validity_bitmap(GroupingPolicyHash *policy, int key_index) +static inline Datum * +gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) { - return (uint64 *) ((char *) policy->output_keys + - (sizeof(uint64) + sizeof(Datum) * policy->num_grouping_columns) * key_index); + Assert(key_index != 0); + + const size_t null_bitmap_bytes = (policy->num_grouping_columns + 7) / 8; + const size_t key_bytes = sizeof(Datum) * policy->num_grouping_columns; + const size_t serialized_key_bytes = TYPEALIGN(8, null_bitmap_bytes + key_bytes); + /* Bitmap goes to the end. */ + return (Datum *) (serialized_key_bytes * key_index + (uint8 *) policy->output_keys); } -static inline Datum * -gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) +static inline uint8 * +gp_hash_key_validity_bitmap(GroupingPolicyHash *policy, int key_index) { Assert(key_index != 0); - return (Datum *) &gp_hash_key_validity_bitmap(policy, key_index)[1]; + + const size_t null_bitmap_bytes = (policy->num_grouping_columns + 7) / 8; + return ((uint8 *) gp_hash_output_keys(policy, key_index + 1)) - null_bitmap_bytes; } -// #define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +static pg_attribute_always_inline bool +byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) +{ + if (likely(bitmap == NULL)) + { + return true; + } + + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + return bitmap[byte_index] & mask; +} + +static pg_attribute_always_inline void +byte_bitmap_set_row_validity(uint8 *bitmap, size_t row_number, bool value) +{ + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + const uint8 new_bit = ((uint8) value) << bit_index; + + bitmap[byte_index] = (bitmap[byte_index] & ~mask) | new_bit; + + Assert(byte_bitmap_row_is_valid(bitmap, row_number) == value); +} + +//#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) #ifndef DEBUG_PRINT #define DEBUG_PRINT(...) #endif @@ -192,10 +228,37 @@ typedef struct HashingConfig CompressedColumnValues single_key; int num_grouping_columns; - const GroupingColumn *grouping_columns; - const CompressedColumnValues *compressed_columns; + const CompressedColumnValues *grouping_column_values; + bool have_scalar_columns; GroupingPolicyHash *policy; uint32 *restrict result_key_indexes; } HashingConfig; + +static inline HashingConfig +build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + HashingConfig config = { + .policy = policy, + .batch_filter = batch_state->vector_qual_result, + .num_grouping_columns = policy->num_grouping_columns, + .grouping_column_values = policy->grouping_column_values, + .result_key_indexes = policy->key_index_for_row, + }; + + Assert(policy->num_grouping_columns > 0); + if (policy->num_grouping_columns == 1) + { + config.single_key = policy->grouping_column_values[0]; + } + + for (int i = 0; i < policy->num_grouping_columns; i++) + { + config.have_scalar_columns |= + (policy->grouping_column_values[i].decompression_type == DT_Scalar || + policy->grouping_column_values[i].buffers[0] != NULL); + } + + return config; +} diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 904a0d867f0..775e6a5e6f5 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -23,73 +23,87 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * { GroupingPolicyHash *policy = config.policy; - BytesView *restrict key = (BytesView *) key_ptr; - - uint64 *restrict serialized_key_validity_word; + text **restrict key = (text **) key_ptr; const int num_columns = config.num_grouping_columns; - Assert(num_columns <= 64); + + size_t bitmap_bytes = (num_columns + 7) / 8; + uint8 *restrict serialized_key_validity_bitmap; /* * Loop through the grouping columns to determine the length of the key. We * need that to allocate memory to store it. */ size_t num_bytes = 0; + num_bytes += VARHDRSZ; for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = &config.grouping_columns[column_index]; - const CompressedColumnValues *column_values = &config.compressed_columns[def->input_offset]; + const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; + + if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) + { + if (!*column_values->output_isnull) + { + const GroupingColumn *def = &config.policy->grouping_columns[column_index]; + if (def->by_value) + { + num_bytes += def->value_bytes; + } + else + { + num_bytes = TYPEALIGN(4, num_bytes) + VARSIZE_ANY(*column_values->output_value); + } + } + + continue; + } - num_bytes = TYPEALIGN(def->alignment_bytes, num_bytes); + const bool is_valid = + !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); + if (!is_valid) + { + continue; + } if (column_values->decompression_type > 0) { - Assert(def->by_value); num_bytes += column_values->decompression_type; } - else if (unlikely(column_values->decompression_type == DT_Scalar)) + else { - if (def->by_value) + Assert(column_values->decompression_type == DT_ArrowText || + column_values->decompression_type == DT_ArrowTextDict); + Assert((column_values->decompression_type == DT_ArrowTextDict) == + (column_values->buffers[3] != NULL)); + + const uint32 data_row = (column_values->decompression_type == DT_ArrowTextDict) ? + ((int16 *) column_values->buffers[3])[row] : + row; + + const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; + + int32 total_bytes; + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { - num_bytes += def->value_bytes; + /* Short varlena, unaligned. */ + total_bytes = value_bytes + VARHDRSZ_SHORT; } else { - num_bytes += - (*column_values->output_isnull) ? 0 : VARSIZE_ANY(*column_values->output_value); - } - } - else if (column_values->decompression_type == DT_ArrowText) - { - if (arrow_row_is_valid(column_values->buffers[0], row)) - { - const uint32 start = ((uint32 *) column_values->buffers[1])[row]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[row + 1] - start; - num_bytes += value_bytes + VARHDRSZ; - } - } - else if (column_values->decompression_type == DT_ArrowTextDict) - { - if (arrow_row_is_valid(column_values->buffers[0], row)) - { - const int16 index = ((int16 *) column_values->buffers[3])[row]; - const uint32 start = ((uint32 *) column_values->buffers[1])[index]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[index + 1] - start; - num_bytes += value_bytes + VARHDRSZ; + /* Long varlena, requires alignment. */ + total_bytes = value_bytes + VARHDRSZ; + num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; } - } - else - { - pg_unreachable(); + + num_bytes += total_bytes; } } /* - * The key can have a null bitmap if any values are null, we always allocate - * the storage for it. + * The key has a null bitmap at the end. */ - num_bytes = TYPEALIGN(ALIGNOF_DOUBLE, num_bytes); - num_bytes += sizeof(*serialized_key_validity_word); + num_bytes += bitmap_bytes; /* * Use temporary storage for the new key, reallocate if it's too small. @@ -111,16 +125,14 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * */ memset(serialized_key_storage, 0, num_bytes); - serialized_key_validity_word = (uint64 *) &( - (char *) serialized_key_storage)[num_bytes - sizeof(*serialized_key_validity_word)]; - *serialized_key_validity_word = ~0ULL; + serialized_key_validity_bitmap = &serialized_key_storage[num_bytes - bitmap_bytes]; /* * We will also fill the output key values in Postgres format. They can go * straight into the next unused key space, if this key is discarded they * will just be overwritten later. */ - uint64 *restrict output_key_validity_word = + uint8 *restrict output_key_validity_bitmap = gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1); Datum *restrict output_key_datums = gp_hash_output_keys(policy, policy->last_used_key_index + 1); @@ -129,47 +141,34 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * * Loop through the grouping columns again and build the actual key. */ uint32 offset = 0; + offset += VARHDRSZ; for (int column_index = 0; column_index < num_columns; column_index++) { - const GroupingColumn *def = &config.grouping_columns[column_index]; - const CompressedColumnValues *column_values = &config.compressed_columns[def->input_offset]; - - offset = TYPEALIGN(def->alignment_bytes, offset); + const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; - if (column_values->decompression_type > 0) - { - Assert(offset <= UINT_MAX - column_values->decompression_type); - memcpy(&serialized_key_storage[offset], - ((char *) column_values->buffers[1]) + column_values->decompression_type * row, - column_values->decompression_type); - arrow_set_row_validity(serialized_key_validity_word, - column_index, - arrow_row_is_valid(column_values->buffers[0], row)); - offset += column_values->decompression_type; - - memcpy(&output_key_datums[column_index], - ((char *) column_values->buffers[1]) + column_values->decompression_type * row, - column_values->decompression_type); - } - else if (unlikely(column_values->decompression_type == DT_Scalar)) + if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) { const bool is_valid = !*column_values->output_isnull; - arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); + byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); if (is_valid) { + const GroupingColumn *def = &config.policy->grouping_columns[column_index]; if (def->by_value) { memcpy(&serialized_key_storage[offset], column_values->output_value, def->value_bytes); - offset += def->value_bytes; memcpy(&output_key_datums[column_index], column_values->output_value, def->value_bytes); + + offset += def->value_bytes; } else { + offset = TYPEALIGN(4, offset); + memcpy(&serialized_key_storage[offset], DatumGetPointer(*column_values->output_value), VARSIZE_ANY(*column_values->output_value)); @@ -180,85 +179,96 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * offset += VARSIZE_ANY(*column_values->output_value); } } - else - { - output_key_datums[column_index] = PointerGetDatum(NULL); - } + continue; } - else if (column_values->decompression_type == DT_ArrowText) + + const bool is_valid = + !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); + byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); + + if (!is_valid) { - const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); - arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); - if (is_valid) - { - const uint32 start = ((uint32 *) column_values->buffers[1])[row]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[row + 1] - start; - const int32 total_bytes = value_bytes + VARHDRSZ; + continue; + } - SET_VARSIZE(&serialized_key_storage[offset], total_bytes); - memcpy(VARDATA(&serialized_key_storage[offset]), - &((uint8 *) column_values->buffers[2])[start], - value_bytes); + if (column_values->decompression_type > 0) + { + Assert(offset <= UINT_MAX - column_values->decompression_type); - output_key_datums[column_index] = PointerGetDatum(&serialized_key_storage[offset]); + memcpy(&serialized_key_storage[offset], + ((char *) column_values->buffers[1]) + column_values->decompression_type * row, + column_values->decompression_type); + memcpy(&output_key_datums[column_index], + ((char *) column_values->buffers[1]) + column_values->decompression_type * row, + column_values->decompression_type); - offset += total_bytes; - } - else - { - output_key_datums[column_index] = PointerGetDatum(NULL); - } + offset += column_values->decompression_type; + + continue; } - else if (column_values->decompression_type == DT_ArrowTextDict) - { - const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); - arrow_set_row_validity(serialized_key_validity_word, column_index, is_valid); - if (is_valid) - { - const int16 index = ((int16 *) column_values->buffers[3])[row]; - const uint32 start = ((uint32 *) column_values->buffers[1])[index]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[index + 1] - start; - const int32 total_bytes = value_bytes + VARHDRSZ; - SET_VARSIZE(&serialized_key_storage[offset], total_bytes); - memcpy(VARDATA(&serialized_key_storage[offset]), - &((uint8 *) column_values->buffers[2])[start], - value_bytes); + Assert(column_values->decompression_type == DT_ArrowText || + column_values->decompression_type == DT_ArrowTextDict); - output_key_datums[column_index] = PointerGetDatum(&serialized_key_storage[offset]); + const uint32 data_row = column_values->decompression_type == DT_ArrowTextDict ? + ((int16 *) column_values->buffers[3])[row] : + row; + const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; - offset += total_bytes; - } - else - { - output_key_datums[column_index] = PointerGetDatum(NULL); - } + void *datum_start; + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, unaligned. */ + datum_start = &serialized_key_storage[offset]; + const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; + SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ_SHORT; } else { - pg_unreachable(); + /* Long varlena, requires alignment. */ + offset = TYPEALIGN(4, offset); + datum_start = &serialized_key_storage[offset]; + const int32 total_bytes = value_bytes + VARHDRSZ; + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ; } + output_key_datums[column_index] = PointerGetDatum(datum_start); + memcpy(&serialized_key_storage[offset], + &((uint8 *) column_values->buffers[2])[start], + value_bytes); + offset += value_bytes; } - Assert((void *) &serialized_key_storage[TYPEALIGN(ALIGNOF_DOUBLE, offset)] == - (void *) serialized_key_validity_word); + Assert(&serialized_key_storage[offset] == (void *) serialized_key_validity_bitmap); + + /* + * Note that we must always save the validity bitmap, even when there are no + * null words, so that the key is uniquely deserializable. Otherwise a key + * with some nulls might collide with a key with no nulls. + */ + offset += bitmap_bytes; + Assert(offset == num_bytes); - if (*serialized_key_validity_word != ~0ULL) + /* + * The output keys also have a validity bitmap, copy it there. + */ + for (size_t i = 0; i < bitmap_bytes; i++) { - offset = TYPEALIGN(ALIGNOF_DOUBLE, offset) + sizeof(*serialized_key_validity_word); - Assert(offset == num_bytes); + output_key_validity_bitmap[i] = serialized_key_validity_bitmap[i]; } - *output_key_validity_word = *serialized_key_validity_word; + DEBUG_PRINT("key is %d bytes: ", offset); + for (size_t i = 0; i < offset; i++) + { + DEBUG_PRINT("%.2x.", serialized_key_storage[i]); + } + DEBUG_PRINT("\n"); - // fprintf(stderr, "key is %d bytes: ", offset); - // for (size_t i = 0; i < offset; i++) - // { - // fprintf(stderr, "%.2x.", key_storage[i]); - // } - // fprintf(stderr, "\n"); + SET_VARSIZE(serialized_key_storage, offset); - *key = (BytesView){ .data = serialized_key_storage, .len = offset }; + *key = (text *) serialized_key_storage; /* * The multi-column key is always considered non-null, and the null flags @@ -268,29 +278,31 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * *valid = true; } -static pg_attribute_always_inline BytesView -serialized_store_key(GroupingPolicyHash *restrict policy, BytesView key) +static pg_attribute_always_inline text * +serialized_store_key(GroupingPolicyHash *restrict policy, text *key) { /* * We will store this key so we have to consume the temporary storage that * was used for it. The subsequent keys will need to allocate new memory. */ - Assert(policy->tmp_key_storage == key.data); + Assert(policy->tmp_key_storage == (void *) key); policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; return key; } static pg_attribute_always_inline void -serialized_destroy_key(BytesView key) +serialized_destroy_key(text *key) { /* Noop, the memory will be reused by the subsequent key. */ } #define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized -#define KEY_HASH(X) hash_bytes_view(X) -#define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) +#define KEY_HASH(X) hash_bytes_view((BytesView){ .len = VARSIZE_4B(X), .data = (uint8 *) (X) }) +#define KEY_EQUAL(a, b) \ + (VARSIZE_4B(a) == VARSIZE_4B(b) && \ + memcmp(VARDATA_4B(a), VARDATA_4B(b), VARSIZE_4B(a) - VARHDRSZ) == 0) #define STORE_HASH -#define CTYPE BytesView +#define CTYPE text * #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 4882a0f8355..5a4a775afb1 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -100,20 +100,16 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * { policy->use_key_index_for_dict = false; - if (policy->num_grouping_columns != 1) - { - return; - } + Assert(policy->num_grouping_columns == 1); + + HashingConfig config = build_hashing_config(policy, batch_state); - const GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues *restrict single_key_column = - &batch_state->compressed_columns[g->input_offset]; - if (single_key_column->decompression_type != DT_ArrowTextDict) + if (config.single_key.decompression_type != DT_ArrowTextDict) { return; } - const int dict_rows = single_key_column->arrow->dictionary->length; + const int dict_rows = config.single_key.arrow->dictionary->length; if ((size_t) dict_rows > arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) { @@ -137,24 +133,13 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * } /* - * Compute key indexes for the dictionary entries. + * We shouldn't add the dictionary entries that are not used by any mathching + * rows. Translate the batch filter bitmap to dictionary rows. */ - HashingConfig config = { - .policy = policy, - .batch_filter = NULL, - .single_key = *single_key_column, - .num_grouping_columns = policy->num_grouping_columns, - .grouping_columns = policy->grouping_columns, - .compressed_columns = batch_state->compressed_columns, - .result_key_indexes = policy->key_index_for_dict, - }; - - Assert((size_t) dict_rows <= policy->num_key_index_for_dict); - - bool have_null_key = false; + const int batch_rows = batch_state->total_batch_rows; + const uint64 *row_filter = batch_state->vector_qual_result; if (batch_state->vector_qual_result != NULL) { - const uint64 *row_filter = batch_state->vector_qual_result; uint64 *restrict dict_filter = policy->tmp_filter; const size_t dict_words = (dict_rows + 63) / 64; memset(dict_filter, 0, sizeof(*dict_filter) * dict_words); @@ -163,7 +148,6 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * Assert(sizeof(*tmp) <= sizeof(*policy->key_index_for_dict)); memset(tmp, 0, sizeof(*tmp) * dict_rows); - const int batch_rows = batch_state->total_batch_rows; int outer; for (outer = 0; outer < batch_rows / 64; outer++) { @@ -203,7 +187,20 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * #undef INNER_LOOP config.batch_filter = dict_filter; + } + else + { + config.batch_filter = NULL; + } + /* + * The dictionary contains no null entries, so we will be adding the null + * key separately. Determine if we have any null key that also passes the + * batch filter. + */ + bool have_null_key = false; + if (batch_state->vector_qual_result != NULL) + { if (config.single_key.arrow->null_count > 0) { Assert(config.single_key.buffers[0] != NULL); @@ -225,12 +222,17 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * } /* - * Build offsets for the array entries as normal non-nullable text values. + * Build key indexes for the dictionary entries as for normal non-nullable + * text values. */ Assert(config.single_key.decompression_type = DT_ArrowTextDict); config.single_key.decompression_type = DT_ArrowText; config.single_key.buffers[0] = NULL; + + Assert((size_t) dict_rows <= policy->num_key_index_for_dict); + config.result_key_indexes = policy->key_index_for_dict; memset(policy->key_index_for_dict, 0, sizeof(*policy->key_index_for_dict) * dict_rows); + single_text_dispatch_for_config(config, 0, dict_rows); /* diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 344b7b379a6..ffa5f26c2d3 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -154,28 +154,30 @@ FUNCTION_NAME(fill_offsets_impl)( * when all the batch and key rows are valid. */ #define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME##_all, (COND) && (config.batch_filter == NULL)) \ + X(NAME, (COND) && (config.batch_filter == NULL)) \ X(NAME##_filter, (COND) && (config.batch_filter != NULL)) #define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && (config.single_key.buffers[0] == NULL)) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && config.single_key.buffers[0] == NULL) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && config.single_key.buffers[0] != NULL) + +#define APPLY_FOR_SCALARS(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && !config.have_scalar_columns) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_scalar, (COND) && config.have_scalar_columns) #define APPLY_FOR_TYPE(X, NAME, COND) \ APPLY_FOR_VALIDITY(X, \ - NAME##_fixed, \ - (COND) && (config.single_key.decompression_type == sizeof(CTYPE))) \ + NAME##_byval, \ + (COND) && config.single_key.decompression_type == sizeof(CTYPE)) \ APPLY_FOR_VALIDITY(X, \ NAME##_text, \ - (COND) && (config.single_key.decompression_type == DT_ArrowText)) \ + (COND) && config.single_key.decompression_type == DT_ArrowText) \ APPLY_FOR_VALIDITY(X, \ NAME##_dict, \ - (COND) && (config.single_key.decompression_type == DT_ArrowTextDict)) \ - APPLY_FOR_BATCH_FILTER(X, \ - NAME##_multi, \ - (COND) && (config.single_key.decompression_type == DT_Invalid)) + (COND) && config.single_key.decompression_type == DT_ArrowTextDict) \ + APPLY_FOR_SCALARS(X, NAME##_multi, (COND) && config.single_key.decompression_type == DT_Invalid) -#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, , true) +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, index, true) #define DEFINE(NAME, CONDITION) \ static pg_noinline void FUNCTION_NAME(NAME)(HashingConfig config, int start_row, int end_row) \ @@ -220,25 +222,9 @@ static void FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row) { - HashingConfig config = { - .policy = policy, - .batch_filter = batch_state->vector_qual_result, - .num_grouping_columns = policy->num_grouping_columns, - .grouping_columns = policy->grouping_columns, - .compressed_columns = batch_state->compressed_columns, - .result_key_indexes = policy->key_index_for_row, - }; - Assert((size_t) end_row <= policy->num_key_index_for_row); - if (policy->num_grouping_columns == 1) - { - const GroupingColumn *g = &policy->grouping_columns[0]; - CompressedColumnValues *restrict single_key_column = - &batch_state->compressed_columns[g->input_offset]; - - config.single_key = *single_key_column; - } + HashingConfig config = build_hashing_config(policy, batch_state); #ifdef HAVE_PREPARE_FUNCTION if (policy->use_key_index_for_dict) diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index 2c8c9fc111d..16075bd2539 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -88,16 +88,23 @@ from 'count']) function, unnest(array[ null, - 'cint2 > 0']) with ordinality as condition(condition, n), + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's', 'cint2', 'cint4', + 'cint4, cint8', 'cint8', - 'x', - 'ss, x', - 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint2, cint4, cint8', + 'x']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -110,21 +117,6 @@ select count(*) from agggroup; 200000 (1 row) -select s, count(*) from agggroup group by s order by count(*), s limit 10; - s | count ----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - select cint2, count(*) from agggroup group by cint2 order by count(*), cint2 limit 10; cint2 | count --------+------- @@ -155,6 +147,21 @@ select cint4, count(*) from agggroup group by cint4 order by count(*), cint4 lim -15760 | 1 (10 rows) +select cint4, cint8, count(*) from agggroup group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16383 | 7417 | 1 + -16383 | 8953 | 1 + -16382 | -8851 | 1 + -16382 | -8612 | 1 + -16382 | -5254 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 899 | 1 +(10 rows) + select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 limit 10; cint8 | count --------+------- @@ -170,34 +177,94 @@ select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 lim -15753 | 1 (10 rows) -select x, count(*) from agggroup group by x order by count(*), x limit 10; - x | count -----+------- - | 19 - 3 | 19981 - 4 | 19981 - 0 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 +select s, cint2, count(*) from agggroup group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+--------+------- + 0 | -16377 | 1 + 0 | -16376 | 1 + 0 | -16375 | 1 + 0 | -16373 | 1 + 0 | -16372 | 1 + 0 | -16371 | 1 + 0 | -16370 | 1 + 0 | -16369 | 1 + 0 | -16368 | 1 + 0 | -16367 | 1 (10 rows) -select ss, x, count(*) from agggroup group by ss, x order by count(*), ss, x limit 10; - ss | x | count -----+----+------- - | | 19 - 3 | 3 | 19981 - 4 | 4 | 19981 - 0 | 0 | 20000 - 5 | 5 | 20000 - 6 | 6 | 20000 - 7 | 7 | 20000 - 8 | 8 | 20000 - 9 | 9 | 20000 - 11 | 11 | 40019 +select s, ss, count(*) from agggroup group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select s, x, count(*) from agggroup group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select ss, cint2, x, count(*) from agggroup group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+---+------- + 0 | -16377 | 0 | 1 + 0 | -16376 | 0 | 1 + 0 | -16375 | 0 | 1 + 0 | -16373 | 0 | 1 + 0 | -16372 | 0 | 1 + 0 | -16371 | 0 | 1 + 0 | -16370 | 0 | 1 + 0 | -16369 | 0 | 1 + 0 | -16368 | 0 | 1 + 0 | -16367 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 + 8 | 8 | 20000 + 9 | 9 | 20000 +(10 rows) + +select ss, x, cint2, count(*) from agggroup group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+--------+------- + 0 | 0 | -16377 | 1 + 0 | 0 | -16376 | 1 + 0 | 0 | -16375 | 1 + 0 | 0 | -16373 | 1 + 0 | 0 | -16372 | 1 + 0 | 0 | -16371 | 1 + 0 | 0 | -16370 | 1 + 0 | 0 | -16369 | 1 + 0 | 0 | -16368 | 1 + 0 | 0 | -16367 | 1 (10 rows) select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -215,27 +282,27 @@ select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup group by t, s, s 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 (10 rows) +select x, count(*) from agggroup group by x order by count(*), x limit 10; + x | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select count(cint2) from agggroup; count -------- 199810 (1 row) -select s, count(cint2) from agggroup group by s order by count(cint2), s limit 10; - s | count ----+------- - 0 | 19981 - 1 | 19981 - 2 | 19981 - 3 | 19981 - 4 | 19981 - 5 | 19981 - 6 | 19981 - 7 | 19981 - 8 | 19981 - 9 | 19981 -(10 rows) - select cint2, count(cint2) from agggroup group by cint2 order by count(cint2), cint2 limit 10; cint2 | count --------+------- @@ -266,6 +333,21 @@ select cint4, count(cint2) from agggroup group by cint4 order by count(cint2), c -15804 | 1 (10 rows) +select cint4, cint8, count(cint2) from agggroup group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), cint8 limit 10; cint8 | count --------+------- @@ -281,34 +363,94 @@ select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), c -15753 | 1 (10 rows) -select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; - x | count -----+------- - | 19 - 3 | 19962 - 4 | 19962 - 0 | 19981 - 5 | 19981 - 6 | 19981 - 7 | 19981 - 8 | 19981 - 9 | 19981 - 11 | 39981 +select s, cint2, count(cint2) from agggroup group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select s, x, count(cint2) from agggroup group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 + 0 | -16377 | 0 | 1 +(10 rows) + +select ss, s, count(cint2) from agggroup group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 + 8 | 8 | 19981 + 9 | 9 | 19981 (10 rows) -select ss, x, count(cint2) from agggroup group by ss, x order by count(cint2), ss, x limit 10; - ss | x | count -----+----+------- - | | 19 - 3 | 3 | 19962 - 4 | 4 | 19962 - 0 | 0 | 19981 - 5 | 5 | 19981 - 6 | 6 | 19981 - 7 | 7 | 19981 - 8 | 8 | 19981 - 9 | 9 | 19981 - 11 | 11 | 39981 +select ss, x, cint2, count(cint2) from agggroup group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+--------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 + 0 | 0 | -16377 | 1 (10 rows) select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -326,27 +468,27 @@ select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup group by t, 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 (10 rows) +select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; + x | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + select min(cint2) from agggroup; min -------- -16383 (1 row) -select s, min(cint2) from agggroup group by s order by min(cint2), s limit 10; - s | min ----+-------- - 0 | -16383 - 4 | -16383 - 5 | -16383 - 6 | -16383 - 2 | -16382 - 7 | -16382 - 8 | -16382 - 3 | -16381 - 1 | -16378 - 9 | -16375 -(10 rows) - select cint2, min(cint2) from agggroup group by cint2 order by min(cint2), cint2 limit 10; cint2 | min --------+-------- @@ -377,6 +519,21 @@ select cint4, min(cint2) from agggroup group by cint4 order by min(cint2), cint4 2223 | -16382 (10 rows) +select cint4, cint8, min(cint2) from agggroup group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+-------- + -16190 | 13646 | -16383 + -13372 | 11094 | -16383 + -10318 | 6326 | -16383 + -9008 | 4390 | -16383 + -3043 | -1794 | -16383 + 6729 | 6717 | -16383 + -14012 | -9888 | -16382 + -8606 | -10357 | -16382 + -3080 | -15609 | -16382 + 2223 | 9035 | -16382 +(10 rows) + select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 limit 10; cint8 | min --------+-------- @@ -392,34 +549,94 @@ select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 206 | -16382 (10 rows) -select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; - x | min -----+-------- - 0 | -16383 - 4 | -16383 - 5 | -16383 - 6 | -16383 - 11 | -16382 - 7 | -16382 - 8 | -16382 - 3 | -16381 - 9 | -16375 - | -16100 +select s, cint2, min(cint2) from agggroup group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+--------+-------- + 0 | -16383 | -16383 + 4 | -16383 | -16383 + 5 | -16383 | -16383 + 6 | -16383 | -16383 + 2 | -16382 | -16382 + 7 | -16382 | -16382 + 8 | -16382 | -16382 + 2 | -16381 | -16381 + 3 | -16381 | -16381 + 4 | -16381 | -16381 +(10 rows) + +select s, ss, min(cint2) from agggroup group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select s, x, min(cint2) from agggroup group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+--------+----+-------- + 0 | -16383 | 0 | -16383 + 4 | -16383 | 4 | -16383 + 5 | -16383 | 5 | -16383 + 6 | -16383 | 6 | -16383 + 7 | -16382 | 7 | -16382 + 8 | -16382 | 8 | -16382 + 11 | -16382 | 11 | -16382 + 3 | -16381 | 3 | -16381 + 4 | -16381 | 4 | -16381 + 5 | -16381 | 5 | -16381 (10 rows) -select ss, x, min(cint2) from agggroup group by ss, x order by min(cint2), ss, x limit 10; - ss | x | min -----+----+-------- - 0 | 0 | -16383 - 4 | 4 | -16383 - 5 | 5 | -16383 - 6 | 6 | -16383 - 7 | 7 | -16382 - 8 | 8 | -16382 - 11 | 11 | -16382 - 3 | 3 | -16381 - 9 | 9 | -16375 - | | -16100 +select ss, s, min(cint2) from agggroup group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 7 | 7 | -16382 + 8 | 8 | -16382 + 11 | 2 | -16382 + 3 | 3 | -16381 + 11 | 1 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+--------+-------- + 0 | 0 | -16383 | -16383 + 4 | 4 | -16383 | -16383 + 5 | 5 | -16383 | -16383 + 6 | 6 | -16383 | -16383 + 7 | 7 | -16382 | -16382 + 8 | 8 | -16382 | -16382 + 11 | 11 | -16382 | -16382 + 3 | 3 | -16381 | -16381 + 4 | 4 | -16381 | -16381 + 5 | 5 | -16381 | -16381 (10 rows) select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -437,27 +654,27 @@ select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup group by t, s, 76781 | 7 | 7 | 7 | -16382 | 9938 | 6519 | -16382 (10 rows) +select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; + x | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 11 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + select count(*) from agggroup where cint2 > 0; count ------- 99664 (1 row) -select s, count(*) from agggroup where cint2 > 0 group by s order by count(*), s limit 10; - s | count ----+------- - 2 | 9868 - 6 | 9890 - 3 | 9893 - 8 | 9898 - 4 | 9906 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 1 | 10096 - 5 | 10110 -(10 rows) - select cint2, count(*) from agggroup where cint2 > 0 group by cint2 order by count(*), cint2 limit 10; cint2 | count -------+------- @@ -488,6 +705,21 @@ select cint4, count(*) from agggroup where cint2 > 0 group by cint4 order by cou -16350 | 1 (10 rows) +select cint4, cint8, count(*) from agggroup where cint2 > 0 group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by count(*), cint8 limit 10; cint8 | count --------+------- @@ -503,34 +735,94 @@ select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by cou -16328 | 1 (10 rows) -select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; - x | count -----+------- - | 7 - 3 | 9886 - 6 | 9890 - 4 | 9897 - 8 | 9898 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 5 | 10110 - 11 | 19973 +select s, cint2, count(*) from agggroup where cint2 > 0 group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 7 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(*) from agggroup where cint2 > 0 group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 7 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 > 0 group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup where cint2 > 0 group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + | 3 | 7 + 11 | 4 | 9 + 11 | 2 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 (10 rows) -select ss, x, count(*) from agggroup where cint2 > 0 group by ss, x order by count(*), ss, x limit 10; - ss | x | count -----+----+------- - | | 7 - 3 | 3 | 9886 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 - 5 | 5 | 10110 - 11 | 11 | 19973 +select ss, x, cint2, count(*) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 (10 rows) select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -548,27 +840,27 @@ select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 (10 rows) +select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; + x | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + select count(cint2) from agggroup where cint2 > 0; count ------- 99664 (1 row) -select s, count(cint2) from agggroup where cint2 > 0 group by s order by count(cint2), s limit 10; - s | count ----+------- - 2 | 9868 - 6 | 9890 - 3 | 9893 - 8 | 9898 - 4 | 9906 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 1 | 10096 - 5 | 10110 -(10 rows) - select cint2, count(cint2) from agggroup where cint2 > 0 group by cint2 order by count(cint2), cint2 limit 10; cint2 | count -------+------- @@ -599,6 +891,21 @@ select cint4, count(cint2) from agggroup where cint2 > 0 group by cint4 order by -16350 | 1 (10 rows) +select cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by count(cint2), cint8 limit 10; cint8 | count --------+------- @@ -614,34 +921,94 @@ select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by -16328 | 1 (10 rows) -select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; - x | count -----+------- - | 7 - 3 | 9886 - 6 | 9890 - 4 | 9897 - 8 | 9898 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 5 | 10110 - 11 | 19973 +select s, cint2, count(cint2) from agggroup where cint2 > 0 group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 7 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 > 0 group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 7 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 (10 rows) -select ss, x, count(cint2) from agggroup where cint2 > 0 group by ss, x order by count(cint2), ss, x limit 10; - ss | x | count -----+----+------- - | | 7 - 3 | 3 | 9886 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 - 5 | 5 | 10110 - 11 | 11 | 19973 +select ss, s, count(cint2) from agggroup where cint2 > 0 group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + | 3 | 7 + 11 | 4 | 9 + 11 | 2 | 9868 + 3 | 3 | 9886 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 (10 rows) select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -659,27 +1026,27 @@ select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 (10 rows) +select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; + x | count +----+------- + | 7 + 3 | 9886 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + select min(cint2) from agggroup where cint2 > 0; min ----- 1 (1 row) -select s, min(cint2) from agggroup where cint2 > 0 group by s order by min(cint2), s limit 10; - s | min ----+----- - 1 | 1 - 2 | 1 - 3 | 1 - 5 | 1 - 7 | 1 - 8 | 1 - 9 | 2 - 6 | 3 - 0 | 4 - 4 | 4 -(10 rows) - select cint2, min(cint2) from agggroup where cint2 > 0 group by cint2 order by min(cint2), cint2 limit 10; cint2 | min -------+----- @@ -710,6 +1077,21 @@ select cint4, min(cint2) from agggroup where cint2 > 0 group by cint4 order by m -11410 | 2 (10 rows) +select cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -12025 | -2210 | 1 + -10344 | -13684 | 1 + -4190 | -2827 | 1 + -1493 | -1043 | 1 + 1863 | 7650 | 1 + 9242 | -9798 | 1 + 11189 | -5168 | 1 + 14078 | 9929 | 1 + 15656 | 12597 | 1 + -11410 | 6033 | 2 +(10 rows) + select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by min(cint2), cint8 limit 10; cint8 | min --------+----- @@ -725,34 +1107,94 @@ select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by m -13639 | 2 (10 rows) -select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; - x | min -----+------ - 11 | 1 - 3 | 1 - 5 | 1 - 7 | 1 - 8 | 1 - 9 | 2 - 6 | 3 - 0 | 4 - 4 | 4 - | 3667 +select s, cint2, min(cint2) from agggroup where cint2 > 0 group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 1 | 1 | 1 + 2 | 1 | 1 + 3 | 1 | 1 + 5 | 1 | 1 + 7 | 1 | 1 + 8 | 1 | 1 + 1 | 2 | 2 + 3 | 2 | 2 + 7 | 2 | 2 + 9 | 2 | 2 +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 > 0 group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 (10 rows) -select ss, x, min(cint2) from agggroup where cint2 > 0 group by ss, x order by min(cint2), ss, x limit 10; - ss | x | min -----+----+------ - 3 | 3 | 1 - 5 | 5 | 1 - 7 | 7 | 1 - 8 | 8 | 1 - 11 | 11 | 1 - 9 | 9 | 2 - 6 | 6 | 3 - 0 | 0 | 4 - 4 | 4 | 4 - | | 3667 +select s, x, min(cint2) from agggroup where cint2 > 0 group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 3 | 1 | 3 | 1 + 5 | 1 | 5 | 1 + 7 | 1 | 7 | 1 + 8 | 1 | 8 | 1 + 11 | 1 | 11 | 1 + 3 | 2 | 3 | 2 + 7 | 2 | 7 | 2 + 9 | 2 | 9 | 2 + 11 | 2 | 11 | 2 + 3 | 3 | 3 | 3 +(10 rows) + +select ss, s, min(cint2) from agggroup where cint2 > 0 group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 11 | 1 | 1 + 11 | 2 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 3 | 3 | 1 | 1 + 5 | 5 | 1 | 1 + 7 | 7 | 1 | 1 + 8 | 8 | 1 | 1 + 11 | 11 | 1 | 1 + 3 | 3 | 2 | 2 + 7 | 7 | 2 | 2 + 9 | 9 | 2 | 2 + 11 | 11 | 2 | 2 + 3 | 3 | 3 | 3 (10 rows) select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; @@ -770,4 +1212,739 @@ select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 > 22147 | 1 | 11 | 11 | 2 | -9569 | 9760 | 2 (10 rows) +select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; + x | min +----+------ + 11 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 3667 +(10 rows) + +select count(*) from agggroup where cint2 is null; + count +------- + 190 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + | 190 +(1 row) + +select cint4, count(*) from agggroup where cint2 is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 1 + -16091 | 1 + -15799 | 1 + -15724 | 1 + -15328 | 1 + -15279 | 1 + -15063 | 1 + -14998 | 1 + -14949 | 1 + -14848 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 1 + -16091 | -4084 | 1 + -15799 | 12603 | 1 + -15724 | 15426 | 1 + -15328 | -6092 | 1 + -15279 | -3475 | 1 + -15063 | 3990 | 1 + -14998 | 14464 | 1 + -14949 | -10395 | 1 + -14848 | 3110 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 1 + -15987 | 1 + -15904 | 1 + -15897 | 1 + -15761 | 1 + -15506 | 1 + -15346 | 1 + -14986 | 1 + -14811 | 1 + -14674 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup where cint2 is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 19 + 1 | | 19 + 2 | | 19 + 3 | | 19 + 4 | | 19 + 5 | | 19 + 6 | | 19 + 7 | | 19 + 8 | | 19 + 9 | | 19 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select s, x, count(*) from agggroup where cint2 is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 19 + 3 | | 3 | 19 + 4 | | 4 | 19 + 5 | | 5 | 19 + 6 | | 6 | 19 + 7 | | 7 | 19 + 8 | | 8 | 19 + 9 | | 9 | 19 + 11 | | 11 | 38 +(9 rows) + +select ss, s, count(*) from agggroup where cint2 is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 + 11 | 1 | 19 + 11 | 2 | 19 +(10 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 19 + 3 | 3 | | 19 + 4 | 4 | | 19 + 5 | 5 | | 19 + 6 | 6 | | 19 + 7 | 7 | | 19 + 8 | 8 | | 19 + 9 | 9 | | 19 + 11 | 11 | | 38 +(9 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +-------+---+----+---+-------+--------+--------+------- + 1051 | 0 | 0 | 0 | | -8612 | 14327 | 1 + 2102 | 0 | 0 | 0 | | 11069 | 16047 | 1 + 3153 | 0 | 0 | 0 | | 6192 | 12700 | 1 + 4204 | 0 | 0 | 0 | | 4165 | -10102 | 1 + 5255 | 0 | 0 | 0 | | 16314 | 13418 | 1 + 6306 | 0 | 0 | 0 | | 701 | -3029 | 1 + 7357 | 0 | 0 | 0 | | 1115 | 4913 | 1 + 8408 | 0 | 0 | 0 | | 15553 | 1743 | 1 + 9459 | 0 | 0 | 0 | | -14640 | 11933 | 1 + 10510 | 0 | 0 | 0 | | -14725 | 6531 | 1 +(10 rows) + +select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; + x | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select count(cint2) from agggroup where cint2 is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + | 0 +(1 row) + +select cint4, count(cint2) from agggroup where cint2 is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 0 + -16091 | 0 + -15799 | 0 + -15724 | 0 + -15328 | 0 + -15279 | 0 + -15063 | 0 + -14998 | 0 + -14949 | 0 + -14848 | 0 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 0 + -15987 | 0 + -15904 | 0 + -15897 | 0 + -15761 | 0 + -15506 | 0 + -15346 | 0 + -14986 | 0 + -14811 | 0 + -14674 | 0 +(10 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 +(9 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 + 11 | 1 | 0 + 11 | 2 | 0 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 +(9 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +-------+---+----+---+-------+--------+--------+------- + 1051 | 0 | 0 | 0 | | -8612 | 14327 | 0 + 2102 | 0 | 0 | 0 | | 11069 | 16047 | 0 + 3153 | 0 | 0 | 0 | | 6192 | 12700 | 0 + 4204 | 0 | 0 | 0 | | 4165 | -10102 | 0 + 5255 | 0 | 0 | 0 | | 16314 | 13418 | 0 + 6306 | 0 | 0 | 0 | | 701 | -3029 | 0 + 7357 | 0 | 0 | 0 | | 1115 | 4913 | 0 + 8408 | 0 | 0 | 0 | | 15553 | 1743 | 0 + 9459 | 0 | 0 | 0 | | -14640 | 11933 | 0 + 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 +(10 rows) + +select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; + x | count +----+------- + 0 | 0 + 11 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(9 rows) + +select min(cint2) from agggroup where cint2 is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + | +(1 row) + +select cint4, min(cint2) from agggroup where cint2 is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -16291 | + -16091 | + -15799 | + -15724 | + -15328 | + -15279 | + -15063 | + -14998 | + -14949 | + -14848 | +(10 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -16291 | 113 | + -16091 | -4084 | + -15799 | 12603 | + -15724 | 15426 | + -15328 | -6092 | + -15279 | -3475 | + -15063 | 3990 | + -14998 | 14464 | + -14949 | -10395 | + -14848 | 3110 | +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -16026 | + -15987 | + -15904 | + -15897 | + -15761 | + -15506 | + -15346 | + -14986 | + -14811 | + -14674 | +(10 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 0 | | + 1 | | + 2 | | + 3 | | + 4 | | + 5 | | + 6 | | + 7 | | + 8 | | + 9 | | +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select s, x, min(cint2) from agggroup where cint2 is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 0 | | 0 | + 3 | | 3 | + 4 | | 4 | + 5 | | 5 | + 6 | | 6 | + 7 | | 7 | + 8 | | 8 | + 9 | | 9 | + 11 | | 11 | +(9 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 0 | 0 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 11 | 1 | + 11 | 2 | +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 0 | 0 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | | + 7 | 7 | | + 8 | 8 | | + 9 | 9 | | + 11 | 11 | | +(9 rows) + +select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | min +-------+---+----+---+-------+--------+--------+----- + 1051 | 0 | 0 | 0 | | -8612 | 14327 | + 2102 | 0 | 0 | 0 | | 11069 | 16047 | + 3153 | 0 | 0 | 0 | | 6192 | 12700 | + 4204 | 0 | 0 | 0 | | 4165 | -10102 | + 5255 | 0 | 0 | 0 | | 16314 | 13418 | + 6306 | 0 | 0 | 0 | | 701 | -3029 | + 7357 | 0 | 0 | 0 | | 1115 | 4913 | + 8408 | 0 | 0 | 0 | | 15553 | 1743 | + 9459 | 0 | 0 | 0 | | -14640 | 11933 | + 10510 | 0 | 0 | 0 | | -14725 | 6531 | +(10 rows) + +select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; + x | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select count(*) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null and x is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(*) from agggroup where cint2 is null and x is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(*) from agggroup where cint2 is null and x is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(*) from agggroup where cint2 is null and x is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(*) from agggroup where cint2 is null and x is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(*) from agggroup where cint2 is null and x is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(*) from agggroup where cint2 is null and x is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(*) from agggroup where cint2 is null and x is null group by x order by count(*), x limit 10; + x | count +---+------- +(0 rows) + +select count(cint2) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null and x is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(cint2) from agggroup where cint2 is null and x is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null and x is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(cint2) from agggroup where cint2 is null and x is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null and x is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(cint2) from agggroup where cint2 is null and x is null group by x order by count(cint2), x limit 10; + x | count +---+------- +(0 rows) + +select min(cint2) from agggroup where cint2 is null and x is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null and x is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- +(0 rows) + +select cint4, min(cint2) from agggroup where cint2 is null and x is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +-------+----- +(0 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +-------+-------+----- +(0 rows) + +select cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +-------+----- +(0 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- +(0 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null and x is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- +(0 rows) + +select s, x, min(cint2) from agggroup where cint2 is null and x is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+---+----- +(0 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+---+----- +(0 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null and x is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- +(0 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+---+-------+----- +(0 rows) + +select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; + t | s | ss | x | cint2 | cint4 | cint8 | min +---+---+----+---+-------+-------+-------+----- +(0 rows) + +select x, min(cint2) from agggroup where cint2 is null and x is null group by x order by min(cint2), x limit 10; + x | min +---+----- +(0 rows) + reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index 1a5d0caa476..6b79a3e4adb 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -85,16 +85,23 @@ from 'count']) function, unnest(array[ null, - 'cint2 > 0']) with ordinality as condition(condition, n), + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's', 'cint2', 'cint4', + 'cint4, cint8', 'cint8', - 'x', - 'ss, x', - 't, s, ss, x, cint2, cint4, cint8']) with ordinality as grouping(grouping, n) + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint2, cint4, cint8', + 'x']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) From 75b85130dce23f56e44acd429573e07f87b47891 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 11:26:57 +0100 Subject: [PATCH 098/242] stuff --- tsl/src/nodes/vector_agg/grouping_policy_hash.h | 2 +- tsl/src/nodes/vector_agg/hash_table_functions_impl.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index cf47b530850..204a508765b 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -236,7 +236,7 @@ typedef struct HashingConfig uint32 *restrict result_key_indexes; } HashingConfig; -static inline HashingConfig +static pg_attribute_always_inline HashingConfig build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { HashingConfig config = { diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index ffa5f26c2d3..1bc08a1f379 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -30,6 +30,7 @@ typedef struct uint32 key_index; } FUNCTION_NAME(entry); +#define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) #define SH_KEY_TYPE CTYPE @@ -154,15 +155,15 @@ FUNCTION_NAME(fill_offsets_impl)( * when all the batch and key rows are valid. */ #define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME, (COND) && (config.batch_filter == NULL)) \ + X(NAME##_nofilter, (COND) && (config.batch_filter == NULL)) \ X(NAME##_filter, (COND) && (config.batch_filter != NULL)) #define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && config.single_key.buffers[0] == NULL) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && config.single_key.buffers[0] == NULL) \ APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && config.single_key.buffers[0] != NULL) #define APPLY_FOR_SCALARS(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME, (COND) && !config.have_scalar_columns) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_noscalar, (COND) && !config.have_scalar_columns) \ APPLY_FOR_BATCH_FILTER(X, NAME##_scalar, (COND) && config.have_scalar_columns) #define APPLY_FOR_TYPE(X, NAME, COND) \ From 4dfa5c7d760a3e8b065ed8395c1d63867a0f17e9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:41:16 +0100 Subject: [PATCH 099/242] Fix variable resolution in vectorized aggregation planning We didn't properly resolve INDEX_VARs in the output targetlist of DecompressChunk nodes, which are present when it uses a custom scan targetlist. Fix this by always working with the targetlist where these variables are resolved to uncompressed chunk variables, like we do during execution. --- tsl/src/nodes/vector_agg/exec.c | 17 +++-- tsl/src/nodes/vector_agg/plan.c | 112 +++++++++++++++++++------------- 2 files changed, 76 insertions(+), 53 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 7e8e59de1cd..230ed3c8ffe 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -25,16 +25,19 @@ get_input_offset(DecompressChunkState *decompress_state, Var *var) { DecompressContext *dcontext = &decompress_state->decompress_context; + /* + * All variable references in the tectorized aggregation node were + * translated to uncompressed chunk variables when it was created. + */ + CustomScan *cscan = castNode(CustomScan, decompress_state->csstate.ss.ps.plan); + Ensure((Index) var->varno == (Index) cscan->scan.scanrelid, + "got vector varno %d expected %d", + var->varno, + cscan->scan.scanrelid); + CompressionColumnDescription *value_column_description = NULL; for (int i = 0; i < dcontext->num_data_columns; i++) { - /* - * See the column lookup in compute_plain_qual() for the discussion of - * which attribute numbers occur where. At the moment here it is - * uncompressed_scan_attno, but it might be an oversight of not rewriting - * the references into INDEX_VAR (or OUTER_VAR...?) when we create the - * VectorAgg node. - */ CompressionColumnDescription *current_column = &dcontext->compressed_chunk_columns[i]; if (current_column->uncompressed_chunk_attno == var->varattno) { diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index ac150b7ea99..47eb1258b33 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -115,11 +115,13 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) * node. */ static Plan * -vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) +vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_targetlist) { - CustomScan *custom = (CustomScan *) makeNode(CustomScan); - custom->custom_plans = list_make1(decompress_chunk); - custom->methods = &scan_methods; + CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); + vector_agg->custom_plans = list_make1(decompress_chunk); + vector_agg->methods = &scan_methods; + + vector_agg->custom_scan_tlist = resolved_targetlist; /* * Note that this is being called from the post-planning hook, and therefore @@ -127,32 +129,31 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) * the previous planning stages, and they contain special varnos referencing * the scan targetlists. */ - custom->custom_scan_tlist = resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); - custom->scan.plan.targetlist = - build_trivial_custom_output_targetlist(custom->custom_scan_tlist); + vector_agg->scan.plan.targetlist = + build_trivial_custom_output_targetlist(vector_agg->custom_scan_tlist); /* * Copy the costs from the normal aggregation node, so that they show up in * the EXPLAIN output. They are not used for any other purposes, because * this hook is called after the planning is finished. */ - custom->scan.plan.plan_rows = agg->plan.plan_rows; - custom->scan.plan.plan_width = agg->plan.plan_width; - custom->scan.plan.startup_cost = agg->plan.startup_cost; - custom->scan.plan.total_cost = agg->plan.total_cost; + vector_agg->scan.plan.plan_rows = agg->plan.plan_rows; + vector_agg->scan.plan.plan_width = agg->plan.plan_width; + vector_agg->scan.plan.startup_cost = agg->plan.startup_cost; + vector_agg->scan.plan.total_cost = agg->plan.total_cost; - custom->scan.plan.parallel_aware = false; - custom->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; - custom->scan.plan.async_capable = false; + vector_agg->scan.plan.parallel_aware = false; + vector_agg->scan.plan.parallel_safe = decompress_chunk->scan.plan.parallel_safe; + vector_agg->scan.plan.async_capable = false; - custom->scan.plan.plan_node_id = agg->plan.plan_node_id; + vector_agg->scan.plan.plan_node_id = agg->plan.plan_node_id; Assert(agg->plan.qual == NIL); - custom->scan.plan.initPlan = agg->plan.initPlan; + vector_agg->scan.plan.initPlan = agg->plan.initPlan; - custom->scan.plan.extParam = bms_copy(agg->plan.extParam); - custom->scan.plan.allParam = bms_copy(agg->plan.allParam); + vector_agg->scan.plan.extParam = bms_copy(agg->plan.extParam); + vector_agg->scan.plan.allParam = bms_copy(agg->plan.allParam); List *grouping_col_offsets = NIL; for (int i = 0; i < agg->numCols; i++) @@ -160,9 +161,9 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) grouping_col_offsets = lappend_int(grouping_col_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); } - custom->custom_private = list_make1(grouping_col_offsets); + vector_agg->custom_private = list_make1(grouping_col_offsets); - return (Plan *) custom; + return (Plan *) vector_agg; } /* @@ -178,44 +179,54 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) return false; } - Var *aggregated_var = castNode(Var, expr); + Var *decompressed_var = castNode(Var, expr); /* - * Check if this particular column is a segmentby or has bulk decompression - * enabled. This hook is called after set_plan_refs, and at this stage the - * output targetlist of the aggregation node uses OUTER_VAR references into - * the child scan targetlist, so first we have to translate this. + * This must be called after resolve_outer_special_vars(), so we should only + * see the uncompressed chunk variables here. */ - Assert(aggregated_var->varno == OUTER_VAR); - TargetEntry *decompressed_target_entry = - list_nth(custom->scan.plan.targetlist, AttrNumberGetAttrOffset(aggregated_var->varattno)); - - if (!IsA(decompressed_target_entry->expr, Var)) - { - /* - * Can only aggregate the plain Vars. Not sure if this is redundant with - * the similar check above. - */ - return false; - } - Var *decompressed_var = castNode(Var, decompressed_target_entry->expr); + Ensure((Index) decompressed_var->varno == (Index) custom->scan.scanrelid, + "expected scan varno %d got %d", + custom->scan.scanrelid, + decompressed_var->varno); /* * Now, we have to translate the decompressed varno into the compressed * column index, to check if the column supports bulk decompression. */ List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); - List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); - List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); int compressed_column_index = 0; for (; compressed_column_index < list_length(decompression_map); compressed_column_index++) { - if (list_nth_int(decompression_map, compressed_column_index) == decompressed_var->varattno) + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + int uncompressed_chunk_attno = 0; + if (custom->custom_scan_tlist == NIL) + { + uncompressed_chunk_attno = custom_scan_attno; + } + else + { + Var *var = castNode(Var, + castNode(TargetEntry, + list_nth(custom->custom_scan_tlist, + AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + uncompressed_chunk_attno = var->varattno; + } + + if (uncompressed_chunk_attno == decompressed_var->varattno) { break; } } Ensure(compressed_column_index < list_length(decompression_map), "compressed column not found"); + + List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); Assert(list_length(decompression_map) == list_length(bulk_decompression_column)); const bool bulk_decompression_enabled_for_column = list_nth_int(bulk_decompression_column, compressed_column_index); @@ -232,6 +243,8 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) /* * Check if this column is a segmentby. */ + List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); + Assert(list_length(is_segmentby_column) == list_length(decompression_map)); const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); if (out_is_segmentby) { @@ -316,7 +329,7 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) * Currently supports either no grouping or grouping by segmentby columns. */ static bool -can_vectorize_grouping(Agg *agg, CustomScan *custom) +can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) { if (agg->numCols == 0) { @@ -326,7 +339,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + TargetEntry *entry = list_nth(resolved_targetlist, offset); bool is_segmentby = false; if (!is_vector_var(custom, entry->expr, &is_segmentby)) @@ -508,7 +521,14 @@ try_insert_vector_agg_node(Plan *plan) return plan; } - if (!can_vectorize_grouping(agg, custom)) + /* + * To make it easier to examine the variables participating in the aggregation, + * the subsequent checks are performed on the aggregated targetlist with + * all variables resolved to uncompressed chunk variables. + */ + List *resolved_targetlist = resolve_outer_special_vars(agg->plan.targetlist, custom); + + if (!can_vectorize_grouping(agg, custom, resolved_targetlist)) { /* No GROUP BY support for now. */ return plan; @@ -516,7 +536,7 @@ try_insert_vector_agg_node(Plan *plan) /* Now check the aggregate functions themselves. */ ListCell *lc; - foreach (lc, agg->plan.targetlist) + foreach (lc, resolved_targetlist) { TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); if (!IsA(target_entry->expr, Aggref)) @@ -535,5 +555,5 @@ try_insert_vector_agg_node(Plan *plan) * Finally, all requirements are satisfied and we can vectorize this partial * aggregation node. */ - return vector_agg_plan_create(agg, custom); + return vector_agg_plan_create(agg, custom, resolved_targetlist); } From bc30ab8fb4fee0522ce5940a59a16689170f8596 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:49:59 +0100 Subject: [PATCH 100/242] changelog --- .unreleased/resolve-vars | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .unreleased/resolve-vars diff --git a/.unreleased/resolve-vars b/.unreleased/resolve-vars new file mode 100644 index 00000000000..51f42a33713 --- /dev/null +++ b/.unreleased/resolve-vars @@ -0,0 +1,2 @@ +Fixes: #7410 "aggregated compressed column not found" error on aggregation query. +Thanks: @uasiddiqi for reporting the "aggregated compressed column not found" error. From 69ed75df7e7ebd7faf7dc348ea604f6a70f52c7c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 13:51:16 +0100 Subject: [PATCH 101/242] typo --- tsl/src/nodes/vector_agg/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 230ed3c8ffe..f5019a23eb0 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -26,7 +26,7 @@ get_input_offset(DecompressChunkState *decompress_state, Var *var) DecompressContext *dcontext = &decompress_state->decompress_context; /* - * All variable references in the tectorized aggregation node were + * All variable references in the vectorized aggregation node were * translated to uncompressed chunk variables when it was created. */ CustomScan *cscan = castNode(CustomScan, decompress_state->csstate.ss.ps.plan); From da0e3de0cda2b5e0229e04ad14e770efc377be0e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:14:05 +0100 Subject: [PATCH 102/242] fix --- tsl/src/nodes/vector_agg/plan.c | 48 +++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 47eb1258b33..f9b1d5527a6 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -74,29 +74,43 @@ resolve_outer_special_vars_mutator(Node *node, void *context) return expression_tree_mutator(node, resolve_outer_special_vars_mutator, context); } - Var *aggregated_var = castNode(Var, node); - Ensure(aggregated_var->varno == OUTER_VAR, - "encountered unexpected varno %d as an aggregate argument", - aggregated_var->varno); - + Var *var = castNode(Var, node); CustomScan *custom = castNode(CustomScan, context); - TargetEntry *decompress_chunk_tentry = - castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, aggregated_var->varattno - 1)); - Var *decompressed_var = castNode(Var, decompress_chunk_tentry->expr); - if (decompressed_var->varno == INDEX_VAR) + if ((Index) var->varno == (Index) custom->scan.scanrelid) + { + /* + * This is already the ucompressed chunk var. We can see it referenced + * by expressions in the output targetlist of DecompressChunk node. + */ + return (Node *) var; + } + + if (var->varno == OUTER_VAR) + { + /* + * Reference into the output targetlist of the DecompressChunk node. + */ + TargetEntry *decompress_chunk_tentry = + castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, var->varattno - 1)); + + return resolve_outer_special_vars_mutator((Node *) decompress_chunk_tentry->expr, context); + } + + if (var->varno == INDEX_VAR) { /* * This is a reference into the custom scan targetlist, we have to resolve * it as well. */ - decompressed_var = - castNode(Var, - castNode(TargetEntry, - list_nth(custom->custom_scan_tlist, decompressed_var->varattno - 1)) - ->expr); - } - Assert(decompressed_var->varno > 0); - return (Node *) copyObject(decompressed_var); + var = castNode(Var, + castNode(TargetEntry, list_nth(custom->custom_scan_tlist, var->varattno - 1)) + ->expr); + Assert(var->varno > 0); + + return (Node *) copyObject(var); + } + + Ensure(false, "encountered unexpected varno %d as an aggregate argument", var->varno); } /* From eecd1ddfb56c49c02636a9508846ebf193a2e517 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:21:47 +0100 Subject: [PATCH 103/242] silence the warning --- tsl/src/nodes/vector_agg/plan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index f9b1d5527a6..fcd9c3840c1 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -111,6 +111,7 @@ resolve_outer_special_vars_mutator(Node *node, void *context) } Ensure(false, "encountered unexpected varno %d as an aggregate argument", var->varno); + return node; } /* From edaa7cb05b1ea510bda100ddb7f49f6141816ee7 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 6 Nov 2024 10:53:23 +0100 Subject: [PATCH 104/242] test --- tsl/test/expected/vector_agg_param.out | 108 ++++++++++++++++++++++--- tsl/test/sql/vector_agg_param.sql | 12 ++- 2 files changed, 107 insertions(+), 13 deletions(-) diff --git a/tsl/test/expected/vector_agg_param.out b/tsl/test/expected/vector_agg_param.out index b481d9c8a97..6835cc971e3 100644 --- a/tsl/test/expected/vector_agg_param.out +++ b/tsl/test/expected/vector_agg_param.out @@ -21,23 +21,36 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; (1 row) analyze pvagg; -explain (costs off) +explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop - -> Function Scan on unnest x + Output: x.x, (sum(pvagg.a)) + -> Function Scan on pg_catalog.unnest x + Output: x.x + Function Call: unnest('{0,1,2}'::integer[]) -> Finalize Aggregate - -> Custom Scan (ChunkAppend) on pvagg + Output: sum(pvagg.a) + -> Custom Scan (ChunkAppend) on public.pvagg + Output: (PARTIAL sum(pvagg.a)) + Startup Exclusion: false + Runtime Exclusion: true -> Custom Scan (VectorAgg) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk - -> Seq Scan on compress_hyper_2_3_chunk - Filter: (s = x.x) + Output: (PARTIAL sum(_hyper_1_1_chunk.a)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk + Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a + Filter: (compress_hyper_2_3_chunk.s = x.x) -> Custom Scan (VectorAgg) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk - -> Seq Scan on compress_hyper_2_4_chunk - Filter: (s = x.x) -(12 rows) + Output: (PARTIAL sum(_hyper_1_2_chunk.a)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk + Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a + Filter: (compress_hyper_2_4_chunk.s = x.x) +(25 rows) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; x | sum @@ -47,4 +60,75 @@ select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg 2 | 1498500 (3 rows) +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: x.x, (sum((_hyper_1_1_chunk.a + x.x))) + -> Function Scan on pg_catalog.unnest x + Output: x.x + Function Call: unnest('{0,1,2}'::integer[]) + -> Finalize Aggregate + Output: sum((_hyper_1_1_chunk.a + x.x)) + -> Append + -> Partial Aggregate + Output: PARTIAL sum((_hyper_1_1_chunk.a + x.x)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk + Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a + -> Partial Aggregate + Output: PARTIAL sum((_hyper_1_2_chunk.a + x.x)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk + Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a +(20 rows) + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + x | sum +---+--------- + 0 | 1998000 + 1 | 1999998 + 2 | 2001996 +(3 rows) + +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: x.x, (sum(_hyper_1_1_chunk.a)) + -> Function Scan on pg_catalog.unnest x + Output: x.x + Function Call: unnest('{0,1,2}'::integer[]) + -> Finalize GroupAggregate + Output: sum(_hyper_1_1_chunk.a), (x.x) + Group Key: (x.x) + -> Append + -> Partial GroupAggregate + Output: (x.x), PARTIAL sum(_hyper_1_1_chunk.a) + Group Key: x.x + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: x.x, _hyper_1_1_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk + Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a + -> Partial GroupAggregate + Output: (x.x), PARTIAL sum(_hyper_1_2_chunk.a) + Group Key: x.x + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: x.x, _hyper_1_2_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk + Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a +(23 rows) + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + x | sum +---+--------- + 0 | 1998000 + 1 | 1998000 + 2 | 1998000 +(3 rows) + drop table pvagg; diff --git a/tsl/test/sql/vector_agg_param.sql b/tsl/test/sql/vector_agg_param.sql index 491a877556d..3c31b8ccf0a 100644 --- a/tsl/test/sql/vector_agg_param.sql +++ b/tsl/test/sql/vector_agg_param.sql @@ -19,10 +19,20 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; analyze pvagg; -explain (costs off) +explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + drop table pvagg; From a74833fdbdcf793e8091fabab66bddd35e40d7a0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:42:16 +0100 Subject: [PATCH 105/242] Update tsl/src/nodes/vector_agg/exec.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Nordström <819732+erimatnor@users.noreply.github.com> Signed-off-by: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> --- tsl/src/nodes/vector_agg/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 0ca647b6cba..0b4c0dce17c 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -86,7 +86,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) int grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { - TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + TargetEntry *tlentry = list_nth_node(TargetEntry, aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { agg_functions_counter++; From baa81b114bfbdfdbccf94bc620f3ece645da8453 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:59:09 +0100 Subject: [PATCH 106/242] review fixes --- tsl/src/nodes/vector_agg/exec.c | 2 +- tsl/src/nodes/vector_agg/function/functions.h | 5 ++++- tsl/src/nodes/vector_agg/function/int24_sum_single.c | 4 ++-- tsl/src/nodes/vector_agg/function/int24_sum_templates.c | 6 +++--- tsl/src/nodes/vector_agg/function/sum_float_single.c | 6 +++--- tsl/src/nodes/vector_agg/function/sum_float_templates.c | 4 ++-- tsl/src/nodes/vector_agg/grouping_policy_batch.c | 4 ++-- 7 files changed, 17 insertions(+), 14 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 0b4c0dce17c..1f198d799a9 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -119,7 +119,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { - TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + TargetEntry *tlentry = list_nth_node(TargetEntry, aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { /* This is an aggregate function. */ diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 2d150659276..397aaac89a1 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -16,7 +16,10 @@ typedef struct /* Size of the aggregate function state. */ size_t state_bytes; - /* Initialize the aggregate function states. */ + /* + * Initialize the n aggregate function states stored contiguously at the + * given pointer. + */ void (*agg_init)(void *restrict agg_states, int n); /* Aggregate a given arrow array. */ diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index 81b6e11c339..4b56ab7ec0b 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -48,7 +48,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); } - state->isnull &= !have_result; + state->isvalid |= have_result; } static pg_attribute_always_inline void @@ -56,7 +56,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) { Int24SumState *state = (Int24SumState *) agg_state; state->result += value; - state->isnull = false; + state->isvalid = true; } typedef Int24SumState FUNCTION_NAME(state); diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c index 8b250cc91cc..6dda8bed102 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c @@ -24,7 +24,7 @@ typedef struct { int64 result; - bool isnull; + bool isvalid; } Int24SumState; static void @@ -34,7 +34,7 @@ int_sum_init(void *restrict agg_states, int n) for (int i = 0; i < n; i++) { states[i].result = 0; - states[i].isnull = true; + states[i].isvalid = false; } } @@ -43,7 +43,7 @@ int_sum_emit(void *agg_state, Datum *out_result, bool *out_isnull) { Int24SumState *state = (Int24SumState *) agg_state; *out_result = Int64GetDatum(state->result); - *out_isnull = state->isnull; + *out_isnull = !state->isvalid; } #endif diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 3b0447e867d..c46a05ca6f6 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -17,7 +17,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) { FloatSumState *state = (FloatSumState *) agg_state; *out_result = CTYPE_TO_DATUM((CTYPE) state->result); - *out_isnull = state->isnull; + *out_isnull = !state->isvalid; } static pg_attribute_always_inline void @@ -76,7 +76,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #undef INNER_LOOP FloatSumState *state = (FloatSumState *) agg_state; - state->isnull &= !have_result_accu[0]; + state->isvalid |= have_result_accu[0]; state->result += sum_accu[0]; } @@ -86,7 +86,7 @@ static pg_attribute_always_inline void FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) { FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - state->isnull = false; + state->isvalid = true; state->result += value; } diff --git a/tsl/src/nodes/vector_agg/function/sum_float_templates.c b/tsl/src/nodes/vector_agg/function/sum_float_templates.c index f2b22523b34..0f41b5847be 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_templates.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_templates.c @@ -19,7 +19,7 @@ typedef struct { double result; - bool isnull; + bool isvalid; } FloatSumState; static void @@ -29,7 +29,7 @@ float_sum_init(void *restrict agg_states, int n) for (int i = 0; i < n; i++) { states[i].result = 0; - states[i].isnull = true; + states[i].isvalid = false; } } #endif diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 805aeeda487..61b904acd74 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -75,7 +75,7 @@ create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, int num_g for (int i = 0; i < policy->num_agg_defs; i++) { VectorAggDef *agg_def = &policy->agg_defs[i]; - policy->agg_states[i] = palloc0(agg_def->func.state_bytes); + policy->agg_states[i] = palloc(agg_def->func.state_bytes); } policy->output_grouping_values = @@ -173,7 +173,7 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc * The batches that are fully filtered out by vectorized quals should * have been skipped by the caller. */ - // Assert(n > 0); + Assert(n > 0); if (n > 0) { From 5927e1c59c5e017422e8434f251f658a4b50ab38 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:29:11 +0100 Subject: [PATCH 107/242] cleanup --- tsl/src/nodes/vector_agg/function/functions.h | 7 +++++++ tsl/src/nodes/vector_agg/grouping_policy_batch.c | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 397aaac89a1..cd05fe4ea5a 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -10,6 +10,13 @@ /* * Function table for a vectorized implementation of an aggregate function. + * + * One state of aggregate function corresponds to one set of rows that are + * supposed to be grouped together (e.g. for one grouping key). + * + * There are functions for adding a compressed batch to one aggregate function + * state (no grouping keys), and to multiple aggregate function states laid out + * contiguously in memory. */ typedef struct { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 61b904acd74..651f5904660 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -174,11 +174,7 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc * have been skipped by the caller. */ Assert(n > 0); - - if (n > 0) - { - agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); - } + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); } } From d11fec5b2c7fc06d832fb96e48bae517cd22acea Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:31:49 +0100 Subject: [PATCH 108/242] fix --- scripts/upload_ci_stats.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/upload_ci_stats.sh b/scripts/upload_ci_stats.sh index 086f7648cf3..c3b938ee392 100755 --- a/scripts/upload_ci_stats.sh +++ b/scripts/upload_ci_stats.sh @@ -94,8 +94,8 @@ then match($0, /^(test| ) ([^ ]+)[ ]+\.\.\.[ ]+([^ ]+) (|\(.*\))[ ]+([0-9]+) ms$/, a) { print ENVIRON["JOB_DATE"], a[2], tolower(a[3] (a[4] ? (" " a[4]) : "")), a[5]; } - match($0, /^([^0-9]+) [0-9]+ +- ([^ ]+) +([0-9]+) ms/, a) { - print ENVIRON["JOB_DATE"], a[2], a[1], a[3]; + match($0, /^([^0-9]+) [0-9]+ +[-+] ([^ ]+) +([0-9]+) ms/, a) { + print ENVIRON["JOB_DATE"], a[2], a[1], a[3]; } ' installcheck.log > tests.tsv From 9f479123d41f7162a1853ab2ae4dc1d44f40acc4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:32:16 +0100 Subject: [PATCH 109/242] fix --- scripts/upload_ci_stats.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/upload_ci_stats.sh b/scripts/upload_ci_stats.sh index 086f7648cf3..c3b938ee392 100755 --- a/scripts/upload_ci_stats.sh +++ b/scripts/upload_ci_stats.sh @@ -94,8 +94,8 @@ then match($0, /^(test| ) ([^ ]+)[ ]+\.\.\.[ ]+([^ ]+) (|\(.*\))[ ]+([0-9]+) ms$/, a) { print ENVIRON["JOB_DATE"], a[2], tolower(a[3] (a[4] ? (" " a[4]) : "")), a[5]; } - match($0, /^([^0-9]+) [0-9]+ +- ([^ ]+) +([0-9]+) ms/, a) { - print ENVIRON["JOB_DATE"], a[2], a[1], a[3]; + match($0, /^([^0-9]+) [0-9]+ +[-+] ([^ ]+) +([0-9]+) ms/, a) { + print ENVIRON["JOB_DATE"], a[2], a[1], a[3]; } ' installcheck.log > tests.tsv From 92c6fd369e1bced64816a44dd81beddc0182a455 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:44:03 +0100 Subject: [PATCH 110/242] Update tsl/src/nodes/vector_agg/plan.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Nordström <819732+erimatnor@users.noreply.github.com> Signed-off-by: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> --- tsl/src/nodes/vector_agg/plan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index fcd9c3840c1..07200d786e6 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -79,7 +79,7 @@ resolve_outer_special_vars_mutator(Node *node, void *context) if ((Index) var->varno == (Index) custom->scan.scanrelid) { /* - * This is already the ucompressed chunk var. We can see it referenced + * This is already the uncompressed chunk var. We can see it referenced * by expressions in the output targetlist of DecompressChunk node. */ return (Node *) var; From 893ecdd771ca14c9c422a7550a1e7c55df67d143 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:46:56 +0100 Subject: [PATCH 111/242] more tests --- tsl/test/expected/vector_agg_functions.out | 8393 +++++++------------- tsl/test/sql/vector_agg_functions.sql | 111 +- 2 files changed, 2802 insertions(+), 5702 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index b600fa6018b..4b2bd54bc0e 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -9,9 +9,9 @@ $$ LANGUAGE SQL; \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, - cfloat4 float4, cfloat8 float8, + cfloat4 float4, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); @@ -22,44 +22,98 @@ NOTICE: adding not-null constraint to column "s" (1,public,aggfns,t) (1 row) -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000 + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); select count(compress_chunk(x)) from show_chunks('aggfns') x; count +------- + 1 +(1 row) + +alter table aggfns add column ss int default 11; +alter table aggfns add column cfloat8 float8 default '13'; +alter table aggfns add column x text default '11'; +insert into aggfns +select *, ss::text as x from ( + select * + , case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + , (mix(s + t * 1039) * 100)::float8 as cfloat8 + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('aggfns') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze aggfns; +create table edges(t int, s int, ss int, f1 int); +select create_hypertable('edges', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +-------------------- + (3,public,edges,t) +(1 row) + +alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); +NOTICE: default order by for hypertable "edges" is set to "t DESC" +insert into edges select + s * 10000 + f1 as t, + s, + s, + f1 +from generate_series(0, 12) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 +; +select count(compress_chunk(x)) from show_chunks('edges') x; + count ------- 2 (1 row) -analyze aggfns; +vacuum freeze analyze edges; +set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; +-- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s) from aggfns%s%s order by 1;', + format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, grouping || ', ', function, variable, ' where ' || condition, - ' group by ' || grouping ) + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) from unnest(array[ 'explain (costs off) ', @@ -75,7 +129,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -92,138 +147,25 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's', - 'ss']) with ordinality as grouping(grouping, n) + 's']) with ordinality as grouping(grouping, n) where - case --- when explain is not null then condition is null and grouping = 's' - when explain is not null then false - when true then true - end - and - case - when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') - when variable = 't' then function in ('min', 'max') - when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') - else true end + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') + and (variable not in ('t', 'cts', 'ctstz', 'cdate') or function in ('min', 'max')) + -- This is not vectorized yet + and (variable != 'cint8' or function != 'stddev') + and (function != 'count' or variable in ('cint2', 's', '*')) + and (condition is distinct from 'cint2 is null' or variable = 'cint2') order by explain, condition.n, variable, function, grouping.n \gexec -select max(cdate) from aggfns order by 1; - max ------------- - 03-05-2322 -(1 row) - -select s, max(cdate) from aggfns group by s order by 1; - s | max ----+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns group by ss order by 1; - ss | max -----+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select min(cdate) from aggfns order by 1; - min ------------- - 01-02-2021 -(1 row) - -select s, min(cdate) from aggfns group by s order by 1; - s | min ----+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns group by ss order by 1; - ss | min -----+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select avg(cfloat4) from aggfns order by 1; - avg ------ - NaN -(1 row) - -select s, avg(cfloat4) from aggfns group by s order by 1; - s | avg ----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select ss, avg(cfloat4) from aggfns group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select count(cfloat4) from aggfns order by 1; +select count(*) from aggfns; count -------- 200000 (1 row) -select s, count(cfloat4) from aggfns group by s order by 1; +select s, count(*) from aggfns group by s order by count(*), s limit 10; s | count ---+------- 0 | 20000 @@ -238,1036 +180,664 @@ select s, count(cfloat4) from aggfns group by s order by 1; 9 | 20000 (10 rows) -select ss, count(cfloat4) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select max(cfloat4) from aggfns order by 1; +select max(cdate) from aggfns; + max +------------ + 06-01-2267 +(1 row) + +select s, max(cdate) from aggfns group by s order by max(cdate), s limit 10; + s | max +---+------------ + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns; + min +------------ + 01-01-2021 +(1 row) + +select s, min(cdate) from aggfns group by s order by min(cdate), s limit 10; + s | min +---+------------ + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns; + avg +----- + NaN +(1 row) + +select s, avg(cfloat4) from aggfns group by s order by avg(cfloat4), s limit 10; + s | avg +---+---------------------- + 3 | -Infinity + 9 | -0.292700759558938 + 4 | -0.177721596086072 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 2 | Infinity + 1 | NaN +(10 rows) + +select max(cfloat4) from aggfns; max ----- NaN (1 row) -select s, max(cfloat4) from aggfns group by s order by 1; +select s, max(cfloat4) from aggfns group by s order by max(cfloat4), s limit 10; s | max ---+---------- - 0 | 49.9977 - 1 | NaN + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select ss, max(cfloat4) from aggfns group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select min(cfloat4) from aggfns order by 1; + 1 | NaN +(10 rows) + +select min(cfloat4) from aggfns; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns group by s order by 1; +select s, min(cfloat4) from aggfns group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns group by ss order by 1; - ss | min -----+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 - 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select stddev(cfloat4) from aggfns order by 1; + 4 | -49.9999 + 6 | -49.9995 + 2 | -49.9991 + 7 | -49.9984 + 1 | -49.9974 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 +(10 rows) + +select stddev(cfloat4) from aggfns; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns group by s order by 1; +select s, stddev(cfloat4) from aggfns group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8941380063426 + 0 | 28.7274163912974 + 7 | 28.7892027644317 + 4 | 28.8273136003882 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270615 1 | NaN 2 | NaN 3 | NaN - 4 | 28.8948189281653 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301629 - 8 | 28.8963276918371 - 9 | 28.8968307405967 -(10 rows) - -select ss, stddev(cfloat4) from aggfns group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.8941380063427 - 1 | NaN - 2 | NaN - 3 | NaN - 4 | 28.8948189281654 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301628 - 8 | 28.8963276918371 - 9 | 28.8968307405966 -(10 rows) - -select sum(cfloat4) from aggfns order by 1; +(10 rows) + +select sum(cfloat4) from aggfns; sum ----- NaN (1 row) -select s, sum(cfloat4) from aggfns group by s order by 1; +select s, sum(cfloat4) from aggfns group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 -(10 rows) - -select ss, sum(cfloat4) from aggfns group by ss order by 1; - ss | sum -----+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 -(10 rows) - -select avg(cfloat8) from aggfns order by 1; - avg --------------------- - -0.131776180773973 + 9 | -5854.02 + 4 | -3554.43 + 6 | -122.193 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 2 | Infinity + 1 | NaN +(10 rows) + +select avg(cfloat8) from aggfns; + avg +----------------- + 1.2289014329263 (1 row) -select s, avg(cfloat8) from aggfns group by s order by 1; +select s, avg(cfloat8) from aggfns group by s order by avg(cfloat8), s limit 10; s | avg ---+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select ss, avg(cfloat8) from aggfns group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select max(cfloat8) from aggfns order by 1; - max ------------------ - 49.997744965367 -(1 row) - -select s, max(cfloat8) from aggfns group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select min(cfloat8) from aggfns order by 1; + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.220256273869891 + 3 | -0.14819676399231 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + 2 | 0.198140166982776 + 1 | 13 +(10 rows) + +select max(cfloat8) from aggfns; + max +------------------ + 49.9995574122295 +(1 row) + +select s, max(cfloat8) from aggfns group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + +select min(cfloat8) from aggfns; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns group by s order by 1; +select s, min(cfloat8) from aggfns group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns group by ss order by 1; - ss | min -----+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select stddev(cfloat8) from aggfns order by 1; - stddev ------------------ - 28.894749851557 + 0 | -49.9994775978848 + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + 1 | 13 +(10 rows) + +select stddev(cfloat8) from aggfns; + stddev +------------------ + 27.6606134001179 (1 row) -select s, stddev(cfloat8) from aggfns group by s order by 1; +select s, stddev(cfloat8) from aggfns group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840889 - 5 | 28.8960532056264 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select ss, stddev(cfloat8) from aggfns group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 - 5 | 28.8960532056265 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select sum(cfloat8) from aggfns order by 1; - sum -------------------- - -26355.2361547947 + 1 | 0 + 2 | 28.7611066711723 + 9 | 28.7642081921344 + 4 | 28.77864036235 + 5 | 28.7843925303698 + 6 | 28.8543767497509 + 3 | 28.9210796983077 + 8 | 28.96331707256 + 0 | 28.965342556856 + 7 | 28.9656492103737 +(10 rows) + +select sum(cfloat8) from aggfns; + sum +----------------- + 245780.28658526 (1 row) -select s, sum(cfloat8) from aggfns group by s order by 1; +select s, sum(cfloat8) from aggfns group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select ss, sum(cfloat8) from aggfns group by ss order by 1; - ss | sum -----+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select avg(cint2) from aggfns order by 1; + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4405.12547739781 + 3 | -2963.93527984619 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 2 | 3962.80333965551 + 1 | 260000 +(10 rows) + +select avg(cint2) from aggfns; avg ---------------------- - -42.1591712126520194 + -33.1461788699264301 (1 row) -select s, avg(cint2) from aggfns group by s order by 1; - s | avg ----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select ss, avg(cint2) from aggfns group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select max(cint2) from aggfns order by 1; +select s, avg(cint2) from aggfns group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 2 | -158.3178019118162254 + 8 | -129.4959711726139833 + 3 | -95.7656773935238477 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 4 | -28.7127771382813673 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 1 | 91.9493518842900756 + 5 | 110.0305290025524248 +(10 rows) + +select count(cint2) from aggfns; + count +-------- + 199810 +(1 row) + +select s, count(cint2) from aggfns group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select max(cint2) from aggfns; max ------- 16383 (1 row) -select s, max(cint2) from aggfns group by s order by 1; +select s, max(cint2) from aggfns group by s order by max(cint2), s limit 10; s | max ---+------- + 3 | 16380 + 2 | 16381 + 5 | 16381 + 7 | 16381 + 8 | 16382 0 | 16383 1 | 16383 - 2 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns group by ss order by 1; - ss | max -----+------- - 0 | 16383 - 1 | 16383 - 2 | 16383 - 3 | 16383 - 4 | 16383 - 5 | 16383 - 6 | 16383 - 7 | 16383 - 8 | 16383 - 9 | 16383 -(10 rows) - -select min(cint2) from aggfns order by 1; +select min(cint2) from aggfns; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns group by s order by 1; +select s, min(cint2) from aggfns group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns group by ss order by 1; - ss | min -----+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 -(10 rows) - -select stddev(cint2) from aggfns order by 1; +select stddev(cint2) from aggfns; stddev ------------------- - 9467.689085960139 + 9475.597346265432 (1 row) -select s, stddev(cint2) from aggfns group by s order by 1; +select s, stddev(cint2) from aggfns group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select ss, stddev(cint2) from aggfns group by ss order by 1; - ss | stddev -----+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select sum(cint2) from aggfns order by 1; + 9 | 9450.322790943425 + 2 | 9458.737760855119 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9473.424234931108 + 8 | 9477.586839536066 + 4 | 9483.720025499142 + 0 | 9484.907423282680 + 1 | 9528.039076724276 +(10 rows) + +select sum(cint2) from aggfns; sum ---------- - -8423824 + -6622938 (1 row) -select s, sum(cint2) from aggfns group by s order by 1; - s | sum ----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select ss, sum(cint2) from aggfns group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select avg(cint4) from aggfns order by 1; - avg ------------------------ - -2833327.786810000000 -(1 row) - -select s, avg(cint4) from aggfns group by s order by 1; +select s, sum(cint2) from aggfns group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 2 | -3163348 + 8 | -2587459 + 3 | -1913494 + 6 | -1220352 + 7 | -1116329 + 4 | -573710 + 9 | -435575 + 0 | 351569 + 1 | 1837240 + 5 | 2198520 +(10 rows) + +select avg(cint4) from aggfns; + avg +--------------------- + -4.9369150000000000 +(1 row) + +select s, avg(cint4) from aggfns group by s order by avg(cint4), s limit 10; s | avg ---+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select ss, avg(cint4) from aggfns group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select max(cint4) from aggfns order by 1; - max ------------- - 1073660631 + 9 | -102.4283000000000000 + 2 | -101.3952000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 4 | 6.6530500000000000 + 0 | 27.7536500000000000 + 3 | 70.4102500000000000 + 1 | 71.5608500000000000 + 5 | 103.1069000000000000 +(10 rows) + +select max(cint4) from aggfns; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint4) from aggfns order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint4) from aggfns order by 1; - stddev ------------ - 620480022 +select s, max(cint4) from aggfns group by s order by max(cint4), s limit 10; + s | max +---+------- + 3 | 16379 + 5 | 16379 + 7 | 16379 + 2 | 16381 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 +(10 rows) + +select min(cint4) from aggfns; + min +-------- + -16383 (1 row) -select s, stddev(cint4) from aggfns group by s order by 1; - s | stddev ----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select ss, stddev(cint4) from aggfns group by ss order by 1; - ss | stddev -----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select sum(cint4) from aggfns order by 1; - sum ---------------- - -566665557362 -(1 row) - -select s, sum(cint4) from aggfns group by s order by 1; - s | sum ----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select ss, sum(cint4) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select avg(cint8) from aggfns order by 1; - avg ------------------------ - -2823388.766060000000 -(1 row) - -select s, avg(cint8) from aggfns group by s order by 1; +select s, min(cint4) from aggfns group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select stddev(cint4) from aggfns; + stddev +------------------- + 9450.334382392243 +(1 row) + +select s, stddev(cint4) from aggfns group by s order by stddev(cint4), s limit 10; + s | stddev +---+------------------- + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 2 | 9440.675087350597 + 4 | 9443.098516157448 + 8 | 9450.281544631633 + 1 | 9459.538662433945 + 3 | 9474.762271621918 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select sum(cint4) from aggfns; + sum +--------- + -987383 +(1 row) + +select s, sum(cint4) from aggfns group by s order by sum(cint4), s limit 10; + s | sum +---+---------- + 9 | -2048566 + 2 | -2027904 + 6 | -1063133 + 7 | -852243 + 8 | -585231 + 4 | 133061 + 0 | 555073 + 3 | 1408205 + 1 | 1431217 + 5 | 2062138 +(10 rows) + +select avg(cint8) from aggfns; + avg +---------------------- + -12.1026800000000000 +(1 row) + +select s, avg(cint8) from aggfns group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select ss, avg(cint8) from aggfns group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select max(cint8) from aggfns order by 1; - max ------------- - 1073660631 + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 1 | -25.4401500000000000 + 4 | -19.5071500000000000 + 2 | -2.4691500000000000 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 39.9743500000000000 + 9 | 61.7467500000000000 +(10 rows) + +select max(cint8) from aggfns; + max +------- + 16383 (1 row) -select s, max(cint8) from aggfns group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint8) from aggfns order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint8) from aggfns order by 1; - stddev ------------ - 620482773 +select s, max(cint8) from aggfns group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16379 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 5 | 16383 +(10 rows) + +select min(cint8) from aggfns; + min +-------- + -16383 (1 row) -select s, stddev(cint8) from aggfns group by s order by 1; - s | stddev ----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select ss, stddev(cint8) from aggfns group by ss order by 1; - ss | stddev -----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select sum(cint8) from aggfns order by 1; - sum ---------------- - -564677753212 -(1 row) - -select s, sum(cint8) from aggfns group by s order by 1; - s | sum ----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select ss, sum(cint8) from aggfns group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select max(cts) from aggfns order by 1; +select s, min(cint8) from aggfns group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 2 | -16379 + 3 | -16378 +(10 rows) + +select sum(cint8) from aggfns; + sum +---------- + -2420536 +(1 row) + +select s, sum(cint8) from aggfns group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -2369740 + 5 | -1633911 + 1 | -508803 + 4 | -390143 + 2 | -49383 + 7 | -47127 + 6 | 238113 + 0 | 306036 + 3 | 799487 + 9 | 1234935 +(10 rows) + +select max(cts) from aggfns; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns group by s order by 1; +select s, max(cts) from aggfns group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns group by ss order by 1; - ss | max -----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select min(cts) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns group by s order by 1; +select s, min(cts) from aggfns group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns group by ss order by 1; - ss | min -----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select max(ctstz) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns group by s order by 1; +select s, max(ctstz) from aggfns group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns group by ss order by 1; - ss | max -----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select min(ctstz) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns group by s order by 1; +select s, min(ctstz) from aggfns group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns group by ss order by 1; - ss | min -----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select avg(s) from aggfns order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns; avg -------------------- 4.5000000000000000 (1 row) -select s, avg(s) from aggfns group by s order by 1; +select s, avg(s) from aggfns group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 @@ -1282,28 +852,13 @@ select s, avg(s) from aggfns group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select count(s) from aggfns order by 1; +select count(s) from aggfns; count -------- 200000 (1 row) -select s, count(s) from aggfns group by s order by 1; +select s, count(s) from aggfns group by s order by count(s), s limit 10; s | count ---+------- 0 | 20000 @@ -1318,28 +873,13 @@ select s, count(s) from aggfns group by s order by 1; 9 | 20000 (10 rows) -select ss, count(s) from aggfns group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select max(s) from aggfns order by 1; +select max(s) from aggfns; max ----- 9 (1 row) -select s, max(s) from aggfns group by s order by 1; +select s, max(s) from aggfns group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -1354,28 +894,13 @@ select s, max(s) from aggfns group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(s) from aggfns order by 1; +select min(s) from aggfns; min ----- 0 (1 row) -select s, min(s) from aggfns group by s order by 1; +select s, min(s) from aggfns group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -1390,28 +915,13 @@ select s, min(s) from aggfns group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(s) from aggfns order by 1; +select stddev(s) from aggfns; stddev -------------------- 2.8722885039992502 (1 row) -select s, stddev(s) from aggfns group by s order by 1; +select s, stddev(s) from aggfns group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -1426,28 +936,13 @@ select s, stddev(s) from aggfns group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(s) from aggfns order by 1; +select sum(s) from aggfns; sum -------- 900000 (1 row) -select s, sum(s) from aggfns group by s order by 1; +select s, sum(s) from aggfns group by s order by sum(s), s limit 10; s | sum ---+-------- 0 | 0 @@ -1462,105 +957,58 @@ select s, sum(s) from aggfns group by s order by 1; 9 | 180000 (10 rows) -select ss, sum(s) from aggfns group by ss order by 1; - ss | sum -----+-------- - 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 - 5 | 100000 - 6 | 120000 - 7 | 140000 - 8 | 160000 - 9 | 180000 -(10 rows) - -select avg(ss) from aggfns order by 1; +select avg(ss) from aggfns; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) -select s, avg(ss) from aggfns group by s order by 1; +select s, avg(ss) from aggfns group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select max(ss) from aggfns order by 1; +select max(ss) from aggfns; max ----- - 9 + 11 (1 row) -select s, max(ss) from aggfns group by s order by 1; +select s, max(ss) from aggfns group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 - 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(ss) from aggfns order by 1; +select min(ss) from aggfns; min ----- 0 (1 row) -select s, min(ss) from aggfns group by s order by 1; +select s, min(ss) from aggfns group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1568,102 +1016,59 @@ select s, min(ss) from aggfns group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(ss) from aggfns order by 1; +select stddev(ss) from aggfns; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) -select s, stddev(ss) from aggfns group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select ss, stddev(ss) from aggfns group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(ss) from aggfns order by 1; - sum --------- - 900000 +select s, stddev(ss) from aggfns group by s order by stddev(ss), s limit 10; + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 4 | 0.21565737387148452722 +(10 rows) + +select sum(ss) from aggfns; + sum +--------- + 1280076 (1 row) -select s, sum(ss) from aggfns group by s order by 1; +select s, sum(ss) from aggfns group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 1 | 220000 + 2 | 220000 (10 rows) -select ss, sum(ss) from aggfns group by ss order by 1; - ss | sum -----+-------- - 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 - 5 | 100000 - 6 | 120000 - 7 | 140000 - 8 | 160000 - 9 | 180000 -(10 rows) - -select max(t) from aggfns order by 1; +select max(t) from aggfns; max -------- 110000 (1 row) -select s, max(t) from aggfns group by s order by 1; +select s, max(t) from aggfns group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 @@ -1678,28 +1083,13 @@ select s, max(t) from aggfns group by s order by 1; 9 | 110000 (10 rows) -select ss, max(t) from aggfns group by ss order by 1; - ss | max -----+-------- - 0 | 20000 - 1 | 30000 - 2 | 40000 - 3 | 50000 - 4 | 60000 - 5 | 70000 - 6 | 80000 - 7 | 90000 - 8 | 100000 - 9 | 110000 -(10 rows) - -select min(t) from aggfns order by 1; +select min(t) from aggfns; min ----- 1 (1 row) -select s, min(t) from aggfns group by s order by 1; +select s, min(t) from aggfns group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 @@ -1714,1180 +1104,685 @@ select s, min(t) from aggfns group by s order by 1; 9 | 90001 (10 rows) -select ss, min(t) from aggfns group by ss order by 1; - ss | min -----+------- - 0 | 1 - 1 | 10001 - 2 | 20001 - 3 | 30001 - 4 | 40001 - 5 | 50001 - 6 | 60001 - 7 | 70001 - 8 | 80001 - 9 | 90001 -(10 rows) - -select max(cdate) from aggfns where cfloat8 > 0 order by 1; +select count(*) from aggfns where cfloat8 > 0; + count +-------- + 109785 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9881 + 4 | 9882 + 9 | 9945 + 8 | 9950 + 3 | 9963 + 5 | 9972 + 7 | 10021 + 2 | 10074 + 6 | 10097 + 1 | 20000 +(10 rows) + +select max(cdate) from aggfns where cfloat8 > 0; max ------------ - 03-05-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 > 0 group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-04-2075 - 1 | 02-21-2103 - 2 | 07-08-2130 - 3 | 11-22-2157 - 4 | 04-11-2185 - 5 | 08-27-2212 - 6 | 01-14-2240 - 7 | 05-31-2267 - 8 | 10-15-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------ - 0 | 10-04-2075 - 1 | 02-21-2103 - 2 | 07-08-2130 - 3 | 11-22-2157 - 4 | 04-11-2185 - 5 | 08-27-2212 - 6 | 01-14-2240 - 7 | 05-31-2267 - 8 | 10-15-2294 - 9 | 03-05-2322 -(10 rows) - -select min(cdate) from aggfns where cfloat8 > 0 order by 1; + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns where cfloat8 > 0; min ------------ - 01-02-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 > 0 group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-11-2075 - 3 | 02-26-2103 - 4 | 07-13-2130 - 5 | 11-27-2157 - 6 | 04-13-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-11-2075 - 3 | 02-26-2103 - 4 | 07-13-2130 - 5 | 11-27-2157 - 6 | 04-13-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 > 0 order by 1; - avg ------------ - -Infinity + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns where cfloat8 > 0; + avg +----- + NaN (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by avg(cfloat4), s limit 10; s | avg ---+-------------------- - 0 | -0.542617154225893 - 1 | -0.540875748760701 - 2 | -0.541406464808325 3 | -Infinity - 4 | -0.544616367218129 - 5 | -0.544616367218129 - 6 | -0.547797322998719 - 7 | -0.547797322998719 - 8 | -0.544139963208192 - 9 | -0.547059247380753 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.542617154225893 - 1 | -0.540875748760701 - 2 | -0.541406464808325 - 3 | -Infinity - 4 | -0.544616367218129 - 5 | -0.544616367218129 - 6 | -0.547797322998719 - 7 | -0.547797322998719 - 8 | -0.544139963208192 - 9 | -0.547059247380753 -(10 rows) - -select count(cfloat4) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99430 -(1 row) + 4 | -0.462286033119876 + 0 | -0.334856044433109 + 2 | -0.219086657095562 + 9 | -0.208302219537011 + 6 | 0.199537611181853 + 7 | 0.313851696029514 + 5 | 0.374879026647364 + 8 | 0.606801085094336 + 1 | NaN +(10 rows) -select s, count(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; - s | count ----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 > 0 order by 1; - max ---------- - 49.9734 +select max(cfloat4) from aggfns where cfloat8 > 0; + max +----- + NaN (1 row) -select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by max(cfloat4), s limit 10; s | max ---+--------- - 0 | 49.9734 - 1 | 49.9734 - 2 | 49.9734 - 3 | 49.9734 - 4 | 49.9734 - 5 | 49.9734 - 6 | 49.9734 - 7 | 49.9734 - 8 | 49.9734 - 9 | 49.9734 -(10 rows) - -select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+--------- - 0 | 49.9734 - 1 | 49.9734 - 2 | 49.9734 - 3 | 49.9734 - 4 | 49.9734 - 5 | 49.9734 - 6 | 49.9734 - 7 | 49.9734 - 8 | 49.9734 - 9 | 49.9734 -(10 rows) - -select min(cfloat4) from aggfns where cfloat8 > 0 order by 1; + 9 | 49.9744 + 3 | 49.9744 + 0 | 49.9863 + 2 | 49.988 + 8 | 49.9923 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 + 5 | 49.9992 + 1 | NaN +(10 rows) + +select min(cfloat4) from aggfns where cfloat8 > 0; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9722 - 1 | -49.9722 - 2 | -49.9722 3 | -Infinity - 4 | -49.9722 - 5 | -49.9722 - 6 | -49.9722 - 7 | -49.9722 - 8 | -49.9722 - 9 | -49.9722 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+----------- - 0 | -49.9722 - 1 | -49.9722 - 2 | -49.9722 - 3 | -Infinity - 4 | -49.9722 - 5 | -49.9722 - 6 | -49.9722 - 7 | -49.9722 - 8 | -49.9722 - 9 | -49.9722 -(10 rows) - -select stddev(cfloat4) from aggfns where cfloat8 > 0 order by 1; + 4 | -49.9993 + 1 | -49.9974 + 8 | -49.9969 + 7 | -49.9969 + 2 | -49.9928 + 0 | -49.9915 + 9 | -49.9911 + 5 | -49.9892 + 6 | -49.9891 +(10 rows) + +select stddev(cfloat4) from aggfns where cfloat8 > 0; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.889048755135 - 1 | 28.8872257367626 - 2 | 28.8886301576555 + 7 | 28.7246858657947 + 0 | 28.7315562731003 + 9 | 28.7729261590403 + 2 | 28.8508703679162 + 4 | 28.8548902125459 + 5 | 28.9107809470208 + 6 | 28.9388387251543 + 8 | 29.1042713834566 + 1 | NaN 3 | NaN - 4 | 28.8889504423898 - 5 | 28.8889504423898 - 6 | 28.8892391773513 - 7 | 28.8892391773513 - 8 | 28.8883896891409 - 9 | 28.8893600799806 -(10 rows) - -select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.889048755135 - 1 | 28.8872257367626 - 2 | 28.8886301576555 - 3 | NaN - 4 | 28.8889504423898 - 5 | 28.8889504423898 - 6 | 28.8892391773513 - 7 | 28.8892391773513 - 8 | 28.8883896891408 - 9 | 28.8893600799806 -(10 rows) - -select sum(cfloat4) from aggfns where cfloat8 > 0 order by 1; - sum ------------ - -Infinity +(10 rows) + +select sum(cfloat4) from aggfns where cfloat8 > 0; + sum +----- + NaN (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -5395.24 - 1 | -5377.93 - 2 | -5382.66 3 | -Infinity - 4 | -5415.12 - 5 | -5415.12 - 6 | -5447.3 - 7 | -5447.3 - 8 | -5410.38 - 9 | -5439.41 -(10 rows) - -select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+----------- - 0 | -5395.24 - 1 | -5377.92 - 2 | -5382.66 - 3 | -Infinity - 4 | -5415.12 - 5 | -5415.12 - 6 | -5447.29 - 7 | -5447.29 - 8 | -5410.38 - 9 | -5439.41 -(10 rows) - -select avg(cfloat8) from aggfns where cfloat8 > 0 order by 1; + 4 | -4568.31 + 0 | -3308.71 + 2 | -2207.08 + 9 | -2071.57 + 6 | 2014.73 + 7 | 3145.11 + 5 | 3738.29 + 8 | 6037.67 + 1 | NaN +(10 rows) + +select avg(cfloat8) from aggfns where cfloat8 > 0; avg ------------------ - 25.0275627282681 + 22.7931225354662 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------ - 0 | 25.0253254492148 - 1 | 25.0296791394684 - 2 | 25.0284447917954 - 3 | 25.0284447917954 - 4 | 25.0283891332554 - 5 | 25.0283891332554 - 6 | 25.0265337956144 - 7 | 25.0265337956144 - 8 | 25.0286117211772 - 9 | 25.0252759158804 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+------------------ - 0 | 25.0253254492148 - 1 | 25.0296791394684 - 2 | 25.0284447917954 - 3 | 25.0284447917954 - 4 | 25.0283891332554 - 5 | 25.0283891332554 - 6 | 25.0265337956144 - 7 | 25.0265337956144 - 8 | 25.0286117211772 - 9 | 25.0252759158804 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 > 0 order by 1; - max ------------------ - 49.997744965367 -(1 row) - -select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 > 0 order by 1; - min ---------------------- - 0.00456937123090029 -(1 row) - -select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; - s | min ----+--------------------- - 0 | 0.00456937123090029 - 1 | 0.00456937123090029 - 2 | 0.00456937123090029 - 3 | 0.00456937123090029 - 4 | 0.00456937123090029 - 5 | 0.00456937123090029 - 6 | 0.00456937123090029 - 7 | 0.00456937123090029 - 8 | 0.00456937123090029 - 9 | 0.00456937123090029 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+--------------------- - 0 | 0.00456937123090029 - 1 | 0.00456937123090029 - 2 | 0.00456937123090029 - 3 | 0.00456937123090029 - 4 | 0.00456937123090029 - 5 | 0.00456937123090029 - 6 | 0.00456937123090029 - 7 | 0.00456937123090029 - 8 | 0.00456937123090029 - 9 | 0.00456937123090029 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 > 0 order by 1; + 1 | 13 + 2 | 24.886472568415 + 6 | 24.9229571834467 + 9 | 24.933601739557 + 8 | 24.9404756362227 + 4 | 24.9773553659677 + 7 | 24.9965050319499 + 5 | 25.0141908239782 + 3 | 25.0243032089187 + 0 | 25.0776526587937 +(10 rows) + +select max(cfloat8) from aggfns where cfloat8 > 0; + max +------------------ + 49.9995574122295 +(1 row) + +select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + +select min(cfloat8) from aggfns where cfloat8 > 0; + min +---------------------- + 0.000765081495046616 +(1 row) + +select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by min(cfloat8), s limit 10; + s | min +---+---------------------- + 4 | 0.000765081495046616 + 7 | 0.000956561416387558 + 6 | 0.00179046764969826 + 0 | 0.00247885473072529 + 2 | 0.00441970769315958 + 3 | 0.00545482616871595 + 5 | 0.00628724228590727 + 9 | 0.0187294092029333 + 8 | 0.0195798231288791 + 1 | 13 +(10 rows) + +select stddev(cfloat8) from aggfns where cfloat8 > 0; stddev ------------------ - 14.4387600969317 + 13.8427996018819 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 14.4393152148108 - 1 | 14.4397230124184 - 2 | 14.4399246592273 - 3 | 14.4399246592273 - 4 | 14.4391994993402 - 5 | 14.4391994993402 - 6 | 14.4396587086659 - 7 | 14.4396587086659 - 8 | 14.4388979969066 - 9 | 14.4386334818318 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 14.4393152148108 - 1 | 14.4397230124184 - 2 | 14.4399246592273 - 3 | 14.4399246592273 - 4 | 14.4391994993402 - 5 | 14.4391994993402 - 6 | 14.4396587086659 - 7 | 14.4396587086659 - 8 | 14.4388979969066 - 9 | 14.4386334818319 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 > 0 order by 1; - sum ------------------ - 2488490.5620717 + 1 | 0 + 9 | 14.3145979997847 + 3 | 14.3699970235247 + 4 | 14.4155254530971 + 6 | 14.4175557556356 + 5 | 14.4400766885504 + 0 | 14.4509605112521 + 7 | 14.4643374353136 + 2 | 14.4807945816176 + 8 | 14.507225286092 +(10 rows) + +select sum(cfloat8) from aggfns where cfloat8 > 0; + sum +------------------ + 2502342.95755615 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------ - 0 | 248826.810941542 - 1 | 248870.099683735 - 2 | 248832.79812003 - 3 | 248832.79812003 - 4 | 248857.273151958 - 5 | 248857.273151958 - 6 | 248863.85206359 - 7 | 248863.85206359 - 8 | 248859.486343665 - 9 | 248826.318431599 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+------------------ - 0 | 248826.810941542 - 1 | 248870.099683735 - 2 | 248832.79812003 - 3 | 248832.79812003 - 4 | 248857.273151958 - 5 | 248857.273151958 - 6 | 248863.85206359 - 7 | 248863.85206359 - 8 | 248859.486343665 - 9 | 248826.318431599 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 > 0 order by 1; - avg ---------------------- - 59.9930038252466277 -(1 row) - -select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+--------------------- - 0 | 62.5336219045701631 - 1 | 61.1402396053558844 - 2 | 64.7349239907379442 - 3 | 60.4202577527184857 - 4 | 58.4389090177133655 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+--------------------- - 0 | 62.5336219045701631 - 1 | 61.1402396053558844 - 2 | 64.7349239907379442 - 3 | 60.4202577527184857 - 4 | 58.4389090177133655 - 5 | 53.6134098459679855 - 6 | 59.4139909411172622 - 7 | 62.9917446894191080 - 8 | 57.2486665995773372 - 9 | 59.3958123615864707 -(10 rows) - -select max(cint2) from aggfns where cfloat8 > 0 order by 1; + 4 | 246826.225726493 + 0 | 247792.285921541 + 9 | 247964.669299894 + 8 | 248157.732580416 + 3 | 249317.132870457 + 5 | 249441.510896711 + 7 | 250489.97692517 + 2 | 250706.324654212 + 6 | 251647.098681261 + 1 | 260000 +(10 rows) + +select avg(cint2) from aggfns where cfloat8 > 0; + avg +---------------------- + -46.3563347281860533 +(1 row) + +select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 9 | -192.8237544036235531 + 3 | -159.9071729957805907 + 2 | -156.9086662691313854 + 7 | -142.7671027664036752 + 4 | -122.8676723701528804 + 6 | -98.2421689135606661 + 8 | -1.6297525648762824 + 0 | 28.7771364925070879 + 1 | 91.9493518842900756 + 5 | 153.6364822808954924 +(10 rows) + +select count(cint2) from aggfns where cfloat8 > 0; + count +-------- + 109689 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9876 + 4 | 9877 + 9 | 9935 + 8 | 9942 + 3 | 9954 + 5 | 9961 + 7 | 10013 + 2 | 10062 + 6 | 10088 + 1 | 19981 +(10 rows) + +select max(cint2) from aggfns where cfloat8 > 0; max ------- - 16377 + 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by max(cint2), s limit 10; s | max ---+------- - 0 | 16377 - 1 | 16377 - 2 | 16377 - 3 | 16377 - 4 | 16377 - 5 | 16377 - 6 | 16377 - 7 | 16377 - 8 | 16377 - 9 | 16377 -(10 rows) - -select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------- - 0 | 16377 - 1 | 16377 - 2 | 16377 - 3 | 16377 - 4 | 16377 - 5 | 16377 - 6 | 16377 - 7 | 16377 - 8 | 16377 - 9 | 16377 -(10 rows) - -select min(cint2) from aggfns where cfloat8 > 0 order by 1; + 2 | 16379 + 3 | 16380 + 8 | 16380 + 5 | 16381 + 6 | 16381 + 7 | 16381 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 9 | 16383 +(10 rows) + +select min(cint2) from aggfns where cfloat8 > 0; min -------- - -16374 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16374 - 1 | -16374 - 2 | -16374 - 3 | -16374 - 4 | -16374 - 5 | -16374 - 6 | -16374 - 7 | -16374 - 8 | -16374 - 9 | -16374 + 0 | -16383 + 4 | -16383 + 6 | -16383 + 8 | -16382 + 5 | -16381 + 7 | -16380 + 1 | -16378 + 3 | -16378 + 2 | -16377 + 9 | -16375 (10 rows) -select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+-------- - 0 | -16374 - 1 | -16374 - 2 | -16374 - 3 | -16374 - 4 | -16374 - 5 | -16374 - 6 | -16374 - 7 | -16374 - 8 | -16374 - 9 | -16374 +select stddev(cint2) from aggfns where cfloat8 > 0; + stddev +------------------- + 9465.641930658310 +(1 row) + +select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by stddev(cint2), s limit 10; + s | stddev +---+------------------- + 2 | 9406.991269284247 + 5 | 9422.095841513016 + 6 | 9433.502305093184 + 9 | 9441.945023643920 + 4 | 9449.079857205037 + 7 | 9460.956887483220 + 3 | 9461.502298006280 + 8 | 9466.374225763893 + 0 | 9519.824544774386 + 1 | 9528.039076724276 +(10 rows) + +select sum(cint2) from aggfns where cfloat8 > 0; + sum +---------- + -5084780 +(1 row) + +select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 9 | -1915704 + 3 | -1591716 + 2 | -1578815 + 7 | -1429527 + 4 | -1213564 + 6 | -991067 + 8 | -16203 + 0 | 284203 + 5 | 1530373 + 1 | 1837240 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 > 0; + avg +--------------------- + -3.1503210821150430 +(1 row) + +select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by avg(cint4), s limit 10; + s | avg +---+----------------------- + 9 | -227.0452488687782805 + 2 | -152.6957514393488187 + 6 | -94.7697335842329405 + 4 | -42.9105444242056264 + 7 | -7.9618800518910288 + 8 | 30.7776884422110553 + 5 | 70.0002005615724027 + 1 | 71.5608500000000000 + 0 | 78.5152312518975812 + 3 | 170.6088527551942186 +(10 rows) + +select max(cint4) from aggfns where cfloat8 > 0; + max +------- + 16383 +(1 row) + +select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by max(cint4), s limit 10; + s | max +---+------- + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16380 + 6 | 16380 + 2 | 16381 + 9 | 16381 + 4 | 16382 + 8 | 16382 + 1 | 16383 (10 rows) -select stddev(cint2) from aggfns where cfloat8 > 0 order by 1; +select min(cint4) from aggfns where cfloat8 > 0; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 2 | -16383 + 7 | -16383 + 0 | -16382 + 1 | -16382 + 9 | -16382 + 5 | -16380 + 3 | -16379 + 4 | -16378 + 6 | -16378 + 8 | -16377 +(10 rows) + +select stddev(cint4) from aggfns where cfloat8 > 0; stddev ------------------- - 9395.467286148261 + 9447.836798758010 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by stddev(cint4), s limit 10; s | stddev ---+------------------- - 0 | 9396.868628954375 - 1 | 9397.478004684803 - 2 | 9396.003979674052 - 3 | 9395.588131506675 - 4 | 9395.667525723886 - 5 | 9394.622668940645 - 6 | 9397.336273737402 - 7 | 9394.449892433625 - 8 | 9394.534603851403 - 9 | 9396.374239570388 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+------------------- - 0 | 9396.868628954375 - 1 | 9397.478004684803 - 2 | 9396.003979674052 - 3 | 9395.588131506675 - 4 | 9395.667525723886 - 5 | 9394.622668940645 - 6 | 9397.336273737402 - 7 | 9394.449892433625 - 8 | 9394.534603851403 - 9 | 9396.374239570388 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 > 0 order by 1; + 0 | 9368.404782340758 + 6 | 9385.470128440942 + 8 | 9411.536015886790 + 4 | 9416.523033700832 + 1 | 9459.538662433945 + 2 | 9460.302598725572 + 9 | 9474.284943213442 + 5 | 9475.929892556881 + 7 | 9500.872262505529 + 3 | 9509.065450373130 +(10 rows) + +select sum(cint4) from aggfns where cfloat8 > 0; sum --------- - 5959705 + -345858 (1 row) -select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------- - 0 | 621209 - 1 | 607306 - 2 | 643012 - 3 | 600094 - 4 | 580649 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------- - 0 | 621209 - 1 | 607306 - 2 | 643012 - 3 | 600094 - 4 | 580649 - 5 | 532542 - 6 | 590278 - 7 | 625697 - 8 | 568880 - 9 | 590038 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 > 0 order by 1; - avg ------------------------ - -3042925.418565825204 -(1 row) - -select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+----------------------- - 0 | -3230391.667404203963 - 1 | -3063702.023936437695 - 2 | -3067528.135686984510 - 3 | -3067528.135686984510 - 4 | -2963500.289651010761 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -3230391.667404203963 - 1 | -3063702.023936437695 - 2 | -3067528.135686984510 - 3 | -3067528.135686984510 - 4 | -2963500.289651010761 - 5 | -2963500.289651010761 - 6 | -3033294.541331456154 - 7 | -3033294.541331456154 - 8 | -3023451.730664789299 - 9 | -2983069.716282812029 -(10 rows) - -select max(cint4) from aggfns where cfloat8 > 0 order by 1; - max ------------- - 1073213373 +select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by sum(cint4), s limit 10; + s | sum +---+---------- + 9 | -2257965 + 2 | -1538257 + 6 | -956890 + 4 | -424042 + 7 | -79786 + 8 | 306238 + 5 | 698042 + 0 | 775809 + 1 | 1431217 + 3 | 1699776 +(10 rows) + +select avg(cint8) from aggfns where cfloat8 > 0; + avg +--------------------- + -3.7972582775424694 (1 row) -select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+------------ - 0 | 1073213373 - 1 | 1073213373 - 2 | 1073213373 - 3 | 1073213373 - 4 | 1073213373 - 5 | 1073213373 - 6 | 1073213373 - 7 | 1073213373 - 8 | 1073213373 - 9 | 1073213373 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073213373 - 1 | 1073213373 - 2 | 1073213373 - 3 | 1073213373 - 4 | 1073213373 - 5 | 1073213373 - 6 | 1073213373 - 7 | 1073213373 - 8 | 1073213373 - 9 | 1073213373 -(10 rows) - -select min(cint4) from aggfns where cfloat8 > 0 order by 1; - min -------------- - -1073053412 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | min ----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 > 0 order by 1; - stddev ------------ - 622278617 +select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by avg(cint8), s limit 10; + s | avg +---+------------------------ + 8 | -166.4501507537688442 + 5 | -78.9197753710389089 + 4 | -61.2938676381299332 + 6 | -32.8705556105773992 + 1 | -25.4401500000000000 + 7 | 1.15707015267937331604 + 0 | 42.9815808116587390 + 9 | 44.5682252388134741 + 3 | 109.7175549533273111 + 2 | 148.9026206075044669 +(10 rows) + +select max(cint8) from aggfns where cfloat8 > 0; + max +------- + 16383 (1 row) -select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+----------- - 0 | 622275017 - 1 | 622236051 - 2 | 622267230 - 3 | 622267230 - 4 | 622322391 - 5 | 622322391 - 6 | 622330015 - 7 | 622330015 - 8 | 622360538 - 9 | 622356873 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 622275017 - 1 | 622236051 - 2 | 622267230 - 3 | 622267230 - 4 | 622322391 - 5 | 622322391 - 6 | 622330015 - 7 | 622330015 - 8 | 622360538 - 9 | 622356873 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 > 0 order by 1; - sum ---------------- - -302558074368 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------------- - 0 | -32119784349 - 1 | -30462389224 - 2 | -30497364725 - 3 | -30497364725 - 4 | -29466083380 - 5 | -29466083380 - 6 | -30163080919 - 7 | -30163080919 - 8 | -30062180558 - 9 | -29660662189 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -32119784349 - 1 | -30462389224 - 2 | -30497364725 - 3 | -30497364725 - 4 | -29466083380 - 5 | -29466083380 - 6 | -30163080919 - 7 | -30163080919 - 8 | -30062180558 - 9 | -29660662189 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 > 0 order by 1; - avg ------------------------ - -7287038.185889570552 -(1 row) - -select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | avg ----+----------------------- - 0 | -7332793.526098762949 - 1 | -7334675.513225384693 - 2 | -7250229.067592033796 - 3 | -7250229.067592033796 - 4 | -7326050.594790304737 - 5 | -7326050.594790304737 - 6 | -7272459.754123089300 - 7 | -7272459.754123089300 - 8 | -7247017.818163532133 - 9 | -7258411.696771598109 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -7332793.526098762949 - 1 | -7334675.513225384693 - 2 | -7250229.067592033796 - 3 | -7250229.067592033796 - 4 | -7326050.594790304737 - 5 | -7326050.594790304737 - 6 | -7272459.754123089300 - 7 | -7272459.754123089300 - 8 | -7247017.818163532133 - 9 | -7258411.696771598109 -(10 rows) - -select max(cint8) from aggfns where cfloat8 > 0 order by 1; - max ------------- - 1073659785 +select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16373 + 7 | 16378 + 6 | 16379 + 0 | 16380 + 8 | 16380 + 3 | 16381 + 4 | 16382 + 9 | 16382 + 1 | 16383 + 5 | 16383 +(10 rows) + +select min(cint8) from aggfns where cfloat8 > 0; + min +-------- + -16383 (1 row) -select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | max ----+------------ - 0 | 1073659785 - 1 | 1073659785 - 2 | 1073659785 - 3 | 1073659785 - 4 | 1073659785 - 5 | 1073659785 - 6 | 1073659785 - 7 | 1073659785 - 8 | 1073659785 - 9 | 1073659785 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073659785 - 1 | 1073659785 - 2 | 1073659785 - 3 | 1073659785 - 4 | 1073659785 - 5 | 1073659785 - 6 | 1073659785 - 7 | 1073659785 - 8 | 1073659785 - 9 | 1073659785 -(10 rows) - -select min(cint8) from aggfns where cfloat8 > 0 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint8) from aggfns where cfloat8 > 0 order by 1; - stddev ------------ - 623577068 +select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 1 | -16383 + 7 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 6 | -16381 + 9 | -16380 + 0 | -16379 + 2 | -16379 + 3 | -16378 +(10 rows) + +select sum(cint8) from aggfns where cfloat8 > 0; + sum +--------- + -416882 (1 row) -select s, stddev(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+----------- - 0 | 623613696 - 1 | 623613596 - 2 | 623588105 - 3 | 623588105 - 4 | 623602577 - 5 | 623602577 - 6 | 623594116 - 7 | 623594116 - 8 | 623620316 - 9 | 623635702 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 623613696 - 1 | 623613596 - 2 | 623588105 - 3 | 623588105 - 4 | 623602577 - 5 | 623602577 - 6 | 623594116 - 7 | 623594116 - 8 | 623620316 - 9 | 623635702 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 > 0 order by 1; - sum ---------------- - -724550206823 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+-------------- - 0 | -72909966030 - 1 | -72928678628 - 2 | -72081777390 - 3 | -72081777390 - 4 | -72842921064 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -72909966030 - 1 | -72928678628 - 2 | -72081777390 - 3 | -72081777390 - 4 | -72842921064 - 5 | -72842921064 - 6 | -72317339795 - 7 | -72317339795 - 8 | -72057098166 - 9 | -72170387501 -(10 rows) - -select max(cts) from aggfns where cfloat8 > 0 order by 1; +select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -1656179 + 5 | -786988 + 4 | -605706 + 1 | -508803 + 6 | -331894 + 7 | 11595 + 0 | 424701 + 9 | 443231 + 3 | 1093116 + 2 | 1500045 +(10 rows) + +select max(cts) from aggfns where cfloat8 > 0; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 > 0 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:20 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:40 2021 - 3 | Fri Jan 01 14:54:19 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:40 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:00 2021 - 8 | Sat Jan 02 04:47:39 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+-------------------------- - 0 | Fri Jan 01 06:34:20 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:40 2021 - 3 | Fri Jan 01 14:54:19 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:40 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:00 2021 - 8 | Sat Jan 02 04:47:39 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns where cfloat8 > 0; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 > 0 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:27 2021 - 3 | Fri Jan 01 09:21:06 2021 - 4 | Fri Jan 01 12:07:45 2021 - 5 | Fri Jan 01 14:54:24 2021 - 6 | Fri Jan 01 17:41:03 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:27 2021 - 3 | Fri Jan 01 09:21:06 2021 - 4 | Fri Jan 01 12:07:45 2021 - 5 | Fri Jan 01 14:54:24 2021 - 6 | Fri Jan 01 17:41:03 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns where cfloat8 > 0; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 > 0 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:20 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:40 2021 PST - 3 | Fri Jan 01 14:54:19 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:40 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:00 2021 PST - 8 | Sat Jan 02 04:47:39 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+------------------------------ - 0 | Fri Jan 01 06:34:20 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:40 2021 PST - 3 | Fri Jan 01 14:54:19 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:40 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:00 2021 PST - 8 | Sat Jan 02 04:47:39 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 > 0; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 > 0 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:27 2021 PST - 3 | Fri Jan 01 09:21:06 2021 PST - 4 | Fri Jan 01 12:07:45 2021 PST - 5 | Fri Jan 01 14:54:24 2021 PST - 6 | Fri Jan 01 17:41:03 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:27 2021 PST - 3 | Fri Jan 01 09:21:06 2021 PST - 4 | Fri Jan 01 12:07:45 2021 PST - 5 | Fri Jan 01 14:54:24 2021 PST - 6 | Fri Jan 01 17:41:03 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 > 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns where cfloat8 > 0; avg -------------------- - 4.5000804586141004 + 4.1832581864553445 (1 row) -select s, avg(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 > 0 group by s order by avg(s), s limit 10; s | avg ---+------------------------ 0 | 0.00000000000000000000 @@ -2902,64 +1797,34 @@ select s, avg(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+------------------------ - 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select count(s) from aggfns where cfloat8 > 0 order by 1; - count -------- - 99430 +select count(s) from aggfns where cfloat8 > 0; + count +-------- + 109785 (1 row) -select s, count(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, count(s) from aggfns where cfloat8 > 0 group by s order by count(s), s limit 10; s | count ---+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | count -----+------- - 0 | 9943 - 1 | 9943 - 2 | 9942 - 3 | 9942 - 4 | 9943 - 5 | 9943 - 6 | 9944 - 7 | 9944 - 8 | 9943 - 9 | 9943 -(10 rows) - -select max(s) from aggfns where cfloat8 > 0 order by 1; + 0 | 9881 + 4 | 9882 + 9 | 9945 + 8 | 9950 + 3 | 9963 + 5 | 9972 + 7 | 10021 + 2 | 10074 + 6 | 10097 + 1 | 20000 +(10 rows) + +select max(s) from aggfns where cfloat8 > 0; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(s) from aggfns where cfloat8 > 0 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -2974,28 +1839,13 @@ select s, max(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(s) from aggfns where cfloat8 > 0 order by 1; +select min(s) from aggfns where cfloat8 > 0; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(s) from aggfns where cfloat8 > 0 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -3010,28 +1860,13 @@ select s, min(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(s) from aggfns where cfloat8 > 0 order by 1; +select stddev(s) from aggfns where cfloat8 > 0; stddev -------------------- - 2.8722957659869625 + 2.9152854040352282 (1 row) -select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -3046,141 +1881,79 @@ select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(s) from aggfns where cfloat8 > 0 order by 1; +select sum(s) from aggfns where cfloat8 > 0; sum -------- - 447443 + 459259 (1 row) -select s, sum(s) from aggfns where cfloat8 > 0 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 > 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select avg(ss) from aggfns where cfloat8 > 0 order by 1; + 1 | 20000 + 2 | 20148 + 3 | 29889 + 4 | 39528 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 +(10 rows) + +select avg(ss) from aggfns where cfloat8 > 0; avg -------------------- - 4.5000804586141004 + 6.8319425718762526 (1 row) -select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by avg(ss), s limit 10; s | avg ---+------------------------ 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0070835863185590 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | avg -----+------------------------ - 0 | 0.00000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select max(ss) from aggfns where cfloat8 > 0 order by 1; +select max(ss) from aggfns where cfloat8 > 0; max ----- - 9 + 11 (1 row) -select s, max(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 > 0 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 - 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(ss) from aggfns where cfloat8 > 0 order by 1; +select min(ss) from aggfns where cfloat8 > 0; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 > 0 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -3188,1330 +1961,744 @@ select s, min(ss) from aggfns where cfloat8 > 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(ss) from aggfns where cfloat8 > 0 order by 1; +select stddev(ss) from aggfns where cfloat8 > 0; stddev -------------------- - 2.8722957659869625 + 3.4547844482354617 (1 row) -select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(ss) from aggfns where cfloat8 > 0 order by 1; +select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by stddev(ss), s limit 10; + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 4 | 0.22257569540261848080 +(10 rows) + +select sum(ss) from aggfns where cfloat8 > 0; sum -------- - 447443 + 749956 (1 row) -select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 9943 - 2 | 19884 - 3 | 29826 - 4 | 39772 - 5 | 49715 - 6 | 59664 - 7 | 69608 - 8 | 79544 - 9 | 89487 -(10 rows) - -select max(t) from aggfns where cfloat8 > 0 order by 1; +select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by sum(ss), s limit 10; + s | sum +---+-------- + 0 | 0 + 3 | 29850 + 4 | 39598 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 + 2 | 110814 + 1 | 220000 +(10 rows) + +select max(t) from aggfns where cfloat8 > 0; max -------- 110000 (1 row) -select s, max(t) from aggfns where cfloat8 > 0 group by s order by 1; +select s, max(t) from aggfns where cfloat8 > 0 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 19999 1 | 30000 2 | 39999 - 3 | 49998 + 3 | 49999 4 | 60000 - 5 | 69999 - 6 | 80000 - 7 | 89999 - 8 | 99998 + 5 | 70000 + 6 | 79998 + 7 | 89995 + 8 | 99997 9 | 110000 (10 rows) -select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | max -----+-------- - 0 | 19999 - 1 | 30000 - 2 | 39999 - 3 | 49998 - 4 | 60000 - 5 | 69999 - 6 | 80000 - 7 | 89999 - 8 | 99998 - 9 | 110000 -(10 rows) - -select min(t) from aggfns where cfloat8 > 0 order by 1; +select min(t) from aggfns where cfloat8 > 0; min ----- 1 (1 row) -select s, min(t) from aggfns where cfloat8 > 0 group by s order by 1; +select s, min(t) from aggfns where cfloat8 > 0 group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 1 | 10001 - 2 | 20006 - 3 | 30005 - 4 | 40004 - 5 | 50003 + 2 | 20001 + 3 | 30001 + 4 | 40003 + 5 | 50001 6 | 60002 7 | 70001 - 8 | 80001 - 9 | 90001 + 8 | 80003 + 9 | 90002 (10 rows) -select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by 1; - ss | min -----+------- - 0 | 1 - 1 | 10001 - 2 | 20006 - 3 | 30005 - 4 | 40004 - 5 | 50003 - 6 | 60002 - 7 | 70001 - 8 | 80001 - 9 | 90001 -(10 rows) - -select max(cdate) from aggfns where cfloat8 <= 0 order by 1; +select count(*) from aggfns where cfloat8 <= 0; + count +------- + 90215 +(1 row) + +select s, count(*) from aggfns where cfloat8 <= 0 group by s order by count(*), s limit 10; + s | count +---+------- + 6 | 9903 + 2 | 9926 + 7 | 9979 + 5 | 10028 + 3 | 10037 + 8 | 10050 + 9 | 10055 + 4 | 10118 + 0 | 10119 +(9 rows) + +select max(cdate) from aggfns where cfloat8 <= 0; max ------------ - 03-04-2322 + 06-01-2267 (1 row) -select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by max(cdate), s limit 10; s | max ---+------------ - 0 | 10-05-2075 - 1 | 02-20-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-10-2185 - 5 | 08-28-2212 - 6 | 01-13-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-04-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------ - 0 | 10-05-2075 - 1 | 02-20-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-10-2185 - 5 | 08-28-2212 - 6 | 01-13-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-04-2322 -(10 rows) - -select min(cdate) from aggfns where cfloat8 <= 0 order by 1; + 0 | 01-01-2021 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(9 rows) + +select min(cdate) from aggfns where cfloat8 <= 0; min ------------ - 01-04-2021 + 01-01-2021 (1 row) -select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by min(cdate), s limit 10; s | min ---+------------ - 0 | 01-04-2021 - 1 | 05-21-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 09-01-2212 - 8 | 01-17-2240 - 9 | 06-03-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------ - 0 | 01-04-2021 - 1 | 05-21-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 09-01-2212 - 8 | 01-17-2240 - 9 | 06-03-2267 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - avg ------ - NaN + 0 | 01-01-2021 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(9 rows) + +select avg(cfloat4) from aggfns where cfloat8 <= 0; + avg +---------- + Infinity (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | avg ----+------------------- - 0 | 0.273710566446533 - 1 | NaN - 2 | Infinity - 3 | 0.271225418012403 - 4 | 0.274902188431565 - 5 | 0.278701234893647 - 6 | 0.279196201482741 - 7 | 0.281055561785383 - 8 | 0.276832673694496 - 9 | 0.276832673694496 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+------------------- - 0 | 0.273710566446533 - 1 | NaN - 2 | Infinity - 3 | 0.271225418012403 - 4 | 0.274902188431565 - 5 | 0.278701234893647 - 6 | 0.279196201482741 - 7 | 0.281055561785383 - 8 | 0.276832673694496 - 9 | 0.276832673694496 -(10 rows) - -select count(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - count --------- - 100570 -(1 row) +select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat4), s limit 10; + s | avg +---+-------------------- + 9 | -0.376175993822296 + 5 | -0.351281471733702 + 3 | -0.328033180425701 + 6 | -0.215785538185229 + 7 | 0.0690012062121504 + 4 | 0.100205441546667 + 8 | 0.308099926433512 + 0 | 0.497406092427368 + 2 | Infinity +(9 rows) -select s, count(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | count ----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - max ------ - NaN +select max(cfloat4) from aggfns where cfloat8 <= 0; + max +---------- + Infinity (1 row) -select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by max(cfloat4), s limit 10; s | max ---+---------- - 0 | 49.9977 - 1 | NaN + 5 | 49.9753 + 9 | 49.9899 + 7 | 49.992 + 6 | 49.9938 + 4 | 49.9946 + 3 | 49.9979 + 0 | 49.9995 + 8 | 49.9997 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select min(cfloat4) from aggfns where cfloat8 <= 0 order by 1; +(9 rows) + +select min(cfloat4) from aggfns where cfloat8 <= 0; min ---------- - -49.9756 + -49.9999 (1 row) -select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by min(cfloat4), s limit 10; s | min ---+---------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 - 3 | -49.9756 - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+---------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 - 3 | -49.9756 - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select stddev(cfloat4) from aggfns where cfloat8 <= 0 order by 1; + 4 | -49.9999 + 6 | -49.9995 + 2 | -49.9991 + 7 | -49.9984 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9874 + 8 | -49.9853 + 3 | -49.974 +(9 rows) + +select stddev(cfloat4) from aggfns where cfloat8 <= 0; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8948722701767 - 1 | NaN + 0 | 28.7188352112159 + 3 | 28.7589901880779 + 4 | 28.7990664583532 + 7 | 28.8547648614793 + 6 | 28.89882973622 + 8 | 28.9050890855561 + 9 | 28.9126192916065 + 5 | 29.1278202173096 2 | NaN - 3 | 28.8971947735823 - 4 | 28.8962786797298 - 5 | 28.8969485514879 - 6 | 28.898342825597 - 7 | 28.8981465590944 - 8 | 28.8998126918449 - 9 | 28.8998126918449 -(10 rows) - -select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.8948722701767 - 1 | NaN - 2 | NaN - 3 | 28.8971947735822 - 4 | 28.8962786797298 - 5 | 28.8969485514879 - 6 | 28.898342825597 - 7 | 28.8981465590944 - 8 | 28.8998126918449 - 9 | 28.8998126918449 -(10 rows) - -select sum(cfloat4) from aggfns where cfloat8 <= 0 order by 1; - sum ------ - NaN +(9 rows) + +select sum(cfloat4) from aggfns where cfloat8 <= 0; + sum +---------- + Infinity (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat4), s limit 10; s | sum ---+---------- - 0 | 2752.71 - 1 | NaN + 9 | -3782.45 + 5 | -3522.65 + 3 | -3292.47 + 6 | -2136.92 + 7 | 688.563 + 4 | 1013.88 + 8 | 3096.4 + 0 | 5033.25 2 | Infinity - 3 | 2727.98 - 4 | 2764.69 - 5 | 2802.9 - 6 | 2807.6 - 7 | 2826.29 - 8 | 2784.11 - 9 | 2784.11 -(10 rows) - -select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+---------- - 0 | 2752.7 - 1 | NaN - 2 | Infinity - 3 | 2727.98 - 4 | 2764.68 - 5 | 2802.89 - 6 | 2807.59 - 7 | 2826.29 - 8 | 2784.1 - 9 | 2784.1 -(10 rows) - -select avg(cfloat8) from aggfns where cfloat8 <= 0 order by 1; +(9 rows) + +select avg(cfloat8) from aggfns where cfloat8 <= 0; avg ------------------- - -25.0059242142437 + -25.0131648946505 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------- - 0 | -25.0026878159296 - 1 | -25.0026878159296 - 2 | -25.0037259853644 - 3 | -25.0033035766331 - 4 | -25.0044243209649 - 5 | -25.0071564832908 - 6 | -25.0084381401581 - 7 | -25.0089627629465 - 8 | -25.0089281362381 - 9 | -25.0089281362381 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+------------------- - 0 | -25.0026878159296 - 1 | -25.0026878159296 - 2 | -25.0037259853644 - 3 | -25.0033035766331 - 4 | -25.0044243209649 - 5 | -25.0071564832908 - 6 | -25.0084381401581 - 7 | -25.0089627629465 - 8 | -25.0089281362381 - 9 | -25.0089281362381 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 <= 0 order by 1; - max ------------------------ - -0.000542588531970978 -(1 row) - -select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+----------------------- - 0 | -0.000542588531970978 - 1 | -0.000542588531970978 - 2 | -0.000542588531970978 - 3 | -0.000542588531970978 - 4 | -0.000542588531970978 - 5 | -0.000542588531970978 - 6 | -0.000542588531970978 - 7 | -0.000542588531970978 - 8 | -0.000542588531970978 - 9 | -0.000542588531970978 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+----------------------- - 0 | -0.000542588531970978 - 1 | -0.000542588531970978 - 2 | -0.000542588531970978 - 3 | -0.000542588531970978 - 4 | -0.000542588531970978 - 5 | -0.000542588531970978 - 6 | -0.000542588531970978 - 7 | -0.000542588531970978 - 8 | -0.000542588531970978 - 9 | -0.000542588531970978 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + 7 | -25.229255062715 + 8 | -25.2270239386592 + 3 | -25.1351069194284 + 0 | -25.0944548448943 + 6 | -25.0686778438405 + 9 | -24.8892608135943 + 2 | -24.8583035779324 + 4 | -24.8301394745889 + 5 | -24.7870942066272 +(9 rows) + +select max(cfloat8) from aggfns where cfloat8 <= 0; + max +---------------------- + -0.00172397121787071 +(1 row) + +select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by max(cfloat8), s limit 10; + s | max +---+---------------------- + 0 | -0.00547224190086126 + 9 | -0.00466627534478903 + 4 | -0.0041270861402154 + 6 | -0.00408347696065903 + 7 | -0.00273226760327816 + 3 | -0.00268903095275164 + 5 | -0.00228420831263065 + 8 | -0.00182925723493099 + 2 | -0.00172397121787071 +(9 rows) + +select min(cfloat8) from aggfns where cfloat8 <= 0; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + 0 | -49.9994775978848 + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 +(9 rows) + +select stddev(cfloat8) from aggfns where cfloat8 <= 0; stddev ------------------ - 14.4806777057013 + 14.4381579706012 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 14.4821730365752 - 1 | 14.4821730365752 - 2 | 14.4818272972739 - 3 | 14.4815478866618 - 4 | 14.48183169158 - 5 | 14.4805923063393 - 6 | 14.4807418968606 - 7 | 14.4812687827814 - 8 | 14.4805491499824 - 9 | 14.4805491499824 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 14.4821730365752 - 1 | 14.4821730365752 - 2 | 14.4818272972739 - 3 | 14.4815478866618 - 4 | 14.48183169158 - 5 | 14.4805923063393 - 6 | 14.4807418968606 - 7 | 14.4812687827813 - 8 | 14.4805491499824 - 9 | 14.4805491499824 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 <= 0 order by 1; + 7 | 14.4030112329564 + 2 | 14.4030502020858 + 6 | 14.4144870413512 + 4 | 14.4341540067486 + 3 | 14.4341919321977 + 5 | 14.4378475427373 + 9 | 14.445355480345 + 8 | 14.4532419971748 + 0 | 14.5136612753879 +(9 rows) + +select sum(cfloat8) from aggfns where cfloat8 <= 0; sum ------------------- - -2514845.79822649 + -2256562.67097089 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------- - 0 | -251452.031364804 - 1 | -251452.031364804 - 2 | -251487.475960795 - 3 | -251483.227373776 - 4 | -251469.495395944 - 5 | -251496.972752456 - 6 | -251484.85393743 - 7 | -251490.12954419 - 8 | -251514.790266147 - 9 | -251514.790266147 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------------------- - 0 | -251452.031364804 - 1 | -251452.031364804 - 2 | -251487.475960795 - 3 | -251483.227373776 - 4 | -251469.495395944 - 5 | -251496.972752456 - 6 | -251484.85393743 - 7 | -251490.12954419 - 8 | -251514.790266147 - 9 | -251514.790266147 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 <= 0 order by 1; - avg ------------------------ - -143.1624265950034836 -(1 row) - -select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; + 0 | -253930.788575485 + 8 | -253531.590583525 + 3 | -252281.068150303 + 7 | -251762.736270833 + 4 | -251231.351203891 + 9 | -250261.517480691 + 5 | -248564.980704058 + 6 | -248255.116687552 + 2 | -246743.521314557 +(9 rows) + +select avg(cint2) from aggfns where cfloat8 <= 0; + avg +---------------------- + -17.0676978728598218 +(1 row) + +select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by avg(cint2), s limit 10; s | avg ---+----------------------- - 0 | -145.9491390464815368 - 1 | -146.0055732484076433 - 2 | -145.5036823248407643 - 3 | -144.9877599761170266 - 4 | -141.3792931806869089 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -145.9491390464815368 - 1 | -146.0055732484076433 - 2 | -145.5036823248407643 - 3 | -144.9877599761170266 - 4 | -141.3792931806869089 - 5 | -139.5590167197452229 - 6 | -141.8382440772446745 - 7 | -144.4554140127388535 - 8 | -137.4765033851055356 - 9 | -144.4668060117447994 -(10 rows) - -select max(cint2) from aggfns where cfloat8 <= 0 order by 1; + 8 | -256.1267058471959359 + 2 | -159.7472527472527473 + 3 | -32.0911538845118181 + 6 | -23.1764884261599110 + 0 | 6.6666006927263731 + 7 | 31.4203451043338684 + 4 | 63.3268012668250198 + 5 | 66.6813373253493014 + 9 | 147.3351582719490344 +(9 rows) + +select count(cint2) from aggfns where cfloat8 <= 0; + count +------- + 90121 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 6 | 9893 + 2 | 9919 + 7 | 9968 + 5 | 10020 + 3 | 10027 + 8 | 10039 + 9 | 10046 + 4 | 10104 + 0 | 10105 +(9 rows) + +select max(cint2) from aggfns where cfloat8 <= 0; max ------- 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by max(cint2), s limit 10; s | max ---+------- - 0 | 16383 - 1 | 16383 - 2 | 16383 - 3 | 16383 + 7 | 16376 + 9 | 16376 + 3 | 16378 + 0 | 16381 + 2 | 16381 + 5 | 16381 + 8 | 16382 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 - 8 | 16383 - 9 | 16383 -(10 rows) +(9 rows) -select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------- - 0 | 16383 - 1 | 16383 - 2 | 16383 - 3 | 16383 - 4 | 16383 - 5 | 16383 - 6 | 16383 - 7 | 16383 - 8 | 16383 - 9 | 16383 -(10 rows) - -select min(cint2) from aggfns where cfloat8 <= 0 order by 1; +select min(cint2) from aggfns where cfloat8 <= 0; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by min(cint2), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 -(10 rows) - -select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 -(10 rows) + 0 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 4 | -16379 + 9 | -16374 +(9 rows) -select stddev(cint2) from aggfns where cfloat8 <= 0 order by 1; +select stddev(cint2) from aggfns where cfloat8 <= 0; stddev ------------------- - 9537.532064200194 + 9487.728001026379 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 0 | 9538.832178541630 - 1 | 9537.717255354464 - 2 | 9540.157933140146 - 3 | 9535.281475740805 - 4 | 9537.335027198989 - 5 | 9538.686769657499 - 6 | 9537.494931550558 - 7 | 9538.995155888144 - 8 | 9537.123911034158 - 9 | 9537.962959664725 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+------------------- - 0 | 9538.832178541630 - 1 | 9537.717255354464 - 2 | 9540.157933140146 - 3 | 9535.281475740805 - 4 | 9537.335027198989 - 5 | 9538.686769657499 - 6 | 9537.494931550558 - 7 | 9538.995155888144 - 8 | 9537.123911034158 - 9 | 9537.962959664725 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 <= 0 order by 1; - sum ------------ - -14383529 + 0 | 9451.115288155243 + 9 | 9456.028731464701 + 7 | 9463.041992703462 + 3 | 9485.287342318946 + 8 | 9487.451140540082 + 6 | 9502.509922580216 + 2 | 9511.416697071789 + 5 | 9513.243501566793 + 4 | 9517.027301293118 +(9 rows) + +select sum(cint2) from aggfns where cfloat8 <= 0; + sum +---------- + -1538158 (1 row) -select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by sum(cint2), s limit 10; s | sum ---+---------- - 0 | -1466351 - 1 | -1467064 - 2 | -1462021 - 3 | -1456982 - 4 | -1420155 - 5 | -1402289 - 6 | -1424907 - 7 | -1451488 - 8 | -1380814 - 9 | -1451458 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+---------- - 0 | -1466351 - 1 | -1467064 - 2 | -1462021 - 3 | -1456982 - 4 | -1420155 - 5 | -1402289 - 6 | -1424907 - 7 | -1451488 - 8 | -1380814 - 9 | -1451458 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 <= 0 order by 1; - avg ------------------------ - -2626106.025594113553 -(1 row) - -select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | avg ----+----------------------- - 0 | -2611631.507507208909 - 1 | -2611631.507507208909 - 2 | -2609754.938158679658 - 3 | -2572787.244482004375 - 4 | -2583154.535149647012 - 5 | -2738485.569155811872 - 6 | -2660373.598150357995 - 7 | -2578784.074681782021 - 8 | -2647231.455304762852 - 9 | -2647231.455304762852 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2611631.507507208909 - 1 | -2611631.507507208909 - 2 | -2609754.938158679658 - 3 | -2572787.244482004375 - 4 | -2583154.535149647012 - 5 | -2738485.569155811872 - 6 | -2660373.598150357995 - 7 | -2578784.074681782021 - 8 | -2647231.455304762852 - 9 | -2647231.455304762852 -(10 rows) - -select max(cint4) from aggfns where cfloat8 <= 0 order by 1; - max ------------- - 1073660631 + 8 | -2571256 + 2 | -1584533 + 3 | -321778 + 6 | -229285 + 0 | 67366 + 7 | 313198 + 4 | 639854 + 5 | 668147 + 9 | 1480129 +(9 rows) + +select avg(cint4) from aggfns where cfloat8 <= 0; + avg +--------------------- + -7.1110680042121598 (1 row) -select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint4) from aggfns where cfloat8 <= 0 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 <= 0 order by 1; - stddev ------------ - 618699699 +select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by avg(cint4), s limit 10; + s | avg +---+---------------------- + 8 | -88.7033830845771144 + 7 | -77.4082573404148712 + 2 | -49.3297400765665928 + 3 | -29.0496164192487795 + 0 | -21.8140132424152584 + 6 | -10.7283651418761991 + 9 | 20.8253605171556440 + 4 | 55.0605850958687488 + 5 | 136.0287195851615477 +(9 rows) + +select max(cint4) from aggfns where cfloat8 <= 0; + max +------- + 16383 (1 row) -select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+----------- - 0 | 618765816 - 1 | 618765816 - 2 | 618735080 - 3 | 618695738 - 4 | 618725626 - 5 | 618719952 - 6 | 618701125 - 7 | 618716683 - 8 | 618723996 - 9 | 618723996 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 618765816 - 1 | 618765816 - 2 | 618735080 - 3 | 618695738 - 4 | 618725626 - 5 | 618719952 - 6 | 618701125 - 7 | 618716683 - 8 | 618723996 - 9 | 618723996 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 <= 0 order by 1; - sum ---------------- - -264107482994 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+-------------- - 0 | -26265178071 - 1 | -26265178071 - 2 | -26248915168 - 3 | -25877094105 - 4 | -25978785160 - 5 | -27540949369 - 6 | -26752716903 - 7 | -25932252655 - 8 | -26623206746 - 9 | -26623206746 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+-------------- - 0 | -26265178071 - 1 | -26265178071 - 2 | -26248915168 - 3 | -25877094105 - 4 | -25978785160 - 5 | -27540949369 - 6 | -26752716903 - 7 | -25932252655 - 8 | -26623206746 - 9 | -26623206746 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 <= 0 order by 1; +select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by max(cint4), s limit 10; + s | max +---+------- + 5 | 16364 + 7 | 16378 + 3 | 16379 + 2 | 16381 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 +(9 rows) + +select min(cint4) from aggfns where cfloat8 <= 0; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16381 + 7 | -16379 + 2 | -16377 + 5 | -16374 +(9 rows) + +select stddev(cint4) from aggfns where cfloat8 <= 0; + stddev +------------------- + 9453.424778209057 +(1 row) + +select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by stddev(cint4), s limit 10; + s | stddev +---+------------------- + 9 | 9377.745829196558 + 2 | 9420.904023095068 + 6 | 9436.031206307503 + 3 | 9440.010647812753 + 0 | 9444.372352979574 + 4 | 9469.197040523380 + 7 | 9470.920199125109 + 8 | 9488.579674823607 + 5 | 9533.551517829360 +(9 rows) + +select sum(cint4) from aggfns where cfloat8 <= 0; + sum +--------- + -641525 +(1 row) + +select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by sum(cint4), s limit 10; + s | sum +---+--------- + 8 | -891469 + 7 | -772457 + 2 | -489647 + 3 | -291571 + 0 | -220736 + 6 | -106243 + 9 | 209399 + 4 | 557103 + 5 | 1364096 +(9 rows) + +select avg(cint8) from aggfns where cfloat8 <= 0; avg ---------------------- - 1589663.454419807100 + -22.2097655600509893 (1 row) -select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | avg ----+---------------------- - 0 | 1609068.184846375659 - 1 | 1609068.184846375659 - 2 | 1561674.145953469875 - 3 | 1654097.121694173792 - 4 | 1574613.534354181167 - 5 | 1583685.317888038182 - 6 | 1613166.887529832936 - 7 | 1554490.104514717582 - 8 | 1568383.139206522820 - 9 | 1568383.139206522820 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+---------------------- - 0 | 1609068.184846375659 - 1 | 1609068.184846375659 - 2 | 1561674.145953469875 - 3 | 1654097.121694173792 - 4 | 1574613.534354181167 - 5 | 1583685.317888038182 - 6 | 1613166.887529832936 - 7 | 1554490.104514717582 - 8 | 1568383.139206522820 - 9 | 1568383.139206522820 -(10 rows) - -select max(cint8) from aggfns where cfloat8 <= 0 order by 1; - max ------------- - 1073660631 +select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by avg(cint8), s limit 10; + s | avg +---+----------------------- + 2 | -156.0979246423534153 + 5 | -84.4558236936577583 + 8 | -71.0010945273631841 + 3 | -29.2546577662648202 + 0 | -11.7269493032908390 + 7 | -5.8845575708988877 + 4 | 21.3049021545760032 + 6 | 57.5590225184287590 + 9 | 78.7373446046742914 +(9 rows) + +select max(cint8) from aggfns where cfloat8 <= 0; + max +------- + 16383 (1 row) -select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint8) from aggfns where cfloat8 <= 0 order by 1; - min -------------- - -1073053412 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | min ----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------- - 0 | -1073053412 - 1 | -1073053412 - 2 | -1073053412 - 3 | -1073053412 - 4 | -1073053412 - 5 | -1073053412 - 6 | -1073053412 - 7 | -1073053412 - 8 | -1073053412 - 9 | -1073053412 -(10 rows) - -select stddev(cint8) from aggfns where cfloat8 <= 0 order by 1; - stddev ------------ - 617379684 +select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16379 + 8 | 16379 + 6 | 16380 + 7 | 16380 + 5 | 16381 + 9 | 16381 + 3 | 16382 + 0 | 16383 + 4 | 16383 +(9 rows) + +select min(cint8) from aggfns where cfloat8 <= 0; + min +-------- + -16383 (1 row) -select s, stddev(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+----------- - 0 | 617360997 - 1 | 617360997 - 2 | 617348601 - 3 | 617433171 - 4 | 617412408 - 5 | 617401473 - 6 | 617425094 - 7 | 617462874 - 8 | 617433744 - 9 | 617433744 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+----------- - 0 | 617360997 - 1 | 617360997 - 2 | 617348601 - 3 | 617433171 - 4 | 617412408 - 5 | 617401473 - 6 | 617425094 - 7 | 617462874 - 8 | 617433744 - 9 | 617433744 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 <= 0 order by 1; - sum --------------- - 159872453611 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+------------- - 0 | 16182398735 - 1 | 16182398735 - 2 | 15707318560 - 3 | 16636908850 - 4 | 15835888315 - 5 | 15927123242 - 6 | 16222006221 - 7 | 15631952491 - 8 | 15773229231 - 9 | 15773229231 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------------- - 0 | 16182398735 - 1 | 16182398735 - 2 | 15707318560 - 3 | 16636908850 - 4 | 15835888315 - 5 | 15927123242 - 6 | 16222006221 - 7 | 15631952491 - 8 | 15773229231 - 9 | 15773229231 -(10 rows) - -select max(cts) from aggfns where cfloat8 <= 0 order by 1; +select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 6 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 7 | -16381 + 2 | -16375 + 3 | -16375 + 9 | -16372 +(9 rows) + +select sum(cint8) from aggfns where cfloat8 <= 0; + sum +---------- + -2003654 +(1 row) + +select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 2 | -1549428 + 5 | -846923 + 8 | -713561 + 3 | -293629 + 0 | -118665 + 7 | -58722 + 4 | 215563 + 6 | 570007 + 9 | 791704 +(9 rows) + +select max(cts) from aggfns where cfloat8 <= 0; max -------------------------- - Sat Jan 02 07:34:20 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:00 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:00 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:20 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:20 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:00 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:00 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:20 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:20 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(9 rows) + +select min(cts) from aggfns where cfloat8 <= 0; min -------------------------- - Fri Jan 01 01:01:04 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:04 2021 - 1 | Fri Jan 01 03:47:43 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:45 2021 - 8 | Fri Jan 01 23:14:24 2021 - 9 | Sat Jan 02 02:01:03 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+-------------------------- - 0 | Fri Jan 01 01:01:04 2021 - 1 | Fri Jan 01 03:47:43 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:45 2021 - 8 | Fri Jan 01 23:14:24 2021 - 9 | Sat Jan 02 02:01:03 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(9 rows) + +select max(ctstz) from aggfns where cfloat8 <= 0; max ------------------------------ - Sat Jan 02 07:34:20 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:00 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:00 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:20 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:20 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:00 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:00 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:20 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:20 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(9 rows) + +select min(ctstz) from aggfns where cfloat8 <= 0; min ------------------------------ - Fri Jan 01 01:01:04 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:04 2021 PST - 1 | Fri Jan 01 03:47:43 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:45 2021 PST - 8 | Fri Jan 01 23:14:24 2021 PST - 9 | Sat Jan 02 02:01:03 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------------------------------ - 0 | Fri Jan 01 01:01:04 2021 PST - 1 | Fri Jan 01 03:47:43 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:45 2021 PST - 8 | Fri Jan 01 23:14:24 2021 PST - 9 | Sat Jan 02 02:01:03 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 <= 0 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(9 rows) + +select avg(s) from aggfns where cfloat8 <= 0; avg -------------------- - 4.4999204534155315 + 4.8854514216039461 (1 row) -select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 @@ -4520,70 +2707,38 @@ select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 -(10 rows) +(9 rows) -select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select count(s) from aggfns where cfloat8 <= 0 order by 1; - count --------- - 100570 +select count(s) from aggfns where cfloat8 <= 0; + count +------- + 90215 (1 row) -select s, count(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, count(s) from aggfns where cfloat8 <= 0 group by s order by count(s), s limit 10; s | count ---+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | count -----+------- - 0 | 10057 - 1 | 10057 - 2 | 10058 - 3 | 10058 - 4 | 10057 - 5 | 10057 - 6 | 10056 - 7 | 10056 - 8 | 10057 - 9 | 10057 -(10 rows) - -select max(s) from aggfns where cfloat8 <= 0 order by 1; + 6 | 9903 + 2 | 9926 + 7 | 9979 + 5 | 10028 + 3 | 10037 + 8 | 10050 + 9 | 10055 + 4 | 10118 + 0 | 10119 +(9 rows) + +select max(s) from aggfns where cfloat8 <= 0; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(s) from aggfns where cfloat8 <= 0 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 - 1 | 1 2 | 2 3 | 3 4 | 4 @@ -4592,34 +2747,18 @@ select s, max(s) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 -(10 rows) +(9 rows) -select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(s) from aggfns where cfloat8 <= 0 order by 1; +select min(s) from aggfns where cfloat8 <= 0; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(s) from aggfns where cfloat8 <= 0 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 - 1 | 1 2 | 2 3 | 3 4 | 4 @@ -4628,34 +2767,18 @@ select s, min(s) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 -(10 rows) +(9 rows) -select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(s) from aggfns where cfloat8 <= 0 order by 1; +select stddev(s) from aggfns where cfloat8 <= 0; stddev -------------------- - 2.8722956022845549 + 2.7706747160155654 (1 row) -select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 - 1 | 0 2 | 0 3 | 0 4 | 0 @@ -4664,143 +2787,78 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 0 8 | 0 9 | 0 -(10 rows) +(9 rows) -select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(s) from aggfns where cfloat8 <= 0 order by 1; +select sum(s) from aggfns where cfloat8 <= 0; sum -------- - 452557 + 440741 (1 row) -select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select avg(ss) from aggfns where cfloat8 <= 0 order by 1; + 2 | 19852 + 3 | 30111 + 4 | 40472 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 +(9 rows) + +select avg(ss) from aggfns where cfloat8 <= 0; avg -------------------- - 4.4999204534155315 + 5.8765755079870079 (1 row) -select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0062265269816169 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 -(10 rows) + 2 | 11.0000000000000000 +(9 rows) -select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select max(ss) from aggfns where cfloat8 <= 0 order by 1; +select max(ss) from aggfns where cfloat8 <= 0; max ----- - 9 + 11 (1 row) -select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 - 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 -(10 rows) + 2 | 11 + 4 | 11 +(9 rows) -select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(ss) from aggfns where cfloat8 <= 0 order by 1; +select min(ss) from aggfns where cfloat8 <= 0; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -4808,282 +2866,96 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by 1; 7 | 7 8 | 8 9 | 9 -(10 rows) + 2 | 11 +(9 rows) -select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(ss) from aggfns where cfloat8 <= 0 order by 1; +select stddev(ss) from aggfns where cfloat8 <= 0; stddev -------------------- - 2.8722956022845549 + 3.1457968709791645 (1 row) -select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(ss) from aggfns where cfloat8 <= 0 order by 1; +select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by stddev(ss), s limit 10; + s | stddev +---+------------------------ + 0 | 0 + 2 | 0 + 3 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 4 | 0.20868929911309143893 +(9 rows) + +select sum(ss) from aggfns where cfloat8 <= 0; sum -------- - 452557 + 530120 (1 row) -select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by 1; - s | sum ----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | sum -----+------- - 0 | 0 - 1 | 10057 - 2 | 20116 - 3 | 30174 - 4 | 40228 - 5 | 50285 - 6 | 60336 - 7 | 70392 - 8 | 80456 - 9 | 90513 -(10 rows) - -select max(t) from aggfns where cfloat8 <= 0 order by 1; +select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by sum(ss), s limit 10; + s | sum +---+-------- + 0 | 0 + 3 | 30093 + 4 | 40535 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 + 2 | 109186 +(9 rows) + +select max(t) from aggfns where cfloat8 <= 0; max -------- - 109999 + 109998 (1 row) -select s, max(t) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, max(t) from aggfns where cfloat8 <= 0 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 - 1 | 29999 2 | 40000 3 | 50000 - 4 | 59999 - 5 | 70000 - 6 | 79999 + 4 | 59998 + 5 | 69999 + 6 | 80000 7 | 90000 8 | 100000 - 9 | 109999 -(10 rows) + 9 | 109998 +(9 rows) -select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | max -----+-------- - 0 | 20000 - 1 | 29999 - 2 | 40000 - 3 | 50000 - 4 | 59999 - 5 | 70000 - 6 | 79999 - 7 | 90000 - 8 | 100000 - 9 | 109999 -(10 rows) - -select min(t) from aggfns where cfloat8 <= 0 order by 1; +select min(t) from aggfns where cfloat8 <= 0; min ----- - 3 + 8 (1 row) -select s, min(t) from aggfns where cfloat8 <= 0 group by s order by 1; +select s, min(t) from aggfns where cfloat8 <= 0 group by s order by min(t), s limit 10; s | min ---+------- - 0 | 3 - 1 | 10002 - 2 | 20001 - 3 | 30001 + 0 | 8 + 2 | 20003 + 3 | 30002 4 | 40001 - 5 | 50001 + 5 | 50004 6 | 60001 - 7 | 70004 - 8 | 80003 - 9 | 90002 -(10 rows) - -select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by 1; - ss | min -----+------- - 0 | 3 - 1 | 10002 - 2 | 20001 - 3 | 30001 - 4 | 40001 - 5 | 50001 - 6 | 60001 - 7 | 70004 - 8 | 80003 - 9 | 90002 -(10 rows) - -select max(cdate) from aggfns where cfloat8 < 1000 order by 1; - max ------------- - 03-05-2322 -(1 row) - -select s, max(cdate) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------ - 0 | 10-05-2075 - 1 | 02-21-2103 - 2 | 07-09-2130 - 3 | 11-24-2157 - 4 | 04-11-2185 - 5 | 08-28-2212 - 6 | 01-14-2240 - 7 | 06-01-2267 - 8 | 10-17-2294 - 9 | 03-05-2322 -(10 rows) - -select min(cdate) from aggfns where cfloat8 < 1000 order by 1; - min ------------- - 01-02-2021 -(1 row) - -select s, min(cdate) from aggfns where cfloat8 < 1000 group by s order by 1; - s | min ----+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------ - 0 | 01-02-2021 - 1 | 05-20-2048 - 2 | 10-06-2075 - 3 | 02-22-2103 - 4 | 07-10-2130 - 5 | 11-25-2157 - 6 | 04-12-2185 - 7 | 08-29-2212 - 8 | 01-15-2240 - 9 | 06-02-2267 -(10 rows) - -select avg(cfloat4) from aggfns where cfloat8 < 1000 order by 1; - avg ------ - NaN -(1 row) + 7 | 70002 + 8 | 80001 + 9 | 90001 +(9 rows) -select s, avg(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.132126759885764 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -0.13252146150968 - 5 | -0.130611110996222 - 6 | -0.131984978889441 - 7 | -0.131050092529273 - 8 | -0.131313872741675 - 9 | -0.132765194868064 -(10 rows) - -select count(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select count(*) from aggfns where cfloat8 < 1000; count -------- 200000 (1 row) -select s, count(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, count(*) from aggfns where cfloat8 < 1000 group by s order by count(*), s limit 10; s | count ---+------- 0 | 20000 @@ -5098,1036 +2970,664 @@ select s, count(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) -select ss, count(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select max(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +select max(cdate) from aggfns where cfloat8 < 1000; + max +------------ + 06-01-2267 +(1 row) + +select s, max(cdate) from aggfns where cfloat8 < 1000 group by s order by max(cdate), s limit 10; + s | max +---+------------ + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select min(cdate) from aggfns where cfloat8 < 1000; + min +------------ + 01-01-2021 +(1 row) + +select s, min(cdate) from aggfns where cfloat8 < 1000 group by s order by min(cdate), s limit 10; + s | min +---+------------ + 0 | 01-01-2021 + 1 | 05-19-2048 + 2 | 10-05-2075 + 3 | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + +select avg(cfloat4) from aggfns where cfloat8 < 1000; + avg +----- + NaN +(1 row) + +select s, avg(cfloat4) from aggfns where cfloat8 < 1000 group by s order by avg(cfloat4), s limit 10; + s | avg +---+---------------------- + 3 | -Infinity + 9 | -0.292700759558938 + 4 | -0.177721596086072 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 2 | Infinity + 1 | NaN +(10 rows) + +select max(cfloat4) from aggfns where cfloat8 < 1000; max ----- NaN (1 row) -select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by max(cfloat4), s limit 10; s | max ---+---------- - 0 | 49.9977 - 1 | NaN + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+---------- - 0 | 49.9977 - 1 | NaN - 2 | Infinity - 3 | 49.9977 - 4 | 49.9977 - 5 | 49.9977 - 6 | 49.9977 - 7 | 49.9977 - 8 | 49.9977 - 9 | 49.9977 -(10 rows) - -select min(cfloat4) from aggfns where cfloat8 < 1000 order by 1; + 1 | NaN +(10 rows) + +select min(cfloat4) from aggfns where cfloat8 < 1000; min ----------- -Infinity (1 row) -select s, min(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 < 1000 group by s order by min(cfloat4), s limit 10; s | min ---+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+----------- - 0 | -49.9756 - 1 | -49.9756 - 2 | -49.9756 - 3 | -Infinity - 4 | -49.9756 - 5 | -49.9756 - 6 | -49.9756 - 7 | -49.9756 - 8 | -49.9756 - 9 | -49.9756 -(10 rows) - -select stddev(cfloat4) from aggfns where cfloat8 < 1000 order by 1; + 4 | -49.9999 + 6 | -49.9995 + 2 | -49.9991 + 7 | -49.9984 + 1 | -49.9974 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 +(10 rows) + +select stddev(cfloat4) from aggfns where cfloat8 < 1000; stddev -------- NaN (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 0 | 28.8941380063426 + 0 | 28.7274163912974 + 7 | 28.7892027644317 + 4 | 28.8273136003882 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270615 1 | NaN 2 | NaN 3 | NaN - 4 | 28.8948189281653 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301629 - 8 | 28.8963276918371 - 9 | 28.8968307405967 -(10 rows) - -select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.8941380063427 - 1 | NaN - 2 | NaN - 3 | NaN - 4 | 28.8948189281654 - 5 | 28.8951827753267 - 6 | 28.8960531969495 - 7 | 28.8959678301628 - 8 | 28.8963276918371 - 9 | 28.8968307405966 -(10 rows) - -select sum(cfloat4) from aggfns where cfloat8 < 1000 order by 1; +(10 rows) + +select sum(cfloat4) from aggfns where cfloat8 < 1000; sum ----- NaN (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 < 1000 group by s order by sum(cfloat4), s limit 10; s | sum ---+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 -(10 rows) - -select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+----------- - 0 | -2642.54 - 1 | NaN - 2 | Infinity - 3 | -Infinity - 4 | -2650.43 - 5 | -2612.22 - 6 | -2639.7 - 7 | -2621 - 8 | -2626.28 - 9 | -2655.3 -(10 rows) - -select avg(cfloat8) from aggfns where cfloat8 < 1000 order by 1; - avg --------------------- - -0.131776180773973 + 9 | -5854.02 + 4 | -3554.43 + 6 | -122.193 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 2 | Infinity + 1 | NaN +(10 rows) + +select avg(cfloat8) from aggfns where cfloat8 < 1000; + avg +----------------- + 1.2289014329263 (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by avg(cfloat8), s limit 10; s | avg ---+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+-------------------- - 0 | -0.131261021163082 - 1 | -0.129096584053477 - 2 | -0.132733892038232 - 3 | -0.132521462687291 - 4 | -0.130611112199258 - 5 | -0.131984980024863 - 6 | -0.131050093692029 - 7 | -0.13131387403002 - 8 | -0.132765196124092 - 9 | -0.134423591727391 -(10 rows) - -select max(cfloat8) from aggfns where cfloat8 < 1000 order by 1; - max ------------------ - 49.997744965367 -(1 row) - -select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+----------------- - 0 | 49.997744965367 - 1 | 49.997744965367 - 2 | 49.997744965367 - 3 | 49.997744965367 - 4 | 49.997744965367 - 5 | 49.997744965367 - 6 | 49.997744965367 - 7 | 49.997744965367 - 8 | 49.997744965367 - 9 | 49.997744965367 -(10 rows) - -select min(cfloat8) from aggfns where cfloat8 < 1000 order by 1; + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.220256273869891 + 3 | -0.14819676399231 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + 2 | 0.198140166982776 + 1 | 13 +(10 rows) + +select max(cfloat8) from aggfns where cfloat8 < 1000; + max +------------------ + 49.9995574122295 +(1 row) + +select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by max(cfloat8), s limit 10; + s | max +---+------------------ + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + +select min(cfloat8) from aggfns where cfloat8 < 1000; min ------------------- - -49.9755693599582 + -49.9994775978848 (1 row) -select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by min(cfloat8), s limit 10; s | min ---+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------------- - 0 | -49.9755693599582 - 1 | -49.9755693599582 - 2 | -49.9755693599582 - 3 | -49.9755693599582 - 4 | -49.9755693599582 - 5 | -49.9755693599582 - 6 | -49.9755693599582 - 7 | -49.9755693599582 - 8 | -49.9755693599582 - 9 | -49.9755693599582 -(10 rows) - -select stddev(cfloat8) from aggfns where cfloat8 < 1000 order by 1; - stddev ------------------ - 28.894749851557 + 0 | -49.9994775978848 + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + 1 | 13 +(10 rows) + +select stddev(cfloat8) from aggfns where cfloat8 < 1000; + stddev +------------------ + 27.6606134001179 (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840889 - 5 | 28.8960532056264 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+------------------ - 0 | 28.893219634188 - 1 | 28.8952055755515 - 2 | 28.8950722121689 - 3 | 28.8948189369737 - 4 | 28.8951827840888 - 5 | 28.8960532056265 - 6 | 28.8959678388464 - 7 | 28.8963277006942 - 8 | 28.8968307494196 - 9 | 28.8953209642426 -(10 rows) - -select sum(cfloat8) from aggfns where cfloat8 < 1000 order by 1; - sum -------------------- - -26355.2361547947 + 1 | 0 + 2 | 28.7611066711723 + 9 | 28.7642081921344 + 4 | 28.77864036235 + 5 | 28.7843925303698 + 6 | 28.8543767497509 + 3 | 28.9210796983077 + 8 | 28.96331707256 + 0 | 28.965342556856 + 7 | 28.9656492103737 +(10 rows) + +select sum(cfloat8) from aggfns where cfloat8 < 1000; + sum +----------------- + 245780.28658526 (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+------------------- - 0 | -2625.22042326164 - 1 | -2581.93168106955 - 2 | -2654.67784076463 - 3 | -2650.42925374582 - 4 | -2612.22224398516 - 5 | -2639.69960049726 - 6 | -2621.00187384058 - 7 | -2626.2774806004 - 8 | -2655.30392248183 - 9 | -2688.47183454782 -(10 rows) - -select avg(cint2) from aggfns where cfloat8 < 1000 order by 1; + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4405.12547739781 + 3 | -2963.93527984619 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 2 | 3962.80333965551 + 1 | 260000 +(10 rows) + +select avg(cint2) from aggfns where cfloat8 < 1000; avg ---------------------- - -42.1591712126520194 + -33.1461788699264301 +(1 row) + +select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by avg(cint2), s limit 10; + s | avg +---+----------------------- + 2 | -158.3178019118162254 + 8 | -129.4959711726139833 + 3 | -95.7656773935238477 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 4 | -28.7127771382813673 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 1 | 91.9493518842900756 + 5 | 110.0305290025524248 +(10 rows) + +select count(cint2) from aggfns where cfloat8 < 1000; + count +-------- + 199810 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select max(cint2) from aggfns where cfloat8 < 1000; + max +------- + 16383 +(1 row) + +select s, max(cint2) from aggfns where cfloat8 < 1000 group by s order by max(cint2), s limit 10; + s | max +---+------- + 3 | 16380 + 2 | 16381 + 5 | 16381 + 7 | 16381 + 8 | 16382 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 6 | 16383 + 9 | 16383 +(10 rows) + +select min(cint2) from aggfns where cfloat8 < 1000; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from aggfns where cfloat8 < 1000 group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select stddev(cint2) from aggfns where cfloat8 < 1000; + stddev +------------------- + 9475.597346265432 +(1 row) + +select s, stddev(cint2) from aggfns where cfloat8 < 1000 group by s order by stddev(cint2), s limit 10; + s | stddev +---+------------------- + 9 | 9450.322790943425 + 2 | 9458.737760855119 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9473.424234931108 + 8 | 9477.586839536066 + 4 | 9483.720025499142 + 0 | 9484.907423282680 + 1 | 9528.039076724276 +(10 rows) + +select sum(cint2) from aggfns where cfloat8 < 1000; + sum +---------- + -6622938 +(1 row) + +select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by sum(cint2), s limit 10; + s | sum +---+---------- + 2 | -3163348 + 8 | -2587459 + 3 | -1913494 + 6 | -1220352 + 7 | -1116329 + 4 | -573710 + 9 | -435575 + 0 | 351569 + 1 | 1837240 + 5 | 2198520 +(10 rows) + +select avg(cint4) from aggfns where cfloat8 < 1000; + avg +--------------------- + -4.9369150000000000 (1 row) -select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+---------------------- - 0 | -42.2972824182973825 - 1 | -43.0287773384715480 - 2 | -40.9893899204244032 - 3 | -42.8851408838396477 - 4 | -42.0152144537310445 - 5 | -43.5287022671537961 - 6 | -41.7711325759471498 - 7 | -41.3288123717531655 - 8 | -40.6353035383614434 - 9 | -43.1119563585406136 -(10 rows) - -select max(cint2) from aggfns where cfloat8 < 1000 order by 1; +select s, avg(cint4) from aggfns where cfloat8 < 1000 group by s order by avg(cint4), s limit 10; + s | avg +---+----------------------- + 9 | -102.4283000000000000 + 2 | -101.3952000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 4 | 6.6530500000000000 + 0 | 27.7536500000000000 + 3 | 70.4102500000000000 + 1 | 71.5608500000000000 + 5 | 103.1069000000000000 +(10 rows) + +select max(cint4) from aggfns where cfloat8 < 1000; max ------- 16383 (1 row) -select s, max(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cint4) from aggfns where cfloat8 < 1000 group by s order by max(cint4), s limit 10; s | max ---+------- + 3 | 16379 + 5 | 16379 + 7 | 16379 + 2 | 16381 0 | 16383 1 | 16383 - 2 | 16383 - 3 | 16383 4 | 16383 - 5 | 16383 6 | 16383 - 7 | 16383 8 | 16383 9 | 16383 (10 rows) -select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------- - 0 | 16383 - 1 | 16383 - 2 | 16383 - 3 | 16383 - 4 | 16383 - 5 | 16383 - 6 | 16383 - 7 | 16383 - 8 | 16383 - 9 | 16383 -(10 rows) - -select min(cint2) from aggfns where cfloat8 < 1000 order by 1; +select min(cint4) from aggfns where cfloat8 < 1000; min -------- - -16375 + -16383 (1 row) -select s, min(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cint4) from aggfns where cfloat8 < 1000 group by s order by min(cint4), s limit 10; s | min ---+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 -(10 rows) - -select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+-------- - 0 | -16375 - 1 | -16375 - 2 | -16375 - 3 | -16375 - 4 | -16375 - 5 | -16375 - 6 | -16375 - 7 | -16375 - 8 | -16375 - 9 | -16375 -(10 rows) - -select stddev(cint2) from aggfns where cfloat8 < 1000 order by 1; + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select stddev(cint4) from aggfns where cfloat8 < 1000; stddev ------------------- - 9467.689085960139 + 9450.334382392243 (1 row) -select s, stddev(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(cint4) from aggfns where cfloat8 < 1000 group by s order by stddev(cint4), s limit 10; s | stddev ---+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+------------------- - 0 | 9468.854793575036 - 1 | 9468.590431229826 - 2 | 9469.116705177088 - 3 | 9466.421782354268 - 4 | 9467.442985677590 - 5 | 9467.599133444078 - 6 | 9468.362090451302 - 7 | 9467.745653535755 - 8 | 9466.743345080951 - 9 | 9468.145452253715 -(10 rows) - -select sum(cint2) from aggfns where cfloat8 < 1000 order by 1; - sum ----------- - -8423824 + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 2 | 9440.675087350597 + 4 | 9443.098516157448 + 8 | 9450.281544631633 + 1 | 9459.538662433945 + 3 | 9474.762271621918 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + +select sum(cint4) from aggfns where cfloat8 < 1000; + sum +--------- + -987383 (1 row) -select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+--------- - 0 | -845142 - 1 | -859758 - 2 | -819009 - 3 | -856888 - 4 | -839506 - 5 | -869747 - 6 | -834629 - 7 | -825791 - 8 | -811934 - 9 | -861420 -(10 rows) - -select avg(cint4) from aggfns where cfloat8 < 1000 order by 1; - avg ------------------------ - -2833327.786810000000 -(1 row) - -select s, avg(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by sum(cint4), s limit 10; + s | sum +---+---------- + 9 | -2048566 + 2 | -2027904 + 6 | -1063133 + 7 | -852243 + 8 | -585231 + 4 | 133061 + 0 | 555073 + 3 | 1408205 + 1 | 1431217 + 5 | 2062138 +(10 rows) + +select avg(cint8) from aggfns where cfloat8 < 1000; + avg +---------------------- + -12.1026800000000000 +(1 row) + +select s, avg(cint8) from aggfns where cfloat8 < 1000 group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2919248.121000000000 - 1 | -2836378.364750000000 - 2 | -2837313.994650000000 - 3 | -2818722.941500000000 - 4 | -2772243.427000000000 - 5 | -2850351.637450000000 - 6 | -2845789.891100000000 - 7 | -2804766.678700000000 - 8 | -2834269.365200000000 - 9 | -2814193.446750000000 -(10 rows) - -select max(cint4) from aggfns where cfloat8 < 1000 order by 1; - max ------------- - 1073660631 + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 1 | -25.4401500000000000 + 4 | -19.5071500000000000 + 2 | -2.4691500000000000 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 39.9743500000000000 + 9 | 61.7467500000000000 +(10 rows) + +select max(cint8) from aggfns where cfloat8 < 1000; + max +------- + 16383 (1 row) -select s, max(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint4) from aggfns where cfloat8 < 1000 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint4) from aggfns where cfloat8 < 1000 order by 1; - stddev ------------ - 620480022 -(1 row) +select s, max(cint8) from aggfns where cfloat8 < 1000 group by s order by max(cint8), s limit 10; + s | max +---+------- + 2 | 16379 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 1 | 16383 + 4 | 16383 + 5 | 16383 +(10 rows) -select s, stddev(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+----------- - 0 | 620497458 - 1 | 620477996 - 2 | 620477953 - 3 | 620458232 - 4 | 620500878 - 5 | 620498014 - 6 | 620492575 - 7 | 620500389 - 8 | 620519080 - 9 | 620517247 -(10 rows) - -select sum(cint4) from aggfns where cfloat8 < 1000 order by 1; - sum ---------------- - -566665557362 -(1 row) - -select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -58384962420 - 1 | -56727567295 - 2 | -56746279893 - 3 | -56374458830 - 4 | -55444868540 - 5 | -57007032749 - 6 | -56915797822 - 7 | -56095333574 - 8 | -56685387304 - 9 | -56283868935 -(10 rows) - -select avg(cint8) from aggfns where cfloat8 < 1000 order by 1; - avg ------------------------ - -2823388.766060000000 -(1 row) - -select s, avg(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | avg ----+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+----------------------- - 0 | -2836378.364750000000 - 1 | -2837313.994650000000 - 2 | -2818722.941500000000 - 3 | -2772243.427000000000 - 4 | -2850351.637450000000 - 5 | -2845789.891100000000 - 6 | -2804766.678700000000 - 7 | -2834269.365200000000 - 8 | -2814193.446750000000 - 9 | -2819857.913500000000 -(10 rows) - -select max(cint8) from aggfns where cfloat8 < 1000 order by 1; - max ------------- - 1073660631 +select min(cint8) from aggfns where cfloat8 < 1000; + min +-------- + -16383 (1 row) -select s, max(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | max ----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------ - 0 | 1073660631 - 1 | 1073660631 - 2 | 1073660631 - 3 | 1073660631 - 4 | 1073660631 - 5 | 1073660631 - 6 | 1073660631 - 7 | 1073660631 - 8 | 1073660631 - 9 | 1073660631 -(10 rows) - -select min(cint8) from aggfns where cfloat8 < 1000 order by 1; - min -------------- - -1073184428 -(1 row) - -select s, min(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | min ----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------- - 0 | -1073184428 - 1 | -1073184428 - 2 | -1073184428 - 3 | -1073184428 - 4 | -1073184428 - 5 | -1073184428 - 6 | -1073184428 - 7 | -1073184428 - 8 | -1073184428 - 9 | -1073184428 -(10 rows) - -select stddev(cint8) from aggfns where cfloat8 < 1000 order by 1; - stddev ------------ - 620482773 +select s, min(cint8) from aggfns where cfloat8 < 1000 group by s order by min(cint8), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 2 | -16379 + 3 | -16378 +(10 rows) + +select sum(cint8) from aggfns where cfloat8 < 1000; + sum +---------- + -2420536 (1 row) -select s, stddev(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+----------- - 0 | 620477996 - 1 | 620477953 - 2 | 620458232 - 3 | 620500878 - 4 | 620498014 - 5 | 620492575 - 6 | 620500389 - 7 | 620519080 - 8 | 620517247 - 9 | 620524975 -(10 rows) - -select sum(cint8) from aggfns where cfloat8 < 1000 order by 1; - sum ---------------- - -564677753212 -(1 row) - -select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by 1; - s | sum ----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------------- - 0 | -56727567295 - 1 | -56746279893 - 2 | -56374458830 - 3 | -55444868540 - 4 | -57007032749 - 5 | -56915797822 - 6 | -56095333574 - 7 | -56685387304 - 8 | -56283868935 - 9 | -56397158270 -(10 rows) - -select max(cts) from aggfns where cfloat8 < 1000 order by 1; +select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by sum(cint8), s limit 10; + s | sum +---+---------- + 8 | -2369740 + 5 | -1633911 + 1 | -508803 + 4 | -390143 + 2 | -49383 + 7 | -47127 + 6 | 238113 + 0 | 306036 + 3 | 799487 + 9 | 1234935 +(10 rows) + +select max(cts) from aggfns where cfloat8 < 1000; max -------------------------- - Sat Jan 02 07:34:21 2021 + Sat Jan 02 02:01:01 2021 (1 row) -select s, max(cts) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 < 1000 group by s order by max(cts), s limit 10; s | max ---+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+-------------------------- - 0 | Fri Jan 01 06:34:21 2021 - 1 | Fri Jan 01 09:21:01 2021 - 2 | Fri Jan 01 12:07:41 2021 - 3 | Fri Jan 01 14:54:21 2021 - 4 | Fri Jan 01 17:41:01 2021 - 5 | Fri Jan 01 20:27:41 2021 - 6 | Fri Jan 01 23:14:21 2021 - 7 | Sat Jan 02 02:01:01 2021 - 8 | Sat Jan 02 04:47:41 2021 - 9 | Sat Jan 02 07:34:21 2021 -(10 rows) - -select min(cts) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select min(cts) from aggfns where cfloat8 < 1000; min -------------------------- - Fri Jan 01 01:01:02 2021 + Fri Jan 01 01:01:01 2021 (1 row) -select s, min(cts) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 < 1000 group by s order by min(cts), s limit 10; s | min ---+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+-------------------------- - 0 | Fri Jan 01 01:01:02 2021 - 1 | Fri Jan 01 03:47:42 2021 - 2 | Fri Jan 01 06:34:22 2021 - 3 | Fri Jan 01 09:21:02 2021 - 4 | Fri Jan 01 12:07:42 2021 - 5 | Fri Jan 01 14:54:22 2021 - 6 | Fri Jan 01 17:41:02 2021 - 7 | Fri Jan 01 20:27:42 2021 - 8 | Fri Jan 01 23:14:22 2021 - 9 | Sat Jan 02 02:01:02 2021 -(10 rows) - -select max(ctstz) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 + 1 | Fri Jan 01 03:47:41 2021 + 2 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + +select max(ctstz) from aggfns where cfloat8 < 1000; max ------------------------------ - Sat Jan 02 07:34:21 2021 PST + Sat Jan 02 02:01:01 2021 PST (1 row) -select s, max(ctstz) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 < 1000 group by s order by max(ctstz), s limit 10; s | max ---+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+------------------------------ - 0 | Fri Jan 01 06:34:21 2021 PST - 1 | Fri Jan 01 09:21:01 2021 PST - 2 | Fri Jan 01 12:07:41 2021 PST - 3 | Fri Jan 01 14:54:21 2021 PST - 4 | Fri Jan 01 17:41:01 2021 PST - 5 | Fri Jan 01 20:27:41 2021 PST - 6 | Fri Jan 01 23:14:21 2021 PST - 7 | Sat Jan 02 02:01:01 2021 PST - 8 | Sat Jan 02 04:47:41 2021 PST - 9 | Sat Jan 02 07:34:21 2021 PST -(10 rows) - -select min(ctstz) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 < 1000; min ------------------------------ - Fri Jan 01 01:01:02 2021 PST + Fri Jan 01 01:01:01 2021 PST (1 row) -select s, min(ctstz) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 < 1000 group by s order by min(ctstz), s limit 10; s | min ---+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------------------------------ - 0 | Fri Jan 01 01:01:02 2021 PST - 1 | Fri Jan 01 03:47:42 2021 PST - 2 | Fri Jan 01 06:34:22 2021 PST - 3 | Fri Jan 01 09:21:02 2021 PST - 4 | Fri Jan 01 12:07:42 2021 PST - 5 | Fri Jan 01 14:54:22 2021 PST - 6 | Fri Jan 01 17:41:02 2021 PST - 7 | Fri Jan 01 20:27:42 2021 PST - 8 | Fri Jan 01 23:14:22 2021 PST - 9 | Sat Jan 02 02:01:02 2021 PST -(10 rows) - -select avg(s) from aggfns where cfloat8 < 1000 order by 1; + 0 | Fri Jan 01 01:01:01 2021 PST + 1 | Fri Jan 01 03:47:41 2021 PST + 2 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select avg(s) from aggfns where cfloat8 < 1000; avg -------------------- 4.5000000000000000 (1 row) -select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 @@ -6142,28 +3642,13 @@ select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9.0000000000000000 (10 rows) -select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select count(s) from aggfns where cfloat8 < 1000 order by 1; +select count(s) from aggfns where cfloat8 < 1000; count -------- 200000 (1 row) -select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, count(s) from aggfns where cfloat8 < 1000 group by s order by count(s), s limit 10; s | count ---+------- 0 | 20000 @@ -6178,28 +3663,13 @@ select s, count(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 20000 (10 rows) -select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | count -----+------- - 0 | 20000 - 1 | 20000 - 2 | 20000 - 3 | 20000 - 4 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 -(10 rows) - -select max(s) from aggfns where cfloat8 < 1000 order by 1; +select max(s) from aggfns where cfloat8 < 1000; max ----- 9 (1 row) -select s, max(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(s) from aggfns where cfloat8 < 1000 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 @@ -6214,28 +3684,13 @@ select s, max(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9 (10 rows) -select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(s) from aggfns where cfloat8 < 1000 order by 1; +select min(s) from aggfns where cfloat8 < 1000; min ----- 0 (1 row) -select s, min(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(s) from aggfns where cfloat8 < 1000 group by s order by min(s), s limit 10; s | min ---+----- 0 | 0 @@ -6250,28 +3705,13 @@ select s, min(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 9 (10 rows) -select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(s) from aggfns where cfloat8 < 1000 order by 1; +select stddev(s) from aggfns where cfloat8 < 1000; stddev -------------------- 2.8722885039992502 (1 row) -select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 @@ -6286,28 +3726,13 @@ select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 0 (10 rows) -select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(s) from aggfns where cfloat8 < 1000 order by 1; +select sum(s) from aggfns where cfloat8 < 1000; sum -------- 900000 (1 row) -select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by sum(s), s limit 10; s | sum ---+-------- 0 | 0 @@ -6322,105 +3747,58 @@ select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 180000 (10 rows) -select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------- - 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 - 5 | 100000 - 6 | 120000 - 7 | 140000 - 8 | 160000 - 9 | 180000 -(10 rows) - -select avg(ss) from aggfns where cfloat8 < 1000 order by 1; +select avg(ss) from aggfns where cfloat8 < 1000; avg -------------------- - 4.5000000000000000 + 6.4009880938689175 (1 row) -select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by avg(ss), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0000000000000000 + 4 | 4.0066500000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 + 1 | 11.0000000000000000 + 2 | 11.0000000000000000 (10 rows) -select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | avg -----+---------------------------- - 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 - 2 | 2.0000000000000000 - 3 | 3.0000000000000000 - 4 | 4.0000000000000000 - 5 | 5.0000000000000000 - 6 | 6.0000000000000000 - 7 | 7.0000000000000000 - 8 | 8.0000000000000000 - 9 | 9.0000000000000000 -(10 rows) - -select max(ss) from aggfns where cfloat8 < 1000 order by 1; +select max(ss) from aggfns where cfloat8 < 1000; max ----- - 9 + 11 (1 row) -select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by max(ss), s limit 10; s | max ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 - 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 + 4 | 11 (10 rows) -select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select min(ss) from aggfns where cfloat8 < 1000 order by 1; +select min(ss) from aggfns where cfloat8 < 1000; min ----- 0 (1 row) -select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by min(ss), s limit 10; s | min ---+----- 0 | 0 - 1 | 1 - 2 | 2 3 | 3 4 | 4 5 | 5 @@ -6428,102 +3806,59 @@ select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by 1; 7 | 7 8 | 8 9 | 9 + 1 | 11 + 2 | 11 (10 rows) -select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+----- - 0 | 0 - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 -(10 rows) - -select stddev(ss) from aggfns where cfloat8 < 1000 order by 1; +select stddev(ss) from aggfns where cfloat8 < 1000; stddev -------------------- - 2.8722885039992502 + 3.3528328280068652 (1 row) -select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by 1; - s | stddev ----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | stddev -----+-------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select sum(ss) from aggfns where cfloat8 < 1000 order by 1; - sum --------- - 900000 +select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by stddev(ss), s limit 10; + s | stddev +---+------------------------ + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 4 | 0.21565737387148452722 +(10 rows) + +select sum(ss) from aggfns where cfloat8 < 1000; + sum +--------- + 1280076 (1 row) -select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 + 3 | 59943 + 4 | 80133 5 | 100000 6 | 120000 7 | 140000 8 | 160000 9 | 180000 + 1 | 220000 + 2 | 220000 (10 rows) -select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | sum -----+-------- - 0 | 0 - 1 | 20000 - 2 | 40000 - 3 | 60000 - 4 | 80000 - 5 | 100000 - 6 | 120000 - 7 | 140000 - 8 | 160000 - 9 | 180000 -(10 rows) - -select max(t) from aggfns where cfloat8 < 1000 order by 1; +select max(t) from aggfns where cfloat8 < 1000; max -------- 110000 (1 row) -select s, max(t) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, max(t) from aggfns where cfloat8 < 1000 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 @@ -6538,28 +3873,13 @@ select s, max(t) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 110000 (10 rows) -select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | max -----+-------- - 0 | 20000 - 1 | 30000 - 2 | 40000 - 3 | 50000 - 4 | 60000 - 5 | 70000 - 6 | 80000 - 7 | 90000 - 8 | 100000 - 9 | 110000 -(10 rows) - -select min(t) from aggfns where cfloat8 < 1000 order by 1; +select min(t) from aggfns where cfloat8 < 1000; min ----- 1 (1 row) -select s, min(t) from aggfns where cfloat8 < 1000 group by s order by 1; +select s, min(t) from aggfns where cfloat8 < 1000 group by s order by min(t), s limit 10; s | min ---+------- 0 | 1 @@ -6574,741 +3894,502 @@ select s, min(t) from aggfns where cfloat8 < 1000 group by s order by 1; 9 | 90001 (10 rows) -select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by 1; - ss | min -----+------- - 0 | 1 - 1 | 10001 - 2 | 20001 - 3 | 30001 - 4 | 40001 - 5 | 50001 - 6 | 60001 - 7 | 70001 - 8 | 80001 - 9 | 90001 -(10 rows) - -select max(cdate) from aggfns where cfloat8 > 1000 order by 1; +select count(*) from aggfns where cfloat8 > 1000; + count +------- + 0 +(1 row) + +select s, count(*) from aggfns where cfloat8 > 1000 group by s order by count(*), s limit 10; + s | count +---+------- +(0 rows) + +select max(cdate) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cdate) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cdate) from aggfns where cfloat8 > 1000 group by s order by max(cdate), s limit 10; s | max ---+----- (0 rows) -select ss, max(cdate) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cdate) from aggfns where cfloat8 > 1000 order by 1; +select min(cdate) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cdate) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cdate) from aggfns where cfloat8 > 1000 group by s order by min(cdate), s limit 10; s | min ---+----- (0 rows) -select ss, min(cdate) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select avg(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select avg(cfloat4) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cfloat4) from aggfns where cfloat8 > 1000 group by s order by avg(cfloat4), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select count(cfloat4) from aggfns where cfloat8 > 1000 order by 1; - count -------- - 0 -(1 row) - -select s, count(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; - s | count ----+------- -(0 rows) - -select ss, count(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select max(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select max(cfloat4) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cfloat4) from aggfns where cfloat8 > 1000 group by s order by max(cfloat4), s limit 10; s | max ---+----- (0 rows) -select ss, max(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select min(cfloat4) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cfloat4) from aggfns where cfloat8 > 1000 group by s order by min(cfloat4), s limit 10; s | min ---+----- (0 rows) -select ss, min(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cfloat4) from aggfns where cfloat8 > 1000; stddev -------- (1 row) -select s, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(cfloat4) from aggfns where cfloat8 > 1000 order by 1; +select sum(cfloat4) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cfloat4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cfloat4) from aggfns where cfloat8 > 1000 group by s order by sum(cfloat4), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select avg(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select avg(cfloat8) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cfloat8) from aggfns where cfloat8 > 1000 group by s order by avg(cfloat8), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select max(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select max(cfloat8) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cfloat8) from aggfns where cfloat8 > 1000 group by s order by max(cfloat8), s limit 10; s | max ---+----- (0 rows) -select ss, max(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select min(cfloat8) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cfloat8) from aggfns where cfloat8 > 1000 group by s order by min(cfloat8), s limit 10; s | min ---+----- (0 rows) -select ss, min(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cfloat8) from aggfns where cfloat8 > 1000; stddev -------- (1 row) -select s, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(cfloat8) from aggfns where cfloat8 > 1000 order by 1; +select sum(cfloat8) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cfloat8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cfloat8) from aggfns where cfloat8 > 1000 group by s order by sum(cfloat8), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select avg(cint2) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint2) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint2) from aggfns where cfloat8 > 1000 group by s order by avg(cint2), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- +select count(cint2) from aggfns where cfloat8 > 1000; + count +------- + 0 +(1 row) + +select s, count(cint2) from aggfns where cfloat8 > 1000 group by s order by count(cint2), s limit 10; + s | count +---+------- (0 rows) -select max(cint2) from aggfns where cfloat8 > 1000 order by 1; +select max(cint2) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint2) from aggfns where cfloat8 > 1000 group by s order by max(cint2), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cint2) from aggfns where cfloat8 > 1000 order by 1; +select min(cint2) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint2) from aggfns where cfloat8 > 1000 group by s order by min(cint2), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(cint2) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cint2) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cint2) from aggfns where cfloat8 > 1000 group by s order by stddev(cint2), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(cint2) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint2) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by sum(cint2), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint2) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select avg(cint4) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint4) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint4) from aggfns where cfloat8 > 1000 group by s order by avg(cint4), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select max(cint4) from aggfns where cfloat8 > 1000 order by 1; +select max(cint4) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint4) from aggfns where cfloat8 > 1000 group by s order by max(cint4), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cint4) from aggfns where cfloat8 > 1000 order by 1; +select min(cint4) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint4) from aggfns where cfloat8 > 1000 group by s order by min(cint4), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(cint4) from aggfns where cfloat8 > 1000 order by 1; +select stddev(cint4) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(cint4) from aggfns where cfloat8 > 1000 group by s order by stddev(cint4), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(cint4) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint4) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by sum(cint4), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint4) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select avg(cint8) from aggfns where cfloat8 > 1000 order by 1; +select avg(cint8) from aggfns where cfloat8 > 1000; avg ----- (0 rows) -select s, avg(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(cint8) from aggfns where cfloat8 > 1000 group by s order by avg(cint8), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select max(cint8) from aggfns where cfloat8 > 1000 order by 1; +select max(cint8) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cint8) from aggfns where cfloat8 > 1000 group by s order by max(cint8), s limit 10; s | max ---+----- (0 rows) -select ss, max(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cint8) from aggfns where cfloat8 > 1000 order by 1; +select min(cint8) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cint8) from aggfns where cfloat8 > 1000 group by s order by min(cint8), s limit 10; s | min ---+----- (0 rows) -select ss, min(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(cint8) from aggfns where cfloat8 > 1000 order by 1; - stddev --------- -(0 rows) - -select s, stddev(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; - s | stddev ----+-------- -(0 rows) - -select ss, stddev(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(cint8) from aggfns where cfloat8 > 1000 order by 1; +select sum(cint8) from aggfns where cfloat8 > 1000; sum ----- (0 rows) -select s, sum(cint8) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(cint8) from aggfns where cfloat8 > 1000 group by s order by sum(cint8), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(cint8) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select max(cts) from aggfns where cfloat8 > 1000 order by 1; +select max(cts) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(cts) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(cts) from aggfns where cfloat8 > 1000 group by s order by max(cts), s limit 10; s | max ---+----- (0 rows) -select ss, max(cts) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(cts) from aggfns where cfloat8 > 1000 order by 1; +select min(cts) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(cts) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(cts) from aggfns where cfloat8 > 1000 group by s order by min(cts), s limit 10; s | min ---+----- (0 rows) -select ss, min(cts) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select max(ctstz) from aggfns where cfloat8 > 1000 order by 1; +select max(ctstz) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(ctstz) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(ctstz) from aggfns where cfloat8 > 1000 group by s order by max(ctstz), s limit 10; s | max ---+----- (0 rows) -select ss, max(ctstz) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(ctstz) from aggfns where cfloat8 > 1000 order by 1; +select min(ctstz) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(ctstz) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(ctstz) from aggfns where cfloat8 > 1000 group by s order by min(ctstz), s limit 10; s | min ---+----- (0 rows) -select ss, min(ctstz) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select avg(s) from aggfns where cfloat8 > 1000 order by 1; +select avg(s) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(s) from aggfns where cfloat8 > 1000 group by s order by avg(s), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select count(s) from aggfns where cfloat8 > 1000 order by 1; +select count(s) from aggfns where cfloat8 > 1000; count ------- 0 (1 row) -select s, count(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, count(s) from aggfns where cfloat8 > 1000 group by s order by count(s), s limit 10; s | count ---+------- (0 rows) -select ss, count(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | count -----+------- -(0 rows) - -select max(s) from aggfns where cfloat8 > 1000 order by 1; +select max(s) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(s) from aggfns where cfloat8 > 1000 group by s order by max(s), s limit 10; s | max ---+----- (0 rows) -select ss, max(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(s) from aggfns where cfloat8 > 1000 order by 1; +select min(s) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(s) from aggfns where cfloat8 > 1000 group by s order by min(s), s limit 10; s | min ---+----- (0 rows) -select ss, min(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(s) from aggfns where cfloat8 > 1000 order by 1; +select stddev(s) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(s) from aggfns where cfloat8 > 1000 group by s order by stddev(s), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(s) from aggfns where cfloat8 > 1000 order by 1; +select sum(s) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(s) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(s) from aggfns where cfloat8 > 1000 group by s order by sum(s), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(s) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select avg(ss) from aggfns where cfloat8 > 1000 order by 1; +select avg(ss) from aggfns where cfloat8 > 1000; avg ----- (1 row) -select s, avg(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, avg(ss) from aggfns where cfloat8 > 1000 group by s order by avg(ss), s limit 10; s | avg ---+----- (0 rows) -select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | avg -----+----- -(0 rows) - -select max(ss) from aggfns where cfloat8 > 1000 order by 1; +select max(ss) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(ss) from aggfns where cfloat8 > 1000 group by s order by max(ss), s limit 10; s | max ---+----- (0 rows) -select ss, max(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(ss) from aggfns where cfloat8 > 1000 order by 1; +select min(ss) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(ss) from aggfns where cfloat8 > 1000 group by s order by min(ss), s limit 10; s | min ---+----- (0 rows) -select ss, min(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select stddev(ss) from aggfns where cfloat8 > 1000 order by 1; +select stddev(ss) from aggfns where cfloat8 > 1000; stddev -------- (0 rows) -select s, stddev(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, stddev(ss) from aggfns where cfloat8 > 1000 group by s order by stddev(ss), s limit 10; s | stddev ---+-------- (0 rows) -select ss, stddev(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | stddev -----+-------- -(0 rows) - -select sum(ss) from aggfns where cfloat8 > 1000 order by 1; +select sum(ss) from aggfns where cfloat8 > 1000; sum ----- (1 row) -select s, sum(ss) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, sum(ss) from aggfns where cfloat8 > 1000 group by s order by sum(ss), s limit 10; s | sum ---+----- (0 rows) -select ss, sum(ss) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | sum -----+----- -(0 rows) - -select max(t) from aggfns where cfloat8 > 1000 order by 1; +select max(t) from aggfns where cfloat8 > 1000; max ----- (1 row) -select s, max(t) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, max(t) from aggfns where cfloat8 > 1000 group by s order by max(t), s limit 10; s | max ---+----- (0 rows) -select ss, max(t) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | max -----+----- -(0 rows) - -select min(t) from aggfns where cfloat8 > 1000 order by 1; +select min(t) from aggfns where cfloat8 > 1000; min ----- (1 row) -select s, min(t) from aggfns where cfloat8 > 1000 group by s order by 1; +select s, min(t) from aggfns where cfloat8 > 1000 group by s order by min(t), s limit 10; s | min ---+----- (0 rows) -select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by 1; - ss | min -----+----- -(0 rows) - -select avg(cint2) from aggfns where cint2 is null order by 1; +select avg(cint2) from aggfns where cint2 is null; avg ----- (1 row) -select s, avg(cint2) from aggfns where cint2 is null group by s order by 1; +select s, avg(cint2) from aggfns where cint2 is null group by s order by avg(cint2), s limit 10; s | avg ---+----- 0 | @@ -7323,28 +4404,13 @@ select s, avg(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, avg(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | avg -----+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select count(cint2) from aggfns where cint2 is null order by 1; +select count(cint2) from aggfns where cint2 is null; count ------- 0 (1 row) -select s, count(cint2) from aggfns where cint2 is null group by s order by 1; +select s, count(cint2) from aggfns where cint2 is null group by s order by count(cint2), s limit 10; s | count ---+------- 0 | 0 @@ -7359,28 +4425,13 @@ select s, count(cint2) from aggfns where cint2 is null group by s order by 1; 9 | 0 (10 rows) -select ss, count(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | count -----+------- - 0 | 0 - 1 | 0 - 2 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(10 rows) - -select max(cint2) from aggfns where cint2 is null order by 1; +select max(cint2) from aggfns where cint2 is null; max ----- (1 row) -select s, max(cint2) from aggfns where cint2 is null group by s order by 1; +select s, max(cint2) from aggfns where cint2 is null group by s order by max(cint2), s limit 10; s | max ---+----- 0 | @@ -7395,28 +4446,13 @@ select s, max(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, max(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | max -----+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select min(cint2) from aggfns where cint2 is null order by 1; +select min(cint2) from aggfns where cint2 is null; min ----- (1 row) -select s, min(cint2) from aggfns where cint2 is null group by s order by 1; +select s, min(cint2) from aggfns where cint2 is null group by s order by min(cint2), s limit 10; s | min ---+----- 0 | @@ -7431,28 +4467,13 @@ select s, min(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, min(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | min -----+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select stddev(cint2) from aggfns where cint2 is null order by 1; +select stddev(cint2) from aggfns where cint2 is null; stddev -------- (1 row) -select s, stddev(cint2) from aggfns where cint2 is null group by s order by 1; +select s, stddev(cint2) from aggfns where cint2 is null group by s order by stddev(cint2), s limit 10; s | stddev ---+-------- 0 | @@ -7467,28 +4488,13 @@ select s, stddev(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | stddev -----+-------- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select sum(cint2) from aggfns where cint2 is null order by 1; +select sum(cint2) from aggfns where cint2 is null; sum ----- (1 row) -select s, sum(cint2) from aggfns where cint2 is null group by s order by 1; +select s, sum(cint2) from aggfns where cint2 is null group by s order by sum(cint2), s limit 10; s | sum ---+----- 0 | @@ -7503,18 +4509,65 @@ select s, sum(cint2) from aggfns where cint2 is null group by s order by 1; 9 | (10 rows) -select ss, sum(cint2) from aggfns where cint2 is null group by ss order by 1; - ss | sum -----+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) +-- Test edge cases for various batch sizes and the filter matching around batch +-- end. +select s, count(*) from edges group by 1 order by 1; + s | count +----+------- + 0 | 61 + 1 | 62 + 2 | 63 + 3 | 64 + 4 | 65 + 5 | 130 + 6 | 131 + 7 | 132 + 8 | 133 + 9 | 134 + 10 | 2247 + 11 | 2248 + 12 | 2249 +(13 rows) + +select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; + s | count | min +----+-------+----- + 3 | 1 | 63 + 4 | 1 | 63 + 5 | 1 | 63 + 6 | 1 | 63 + 7 | 1 | 63 + 8 | 1 | 63 + 9 | 1 | 63 + 10 | 1 | 63 + 11 | 1 | 63 + 12 | 1 | 63 +(10 rows) + +select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; + s | count | min +----+-------+----- + 4 | 1 | 64 + 5 | 1 | 64 + 6 | 1 | 64 + 7 | 1 | 64 + 8 | 1 | 64 + 9 | 1 | 64 + 10 | 1 | 64 + 11 | 1 | 64 + 12 | 1 | 64 +(9 rows) + +select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + s | count | min +----+-------+----- + 5 | 1 | 65 + 6 | 1 | 65 + 7 | 1 | 65 + 8 | 1 | 65 + 9 | 1 | 65 + 10 | 1 | 65 + 11 | 1 | 65 + 12 | 1 | 65 +(8 rows) diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 35ec690bf07..eeedff5e2be 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -12,51 +12,93 @@ $$ LANGUAGE SQL; \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int -create table aggfns(t int, s int, ss int, +create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, - cfloat4 float4, cfloat8 float8, + cfloat4 float4, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); -insert into aggfns -select s * 10000::int + t, - s, +create view source as +select s * 10000 + t as t, s, - case when t % 1051 = 0 then null else (mix(s + t + 1) * 32767)::int2 end, - (mix(s + t + 2) * 32767 * 65536)::int4, - (mix(s + t + 3) * 32767 * 65536)::int8, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8, case when s = 1 and t = 1061 then 'nan'::float4 when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 - else (mix(s + t + 4) * 100)::float4 end, - (mix(s + t + 5) * 100)::float8, - '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000::int + t), - '2021-01-01 01:01:01'::timestamptz + interval '1 day' * (s * 10000::int + t) + else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, + '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, + '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, + '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate from generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) ; +insert into aggfns select * from source where s = 1; + alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't', timescaledb.compress_segmentby = 's'); select count(compress_chunk(x)) from show_chunks('aggfns') x; -analyze aggfns; +alter table aggfns add column ss int default 11; +alter table aggfns add column cfloat8 float8 default '13'; +alter table aggfns add column x text default '11'; +insert into aggfns +select *, ss::text as x from ( + select * + , case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + , (mix(s + t * 1039) * 100)::float8 as cfloat8 + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('aggfns') x; +vacuum freeze analyze aggfns; + + +create table edges(t int, s int, ss int, f1 int); +select create_hypertable('edges', 't'); +alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); +insert into edges select + s * 10000 + f1 as t, + s, + s, + f1 +from generate_series(0, 12) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 +; +select count(compress_chunk(x)) from show_chunks('edges') x; +vacuum freeze analyze edges; + + +set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; +-- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select - format('%sselect %s%s(%s) from aggfns%s%s order by 1;', + format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, grouping || ', ', function, variable, ' where ' || condition, - ' group by ' || grouping ) + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) from unnest(array[ 'explain (costs off) ', @@ -72,7 +114,8 @@ from 'cfloat8', 'cts', 'ctstz', - 'cdate']) variable, + 'cdate', + '*']) variable, unnest(array[ 'min', 'max', @@ -89,20 +132,24 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's', - 'ss']) with ordinality as grouping(grouping, n) + 's']) with ordinality as grouping(grouping, n) where - case --- when explain is not null then condition is null and grouping = 's' - when explain is not null then false - when true then true - end - and - case - when condition = 'cint2 is null' then variable = 'cint2' - when function = 'count' then variable in ('cfloat4', 's') - when variable = 't' then function in ('min', 'max') - when variable in ('cts', 'ctstz', 'cdate') then function in ('min', 'max') - else true end + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') + and (variable not in ('t', 'cts', 'ctstz', 'cdate') or function in ('min', 'max')) + -- This is not vectorized yet + and (variable != 'cint8' or function != 'stddev') + and (function != 'count' or variable in ('cint2', 's', '*')) + and (condition is distinct from 'cint2 is null' or variable = 'cint2') order by explain, condition.n, variable, function, grouping.n \gexec + + +-- Test edge cases for various batch sizes and the filter matching around batch +-- end. +select s, count(*) from edges group by 1 order by 1; + +select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; +select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; +select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; From 7d83fb0c9da9063d3ac4baf3662cdb82f832eac8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:55:03 +0100 Subject: [PATCH 112/242] more cosmetic changes --- tsl/src/compression/arrow_c_data_interface.h | 7 +++++-- tsl/src/nodes/decompress_chunk/compressed_batch.c | 3 +++ tsl/src/nodes/decompress_chunk/vector_quals.h | 12 ++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index a4fb8e3e9a6..1473e24945b 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -176,8 +176,9 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) const size_t qword_index = row_number / 64; const size_t bit_index = row_number % 64; const uint64 mask = 1ull << bit_index; + const uint64 new_bit = (value ? 1ull : 0ull) << bit_index; - bitmap[qword_index] = (bitmap[qword_index] & ~mask) | ((-(uint64) value) & mask); + bitmap[qword_index] = (bitmap[qword_index] & ~mask) | new_bit; Assert(arrow_row_is_valid(bitmap, row_number) == value); } @@ -207,7 +208,9 @@ arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 return storage; } -/* Increase the `source_value` to be an even multiple of `pad_to`. */ +/* + * Increase the `source_value` to be an even multiple of `pad_to`. + */ static inline uint64 pad_to_multiple(uint64 pad_to, uint64 source_value) { diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index eef5617c95e..b1591ecf72e 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -265,6 +265,8 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state column_values->decompression_type = value_bytes; column_values->buffers[0] = arrow->buffers[0]; column_values->buffers[1] = arrow->buffers[1]; + column_values->buffers[2] = NULL; + column_values->buffers[3] = NULL; } else { @@ -290,6 +292,7 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state column_values->buffers[0] = arrow->buffers[0]; column_values->buffers[1] = arrow->buffers[1]; column_values->buffers[2] = arrow->buffers[2]; + column_values->buffers[3] = NULL; } else { diff --git a/tsl/src/nodes/decompress_chunk/vector_quals.h b/tsl/src/nodes/decompress_chunk/vector_quals.h index a3184d875c7..4fd2e058e4a 100644 --- a/tsl/src/nodes/decompress_chunk/vector_quals.h +++ b/tsl/src/nodes/decompress_chunk/vector_quals.h @@ -18,12 +18,16 @@ */ typedef struct VectorQualInfo { - /* The range-table index of the relation to compute vectorized quals - * for */ + /* + * The range-table index of the relation to compute vectorized quals + * for. + */ Index rti; - /* AttrNumber-indexed array indicating whether an attribute/column is a - * vectorizable type */ + /* + * Array indexed by uncompressed attno indicating whether an + * attribute/column is a vectorizable type. + */ bool *vector_attrs; } VectorQualInfo; From de1b6daeb2345b61ff24379f390ec5f0f6c315d2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:28:17 +0100 Subject: [PATCH 113/242] int128 --- tsl/test/expected/vector_agg_functions.out | 7 ++++++- tsl/test/sql/vector_agg_functions.sql | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 4b2bd54bc0e..9eeaa7c1e86 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -101,7 +101,12 @@ select count(compress_chunk(x)) from show_chunks('edges') x; (1 row) vacuum freeze analyze edges; -set timescaledb.debug_require_vector_agg = 'require'; +-- We can't vectorize some aggregate functions on platforms withouth int128 +-- support. Just relax the test requirements for them. +select case when typbyval then 'require' else 'allow' end guc_value +from pg_type where oid = 'int8'::regtype +\gset +set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. -- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index eeedff5e2be..5cb25a2075f 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -84,8 +84,13 @@ from generate_series(0, 12) s, select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; +-- We can't vectorize some aggregate functions on platforms withouth int128 +-- support. Just relax the test requirements for them. +select case when typbyval then 'require' else 'allow' end guc_value +from pg_type where oid = 'int8'::regtype +\gset -set timescaledb.debug_require_vector_agg = 'require'; +set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. -- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; From b7984ca31d983688446aa83c6d33eef422ccfdfb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:38:19 +0100 Subject: [PATCH 114/242] review fixes --- tsl/src/nodes/vector_agg/exec.c | 4 +- tsl/src/nodes/vector_agg/function/functions.h | 12 +- .../vector_agg/function/int24_sum_single.c | 4 +- .../vector_agg/function/int24_sum_templates.c | 6 +- .../vector_agg/function/sum_float_single.c | 6 +- .../vector_agg/function/sum_float_templates.c | 4 +- tsl/test/expected/agg_partials_pushdown.out | 22 +- tsl/test/expected/compression.out | 6 +- .../expected/transparent_decompression-14.out | 8 +- .../expected/transparent_decompression-15.out | 8 +- .../expected/transparent_decompression-16.out | 8 +- .../expected/transparent_decompression-17.out | 8 +- tsl/test/expected/vector_agg_functions.out | 2767 ++++++++--------- tsl/test/sql/vector_agg_functions.sql | 24 +- 14 files changed, 1455 insertions(+), 1432 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index ebf8c2c5b7a..587c6882d95 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -87,7 +87,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) int grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { - TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + TargetEntry *tlentry = list_nth_node(TargetEntry, aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { agg_functions_counter++; @@ -120,7 +120,7 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) grouping_column_counter = 0; for (int i = 0; i < tlist_length; i++) { - TargetEntry *tlentry = (TargetEntry *) list_nth(aggregated_tlist, i); + TargetEntry *tlentry = list_nth_node(TargetEntry, aggregated_tlist, i); if (IsA(tlentry->expr, Aggref)) { /* This is an aggregate function. */ diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index 67cecf554e1..5845333d79d 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -10,13 +10,23 @@ /* * Function table for a vectorized implementation of an aggregate function. + * + * One state of aggregate function corresponds to one set of rows that are + * supposed to be grouped together (e.g. for one grouping key). + * + * There are functions for adding a compressed batch to one aggregate function + * state (no grouping keys), and to multiple aggregate function states laid out + * contiguously in memory. */ typedef struct { /* Size of the aggregate function state. */ size_t state_bytes; - /* Initialize the aggregate function states. */ + /* + * Initialize the n aggregate function states stored contiguously at the + * given pointer. + */ void (*agg_init)(void *restrict agg_states, int n); /* Aggregate a given arrow array. */ diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index f7251599a90..05a6639e93f 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -48,7 +48,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); } - state->isnull &= !have_result; + state->isvalid |= have_result; } static pg_attribute_always_inline void @@ -56,7 +56,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) { Int24SumState *state = (Int24SumState *) agg_state; state->result += value; - state->isnull = false; + state->isvalid = true; } typedef Int24SumState FUNCTION_NAME(state); diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c index 8b250cc91cc..6dda8bed102 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_templates.c @@ -24,7 +24,7 @@ typedef struct { int64 result; - bool isnull; + bool isvalid; } Int24SumState; static void @@ -34,7 +34,7 @@ int_sum_init(void *restrict agg_states, int n) for (int i = 0; i < n; i++) { states[i].result = 0; - states[i].isnull = true; + states[i].isvalid = false; } } @@ -43,7 +43,7 @@ int_sum_emit(void *agg_state, Datum *out_result, bool *out_isnull) { Int24SumState *state = (Int24SumState *) agg_state; *out_result = Int64GetDatum(state->result); - *out_isnull = state->isnull; + *out_isnull = !state->isvalid; } #endif diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index c8fbea2d43a..dd97b639d89 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -17,7 +17,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) { FloatSumState *state = (FloatSumState *) agg_state; *out_result = CTYPE_TO_DATUM((CTYPE) state->result); - *out_isnull = state->isnull; + *out_isnull = !state->isvalid; } static pg_attribute_always_inline void @@ -76,7 +76,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui #undef INNER_LOOP FloatSumState *state = (FloatSumState *) agg_state; - state->isnull &= !have_result_accu[0]; + state->isvalid |= have_result_accu[0]; state->result += sum_accu[0]; } @@ -86,7 +86,7 @@ static pg_attribute_always_inline void FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) { FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - state->isnull = false; + state->isvalid = true; state->result += value; } diff --git a/tsl/src/nodes/vector_agg/function/sum_float_templates.c b/tsl/src/nodes/vector_agg/function/sum_float_templates.c index f2b22523b34..0f41b5847be 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_templates.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_templates.c @@ -19,7 +19,7 @@ typedef struct { double result; - bool isnull; + bool isvalid; } FloatSumState; static void @@ -29,7 +29,7 @@ float_sum_init(void *restrict agg_states, int n) for (int i = 0; i < n; i++) { states[i].result = 0; - states[i].isnull = true; + states[i].isvalid = false; } } #endif diff --git a/tsl/test/expected/agg_partials_pushdown.out b/tsl/test/expected/agg_partials_pushdown.out index f5585540ac9..4839d002561 100644 --- a/tsl/test/expected/agg_partials_pushdown.out +++ b/tsl/test/expected/agg_partials_pushdown.out @@ -40,6 +40,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Append (actual rows=2 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -49,6 +50,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((compress_hyper_2_3_chunk._ts_meta_max_1 >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (compress_hyper_2_3_chunk._ts_meta_min_1 <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -56,7 +58,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk (actual rows=5 loops=1) Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.device_id, compress_hyper_2_4_chunk.filter_1, compress_hyper_2_4_chunk.filler_2, compress_hyper_2_4_chunk.filler_3, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk."time", compress_hyper_2_4_chunk.v0, compress_hyper_2_4_chunk.v1, compress_hyper_2_4_chunk.v2, compress_hyper_2_4_chunk.v3 Filter: ((compress_hyper_2_4_chunk._ts_meta_max_1 >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (compress_hyper_2_4_chunk._ts_meta_min_1 <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -(21 rows) +(23 rows) -- Create partially compressed chunk INSERT INTO testtable(time,device_id,v0,v1,v2,v3) @@ -79,6 +81,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Append (actual rows=4 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -93,6 +96,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) @@ -105,7 +109,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" >= 'Fri Dec 31 16:00:00 1999 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone)) -(31 rows) +(33 rows) -- Same query using chunk append SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= '2000-01-01 00:00:00+0'::text::timestamptz AND time <= '2000-02-01 00:00:00+0'; @@ -127,6 +131,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -141,6 +146,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -153,7 +159,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -(35 rows) +(37 rows) -- Perform chunk append startup chunk exclusion - issue 6282 :PREFIX @@ -169,6 +175,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 2 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -183,7 +190,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) Rows Removed by Filter: 15 -(23 rows) +(24 rows) -- Force plain / sorted aggregation SET enable_hashagg = OFF; @@ -206,6 +213,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_1_chunk.v0)), (PARTIAL sum(_hyper_1_1_chunk.v1)), (PARTIAL sum(_hyper_1_1_chunk.v2)), (PARTIAL sum(_hyper_1_1_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=25 loops=1) Output: _hyper_1_1_chunk.v0, _hyper_1_1_chunk.v1, _hyper_1_1_chunk.v2, _hyper_1_1_chunk.v3 Vectorized Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -220,6 +228,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Filter: ((_hyper_1_1_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_1_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -232,7 +241,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Seq Scan on _timescaledb_internal._hyper_1_2_chunk (actual rows=25 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Filter: ((_hyper_1_2_chunk."time" <= 'Mon Jan 31 16:00:00 2000 PST'::timestamp with time zone) AND (_hyper_1_2_chunk."time" >= ('2000-01-01 00:00:00+0'::cstring)::timestamp with time zone)) -(35 rows) +(37 rows) RESET enable_hashagg; -- Check chunk exclusion for index scans @@ -256,6 +265,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= Chunks excluded during startup: 2 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)), (PARTIAL sum(_hyper_1_2_chunk.v0)), (PARTIAL sum(_hyper_1_2_chunk.v1)), (PARTIAL sum(_hyper_1_2_chunk.v2)), (PARTIAL sum(_hyper_1_2_chunk.v3)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Vectorized Filter: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) @@ -269,7 +279,7 @@ SELECT count(*), sum(v0), sum(v1), sum(v2), sum(v3) FROM testtable WHERE time >= -> Index Scan using _hyper_1_2_chunk_testtable_time_idx on _timescaledb_internal._hyper_1_2_chunk (actual rows=10 loops=1) Output: _hyper_1_2_chunk.v0, _hyper_1_2_chunk.v1, _hyper_1_2_chunk.v2, _hyper_1_2_chunk.v3 Index Cond: ((_hyper_1_2_chunk."time" >= ('2000-01-09 00:00:00+0'::cstring)::timestamp with time zone) AND (_hyper_1_2_chunk."time" <= ('2000-02-01 00:00:00+0'::cstring)::timestamp with time zone)) -(22 rows) +(23 rows) RESET enable_seqscan; -- Check Append Node under ChunkAppend diff --git a/tsl/test/expected/compression.out b/tsl/test/expected/compression.out index 5e186d55014..05620c4ddea 100644 --- a/tsl/test/expected/compression.out +++ b/tsl/test/expected/compression.out @@ -1808,11 +1808,12 @@ SELECT sum(cpu) FROM f_sensor_data; Workers Planned: 4 -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_37_73_chunk.cpu)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_37_73_chunk Output: _hyper_37_73_chunk.cpu -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_38_74_chunk Output: compress_hyper_38_74_chunk._ts_meta_count, compress_hyper_38_74_chunk.sensor_id, compress_hyper_38_74_chunk._ts_meta_min_1, compress_hyper_38_74_chunk._ts_meta_max_1, compress_hyper_38_74_chunk."time", compress_hyper_38_74_chunk.cpu, compress_hyper_38_74_chunk.temperature -(11 rows) +(12 rows) -- Encourage use of Index Scan SET enable_seqscan = false; @@ -1863,11 +1864,12 @@ SELECT sum(cpu) FROM f_sensor_data; Output: _hyper_37_73_chunk.cpu -> Custom Scan (VectorAgg) Output: (PARTIAL sum(_hyper_37_73_chunk.cpu)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_37_73_chunk Output: _hyper_37_73_chunk.cpu -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_38_74_chunk Output: compress_hyper_38_74_chunk._ts_meta_count, compress_hyper_38_74_chunk.sensor_id, compress_hyper_38_74_chunk._ts_meta_min_1, compress_hyper_38_74_chunk._ts_meta_max_1, compress_hyper_38_74_chunk."time", compress_hyper_38_74_chunk.cpu, compress_hyper_38_74_chunk.temperature -(16 rows) +(17 rows) :explain SELECT * FROM f_sensor_data WHERE sensor_id > 100; diff --git a/tsl/test/expected/transparent_decompression-14.out b/tsl/test/expected/transparent_decompression-14.out index 5233f1b06e0..edfa23a6990 100644 --- a/tsl/test/expected/transparent_decompression-14.out +++ b/tsl/test/expected/transparent_decompression-14.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); diff --git a/tsl/test/expected/transparent_decompression-15.out b/tsl/test/expected/transparent_decompression-15.out index 65ecd4bba38..a8492d98fdd 100644 --- a/tsl/test/expected/transparent_decompression-15.out +++ b/tsl/test/expected/transparent_decompression-15.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); diff --git a/tsl/test/expected/transparent_decompression-16.out b/tsl/test/expected/transparent_decompression-16.out index 1513901658a..f2878e7d1c3 100644 --- a/tsl/test/expected/transparent_decompression-16.out +++ b/tsl/test/expected/transparent_decompression-16.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); diff --git a/tsl/test/expected/transparent_decompression-17.out b/tsl/test/expected/transparent_decompression-17.out index 1513901658a..f2878e7d1c3 100644 --- a/tsl/test/expected/transparent_decompression-17.out +++ b/tsl/test/expected/transparent_decompression-17.out @@ -2067,6 +2067,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_15_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_15_chunk (actual rows=1 loops=1) @@ -2079,12 +2080,13 @@ WHERE device_id = 1; Rows Removed by Filter: 2688 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_5_16_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_5_16_chunk (actual rows=1 loops=1) Output: compress_hyper_5_16_chunk._ts_meta_count, compress_hyper_5_16_chunk.device_id, compress_hyper_5_16_chunk.device_id_peer, compress_hyper_5_16_chunk._ts_meta_min_3, compress_hyper_5_16_chunk._ts_meta_max_3, compress_hyper_5_16_chunk."time", compress_hyper_5_16_chunk._ts_meta_min_1, compress_hyper_5_16_chunk._ts_meta_max_1, compress_hyper_5_16_chunk.v0, compress_hyper_5_16_chunk._ts_meta_min_2, compress_hyper_5_16_chunk._ts_meta_max_2, compress_hyper_5_16_chunk.v1, compress_hyper_5_16_chunk.v2, compress_hyper_5_16_chunk.v3 Index Cond: (compress_hyper_5_16_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); @@ -6128,6 +6130,7 @@ WHERE device_id = 1; -> Append (actual rows=3 loops=1) -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_4_chunk (actual rows=720 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_17_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_17_chunk (actual rows=1 loops=1) @@ -6140,12 +6143,13 @@ WHERE device_id = 1; Heap Fetches: 0 -> Custom Scan (VectorAgg) (actual rows=1 loops=1) Output: (PARTIAL count(*)) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_2_10_chunk (actual rows=336 loops=1) Bulk Decompression: false -> Index Scan using compress_hyper_6_20_chunk_device_id_device_id_peer__ts_meta_idx on _timescaledb_internal.compress_hyper_6_20_chunk (actual rows=1 loops=1) Output: compress_hyper_6_20_chunk._ts_meta_count, compress_hyper_6_20_chunk.device_id, compress_hyper_6_20_chunk.device_id_peer, compress_hyper_6_20_chunk._ts_meta_min_3, compress_hyper_6_20_chunk._ts_meta_max_3, compress_hyper_6_20_chunk."time", compress_hyper_6_20_chunk._ts_meta_min_1, compress_hyper_6_20_chunk._ts_meta_max_1, compress_hyper_6_20_chunk.v0, compress_hyper_6_20_chunk._ts_meta_min_2, compress_hyper_6_20_chunk._ts_meta_max_2, compress_hyper_6_20_chunk.v1, compress_hyper_6_20_chunk.v2, compress_hyper_6_20_chunk.v3 Index Cond: (compress_hyper_6_20_chunk.device_id = 1) -(22 rows) +(24 rows) -- should be able to order using an index CREATE INDEX tmp_idx ON :TEST_TABLE (device_id); diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index b14850f6fbe..b1f90506bf4 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -11,7 +11,7 @@ $$ LANGUAGE SQL; \set GROUPING_CARDINALITY 10::int create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, - cfloat4 float4, cfloat8 float8, + cfloat4 float4, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); @@ -33,7 +33,6 @@ select s * 10000 + t as t, when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, - (mix(s + t * 1039) * 100)::float8 as cfloat8, '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate @@ -51,11 +50,12 @@ select count(compress_chunk(x)) from show_chunks('aggfns') x; (1 row) alter table aggfns add column ss int default 11; +alter table aggfns add column cfloat8 float8 default '13'; alter table aggfns add column x text default '11'; insert into aggfns select *, ss::text as x from ( - select *, - case + select * + , case -- null in entire batch when s = 2 then null -- null for some rows @@ -65,6 +65,7 @@ select *, ss::text as x from ( -- not null for entire batch else s end as ss + , (mix(s + t * 1039) * 100)::float8 as cfloat8 from source where s != 1 ) t ; @@ -90,8 +91,8 @@ insert into edges select s, s, f1 -from generate_series(0, 10) s, - lateral generate_series(0, 60 + s + (s / 5::int) * 64) f1 +from generate_series(0, 12) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 ; select count(compress_chunk(x)) from show_chunks('edges') x; count @@ -100,7 +101,12 @@ select count(compress_chunk(x)) from show_chunks('edges') x; (1 row) vacuum freeze analyze edges; -set timescaledb.debug_require_vector_agg = 'require'; +-- We can't vectorize some aggregate functions on platforms withouth int128 +-- support. Just relax the test requirements for them. +select case when typbyval then 'require' else 'allow' end guc_value +from pg_type where oid = 'int8'::regtype +\gset +set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. -- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; @@ -448,75 +454,75 @@ select ss, sum(cfloat4) from aggfns group by ss order by sum(cfloat4), ss limit (10 rows) select avg(cfloat8) from aggfns; - avg --------------------- - -0.162669734027353 + avg +----------------- + 1.2289014329263 (1 row) select s, avg(cfloat8) from aggfns group by s order by avg(cfloat8), s limit 10; - s | avg ----+----------------------- - 8 | -0.607624531147303 - 7 | -0.454194548579399 - 9 | -0.448788876848994 - 3 | -0.364286396751413 - 0 | -0.306925132697215 - 1 | -0.0518103775125928 - 6 | -4.20950399711728e-05 - 5 | 0.0180876209540293 - 4 | 0.032399496253347 - 2 | 0.55648750109598 + s | avg +---+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.220256273869891 + 3 | -0.14819676399231 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + 2 | 0.198140166982776 + 1 | 13 (10 rows) select ss, avg(cfloat8) from aggfns group by ss order by avg(cfloat8), ss limit 10; - ss | avg -----+----------------------- - | -6.85744955032868 - 8 | -0.607624531147303 - 7 | -0.454194548579399 - 9 | -0.448788876848994 - 3 | -0.358112026103399 - 0 | -0.306925132697215 - 6 | -4.20950399711728e-05 - 5 | 0.0180876209540293 - 4 | 0.0258167200477049 - 11 | 0.25552084043733 + ss | avg +----+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.224160255000712 + 3 | -0.153492446187821 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + | 5.42090986487701 + 11 | 6.59778165165114 (10 rows) select max(cfloat8) from aggfns; max ------------------ - 49.9996809987351 + 49.9995574122295 (1 row) select s, max(cfloat8) from aggfns group by s order by max(cfloat8), s limit 10; s | max ---+------------------ - 4 | 49.9951320933178 + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 1 | 49.9971219105646 - 2 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select ss, max(cfloat8) from aggfns group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - | 41.8287402018905 - 4 | 49.9951320933178 + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 11 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select min(cfloat8) from aggfns; @@ -529,102 +535,102 @@ select s, min(cfloat8) from aggfns group by s order by min(cfloat8), s limit 10; s | min ---+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 1 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - 2 | -49.9854512279853 + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + 1 | 13 (10 rows) select ss, min(cfloat8) from aggfns group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 11 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - | -40.4587021796033 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 (10 rows) select stddev(cfloat8) from aggfns; - stddev ------------------ - 28.892061623641 + stddev +------------------ + 27.6606134001179 (1 row) select s, stddev(cfloat8) from aggfns group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 8 | 28.785076111741 - 9 | 28.7991243564982 - 4 | 28.8027578036838 - 7 | 28.8638207913961 - 2 | 28.871977070659 - 3 | 28.8844659681246 - 1 | 28.9470128733139 + 1 | 0 + 2 | 28.7611066711723 + 9 | 28.7642081921344 + 4 | 28.77864036235 + 5 | 28.7843925303698 + 6 | 28.8543767497509 + 3 | 28.9210796983077 + 8 | 28.96331707256 0 | 28.965342556856 - 5 | 28.9663806098752 - 6 | 29.0218963292706 + 7 | 28.9656492103737 (10 rows) select ss, stddev(cfloat8) from aggfns group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - | 27.2393448599587 - 8 | 28.7850761117411 - 9 | 28.7991243564982 - 4 | 28.8000379619243 - 7 | 28.863820791396 - 3 | 28.8859339629585 - 11 | 28.9120343325061 + 11 | 21.3262797346004 + | 22.894065438835 + 9 | 28.7642081921344 + 4 | 28.7760615445521 + 5 | 28.7843925303698 + 6 | 28.8543767497508 + 3 | 28.926156595386 + 8 | 28.96331707256 0 | 28.9653425568561 - 5 | 28.9663806098753 - 6 | 29.0218963292706 + 7 | 28.9656492103736 (10 rows) select sum(cfloat8) from aggfns; - sum -------------------- - -32533.9468054706 + sum +----------------- + 245780.28658526 (1 row) select s, sum(cfloat8) from aggfns group by s order by sum(cfloat8), s limit 10; - s | sum ----+-------------------- - 8 | -12152.4906229461 - 7 | -9083.89097158797 - 9 | -8975.77753697988 - 3 | -7285.72793502826 - 0 | -6138.50265394431 - 1 | -1036.20755025186 - 6 | -0.841900799423456 - 5 | 361.752419080585 - 4 | 647.98992506694 - 2 | 11129.7500219196 + s | sum +---+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4405.12547739781 + 3 | -2963.93527984619 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 2 | 3962.80333965551 + 1 | 260000 (10 rows) select ss, sum(cfloat8) from aggfns group by ss order by sum(cfloat8), ss limit 10; - ss | sum -----+-------------------- - 8 | -12152.4906229461 - 7 | -9083.89097158797 - 9 | -8975.77753697988 - 3 | -7155.43639357202 - 0 | -6138.50265394431 - | -130.291541456245 - 6 | -0.841900799423456 - 5 | 361.752419080585 - 4 | 515.843883273192 - 11 | 10225.6885134615 + ss | sum +----+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4478.94605516922 + 3 | -3066.93256727885 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + | 102.997287432663 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 11 | 264036.623917427 (10 rows) select avg(cint2) from aggfns; @@ -1780,39 +1786,39 @@ select ss, min(t) from aggfns group by ss order by min(t), ss limit 10; (10 rows) select count(*) from aggfns where cfloat8 > 0; - count -------- - 99508 + count +-------- + 109785 (1 row) select s, count(*) from aggfns where cfloat8 > 0 group by s order by count(*), s limit 10; s | count ---+------- - 8 | 9788 - 7 | 9873 - 9 | 9879 0 | 9881 - 3 | 9902 - 1 | 9959 - 6 | 10004 - 5 | 10009 - 4 | 10038 - 2 | 10175 + 4 | 9882 + 9 | 9945 + 8 | 9950 + 3 | 9963 + 5 | 9972 + 7 | 10021 + 2 | 10074 + 6 | 10097 + 1 | 20000 (10 rows) select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by count(*), ss limit 10; ss | count ----+------- - | 8 - 8 | 9788 - 7 | 9873 - 9 | 9879 + | 13 + 4 | 9872 0 | 9881 - 3 | 9894 - 6 | 10004 - 5 | 10009 - 4 | 10026 - 11 | 20146 + 9 | 9945 + 3 | 9950 + 8 | 9950 + 5 | 9972 + 7 | 10021 + 6 | 10097 + 11 | 30084 (10 rows) select max(cdate) from aggfns where cfloat8 > 0; @@ -1894,33 +1900,33 @@ select avg(cfloat4) from aggfns where cfloat8 > 0; (1 row) select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by avg(cfloat4), s limit 10; - s | avg ----+---------------------- - 3 | -Infinity - 9 | -0.571001239751741 - 4 | -0.553028167922753 - 0 | -0.334856044433109 - 7 | 0.000229969466191699 - 6 | 0.128349247144726 - 5 | 0.259525063716658 - 8 | 0.547502054482631 - 2 | Infinity - 1 | NaN + s | avg +---+-------------------- + 3 | -Infinity + 4 | -0.462286033119876 + 0 | -0.334856044433109 + 2 | -0.219086657095562 + 9 | -0.208302219537011 + 6 | 0.199537611181853 + 7 | 0.313851696029514 + 5 | 0.374879026647364 + 8 | 0.606801085094336 + 1 | NaN (10 rows) select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat4), ss limit 10; - ss | avg -----+---------------------- - 3 | -Infinity - | -7.18416403234005 - 9 | -0.571001239751741 - 4 | -0.538788339134091 - 0 | -0.334856044433109 - 7 | 0.000229969466191699 - 6 | 0.128349247144726 - 5 | 0.259525063716658 - 8 | 0.547502054482631 - 11 | NaN + ss | avg +----+-------------------- + 3 | -Infinity + 4 | -0.458554823065329 + 0 | -0.334856044433109 + 9 | -0.208302219537011 + 6 | 0.199537611181853 + 7 | 0.313851696029514 + 5 | 0.374879026647364 + 8 | 0.606801085094336 + | 1.47322510755979 + 11 | NaN (10 rows) select max(cfloat4) from aggfns where cfloat8 > 0; @@ -1930,31 +1936,31 @@ select max(cfloat4) from aggfns where cfloat8 > 0; (1 row) select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by max(cfloat4), s limit 10; - s | max ----+---------- - 9 | 49.967 - 0 | 49.9863 - 8 | 49.9869 - 7 | 49.992 - 6 | 49.994 - 4 | 49.9946 - 3 | 49.9979 - 5 | 49.9992 - 2 | Infinity - 1 | NaN + s | max +---+--------- + 9 | 49.9744 + 3 | 49.9744 + 0 | 49.9863 + 2 | 49.988 + 8 | 49.9923 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 + 5 | 49.9992 + 1 | NaN (10 rows) select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by max(cfloat4), ss limit 10; ss | max ----+--------- | 47.2047 - 9 | 49.967 + 9 | 49.9744 + 3 | 49.9744 0 | 49.9863 - 8 | 49.9869 - 7 | 49.992 - 6 | 49.994 - 4 | 49.9946 - 3 | 49.9979 + 8 | 49.9923 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 5 | 49.9992 11 | NaN (10 rows) @@ -1969,28 +1975,28 @@ select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by min(cfl s | min ---+----------- 3 | -Infinity - 4 | -49.9999 - 2 | -49.9991 - 6 | -49.9985 + 4 | -49.9993 + 1 | -49.9974 8 | -49.9969 7 | -49.9969 + 2 | -49.9928 0 | -49.9915 9 | -49.9911 5 | -49.9892 - 1 | -49.9631 + 6 | -49.9891 (10 rows) select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by min(cfloat4), ss limit 10; ss | min ----+----------- 3 | -Infinity - 4 | -49.9999 - 6 | -49.9985 + 4 | -49.9993 8 | -49.9969 7 | -49.9969 0 | -49.9915 9 | -49.9911 5 | -49.9892 + 6 | -49.9891 | -41.6131 11 | NaN (10 rows) @@ -2004,29 +2010,29 @@ select stddev(cfloat4) from aggfns where cfloat8 > 0; select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 9 | 28.674138151974 + 7 | 28.7246858657947 0 | 28.7315562731003 - 7 | 28.732480405586 - 5 | 28.8919716001815 - 6 | 28.910903762573 - 8 | 28.9950881019358 - 4 | 29.0042743342058 + 9 | 28.7729261590403 + 2 | 28.8508703679162 + 4 | 28.8548902125459 + 5 | 28.9107809470208 + 6 | 28.9388387251543 + 8 | 29.1042713834566 1 | NaN - 2 | NaN 3 | NaN (10 rows) select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - | 28.5013049189088 - 9 | 28.674138151974 + 7 | 28.7246858657947 0 | 28.7315562731003 - 7 | 28.732480405586 - 5 | 28.8919716001816 - 6 | 28.9109037625729 - 4 | 28.9941139499009 - 8 | 28.9950881019358 + 9 | 28.7729261590403 + 4 | 28.8497176060195 + 5 | 28.9107809470208 + 6 | 28.9388387251543 + 8 | 29.1042713834566 + | 29.539145536489 3 | NaN 11 | NaN (10 rows) @@ -2041,14 +2047,14 @@ select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by sum(cfl s | sum ---+----------- 3 | -Infinity - 9 | -5640.92 - 4 | -5551.3 + 4 | -4568.31 0 | -3308.71 - 7 | 2.27051 - 6 | 1284.01 - 5 | 2597.59 - 8 | 5358.95 - 2 | Infinity + 2 | -2207.08 + 9 | -2071.57 + 6 | 2014.73 + 7 | 3145.11 + 5 | 3738.29 + 8 | 6037.67 1 | NaN (10 rows) @@ -2056,267 +2062,267 @@ select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by sum(c ss | sum ----+----------- 3 | -Infinity - 9 | -5640.92 - 4 | -5401.89 + 4 | -4526.85 0 | -3308.71 - | -57.4733 - 7 | 2.27049 - 6 | 1284.01 - 5 | 2597.59 - 8 | 5358.95 + 9 | -2071.57 + | 19.1519 + 6 | 2014.73 + 7 | 3145.11 + 5 | 3738.29 + 8 | 6037.67 11 | NaN (10 rows) select avg(cfloat8) from aggfns where cfloat8 > 0; avg ------------------ - 24.9952835571616 + 22.7931225354662 (1 row) select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------ - 9 | 24.7725645778889 - 4 | 24.8521087115606 - 8 | 24.8544030681421 - 3 | 24.8618573121353 - 7 | 24.8695268926044 + 1 | 13 + 2 | 24.886472568415 + 6 | 24.9229571834467 + 9 | 24.933601739557 + 8 | 24.9404756362227 + 4 | 24.9773553659677 + 7 | 24.9965050319499 + 5 | 25.0141908239782 + 3 | 25.0243032089187 0 | 25.0776526587937 - 5 | 25.1286151190947 - 1 | 25.1502211388742 - 2 | 25.1714788850795 - 6 | 25.2046932748616 (10 rows) select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat8), ss limit 10; ss | avg ----+------------------ - | 19.1114503482822 - 9 | 24.7725645778889 - 4 | 24.8486849063598 - 8 | 24.8544030681421 - 3 | 24.8665069235878 - 7 | 24.8695268926044 + | 16.6705740293345 + 11 | 16.9860875451313 + 6 | 24.9229571834467 + 9 | 24.933601739557 + 8 | 24.9404756362227 + 4 | 24.9719502302445 + 7 | 24.9965050319499 + 5 | 25.0141908239782 + 3 | 25.0352176289523 0 | 25.0776526587937 - 5 | 25.1286151190947 - 11 | 25.1624839845733 - 6 | 25.2046932748616 (10 rows) select max(cfloat8) from aggfns where cfloat8 > 0; max ------------------ - 49.9996809987351 + 49.9995574122295 (1 row) select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by max(cfloat8), s limit 10; s | max ---+------------------ - 4 | 49.9951320933178 + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 1 | 49.9971219105646 - 2 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - | 41.8287402018905 - 4 | 49.9951320933178 + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 11 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select min(cfloat8) from aggfns where cfloat8 > 0; - min --------------------- - 0.0010170042514801 + min +---------------------- + 0.000765081495046616 (1 row) select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by min(cfloat8), s limit 10; - s | min ----+--------------------- - 4 | 0.0010170042514801 - 8 | 0.0024349894374609 - 0 | 0.00247885473072529 - 2 | 0.00317355152219534 - 5 | 0.00554935541003942 - 3 | 0.0064867315813899 - 1 | 0.00709095038473606 - 6 | 0.00739246606826782 - 9 | 0.00767894089221954 - 7 | 0.011315057054162 + s | min +---+---------------------- + 4 | 0.000765081495046616 + 7 | 0.000956561416387558 + 6 | 0.00179046764969826 + 0 | 0.00247885473072529 + 2 | 0.00441970769315958 + 3 | 0.00545482616871595 + 5 | 0.00628724228590727 + 9 | 0.0187294092029333 + 8 | 0.0195798231288791 + 1 | 13 (10 rows) select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by min(cfloat8), ss limit 10; - ss | min -----+--------------------- - 4 | 0.0010170042514801 - 8 | 0.0024349894374609 - 0 | 0.00247885473072529 - 11 | 0.00317355152219534 - 5 | 0.00554935541003942 - 3 | 0.0064867315813899 - 6 | 0.00739246606826782 - 9 | 0.00767894089221954 - 7 | 0.011315057054162 - | 1.90123561769724 + ss | min +----+---------------------- + 4 | 0.000765081495046616 + 7 | 0.000956561416387558 + 6 | 0.00179046764969826 + 0 | 0.00247885473072529 + 11 | 0.00441970769315958 + 3 | 0.00545482616871595 + 5 | 0.00628724228590727 + 9 | 0.0187294092029333 + 8 | 0.0195798231288791 + | 0.312147964723408 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 > 0; stddev ------------------ - 14.4329501580672 + 13.8427996018819 (1 row) select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 6 | 14.3328227216185 - 2 | 14.3582158038201 - 5 | 14.3890422905482 - 7 | 14.40630591898 - 1 | 14.41953078787 - 9 | 14.4290904798623 + 1 | 0 + 9 | 14.3145979997847 + 3 | 14.3699970235247 + 4 | 14.4155254530971 + 6 | 14.4175557556356 + 5 | 14.4400766885504 0 | 14.4509605112521 - 8 | 14.4600764022666 - 3 | 14.518507589479 - 4 | 14.5634752749342 + 7 | 14.4643374353136 + 2 | 14.4807945816176 + 8 | 14.507225286092 (10 rows) select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - 6 | 14.3328227216185 - 5 | 14.3890422905482 - 11 | 14.3891033811778 - 7 | 14.40630591898 - 9 | 14.4290904798623 + 11 | 10.0892977778207 + 9 | 14.3145979997847 + 3 | 14.3656116060957 + 4 | 14.4158826742614 + 6 | 14.4175557556357 + 5 | 14.4400766885504 0 | 14.4509605112521 - 8 | 14.4600764022666 - 3 | 14.5154972360802 - 4 | 14.5618677753879 - | 18.0721539273599 + 7 | 14.4643374353136 + 8 | 14.507225286092 + | 15.8897779049656 (10 rows) select sum(cfloat8) from aggfns where cfloat8 > 0; sum ------------------ - 2487230.67620604 + 2502342.95755615 (1 row) select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------ - 8 | 243274.897230975 - 9 | 244728.165464965 - 7 | 245536.839010683 - 3 | 246182.111104764 + 4 | 246826.225726493 0 | 247792.285921541 - 4 | 249465.467246645 - 1 | 250471.052322048 - 5 | 251512.308727019 - 6 | 252147.751521715 - 2 | 256119.797655684 + 9 | 247964.669299894 + 8 | 248157.732580416 + 3 | 249317.132870457 + 5 | 249441.510896711 + 7 | 250489.97692517 + 2 | 250706.324654212 + 6 | 251647.098681261 + 1 | 260000 (10 rows) select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by sum(cfloat8), ss limit 10; ss | sum ----+------------------ - | 152.891602786258 - 8 | 243274.897230975 - 9 | 244728.165464965 - 7 | 245536.839010683 - 3 | 246029.219501978 + | 216.717462381348 + 4 | 246523.092672974 0 | 247792.285921541 - 4 | 249132.914871164 - 5 | 251512.308727019 - 6 | 252147.751521715 - 11 | 506923.402353213 + 9 | 247964.669299894 + 8 | 248157.732580416 + 3 | 249100.415408076 + 5 | 249441.510896711 + 7 | 250489.97692517 + 6 | 251647.098681261 + 11 | 511009.457707731 (10 rows) select avg(cint2) from aggfns where cfloat8 > 0; avg ---------------------- - -33.4239400492883368 + -46.3563347281860533 (1 row) select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by avg(cint2), s limit 10; s | avg ---+----------------------- - 2 | -192.2076529608498918 - 8 | -130.5056237218813906 - 6 | -118.4532719631779067 - 7 | -93.6346582843236666 - 9 | -31.1112687474665586 - 4 | -28.4397806580259222 - 3 | 6.3638661409362046 + 9 | -192.8237544036235531 + 3 | -159.9071729957805907 + 2 | -156.9086662691313854 + 7 | -142.7671027664036752 + 4 | -122.8676723701528804 + 6 | -98.2421689135606661 + 8 | -1.6297525648762824 0 | 28.7771364925070879 - 5 | 73.4329298789636891 - 1 | 153.3246909858305698 + 1 | 91.9493518842900756 + 5 | 153.6364822808954924 (10 rows) select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by avg(cint2), ss limit 10; ss | avg ----+------------------------ - | -3486.7500000000000000 - 8 | -130.5056237218813906 - 6 | -118.4532719631779067 - 7 | -93.6346582843236666 - 9 | -31.1112687474665586 - 4 | -26.8886005190656818 - 11 | -22.0641860002980774 - 3 | 9.1914398462005464 + | -2431.3076923076923077 + 9 | -192.8237544036235531 + 3 | -156.9368272809576501 + 7 | -142.7671027664036752 + 4 | -119.1966149792236749 + 6 | -98.2421689135606661 + 8 | -1.6297525648762824 + 11 | 7.3528100356037667 0 | 28.7771364925070879 - 5 | 73.4329298789636891 + 5 | 153.6364822808954924 (10 rows) select count(cint2) from aggfns where cfloat8 > 0; - count -------- - 99415 + count +-------- + 109689 (1 row) select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by count(cint2), s limit 10; s | count ---+------- - 8 | 9780 - 7 | 9862 - 9 | 9868 0 | 9876 - 3 | 9891 - 1 | 9951 - 6 | 9994 - 5 | 9997 - 4 | 10030 - 2 | 10166 + 4 | 9877 + 9 | 9935 + 8 | 9942 + 3 | 9954 + 5 | 9961 + 7 | 10013 + 2 | 10062 + 6 | 10088 + 1 | 19981 (10 rows) select ss, count(cint2) from aggfns where cfloat8 > 0 group by ss order by count(cint2), ss limit 10; ss | count ----+------- - | 8 - 8 | 9780 - 7 | 9862 - 9 | 9868 + | 13 + 4 | 9867 0 | 9876 - 3 | 9883 - 6 | 9994 - 5 | 9997 - 4 | 10018 - 11 | 20129 + 9 | 9935 + 3 | 9941 + 8 | 9942 + 5 | 9961 + 7 | 10013 + 6 | 10088 + 11 | 30053 (10 rows) select max(cint2) from aggfns where cfloat8 > 0; @@ -2328,12 +2334,12 @@ select max(cint2) from aggfns where cfloat8 > 0; select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by max(cint2), s limit 10; s | max ---+------- - 7 | 16376 - 8 | 16377 - 3 | 16378 - 2 | 16381 + 2 | 16379 + 3 | 16380 + 8 | 16380 5 | 16381 6 | 16381 + 7 | 16381 0 | 16383 1 | 16383 4 | 16383 @@ -2343,12 +2349,12 @@ select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by max(cint2 select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by max(cint2), ss limit 10; ss | max ----+------- - | 16362 - 7 | 16376 - 8 | 16377 - 3 | 16378 + | 7971 + 3 | 16380 + 8 | 16380 5 | 16381 6 | 16381 + 7 | 16381 0 | 16383 4 | 16383 9 | 16383 @@ -2366,13 +2372,13 @@ select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by min(cint2 ---+-------- 0 | -16383 4 | -16383 - 5 | -16383 6 | -16383 - 2 | -16382 8 | -16382 - 3 | -16381 + 5 | -16381 7 | -16380 - 1 | -16375 + 1 | -16378 + 3 | -16378 + 2 | -16377 9 | -16375 (10 rows) @@ -2381,12 +2387,12 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by min(cin ----+-------- 0 | -16383 4 | -16383 - 5 | -16383 6 | -16383 8 | -16382 - 11 | -16382 - 3 | -16381 + 5 | -16381 7 | -16380 + 3 | -16378 + 11 | -16378 9 | -16375 | -16100 (10 rows) @@ -2394,109 +2400,109 @@ select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by min(cin select stddev(cint2) from aggfns where cfloat8 > 0; stddev ------------------- - 9482.476108257174 + 9465.641930658310 (1 row) select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 7 | 9443.605223480219 - 9 | 9445.366293176026 - 2 | 9449.155608372061 - 5 | 9459.529677447783 - 6 | 9486.777343214059 - 8 | 9492.639754117457 - 4 | 9493.176100060461 - 3 | 9515.443968190559 - 1 | 9518.651130887721 + 2 | 9406.991269284247 + 5 | 9422.095841513016 + 6 | 9433.502305093184 + 9 | 9441.945023643920 + 4 | 9449.079857205037 + 7 | 9460.956887483220 + 3 | 9461.502298006280 + 8 | 9466.374225763893 0 | 9519.824544774386 + 1 | 9528.039076724276 (10 rows) select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by stddev(cint2), ss limit 10; ss | stddev ----+------------------- - 7 | 9443.605223480219 - 9 | 9445.366293176026 - 5 | 9459.529677447783 - 11 | 9484.466820490862 - 6 | 9486.777343214059 - 8 | 9492.639754117457 - 4 | 9494.123547409782 - 3 | 9514.580778499309 + | 7759.524506314969 + 5 | 9422.095841513016 + 6 | 9433.502305093184 + 9 | 9441.945023643920 + 4 | 9447.849754018911 + 7 | 9460.956887483220 + 3 | 9463.490872675688 + 8 | 9466.374225763893 + 11 | 9488.645998388904 0 | 9519.824544774386 - | 10616.58070796 (10 rows) select sum(cint2) from aggfns where cfloat8 > 0; sum ---------- - -3322841 + -5084780 (1 row) select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by sum(cint2), s limit 10; s | sum ---+---------- - 2 | -1953983 - 8 | -1276345 - 6 | -1183822 - 7 | -923425 - 9 | -307006 - 4 | -285251 - 3 | 62945 + 9 | -1915704 + 3 | -1591716 + 2 | -1578815 + 7 | -1429527 + 4 | -1213564 + 6 | -991067 + 8 | -16203 0 | 284203 - 5 | 734109 - 1 | 1525734 + 5 | 1530373 + 1 | 1837240 (10 rows) select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by sum(cint2), ss limit 10; ss | sum ----+---------- - 8 | -1276345 - 6 | -1183822 - 7 | -923425 - 11 | -444130 - 9 | -307006 - 4 | -269370 - | -27894 - 3 | 90839 + 9 | -1915704 + 3 | -1560109 + 7 | -1429527 + 4 | -1176113 + 6 | -991067 + | -31607 + 8 | -16203 + 11 | 220974 0 | 284203 - 5 | 734109 + 5 | 1530373 (10 rows) select avg(cint4) from aggfns where cfloat8 > 0; avg --------------------- - 16.4940105318165374 + -3.1503210821150430 (1 row) select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by avg(cint4), s limit 10; s | avg ---+----------------------- - 9 | -117.7671829132503290 - 6 | -107.0337864854058377 - 8 | -41.8582958724969350 - 2 | -22.1725798525798526 - 3 | 2.1840032316703696 - 5 | 44.2106104505944650 + 9 | -227.0452488687782805 + 2 | -152.6957514393488187 + 6 | -94.7697335842329405 + 4 | -42.9105444242056264 + 7 | -7.9618800518910288 + 8 | 30.7776884422110553 + 5 | 70.0002005615724027 + 1 | 71.5608500000000000 0 | 78.5152312518975812 - 7 | 90.9036766940139775 - 1 | 116.6009639522040365 - 4 | 120.7540346682606097 + 3 | 170.6088527551942186 (10 rows) select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by avg(cint4), ss limit 10; ss | avg ----+----------------------- - 9 | -117.7671829132503290 - 6 | -107.0337864854058377 - 8 | -41.8582958724969350 - 3 | 2.0119264200525571 - 11 | 43.0645785763923359 - 5 | 44.2106104505944650 + 9 | -227.0452488687782805 + 6 | -94.7697335842329405 + 4 | -40.9285858995137763 + 7 | -7.9618800518910288 + 11 | -4.2226765057838053 + 8 | 30.7776884422110553 + 5 | 70.0002005615724027 0 | 78.5152312518975812 - 7 | 90.9036766940139775 - 4 | 127.6853181727508478 - | 215.0000000000000000 + 3 | 169.6967839195979899 + | 868.6923076923076923 (10 rows) select max(cint4) from aggfns where cfloat8 > 0; @@ -2508,30 +2514,30 @@ select max(cint4) from aggfns where cfloat8 > 0; select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by max(cint4), s limit 10; s | max ---+------- - 8 | 16378 3 | 16379 5 | 16379 7 | 16379 0 | 16380 + 6 | 16380 2 | 16381 + 9 | 16381 4 | 16382 + 8 | 16382 1 | 16383 - 6 | 16383 - 9 | 16383 (10 rows) select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by max(cint4), ss limit 10; ss | max ----+------- | 14812 - 8 | 16378 3 | 16379 5 | 16379 7 | 16379 0 | 16380 + 6 | 16380 + 9 | 16381 4 | 16382 - 6 | 16383 - 9 | 16383 + 8 | 16382 11 | 16383 (10 rows) @@ -2545,138 +2551,138 @@ select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by min(cint4 s | min ---+-------- 2 | -16383 + 7 | -16383 0 | -16382 1 | -16382 - 3 | -16382 - 4 | -16382 - 7 | -16382 9 | -16382 - 6 | -16381 5 | -16380 - 8 | -16370 + 3 | -16379 + 4 | -16378 + 6 | -16378 + 8 | -16377 (10 rows) select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by min(cint4), ss limit 10; ss | min ----+-------- + 7 | -16383 11 | -16383 0 | -16382 - 3 | -16382 - 4 | -16382 - 7 | -16382 9 | -16382 - 6 | -16381 5 | -16380 - 8 | -16370 + 3 | -16379 + 4 | -16378 + 6 | -16378 + 8 | -16377 | -15907 (10 rows) select stddev(cint4) from aggfns where cfloat8 > 0; stddev ------------------- - 9450.307594212300 + 9447.836798758010 (1 row) select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by stddev(cint4), s limit 10; s | stddev ---+------------------- 0 | 9368.404782340758 - 6 | 9401.528449816030 - 9 | 9409.138533616049 - 1 | 9417.758518179972 - 3 | 9465.021007666210 - 4 | 9468.463171050067 - 8 | 9473.020262302973 - 7 | 9483.434940826228 - 5 | 9496.029307690310 - 2 | 9517.950578375538 + 6 | 9385.470128440942 + 8 | 9411.536015886790 + 4 | 9416.523033700832 + 1 | 9459.538662433945 + 2 | 9460.302598725572 + 9 | 9474.284943213442 + 5 | 9475.929892556881 + 7 | 9500.872262505529 + 3 | 9509.065450373130 (10 rows) select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by stddev(cint4), ss limit 10; ss | stddev ----+------------------- + | 8985.945186647640 0 | 9368.404782340758 - 6 | 9401.528449816030 - 9 | 9409.138533616049 - 3 | 9464.282001021753 - 4 | 9468.064640965656 - 11 | 9468.713124828893 - 8 | 9473.020262302973 - 7 | 9483.434940826228 - 5 | 9496.029307690310 - | 11050.03141560 + 6 | 9385.470128440942 + 8 | 9411.536015886790 + 4 | 9416.391322858156 + 11 | 9460.260597896060 + 9 | 9474.284943213442 + 5 | 9475.929892556881 + 7 | 9500.872262505529 + 3 | 9510.123363067463 (10 rows) select sum(cint4) from aggfns where cfloat8 > 0; sum --------- - 1641286 + -345858 (1 row) select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by sum(cint4), s limit 10; s | sum ---+---------- - 9 | -1163422 - 6 | -1070766 - 8 | -409709 - 2 | -225606 - 3 | 21626 - 5 | 442504 + 9 | -2257965 + 2 | -1538257 + 6 | -956890 + 4 | -424042 + 7 | -79786 + 8 | 306238 + 5 | 698042 0 | 775809 - 7 | 897492 - 1 | 1161229 - 4 | 1212129 + 1 | 1431217 + 3 | 1699776 (10 rows) select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by sum(cint4), ss limit 10; ss | sum ----+---------- - 9 | -1163422 - 6 | -1070766 - 8 | -409709 - | 1720 - 3 | 19906 - 5 | 442504 + 9 | -2257965 + 6 | -956890 + 4 | -404047 + 11 | -127035 + 7 | -79786 + | 11293 + 8 | 306238 + 5 | 698042 0 | 775809 - 11 | 867579 - 7 | 897492 - 4 | 1280173 + 3 | 1688483 (10 rows) select avg(cint8) from aggfns where cfloat8 > 0; - avg --------------------- - 8.1991196687703501 + avg +--------------------- + -3.7972582775424694 (1 row) select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by avg(cint8), s limit 10; - s | avg ----+---------------------- - 1 | -96.1673862837634301 - 5 | -90.0727345389149765 - 8 | -59.1858398038414385 - 3 | -12.3414461724904060 - 4 | -2.5818888224745965 - 2 | 21.0509090909090909 - 6 | 35.7028188724510196 - 0 | 42.9815808116587390 - 7 | 64.3715182821837334 - 9 | 179.2666261767385363 + s | avg +---+------------------------ + 8 | -166.4501507537688442 + 5 | -78.9197753710389089 + 4 | -61.2938676381299332 + 6 | -32.8705556105773992 + 1 | -25.4401500000000000 + 7 | 1.15707015267937331604 + 0 | 42.9815808116587390 + 9 | 44.5682252388134741 + 3 | 109.7175549533273111 + 2 | 148.9026206075044669 (10 rows) select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by avg(cint8), ss limit 10; ss | avg ----+------------------------ - 5 | -90.0727345389149765 - 8 | -59.1858398038414385 - 11 | -38.8234388960587710 - 3 | -13.0468971093592076 - 4 | 1.26491123079992020746 - 6 | 35.7028188724510196 + 8 | -166.4501507537688442 + 5 | -78.9197753710389089 + 4 | -61.5197528363047002 + 6 | -32.8705556105773992 + 7 | 1.15707015267937331604 + 11 | 33.0028919026725170 0 | 42.9815808116587390 - 7 | 64.3715182821837334 - 9 | 179.2666261767385363 - | 860.1250000000000000 + 9 | 44.5682252388134741 + 3 | 106.1022110552763819 + | 2876.8461538461538462 (10 rows) select max(cint8) from aggfns where cfloat8 > 0; @@ -2688,15 +2694,15 @@ select max(cint8) from aggfns where cfloat8 > 0; select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by max(cint8), s limit 10; s | max ---+------- - 2 | 16372 - 8 | 16374 + 2 | 16373 + 7 | 16378 + 6 | 16379 0 | 16380 - 6 | 16380 - 7 | 16380 + 8 | 16380 3 | 16381 + 4 | 16382 9 | 16382 1 | 16383 - 4 | 16383 5 | 16383 (10 rows) @@ -2704,13 +2710,13 @@ select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by max(cin ss | max ----+------- | 13750 - 8 | 16374 + 7 | 16378 + 6 | 16379 0 | 16380 - 6 | 16380 - 7 | 16380 + 8 | 16380 3 | 16381 + 4 | 16382 9 | 16382 - 4 | 16383 5 | 16383 11 | 16383 (10 rows) @@ -2726,20 +2732,21 @@ select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by min(cint8 ---+-------- 1 | -16383 7 | -16383 + 8 | -16383 5 | -16382 4 | -16381 6 | -16381 9 | -16380 0 | -16379 - 2 | -16378 + 2 | -16379 3 | -16378 - 8 | -16374 (10 rows) select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by min(cint8), ss limit 10; ss | min ----+-------- 7 | -16383 + 8 | -16383 11 | -16383 5 | -16382 4 | -16381 @@ -2747,44 +2754,43 @@ select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by min(cin 9 | -16380 0 | -16379 3 | -16378 - 8 | -16374 - | -14174 + | -11918 (10 rows) select sum(cint8) from aggfns where cfloat8 > 0; - sum --------- - 815878 + sum +--------- + -416882 (1 row) select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by sum(cint8), s limit 10; - s | sum ----+--------- - 1 | -957731 - 5 | -901538 - 8 | -579311 - 3 | -122205 - 4 | -25917 - 2 | 214193 - 6 | 357171 - 0 | 424701 - 7 | 635540 - 9 | 1770975 + s | sum +---+---------- + 8 | -1656179 + 5 | -786988 + 4 | -605706 + 1 | -508803 + 6 | -331894 + 7 | 11595 + 0 | 424701 + 9 | 443231 + 3 | 1093116 + 2 | 1500045 (10 rows) select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by sum(cint8), ss limit 10; - ss | sum -----+--------- - 5 | -901538 - 11 | -782137 - 8 | -579311 - 3 | -129086 - | 6881 - 4 | 12682 - 6 | 357171 - 0 | 424701 - 7 | 635540 - 9 | 1770975 + ss | sum +----+---------- + 8 | -1656179 + 5 | -786988 + 4 | -607323 + 6 | -331894 + 7 | 11595 + | 37399 + 0 | 424701 + 9 | 443231 + 11 | 992859 + 3 | 1055717 (10 rows) select max(cts) from aggfns where cfloat8 > 0; @@ -2934,7 +2940,7 @@ select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by min(cts select avg(s) from aggfns where cfloat8 > 0; avg -------------------- - 4.4876994814487277 + 4.1832581864553445 (1 row) select s, avg(s) from aggfns where cfloat8 > 0 group by s order by avg(s), s limit 10; @@ -2956,7 +2962,7 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by avg(s), ss ss | avg ----+------------------------ 0 | 0.00000000000000000000 - 11 | 1.5068499950362355 + 11 | 1.3358595931392102 3 | 3.0000000000000000 | 3.0000000000000000 4 | 4.0000000000000000 @@ -2968,39 +2974,39 @@ select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by avg(s), ss (10 rows) select count(s) from aggfns where cfloat8 > 0; - count -------- - 99508 + count +-------- + 109785 (1 row) select s, count(s) from aggfns where cfloat8 > 0 group by s order by count(s), s limit 10; s | count ---+------- - 8 | 9788 - 7 | 9873 - 9 | 9879 0 | 9881 - 3 | 9902 - 1 | 9959 - 6 | 10004 - 5 | 10009 - 4 | 10038 - 2 | 10175 + 4 | 9882 + 9 | 9945 + 8 | 9950 + 3 | 9963 + 5 | 9972 + 7 | 10021 + 2 | 10074 + 6 | 10097 + 1 | 20000 (10 rows) select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by count(s), ss limit 10; ss | count ----+------- - | 8 - 8 | 9788 - 7 | 9873 - 9 | 9879 + | 13 + 4 | 9872 0 | 9881 - 3 | 9894 - 6 | 10004 - 5 | 10009 - 4 | 10026 - 11 | 20146 + 9 | 9945 + 3 | 9950 + 8 | 9950 + 5 | 9972 + 7 | 10021 + 6 | 10097 + 11 | 30084 (10 rows) select max(s) from aggfns where cfloat8 > 0; @@ -3078,7 +3084,7 @@ select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by min(s), ss select stddev(s) from aggfns where cfloat8 > 0; stddev -------------------- - 2.8656139545132202 + 2.9152854040352282 (1 row) select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by stddev(s), s limit 10; @@ -3108,49 +3114,49 @@ select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by stddev(s 8 | 0 9 | 0 | 0 - 11 | 0.50352713246563412901 + 11 | 0.47440470436008342899 (10 rows) select sum(s) from aggfns where cfloat8 > 0; sum -------- - 446562 + 459259 (1 row) select s, sum(s) from aggfns where cfloat8 > 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 9959 - 2 | 20350 - 3 | 29706 - 4 | 40152 - 5 | 50045 - 6 | 60024 - 7 | 69111 - 8 | 78304 - 9 | 88911 + 1 | 20000 + 2 | 20148 + 3 | 29889 + 4 | 39528 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 (10 rows) select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by sum(s), ss limit 10; ss | sum ----+------- 0 | 0 - | 24 - 3 | 29682 - 11 | 30357 - 4 | 40104 - 5 | 50045 - 6 | 60024 - 7 | 69111 - 8 | 78304 - 9 | 88911 + | 39 + 3 | 29850 + 4 | 39488 + 11 | 40188 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 (10 rows) select avg(ss) from aggfns where cfloat8 > 0; avg -------------------- - 6.4099195979899497 + 6.8319425718762526 (1 row) select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by avg(ss), s limit 10; @@ -3158,7 +3164,7 @@ select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by avg(ss), s l ---+------------------------ 0 | 0.00000000000000000000 3 | 3.0000000000000000 - 4 | 4.0083682008368201 + 4 | 4.0070835863185590 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -3258,7 +3264,7 @@ select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by min(ss), s select stddev(ss) from aggfns where cfloat8 > 0; stddev -------------------- - 3.3546680341938823 + 3.4547844482354617 (1 row) select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by stddev(ss), s limit 10; @@ -3273,7 +3279,7 @@ select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by stddev(ss 7 | 0 8 | 0 9 | 0 - 4 | 0.24189503558873125235 + 4 | 0.22257569540261848080 (10 rows) select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by stddev(ss), ss limit 10; @@ -3294,43 +3300,43 @@ select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by stddev( select sum(ss) from aggfns where cfloat8 > 0; sum -------- - 637787 + 749956 (1 row) select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 3 | 29682 - 4 | 40236 - 5 | 50045 - 6 | 60024 - 7 | 69111 - 8 | 78304 - 9 | 88911 - 1 | 109549 - 2 | 111925 + 3 | 29850 + 4 | 39598 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 + 2 | 110814 + 1 | 220000 (10 rows) select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 - 3 | 29682 - 4 | 40104 - 5 | 50045 - 6 | 60024 - 7 | 69111 - 8 | 78304 - 9 | 88911 - 11 | 221606 + 3 | 29850 + 4 | 39488 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 + 11 | 330924 | (10 rows) select max(t) from aggfns where cfloat8 > 0; max -------- - 109994 + 110000 (1 row) select s, max(t) from aggfns where cfloat8 > 0 group by s order by max(t), s limit 10; @@ -3338,29 +3344,29 @@ select s, max(t) from aggfns where cfloat8 > 0 group by s order by max(t), s lim ---+-------- 0 | 19999 1 | 30000 - 2 | 40000 - 3 | 50000 + 2 | 39999 + 3 | 49999 4 | 60000 5 | 70000 - 6 | 80000 - 7 | 89997 - 8 | 100000 - 9 | 109994 + 6 | 79998 + 7 | 89995 + 8 | 99997 + 9 | 110000 (10 rows) select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 19999 - | 46332 - 3 | 50000 + | 49491 + 3 | 49999 11 | 59192 4 | 60000 5 | 70000 - 6 | 80000 - 7 | 89997 - 8 | 100000 - 9 | 109994 + 6 | 79998 + 7 | 89995 + 8 | 99997 + 9 | 110000 (10 rows) select min(t) from aggfns where cfloat8 > 0; @@ -3373,12 +3379,12 @@ select s, min(t) from aggfns where cfloat8 > 0 group by s order by min(t), s lim s | min ---+------- 0 | 1 - 1 | 10003 - 2 | 20002 - 3 | 30003 - 4 | 40001 - 5 | 50002 - 6 | 60001 + 1 | 10001 + 2 | 20001 + 3 | 30001 + 4 | 40003 + 5 | 50001 + 6 | 60002 7 | 70001 8 | 80003 9 | 90002 @@ -3388,51 +3394,50 @@ select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by min(t), ss ss | min ----+------- 0 | 1 - 11 | 10003 - 3 | 30003 + 11 | 10001 + 3 | 30001 | 30537 - 4 | 40001 - 5 | 50002 - 6 | 60001 + 4 | 40003 + 5 | 50001 + 6 | 60002 7 | 70001 8 | 80003 9 | 90002 (10 rows) select count(*) from aggfns where cfloat8 <= 0; - count --------- - 100492 + count +------- + 90215 (1 row) select s, count(*) from aggfns where cfloat8 <= 0 group by s order by count(*), s limit 10; s | count ---+------- - 2 | 9825 - 4 | 9962 - 5 | 9991 - 6 | 9996 - 1 | 10041 - 3 | 10098 + 6 | 9903 + 2 | 9926 + 7 | 9979 + 5 | 10028 + 3 | 10037 + 8 | 10050 + 9 | 10055 + 4 | 10118 0 | 10119 - 9 | 10121 - 7 | 10127 - 8 | 10212 -(10 rows) +(9 rows) select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by count(*), ss limit 10; ss | count ----+------- - | 11 - 4 | 9955 - 5 | 9991 - 6 | 9996 - 3 | 10087 + | 6 + 6 | 9903 + 11 | 9935 + 7 | 9979 + 5 | 10028 + 3 | 10031 + 8 | 10050 + 9 | 10055 + 4 | 10109 0 | 10119 - 9 | 10121 - 7 | 10127 - 8 | 10212 - 11 | 19873 (10 rows) select max(cdate) from aggfns where cfloat8 <= 0; @@ -3445,7 +3450,6 @@ select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by max(cdat s | max ---+------------ 0 | 01-01-2021 - 1 | 05-19-2048 2 | 10-05-2075 3 | 02-21-2103 4 | 07-09-2130 @@ -3454,7 +3458,7 @@ select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by max(cdat 7 | 08-28-2212 8 | 01-14-2240 9 | 06-01-2267 -(10 rows) +(9 rows) select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by max(cdate), ss limit 10; ss | max @@ -3481,7 +3485,6 @@ select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by min(cdat s | min ---+------------ 0 | 01-01-2021 - 1 | 05-19-2048 2 | 10-05-2075 3 | 02-21-2103 4 | 07-09-2130 @@ -3490,13 +3493,13 @@ select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by min(cdat 7 | 08-28-2212 8 | 01-14-2240 9 | 06-01-2267 -(10 rows) +(9 rows) select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by min(cdate), ss limit 10; ss | min ----+------------ 0 | 01-01-2021 - 11 | 05-19-2048 + 11 | 10-05-2075 3 | 02-21-2103 | 02-21-2103 4 | 07-09-2130 @@ -3508,255 +3511,248 @@ select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by min(cd (10 rows) select avg(cfloat4) from aggfns where cfloat8 <= 0; - avg -------------------- - 0.106185028347415 + avg +---------- + Infinity (1 row) select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat4), s limit 10; - s | avg ----+--------------------- - 1 | -0.369617656298752 - 5 | -0.238408898764696 - 6 | -0.140676149758002 - 9 | -0.0210546333041521 - 2 | 0.174820695098385 - 4 | 0.200448185895117 - 3 | 0.200936527140099 - 8 | 0.369675376818395 - 7 | 0.378335182597323 - 0 | 0.497406092427368 -(10 rows) + s | avg +---+-------------------- + 9 | -0.376175993822296 + 5 | -0.351281471733702 + 3 | -0.328033180425701 + 6 | -0.215785538185229 + 7 | 0.0690012062121504 + 4 | 0.100205441546667 + 8 | 0.308099926433512 + 0 | 0.497406092427368 + 2 | Infinity +(9 rows) select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat4), ss limit 10; - ss | avg -----+--------------------- - 5 | -0.238408898764696 - 6 | -0.140676149758002 - 11 | -0.101489562396578 - 9 | -0.0210546333041521 - 3 | 0.198087105455873 - 4 | 0.20291806567958 - 8 | 0.369675376818395 - 7 | 0.378335182597323 - 0 | 0.497406092427368 - | 2.81385621157559 + ss | avg +----+-------------------- + | -7.61213672161102 + 9 | -0.376175993822296 + 5 | -0.351281471733702 + 3 | -0.323676224863234 + 6 | -0.215785538185229 + 7 | 0.0690012062121504 + 4 | 0.113266462457489 + 8 | 0.308099926433512 + 0 | 0.497406092427368 + 11 | Infinity (10 rows) select max(cfloat4) from aggfns where cfloat8 <= 0; - max ---------- - 49.9997 + max +---------- + Infinity (1 row) select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by max(cfloat4), s limit 10; - s | max ----+--------- - 3 | 49.9831 - 5 | 49.9847 - 9 | 49.9899 - 4 | 49.9928 - 6 | 49.9956 - 7 | 49.9969 - 2 | 49.9977 - 0 | 49.9995 - 8 | 49.9997 - 1 | 49.9997 -(10 rows) + s | max +---+---------- + 5 | 49.9753 + 9 | 49.9899 + 7 | 49.992 + 6 | 49.9938 + 4 | 49.9946 + 3 | 49.9979 + 0 | 49.9995 + 8 | 49.9997 + 2 | Infinity +(9 rows) select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat4), ss limit 10; - ss | max -----+--------- - | 43.8334 - 3 | 49.9831 - 5 | 49.9847 - 9 | 49.9899 - 4 | 49.9928 - 6 | 49.9956 - 7 | 49.9969 - 0 | 49.9995 - 8 | 49.9997 - 11 | 49.9997 + ss | max +----+---------- + | 43.8334 + 5 | 49.9753 + 9 | 49.9899 + 7 | 49.992 + 6 | 49.9938 + 4 | 49.9946 + 3 | 49.9979 + 0 | 49.9995 + 8 | 49.9997 + 11 | Infinity (10 rows) select min(cfloat4) from aggfns where cfloat8 <= 0; min ---------- - -49.9995 + -49.9999 (1 row) select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by min(cfloat4), s limit 10; s | min ---+---------- + 4 | -49.9999 6 | -49.9995 + 2 | -49.9991 7 | -49.9984 - 1 | -49.9974 0 | -49.9949 5 | -49.9942 - 2 | -49.9932 - 8 | -49.9837 - 9 | -49.9836 - 4 | -49.9742 + 9 | -49.9874 + 8 | -49.9853 3 | -49.974 -(10 rows) +(9 rows) select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat4), ss limit 10; ss | min ----+---------- + 4 | -49.9999 6 | -49.9995 + 11 | -49.9991 7 | -49.9984 - 11 | -49.9974 0 | -49.9949 5 | -49.9942 - 8 | -49.9837 - 9 | -49.9836 - 4 | -49.9742 + 9 | -49.9874 + 8 | -49.9853 3 | -49.974 | -45.4083 (10 rows) select stddev(cfloat4) from aggfns where cfloat8 <= 0; - stddev ------------------- - 28.9176238982259 + stddev +-------- + NaN (1 row) select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat4), s limit 10; s | stddev ---+------------------ - 4 | 28.6443792572409 0 | 28.7188352112159 - 3 | 28.8001993440446 - 7 | 28.8445902712948 - 6 | 28.9280364258487 - 9 | 29.0050149205695 - 8 | 29.0137169777563 - 2 | 29.0305221043722 - 1 | 29.0393254603524 - 5 | 29.149709761256 -(10 rows) + 3 | 28.7589901880779 + 4 | 28.7990664583532 + 7 | 28.8547648614793 + 6 | 28.89882973622 + 8 | 28.9050890855561 + 9 | 28.9126192916065 + 5 | 29.1278202173096 + 2 | NaN +(9 rows) select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat4), ss limit 10; ss | stddev ----+------------------ - 4 | 28.644441921671 0 | 28.7188352112159 - 3 | 28.7972864714779 - 7 | 28.8445902712948 - 6 | 28.9280364258488 - 9 | 29.0050149205695 - 8 | 29.0137169777563 - 11 | 29.0353370214802 - 5 | 29.1497097612561 - | 32.7733939400537 + 3 | 28.7564997868619 + 4 | 28.7937148382071 + 7 | 28.8547648614793 + 6 | 28.89882973622 + 8 | 28.9050890855561 + 9 | 28.9126192916064 + 5 | 29.1278202173095 + | 34.8729157239149 + 11 | NaN (10 rows) select sum(cfloat4) from aggfns where cfloat8 <= 0; - sum ---------- - 10670.7 + sum +---------- + Infinity (1 row) select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat4), s limit 10; s | sum ---+---------- - 1 | -3711.33 - 5 | -2381.94 - 6 | -1406.2 - 9 | -213.094 - 2 | 1717.61 - 4 | 1996.86 - 3 | 2029.06 - 8 | 3775.12 - 7 | 3831.4 + 9 | -3782.45 + 5 | -3522.65 + 3 | -3292.47 + 6 | -2136.92 + 7 | 688.563 + 4 | 1013.88 + 8 | 3096.4 0 | 5033.25 -(10 rows) + 2 | Infinity +(9 rows) select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat4), ss limit 10; ss | sum ----+---------- - 5 | -2381.94 - 11 | -2016.9 - 6 | -1406.2 - 9 | -213.094 - | 30.9524 - 3 | 1998.1 - 4 | 2020.05 - 8 | 3775.12 - 7 | 3831.4 + 9 | -3782.45 + 5 | -3522.65 + 3 | -3246.8 + 6 | -2136.92 + | -45.6728 + 7 | 688.563 + 4 | 1145.01 + 8 | 3096.4 0 | 5033.25 + 11 | Infinity (10 rows) select avg(cfloat8) from aggfns where cfloat8 <= 0; avg ------------------- - -25.0742807687329 + -25.0131648946505 (1 row) select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by avg(cfloat8), s limit 10; s | avg ---+------------------- - 6 | -25.2249493219802 - 7 | -25.1427599469014 - 5 | -25.1376795423819 - 3 | -25.1007961021779 + 7 | -25.229255062715 + 8 | -25.2270239386592 + 3 | -25.1351069194284 0 | -25.0944548448943 - 9 | -25.0670826007257 - 1 | -25.048029068051 - 8 | -25.0124743296045 - 4 | -24.9766590364965 - 2 | -24.9353738049633 -(10 rows) + 6 | -25.0686778438405 + 9 | -24.8892608135943 + 2 | -24.8583035779324 + 4 | -24.8301394745889 + 5 | -24.7870942066272 +(9 rows) select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat8), ss limit 10; ss | avg ----+------------------- - | -25.7439222038639 - 6 | -25.2249493219802 - 7 | -25.1427599469014 - 5 | -25.1376795423819 - 3 | -25.1000947650986 + 7 | -25.229255062715 + 8 | -25.2270239386592 + 3 | -25.1388045035744 0 | -25.0944548448943 - 9 | -25.0670826007257 - 8 | -25.0124743296045 - 11 | -24.9935950203669 - 4 | -24.9740905060663 + 6 | -25.0686778438405 + 9 | -24.8892608135943 + 11 | -24.858866008083 + 4 | -24.8295616508204 + 5 | -24.7870942066272 + | -18.9533624914475 (10 rows) select max(cfloat8) from aggfns where cfloat8 <= 0; - max ------------------------ - -0.000587338581681252 + max +---------------------- + -0.00172397121787071 (1 row) select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by max(cfloat8), s limit 10; - s | max ----+----------------------- - 4 | -0.015261210501194 - 6 | -0.00991490669548512 - 0 | -0.00547224190086126 - 7 | -0.00457693822681904 - 9 | -0.00377818942070007 - 3 | -0.00155717134475708 - 5 | -0.00140282791107893 - 1 | -0.00135276932269335 - 8 | -0.00127912499010563 - 2 | -0.000587338581681252 -(10 rows) + s | max +---+---------------------- + 0 | -0.00547224190086126 + 9 | -0.00466627534478903 + 4 | -0.0041270861402154 + 6 | -0.00408347696065903 + 7 | -0.00273226760327816 + 3 | -0.00268903095275164 + 5 | -0.00228420831263065 + 8 | -0.00182925723493099 + 2 | -0.00172397121787071 +(9 rows) select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat8), ss limit 10; - ss | max -----+----------------------- - | -3.40055420529097 - 4 | -0.015261210501194 - 6 | -0.00991490669548512 - 0 | -0.00547224190086126 - 7 | -0.00457693822681904 - 9 | -0.00377818942070007 - 3 | -0.00155717134475708 - 5 | -0.00140282791107893 - 8 | -0.00127912499010563 - 11 | -0.000587338581681252 + ss | max +----+---------------------- + | -5.18986904062331 + 0 | -0.00547224190086126 + 9 | -0.00466627534478903 + 4 | -0.0041270861402154 + 6 | -0.00408347696065903 + 7 | -0.00273226760327816 + 3 | -0.00268903095275164 + 5 | -0.00228420831263065 + 8 | -0.00182925723493099 + 11 | -0.00172397121787071 (10 rows) select min(cfloat8) from aggfns where cfloat8 <= 0; @@ -3769,174 +3765,169 @@ select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by min(cf s | min ---+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 1 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - 2 | -49.9854512279853 -(10 rows) + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 +(9 rows) select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 11 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - | -40.4587021796033 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 <= 0; stddev ------------------ - 14.4132133795776 + 14.4381579706012 (1 row) select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 8 | 14.3287207237224 - 4 | 14.338825539003 - 2 | 14.3532302747139 - 6 | 14.4046796063746 - 5 | 14.4106499899109 - 1 | 14.4216091274813 - 7 | 14.4303638321788 - 9 | 14.4471294863496 - 3 | 14.484217665042 + 7 | 14.4030112329564 + 2 | 14.4030502020858 + 6 | 14.4144870413512 + 4 | 14.4341540067486 + 3 | 14.4341919321977 + 5 | 14.4378475427373 + 9 | 14.445355480345 + 8 | 14.4532419971748 0 | 14.5136612753879 -(10 rows) +(9 rows) select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - | 13.2313932766119 - 8 | 14.3287207237224 - 4 | 14.3399291680111 - 11 | 14.3870105146555 - 6 | 14.4046796063746 - 5 | 14.4106499899109 - 7 | 14.4303638321788 - 9 | 14.4471294863496 - 3 | 14.4861084104713 + 7 | 14.4030112329563 + 11 | 14.4033336871388 + 6 | 14.4144870413512 + 3 | 14.4335904065982 + 4 | 14.4339025361113 + 5 | 14.4378475427373 + 9 | 14.445355480345 + 8 | 14.4532419971748 0 | 14.5136612753879 + | 15.4584765893444 (10 rows) select sum(cfloat8) from aggfns where cfloat8 <= 0; sum ------------------- - -2519764.62301151 + -2256562.67097089 (1 row) select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by sum(cfloat8), s limit 10; s | sum ---+------------------- - 8 | -255427.387853921 - 7 | -254620.729982271 0 | -253930.788575485 - 9 | -253703.943001945 - 3 | -253467.839039792 - 6 | -252148.593422514 - 1 | -251507.2598723 - 5 | -251150.556307938 - 4 | -248817.477321578 - 2 | -244990.047633764 -(10 rows) + 8 | -253531.590583525 + 3 | -252281.068150303 + 7 | -251762.736270833 + 4 | -251231.351203891 + 9 | -250261.517480691 + 5 | -248564.980704058 + 6 | -248255.116687552 + 2 | -246743.521314557 +(9 rows) select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat8), ss limit 10; ss | sum ----+------------------- - 11 | -496697.713839752 - 8 | -255427.387853921 - 7 | -254620.729982271 0 | -253930.788575485 - 9 | -253703.943001945 - 3 | -253184.65589555 - 6 | -252148.593422514 - 5 | -251150.556307938 - 4 | -248617.07098789 - | -283.183144242503 + 8 | -253531.590583525 + 3 | -252167.347975355 + 7 | -251762.736270833 + 4 | -251002.038728143 + 9 | -250261.517480691 + 5 | -248564.980704058 + 6 | -248255.116687552 + 11 | -246972.833790304 + | -113.720174948685 (10 rows) select avg(cint2) from aggfns where cfloat8 <= 0; avg ---------------------- - -32.8711290402908511 + -17.0676978728598218 (1 row) select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by avg(cint2), s limit 10; s | avg ---+----------------------- - 3 | -195.8809712586719524 - 8 | -128.5279874522105676 - 2 | -123.2159959246051961 - 4 | -28.9879409104612602 - 7 | -19.0635438284415456 - 9 | -12.7132403836645901 - 6 | -3.6577550816060879 + 8 | -256.1267058471959359 + 2 | -159.7472527472527473 + 3 | -32.0911538845118181 + 6 | -23.1764884261599110 0 | 6.6666006927263731 - 1 | 31.0574277168494516 - 5 | 146.6757812500000000 -(10 rows) + 7 | 31.4203451043338684 + 4 | 63.3268012668250198 + 5 | 66.6813373253493014 + 9 | 147.3351582719490344 +(9 rows) select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by avg(cint2), ss limit 10; ss | avg ----+----------------------- - 3 | -196.2831630122035916 - 8 | -128.5279874522105676 - 11 | -45.6090066492041104 - 4 | -28.2469831053901850 - 7 | -19.0635438284415456 - 9 | -12.7132403836645901 - 6 | -3.6577550816060879 + 8 | -256.1267058471959359 + 11 | -158.1923851732473811 + 3 | -32.6703921764294981 + 6 | -23.1764884261599110 0 | 6.6666006927263731 - 5 | 146.6757812500000000 - | 172.6363636363636364 + 7 | 31.4203451043338684 + 4 | 61.9965329370975731 + 5 | 66.6813373253493014 + 9 | 147.3351582719490344 + | 935.3333333333333333 (10 rows) select count(cint2) from aggfns where cfloat8 <= 0; - count --------- - 100395 + count +------- + 90121 (1 row) select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by count(cint2), s limit 10; s | count ---+------- - 2 | 9815 - 4 | 9951 - 5 | 9984 - 6 | 9987 - 1 | 10030 - 3 | 10090 + 6 | 9893 + 2 | 9919 + 7 | 9968 + 5 | 10020 + 3 | 10027 + 8 | 10039 + 9 | 10046 + 4 | 10104 0 | 10105 - 9 | 10113 - 7 | 10119 - 8 | 10201 -(10 rows) +(9 rows) select ss, count(cint2) from aggfns where cfloat8 <= 0 group by ss order by count(cint2), ss limit 10; ss | count ----+------- - | 11 - 4 | 9944 - 5 | 9984 - 6 | 9987 - 3 | 10079 + | 6 + 6 | 9893 + 11 | 9928 + 7 | 9968 + 5 | 10020 + 3 | 10021 + 8 | 10039 + 9 | 10046 + 4 | 10095 0 | 10105 - 9 | 10113 - 7 | 10119 - 8 | 10201 - 11 | 19852 (10 rows) select max(cint2) from aggfns where cfloat8 <= 0; @@ -3948,29 +3939,28 @@ select max(cint2) from aggfns where cfloat8 <= 0; select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by max(cint2), s limit 10; s | max ---+------- - 2 | 16375 - 9 | 16375 - 3 | 16380 + 7 | 16376 + 9 | 16376 + 3 | 16378 0 | 16381 + 2 | 16381 5 | 16381 - 7 | 16381 - 1 | 16382 8 | 16382 4 | 16383 6 | 16383 -(10 rows) +(9 rows) select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by max(cint2), ss limit 10; ss | max ----+------- - | 10632 - 9 | 16375 - 3 | 16380 + | 16362 + 7 | 16376 + 9 | 16376 + 3 | 16378 0 | 16381 5 | 16381 - 7 | 16381 + 11 | 16381 8 | 16382 - 11 | 16382 4 | 16383 6 | 16383 (10 rows) @@ -3985,138 +3975,134 @@ select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by min(cint s | min ---+-------- 0 | -16383 + 5 | -16383 6 | -16383 2 | -16382 7 | -16382 8 | -16382 - 3 | -16380 + 3 | -16381 4 | -16379 - 1 | -16378 - 5 | -16374 9 | -16374 -(10 rows) +(9 rows) select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by min(cint2), ss limit 10; ss | min ----+-------- 0 | -16383 + 5 | -16383 6 | -16383 7 | -16382 8 | -16382 11 | -16382 - 3 | -16380 + 3 | -16381 4 | -16379 - 5 | -16374 9 | -16374 - | -9099 + | -7696 (10 rows) select stddev(cint2) from aggfns where cfloat8 <= 0; stddev ------------------- - 9468.828025193727 + 9487.728001026379 (1 row) select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by stddev(cint2), s limit 10; s | stddev ---+------------------- - 3 | 9431.449699785939 - 6 | 9448.435617417508 0 | 9451.115288155243 - 9 | 9455.614886560824 - 8 | 9463.597928793709 - 2 | 9469.005892286076 - 4 | 9474.656350647745 - 5 | 9476.359682175140 - 7 | 9480.532843811240 - 1 | 9537.428149419877 -(10 rows) + 9 | 9456.028731464701 + 7 | 9463.041992703462 + 3 | 9485.287342318946 + 8 | 9487.451140540082 + 6 | 9502.509922580216 + 2 | 9511.416697071789 + 5 | 9513.243501566793 + 4 | 9517.027301293118 +(9 rows) select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint2), ss limit 10; - ss | stddev -----+------------------- - | 6505.198648353904 - 3 | 9434.362465275590 - 6 | 9448.435617417508 - 0 | 9451.115288155243 - 9 | 9455.614886560824 - 8 | 9463.597928793709 - 4 | 9473.486702235684 - 5 | 9476.359682175140 - 7 | 9480.532843811240 - 11 | 9504.295955675669 + ss | stddev +----+-------------------- + 0 | 9451.115288155243 + 9 | 9456.028731464701 + 7 | 9463.041992703462 + 3 | 9485.440311868001 + 8 | 9487.451140540082 + 6 | 9502.509922580216 + 11 | 9510.413974851870 + 5 | 9513.243501566793 + 4 | 9518.051043653511 + | 10051.146773710285 (10 rows) select sum(cint2) from aggfns where cfloat8 <= 0; sum ---------- - -3300097 + -1538158 (1 row) select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by sum(cint2), s limit 10; s | sum ---+---------- - 3 | -1976439 - 8 | -1311114 - 2 | -1209365 - 4 | -288459 - 7 | -192904 - 9 | -128569 - 6 | -36530 + 8 | -2571256 + 2 | -1584533 + 3 | -321778 + 6 | -229285 0 | 67366 - 1 | 311506 - 5 | 1464411 -(10 rows) + 7 | 313198 + 4 | 639854 + 5 | 668147 + 9 | 1480129 +(9 rows) select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by sum(cint2), ss limit 10; ss | sum ----+---------- - 3 | -1978338 - 8 | -1311114 - 11 | -905430 - 4 | -280888 - 7 | -192904 - 9 | -128569 - 6 | -36530 - | 1899 + 8 | -2571256 + 11 | -1570534 + 3 | -327390 + 6 | -229285 + | 5612 0 | 67366 - 5 | 1464411 + 7 | 313198 + 4 | 625855 + 5 | 668147 + 9 | 1480129 (10 rows) select avg(cint4) from aggfns where cfloat8 <= 0; - avg ----------------------- - -26.1579926760339131 + avg +--------------------- + -7.1110680042121598 (1 row) select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by avg(cint4), s limit 10; - s | avg ----+------------------------ - 2 | -183.4400000000000000 - 7 | -172.7792041078305520 - 4 | -108.3184099578397912 - 9 | -87.4561802193459144 - 0 | -21.8140132424152584 - 8 | -17.1878182530356443 - 6 | 0.76360544217687074830 - 1 | 26.8885569166417687 - 3 | 137.3122400475341652 - 5 | 162.1092983685316785 -(10 rows) + s | avg +---+---------------------- + 8 | -88.7033830845771144 + 7 | -77.4082573404148712 + 2 | -49.3297400765665928 + 3 | -29.0496164192487795 + 0 | -21.8140132424152584 + 6 | -10.7283651418761991 + 9 | 20.8253605171556440 + 4 | 55.0605850958687488 + 5 | 136.0287195851615477 +(9 rows) select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by avg(cint4), ss limit 10; - ss | avg -----+------------------------ - 7 | -172.7792041078305520 - 4 | -109.1407332998493219 - 9 | -87.4561802193459144 - 11 | -76.7313440346198360 - 0 | -21.8140132424152584 - 8 | -17.1878182530356443 - 6 | 0.76360544217687074830 - 3 | 133.4929116684841876 - 5 | 162.1092983685316785 - | 3639.6363636363636364 + ss | avg +----+----------------------- + 8 | -88.7033830845771144 + 7 | -77.4082573404148712 + 11 | -53.3737292400603926 + 3 | -32.1038779782673711 + 0 | -21.8140132424152584 + 6 | -10.7283651418761991 + 9 | 20.8253605171556440 + 4 | 59.1279058264912454 + 5 | 136.0287195851615477 + | 5077.1666666666666667 (10 rows) select max(cint4) from aggfns where cfloat8 <= 0; @@ -4128,31 +4114,30 @@ select max(cint4) from aggfns where cfloat8 <= 0; select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by max(cint4), s limit 10; s | max ---+------- - 5 | 16357 - 2 | 16376 - 7 | 16376 + 5 | 16364 + 7 | 16378 3 | 16379 - 6 | 16379 - 1 | 16381 - 9 | 16381 + 2 | 16381 0 | 16383 4 | 16383 + 6 | 16383 8 | 16383 -(10 rows) + 9 | 16383 +(9 rows) select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by max(cint4), ss limit 10; ss | max ----+------- - | 12486 - 5 | 16357 - 7 | 16376 + | 13078 + 5 | 16364 + 7 | 16378 3 | 16379 - 6 | 16379 - 9 | 16381 11 | 16381 0 | 16383 4 | 16383 + 6 | 16383 8 | 16383 + 9 | 16383 (10 rows) select min(cint4) from aggfns where cfloat8 <= 0; @@ -4165,138 +4150,134 @@ select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by min(cint s | min ---+-------- 0 | -16383 - 7 | -16383 - 1 | -16382 - 2 | -16382 + 3 | -16382 4 | -16382 6 | -16382 8 | -16382 9 | -16381 - 3 | -16379 - 5 | -16375 -(10 rows) + 7 | -16379 + 2 | -16377 + 5 | -16374 +(9 rows) select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by min(cint4), ss limit 10; ss | min ----+-------- 0 | -16383 - 7 | -16383 + 3 | -16382 4 | -16382 6 | -16382 8 | -16382 - 11 | -16382 9 | -16381 - 3 | -16379 - 5 | -16375 - | -11573 + 7 | -16379 + 11 | -16377 + 5 | -16374 + | -8992 (10 rows) select stddev(cint4) from aggfns where cfloat8 <= 0; stddev ------------------- - 9450.360040184708 + 9453.424778209057 (1 row) select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by stddev(cint4), s limit 10; s | stddev ---+------------------- - 2 | 9359.751806276146 - 4 | 9416.548048818506 - 6 | 9419.427850127196 - 8 | 9428.883569195765 - 9 | 9443.762847438393 + 9 | 9377.745829196558 + 2 | 9420.904023095068 + 6 | 9436.031206307503 + 3 | 9440.010647812753 0 | 9444.372352979574 - 3 | 9484.296797827590 - 7 | 9486.697094022398 - 1 | 9501.054201574921 - 5 | 9513.457526639607 -(10 rows) + 4 | 9469.197040523380 + 7 | 9470.920199125109 + 8 | 9488.579674823607 + 5 | 9533.551517829360 +(9 rows) select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint4), ss limit 10; ss | stddev ----+------------------- - | 8175.417839752624 - 4 | 9415.625139634959 - 6 | 9419.427850127196 - 8 | 9428.883569195765 - 11 | 9432.239512888477 - 9 | 9443.762847438393 + 9 | 9377.745829196558 + 11 | 9422.029173765748 + 6 | 9436.031206307503 + 3 | 9439.178404000439 0 | 9444.372352979574 - 3 | 9485.269059849581 - 7 | 9486.697094022398 - 5 | 9513.457526639607 + 4 | 9468.093604068949 + 7 | 9470.920199125109 + 8 | 9488.579674823607 + 5 | 9533.551517829360 + | 10351.23962464 (10 rows) select sum(cint4) from aggfns where cfloat8 <= 0; - sum ----------- - -2628669 + sum +--------- + -641525 (1 row) select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by sum(cint4), s limit 10; - s | sum ----+---------- - 2 | -1802298 - 7 | -1749735 - 4 | -1079068 - 9 | -885144 - 0 | -220736 - 8 | -175522 - 6 | 7633 - 1 | 269988 - 3 | 1386579 - 5 | 1619634 -(10 rows) + s | sum +---+--------- + 8 | -891469 + 7 | -772457 + 2 | -489647 + 3 | -291571 + 0 | -220736 + 6 | -106243 + 9 | 209399 + 4 | 557103 + 5 | 1364096 +(9 rows) select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by sum(cint4), ss limit 10; - ss | sum -----+---------- - 7 | -1749735 - 11 | -1524882 - 4 | -1086496 - 9 | -885144 - 0 | -220736 - 8 | -175522 - 6 | 7633 - | 40036 - 3 | 1346543 - 5 | 1619634 + ss | sum +----+--------- + 8 | -891469 + 7 | -772457 + 11 | -530268 + 3 | -322034 + 0 | -220736 + 6 | -106243 + | 30463 + 9 | 209399 + 4 | 597724 + 5 | 1364096 (10 rows) select avg(cint8) from aggfns where cfloat8 <= 0; avg ---------------------- - -32.2056880149663655 + -22.2097655600509893 (1 row) select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by avg(cint8), s limit 10; s | avg ---+----------------------- - 8 | -175.3259890325107716 - 5 | -73.3032729456510860 - 7 | -67.4105855633455120 - 9 | -52.9631459341962257 - 4 | -36.5615338285484842 - 2 | -26.8270737913486005 - 6 | -11.9105642256902761 + 2 | -156.0979246423534153 + 5 | -84.4558236936577583 + 8 | -71.0010945273631841 + 3 | -29.2546577662648202 0 | -11.7269493032908390 - 1 | 44.7094910865451648 - 3 | 91.2747078629431571 -(10 rows) + 7 | -5.8845575708988877 + 4 | 21.3049021545760032 + 6 | 57.5590225184287590 + 9 | 78.7373446046742914 +(9 rows) select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by avg(cint8), ss limit 10; ss | avg ----+----------------------- - 8 | -175.3259890325107716 - 5 | -73.3032729456510860 - 7 | -67.4105855633455120 - 9 | -52.9631459341962257 - 4 | -35.5581115017579106 - 6 | -11.9105642256902761 + 11 | -161.0356316054353296 + 5 | -84.4558236936577583 + 8 | -71.0010945273631841 + 3 | -30.2171269065895723 0 | -11.7269493032908390 - 11 | 8.8113017662154682 - 3 | 87.4090413403390503 - | 3636.0909090909090909 + 7 | -5.8845575708988877 + 4 | 26.3155603917301415 + 6 | 57.5590225184287590 + 9 | 78.7373446046742914 + | 1579.8333333333333333 (10 rows) select max(cint8) from aggfns where cfloat8 <= 0; @@ -4308,31 +4289,30 @@ select max(cint8) from aggfns where cfloat8 <= 0; select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by max(cint8), s limit 10; s | max ---+------- - 5 | 16363 - 6 | 16375 - 7 | 16375 2 | 16379 - 8 | 16380 + 8 | 16379 + 6 | 16380 + 7 | 16380 + 5 | 16381 9 | 16381 - 1 | 16382 3 | 16382 - 4 | 16382 0 | 16383 -(10 rows) + 4 | 16383 +(9 rows) select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by max(cint8), ss limit 10; ss | max ----+------- | 12678 - 5 | 16363 - 6 | 16375 - 7 | 16375 - 8 | 16380 + 8 | 16379 + 11 | 16379 + 6 | 16380 + 7 | 16380 + 5 | 16381 9 | 16381 3 | 16382 - 4 | 16382 - 11 | 16382 0 | 16383 + 4 | 16383 (10 rows) select min(cint8) from aggfns where cfloat8 <= 0; @@ -4350,11 +4330,10 @@ select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by min(cint 5 | -16382 4 | -16381 7 | -16381 - 2 | -16379 - 9 | -16377 - 1 | -16376 + 2 | -16375 3 | -16375 -(10 rows) + 9 | -16372 +(9 rows) select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by min(cint8), ss limit 10; ss | min @@ -4365,46 +4344,45 @@ select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by min(ci 5 | -16382 4 | -16381 7 | -16381 - 11 | -16379 - 9 | -16377 3 | -16375 - | -11918 + 11 | -16375 + 9 | -16372 + | -14174 (10 rows) select sum(cint8) from aggfns where cfloat8 <= 0; sum ---------- - -3236414 + -2003654 (1 row) select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by sum(cint8), s limit 10; s | sum ---+---------- - 8 | -1790429 - 5 | -732373 - 7 | -682667 - 9 | -536040 - 4 | -364226 - 2 | -263576 - 6 | -119058 + 2 | -1549428 + 5 | -846923 + 8 | -713561 + 3 | -293629 0 | -118665 - 1 | 448928 - 3 | 921692 -(10 rows) + 7 | -58722 + 4 | 215563 + 6 | 570007 + 9 | 791704 +(9 rows) select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by sum(cint8), ss limit 10; ss | sum ----+---------- - 8 | -1790429 - 5 | -732373 - 7 | -682667 - 9 | -536040 - 4 | -353981 - 6 | -119058 + 11 | -1599889 + 5 | -846923 + 8 | -713561 + 3 | -303108 0 | -118665 - | 39997 - 11 | 175107 - 3 | 881695 + 7 | -58722 + | 9479 + 4 | 266024 + 6 | 570007 + 9 | 791704 (10 rows) select max(cts) from aggfns where cfloat8 <= 0; @@ -4417,7 +4395,6 @@ select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by max(cts), s | max ---+-------------------------- 0 | Fri Jan 01 01:01:01 2021 - 1 | Fri Jan 01 03:47:41 2021 2 | Fri Jan 01 06:34:21 2021 3 | Fri Jan 01 09:21:01 2021 4 | Fri Jan 01 12:07:41 2021 @@ -4426,7 +4403,7 @@ select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by max(cts), 7 | Fri Jan 01 20:27:41 2021 8 | Fri Jan 01 23:14:21 2021 9 | Sat Jan 02 02:01:01 2021 -(10 rows) +(9 rows) select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by max(cts), ss limit 10; ss | max @@ -4453,7 +4430,6 @@ select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by min(cts), s | min ---+-------------------------- 0 | Fri Jan 01 01:01:01 2021 - 1 | Fri Jan 01 03:47:41 2021 2 | Fri Jan 01 06:34:21 2021 3 | Fri Jan 01 09:21:01 2021 4 | Fri Jan 01 12:07:41 2021 @@ -4462,13 +4438,13 @@ select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by min(cts), 7 | Fri Jan 01 20:27:41 2021 8 | Fri Jan 01 23:14:21 2021 9 | Sat Jan 02 02:01:01 2021 -(10 rows) +(9 rows) select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by min(cts), ss limit 10; ss | min ----+-------------------------- 0 | Fri Jan 01 01:01:01 2021 - 11 | Fri Jan 01 03:47:41 2021 + 11 | Fri Jan 01 06:34:21 2021 3 | Fri Jan 01 09:21:01 2021 | Fri Jan 01 09:21:01 2021 4 | Fri Jan 01 12:07:41 2021 @@ -4489,7 +4465,6 @@ select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by max(ctst s | max ---+------------------------------ 0 | Fri Jan 01 01:01:01 2021 PST - 1 | Fri Jan 01 03:47:41 2021 PST 2 | Fri Jan 01 06:34:21 2021 PST 3 | Fri Jan 01 09:21:01 2021 PST 4 | Fri Jan 01 12:07:41 2021 PST @@ -4498,7 +4473,7 @@ select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by max(ctst 7 | Fri Jan 01 20:27:41 2021 PST 8 | Fri Jan 01 23:14:21 2021 PST 9 | Sat Jan 02 02:01:01 2021 PST -(10 rows) +(9 rows) select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by max(ctstz), ss limit 10; ss | max @@ -4525,7 +4500,6 @@ select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by min(ctst s | min ---+------------------------------ 0 | Fri Jan 01 01:01:01 2021 PST - 1 | Fri Jan 01 03:47:41 2021 PST 2 | Fri Jan 01 06:34:21 2021 PST 3 | Fri Jan 01 09:21:01 2021 PST 4 | Fri Jan 01 12:07:41 2021 PST @@ -4534,13 +4508,13 @@ select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by min(ctst 7 | Fri Jan 01 20:27:41 2021 PST 8 | Fri Jan 01 23:14:21 2021 PST 9 | Sat Jan 02 02:01:01 2021 PST -(10 rows) +(9 rows) select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by min(ctstz), ss limit 10; ss | min ----+------------------------------ 0 | Fri Jan 01 01:01:01 2021 PST - 11 | Fri Jan 01 03:47:41 2021 PST + 11 | Fri Jan 01 06:34:21 2021 PST 3 | Fri Jan 01 09:21:01 2021 PST | Fri Jan 01 09:21:01 2021 PST 4 | Fri Jan 01 12:07:41 2021 PST @@ -4554,14 +4528,13 @@ select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by min(ct select avg(s) from aggfns where cfloat8 <= 0; avg -------------------- - 4.5121800740357441 + 4.8854514216039461 (1 row) select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by avg(s), s limit 10; s | avg ---+---------------------------- 0 | 0.000000000000000000000000 - 1 | 1.00000000000000000000 2 | 2.0000000000000000 3 | 3.0000000000000000 4 | 4.0000000000000000 @@ -4570,13 +4543,13 @@ select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by avg(s), s li 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 -(10 rows) +(9 rows) select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by avg(s), ss limit 10; ss | avg ----+---------------------------- 0 | 0.000000000000000000000000 - 11 | 1.4954460826246666 + 11 | 2.0018117765475591 3 | 3.0000000000000000 | 3.0000000000000000 4 | 4.0000000000000000 @@ -4588,39 +4561,38 @@ select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by avg(s), ss (10 rows) select count(s) from aggfns where cfloat8 <= 0; - count --------- - 100492 + count +------- + 90215 (1 row) select s, count(s) from aggfns where cfloat8 <= 0 group by s order by count(s), s limit 10; s | count ---+------- - 2 | 9825 - 4 | 9962 - 5 | 9991 - 6 | 9996 - 1 | 10041 - 3 | 10098 + 6 | 9903 + 2 | 9926 + 7 | 9979 + 5 | 10028 + 3 | 10037 + 8 | 10050 + 9 | 10055 + 4 | 10118 0 | 10119 - 9 | 10121 - 7 | 10127 - 8 | 10212 -(10 rows) +(9 rows) select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by count(s), ss limit 10; ss | count ----+------- - | 11 - 4 | 9955 - 5 | 9991 - 6 | 9996 - 3 | 10087 + | 6 + 6 | 9903 + 11 | 9935 + 7 | 9979 + 5 | 10028 + 3 | 10031 + 8 | 10050 + 9 | 10055 + 4 | 10109 0 | 10119 - 9 | 10121 - 7 | 10127 - 8 | 10212 - 11 | 19873 (10 rows) select max(s) from aggfns where cfloat8 <= 0; @@ -4633,7 +4605,6 @@ select s, max(s) from aggfns where cfloat8 <= 0 group by s order by max(s), s li s | max ---+----- 0 | 0 - 1 | 1 2 | 2 3 | 3 4 | 4 @@ -4642,7 +4613,7 @@ select s, max(s) from aggfns where cfloat8 <= 0 group by s order by max(s), s li 7 | 7 8 | 8 9 | 9 -(10 rows) +(9 rows) select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by max(s), ss limit 10; ss | max @@ -4669,7 +4640,6 @@ select s, min(s) from aggfns where cfloat8 <= 0 group by s order by min(s), s li s | min ---+----- 0 | 0 - 1 | 1 2 | 2 3 | 3 4 | 4 @@ -4678,13 +4648,13 @@ select s, min(s) from aggfns where cfloat8 <= 0 group by s order by min(s), s li 7 | 7 8 | 8 9 | 9 -(10 rows) +(9 rows) select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by min(s), ss limit 10; ss | min ----+----- 0 | 0 - 11 | 1 + 11 | 2 3 | 3 | 3 4 | 4 @@ -4698,14 +4668,13 @@ select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by min(s), ss select stddev(s) from aggfns where cfloat8 <= 0; stddev -------------------- - 2.8788449199038282 + 2.7706747160155654 (1 row) select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by stddev(s), s limit 10; s | stddev ---+-------- 0 | 0 - 1 | 0 2 | 0 3 | 0 4 | 0 @@ -4714,7 +4683,7 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by stddev(s) 7 | 0 8 | 0 9 | 0 -(10 rows) +(9 rows) select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by stddev(s), ss limit 10; ss | stddev @@ -4728,49 +4697,48 @@ select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by stddev( 8 | 0 9 | 0 | 0 - 11 | 0.50210095387112910955 + 11 | 0.06017171256636552646 (10 rows) select sum(s) from aggfns where cfloat8 <= 0; sum -------- - 453438 + 440741 (1 row) select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by sum(s), s limit 10; s | sum ---+------- 0 | 0 - 1 | 10041 - 2 | 19650 - 3 | 30294 - 4 | 39848 - 5 | 49955 - 6 | 59976 - 7 | 70889 - 8 | 81696 - 9 | 91089 -(10 rows) + 2 | 19852 + 3 | 30111 + 4 | 40472 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 +(9 rows) select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by sum(s), ss limit 10; ss | sum ----+------- 0 | 0 - | 33 - 11 | 29719 - 3 | 30261 - 4 | 39820 - 5 | 49955 - 6 | 59976 - 7 | 70889 - 8 | 81696 - 9 | 91089 + | 18 + 11 | 19888 + 3 | 30093 + 4 | 40436 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 (10 rows) select avg(ss) from aggfns where cfloat8 <= 0; avg -------------------- - 6.3921437883779023 + 5.8765755079870079 (1 row) select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by avg(ss), s limit 10; @@ -4778,15 +4746,14 @@ select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by avg(ss), s ---+---------------------------- 0 | 0.000000000000000000000000 3 | 3.0000000000000000 - 4 | 4.0049186910258984 + 4 | 4.0062265269816169 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 8 | 8.0000000000000000 9 | 9.0000000000000000 - 1 | 11.0000000000000000 2 | 11.0000000000000000 -(10 rows) +(9 rows) select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by avg(ss), ss limit 10; ss | avg @@ -4819,10 +4786,9 @@ select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by max(ss), s 7 | 7 8 | 8 9 | 9 - 1 | 11 2 | 11 4 | 11 -(10 rows) +(9 rows) select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by max(ss), ss limit 10; ss | max @@ -4856,9 +4822,8 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by min(ss), s 7 | 7 8 | 8 9 | 9 - 1 | 11 2 | 11 -(10 rows) +(9 rows) select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by min(ss), ss limit 10; ss | min @@ -4878,14 +4843,13 @@ select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by min(ss), select stddev(ss) from aggfns where cfloat8 <= 0; stddev -------------------- - 3.3510077839151207 + 3.1457968709791645 (1 row) select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by stddev(ss), s limit 10; s | stddev ---+------------------------ 0 | 0 - 1 | 0 2 | 0 3 | 0 5 | 0 @@ -4893,8 +4857,8 @@ select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by stddev(s 7 | 0 8 | 0 9 | 0 - 4 | 0.18549958974449259010 -(10 rows) + 4 | 0.20868929911309143893 +(9 rows) select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by stddev(ss), ss limit 10; ss | stddev @@ -4914,73 +4878,71 @@ select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by stddev select sum(ss) from aggfns where cfloat8 <= 0; sum -------- - 642289 + 530120 (1 row) select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by sum(ss), s limit 10; s | sum ---+-------- 0 | 0 - 3 | 30261 - 4 | 39897 - 5 | 49955 - 6 | 59976 - 7 | 70889 - 8 | 81696 - 9 | 91089 - 2 | 108075 - 1 | 110451 -(10 rows) + 3 | 30093 + 4 | 40535 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 + 2 | 109186 +(9 rows) select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by sum(ss), ss limit 10; ss | sum ----+-------- 0 | 0 - 3 | 30261 - 4 | 39820 - 5 | 49955 - 6 | 59976 - 7 | 70889 - 8 | 81696 - 9 | 91089 - 11 | 218603 + 3 | 30093 + 4 | 40436 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 + 11 | 109285 | (10 rows) select max(t) from aggfns where cfloat8 <= 0; max -------- - 110000 + 109998 (1 row) select s, max(t) from aggfns where cfloat8 <= 0 group by s order by max(t), s limit 10; s | max ---+-------- 0 | 20000 - 1 | 29999 - 2 | 39999 - 3 | 49996 - 4 | 59999 - 5 | 69998 - 6 | 79999 + 2 | 40000 + 3 | 50000 + 4 | 59998 + 5 | 69999 + 6 | 80000 7 | 90000 - 8 | 99999 - 9 | 110000 -(10 rows) + 8 | 100000 + 9 | 109998 +(9 rows) select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by max(t), ss limit 10; ss | max ----+-------- 0 | 20000 - | 49491 - 3 | 49996 - 11 | 54964 - 4 | 59999 - 5 | 69998 - 6 | 79999 + | 48438 + 3 | 50000 + 11 | 58135 + 4 | 59998 + 5 | 69999 + 6 | 80000 7 | 90000 - 8 | 99999 - 9 | 110000 + 8 | 100000 + 9 | 109998 (10 rows) select min(t) from aggfns where cfloat8 <= 0; @@ -4993,28 +4955,27 @@ select s, min(t) from aggfns where cfloat8 <= 0 group by s order by min(t), s li s | min ---+------- 0 | 8 - 1 | 10001 - 2 | 20001 - 3 | 30001 - 4 | 40003 - 5 | 50001 - 6 | 60002 - 7 | 70005 + 2 | 20003 + 3 | 30002 + 4 | 40001 + 5 | 50004 + 6 | 60001 + 7 | 70002 8 | 80001 9 | 90001 -(10 rows) +(9 rows) select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by min(t), ss limit 10; ss | min ----+------- 0 | 8 - 11 | 10001 - 3 | 30001 - | 32643 - 4 | 40003 - 5 | 50001 - 6 | 60002 - 7 | 70005 + 11 | 20003 + 3 | 30002 + | 33696 + 4 | 40001 + 5 | 50004 + 6 | 60001 + 7 | 70002 8 | 80001 9 | 90001 (10 rows) @@ -5308,75 +5269,75 @@ select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by su (10 rows) select avg(cfloat8) from aggfns where cfloat8 < 1000; - avg --------------------- - -0.162669734027353 + avg +----------------- + 1.2289014329263 (1 row) select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by avg(cfloat8), s limit 10; - s | avg ----+----------------------- - 8 | -0.607624531147303 - 7 | -0.454194548579399 - 9 | -0.448788876848994 - 3 | -0.364286396751413 - 0 | -0.306925132697215 - 1 | -0.0518103775125928 - 6 | -4.20950399711728e-05 - 5 | 0.0180876209540293 - 4 | 0.032399496253347 - 2 | 0.55648750109598 + s | avg +---+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.220256273869891 + 3 | -0.14819676399231 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + 2 | 0.198140166982776 + 1 | 13 (10 rows) select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by avg(cfloat8), ss limit 10; - ss | avg -----+----------------------- - | -6.85744955032868 - 8 | -0.607624531147303 - 7 | -0.454194548579399 - 9 | -0.448788876848994 - 3 | -0.358112026103399 - 0 | -0.306925132697215 - 6 | -4.20950399711728e-05 - 5 | 0.0180876209540293 - 4 | 0.0258167200477049 - 11 | 0.25552084043733 + ss | avg +----+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.224160255000712 + 3 | -0.153492446187821 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + | 5.42090986487701 + 11 | 6.59778165165114 (10 rows) select max(cfloat8) from aggfns where cfloat8 < 1000; max ------------------ - 49.9996809987351 + 49.9995574122295 (1 row) select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by max(cfloat8), s limit 10; s | max ---+------------------ - 4 | 49.9951320933178 + 1 | 13 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 1 | 49.9971219105646 - 2 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 2 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by max(cfloat8), ss limit 10; ss | max ----+------------------ - | 41.8287402018905 - 4 | 49.9951320933178 + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 0 | 49.9965498689562 - 8 | 49.9969401862472 - 11 | 49.9983029672876 - 6 | 49.9984448775649 - 9 | 49.998860899359 - 5 | 49.9991805525497 - 3 | 49.9995571095496 - 7 | 49.9996809987351 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 (10 rows) select min(cfloat8) from aggfns where cfloat8 < 1000; @@ -5389,102 +5350,102 @@ select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by min( s | min ---+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 1 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - 2 | -49.9854512279853 + 2 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + 1 | 13 (10 rows) select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by min(cfloat8), ss limit 10; ss | min ----+------------------- 0 | -49.9994775978848 - 9 | -49.9993407865986 - 4 | -49.998479289934 - 11 | -49.9980724882334 - 8 | -49.9969880329445 - 7 | -49.9969201860949 - 5 | -49.9964643968269 - 6 | -49.9959305627272 - 3 | -49.9903481686488 - | -40.4587021796033 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 (10 rows) select stddev(cfloat8) from aggfns where cfloat8 < 1000; - stddev ------------------ - 28.892061623641 + stddev +------------------ + 27.6606134001179 (1 row) select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by stddev(cfloat8), s limit 10; s | stddev ---+------------------ - 8 | 28.785076111741 - 9 | 28.7991243564982 - 4 | 28.8027578036838 - 7 | 28.8638207913961 - 2 | 28.871977070659 - 3 | 28.8844659681246 - 1 | 28.9470128733139 + 1 | 0 + 2 | 28.7611066711723 + 9 | 28.7642081921344 + 4 | 28.77864036235 + 5 | 28.7843925303698 + 6 | 28.8543767497509 + 3 | 28.9210796983077 + 8 | 28.96331707256 0 | 28.965342556856 - 5 | 28.9663806098752 - 6 | 29.0218963292706 + 7 | 28.9656492103737 (10 rows) select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by stddev(cfloat8), ss limit 10; ss | stddev ----+------------------ - | 27.2393448599587 - 8 | 28.7850761117411 - 9 | 28.7991243564982 - 4 | 28.8000379619243 - 7 | 28.863820791396 - 3 | 28.8859339629585 - 11 | 28.9120343325061 + 11 | 21.3262797346004 + | 22.894065438835 + 9 | 28.7642081921344 + 4 | 28.7760615445521 + 5 | 28.7843925303698 + 6 | 28.8543767497508 + 3 | 28.926156595386 + 8 | 28.96331707256 0 | 28.9653425568561 - 5 | 28.9663806098753 - 6 | 29.0218963292706 + 7 | 28.9656492103736 (10 rows) select sum(cfloat8) from aggfns where cfloat8 < 1000; - sum -------------------- - -32533.9468054706 + sum +----------------- + 245780.28658526 (1 row) select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by sum(cfloat8), s limit 10; - s | sum ----+-------------------- - 8 | -12152.4906229461 - 7 | -9083.89097158797 - 9 | -8975.77753697988 - 3 | -7285.72793502826 - 0 | -6138.50265394431 - 1 | -1036.20755025186 - 6 | -0.841900799423456 - 5 | 361.752419080585 - 4 | 647.98992506694 - 2 | 11129.7500219196 + s | sum +---+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4405.12547739781 + 3 | -2963.93527984619 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 2 | 3962.80333965551 + 1 | 260000 (10 rows) select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by sum(cfloat8), ss limit 10; - ss | sum -----+-------------------- - 8 | -12152.4906229461 - 7 | -9083.89097158797 - 9 | -8975.77753697988 - 3 | -7155.43639357202 - 0 | -6138.50265394431 - | -130.291541456245 - 6 | -0.841900799423456 - 5 | 361.752419080585 - 4 | 515.843883273192 - 11 | 10225.6885134615 + ss | sum +----+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4478.94605516922 + 3 | -3066.93256727885 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + | 102.997287432663 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 11 | 264036.623917427 (10 rows) select avg(cint2) from aggfns where cfloat8 < 1000; @@ -7581,6 +7542,8 @@ order by count(*) desc, cint2 limit 10 16 | 16 | -45.4426 | 1373 (10 rows) +-- Test edge cases for various batch sizes and the filter matching around batch +-- end. select s, count(*) from edges group by 1 order by 1; s | count ----+------- @@ -7594,8 +7557,10 @@ select s, count(*) from edges group by 1 order by 1; 7 | 132 8 | 133 9 | 134 - 10 | 199 -(11 rows) + 10 | 2247 + 11 | 2248 + 12 | 2249 +(13 rows) select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; s | count | min @@ -7608,7 +7573,9 @@ select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; 8 | 1 | 63 9 | 1 | 63 10 | 1 | 63 -(8 rows) + 11 | 1 | 63 + 12 | 1 | 63 +(10 rows) select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; s | count | min @@ -7620,7 +7587,9 @@ select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; 8 | 1 | 64 9 | 1 | 64 10 | 1 | 64 -(7 rows) + 11 | 1 | 64 + 12 | 1 | 64 +(9 rows) select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; s | count | min @@ -7631,7 +7600,9 @@ select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; 8 | 1 | 65 9 | 1 | 65 10 | 1 | 65 -(6 rows) + 11 | 1 | 65 + 12 | 1 | 65 +(8 rows) select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; ss | count | min @@ -7644,7 +7615,9 @@ select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; 8 | 1 | 63 9 | 1 | 63 10 | 1 | 63 -(8 rows) + 11 | 1 | 63 + 12 | 1 | 63 +(10 rows) select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; ss | count | min @@ -7656,7 +7629,9 @@ select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; 8 | 1 | 64 9 | 1 | 64 10 | 1 | 64 -(7 rows) + 11 | 1 | 64 + 12 | 1 | 64 +(9 rows) select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; ss | count | min @@ -7667,5 +7642,7 @@ select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; 8 | 1 | 65 9 | 1 | 65 10 | 1 | 65 -(6 rows) + 11 | 1 | 65 + 12 | 1 | 65 +(8 rows) diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 479cd49a7c8..243cfafc0a6 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -14,7 +14,7 @@ $$ LANGUAGE SQL; create table aggfns(t int, s int, cint2 int2, cint4 int4, cint8 int8, - cfloat4 float4, cfloat8 float8, + cfloat4 float4, cts timestamp, ctstz timestamptz, cdate date); select create_hypertable('aggfns', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); @@ -30,7 +30,6 @@ select s * 10000 + t as t, when s = 2 and t = 1061 then '+inf'::float4 when s = 3 and t = 1061 then '-inf'::float4 else (mix(s + t * 1033) * 100::int)::float4 end as cfloat4, - (mix(s + t * 1039) * 100)::float8 as cfloat8, '2021-01-01 01:01:01'::timestamp + interval '1 second' * (s * 10000) as cts, '2021-01-01 01:01:01'::timestamptz + interval '1 second' * (s * 10000) as ctstz, '2021-01-01'::date + interval '1 day' * (s * 10000) as cdate @@ -47,12 +46,13 @@ alter table aggfns set (timescaledb.compress, timescaledb.compress_orderby = 't' select count(compress_chunk(x)) from show_chunks('aggfns') x; alter table aggfns add column ss int default 11; +alter table aggfns add column cfloat8 float8 default '13'; alter table aggfns add column x text default '11'; insert into aggfns select *, ss::text as x from ( - select *, - case + select * + , case -- null in entire batch when s = 2 then null -- null for some rows @@ -62,6 +62,7 @@ select *, ss::text as x from ( -- not null for entire batch else s end as ss + , (mix(s + t * 1039) * 100)::float8 as cfloat8 from source where s != 1 ) t ; @@ -77,17 +78,22 @@ insert into edges select s, s, f1 -from generate_series(0, 10) s, - lateral generate_series(0, 60 + s + (s / 5::int) * 64) f1 +from generate_series(0, 12) s, + lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 ; select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; +-- We can't vectorize some aggregate functions on platforms withouth int128 +-- support. Just relax the test requirements for them. +select case when typbyval then 'require' else 'allow' end guc_value +from pg_type where oid = 'int8'::regtype +\gset -set timescaledb.debug_require_vector_agg = 'require'; +set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. --- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', @@ -151,6 +157,8 @@ select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 order by count(*) desc, cint2 limit 10 ; +-- Test edge cases for various batch sizes and the filter matching around batch +-- end. select s, count(*) from edges group by 1 order by 1; select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; From cd5bdedc18ba8bf39b6e5ad5957bddaa143f5890 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:08:37 +0100 Subject: [PATCH 115/242] another way to check for int128 support --- src/guc.c | 18 ++++++++++++++++++ tsl/test/expected/vector_agg_functions.out | 4 ++-- tsl/test/sql/vector_agg_functions.sql | 4 ++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/guc.c b/src/guc.c index 75d85420095..ce7238e1070 100644 --- a/src/guc.c +++ b/src/guc.c @@ -180,6 +180,9 @@ char *ts_current_timestamp_mock = NULL; int ts_guc_debug_toast_tuple_target = 128; #ifdef TS_DEBUG + +bool ts_guc_debug_have_int128; + static const struct config_enum_entry debug_require_options[] = { { "allow", DRO_Allow, false }, { "forbid", DRO_Forbid, false }, { "require", DRO_Require, false }, @@ -1063,6 +1066,21 @@ _guc_init(void) /* assign_hook= */ NULL, /* show_hook= */ NULL); + DefineCustomBoolVariable(/* name= */ MAKE_EXTOPTION("debug_have_int128"), + /* short_desc= */ "whether we have int128 support", + /* long_desc= */ "this is for debugging purposes", + /* valueAddr= */ &ts_guc_debug_have_int128, +#ifdef HAVE_INT128 + /* bootValue= */ true, +#else + /* bootValue= */ false, +#endif + /* context= */ PGC_INTERNAL, + /* flags= */ 0, + /* check_hook= */ NULL, + /* assign_hook= */ NULL, + /* show_hook= */ NULL); + DefineCustomEnumVariable(/* name= */ MAKE_EXTOPTION("debug_require_vector_agg"), /* short_desc= */ "ensure that vectorized aggregation is used or not", diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 9eeaa7c1e86..f200a5113df 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -103,8 +103,8 @@ select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; -- We can't vectorize some aggregate functions on platforms withouth int128 -- support. Just relax the test requirements for them. -select case when typbyval then 'require' else 'allow' end guc_value -from pg_type where oid = 'int8'::regtype +select case when setting::bool then 'require' else 'allow' end guc_value +from pg_settings where name = 'timescaledb.debug_have_int128' \gset set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 5cb25a2075f..92ec02a22fb 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -86,8 +86,8 @@ vacuum freeze analyze edges; -- We can't vectorize some aggregate functions on platforms withouth int128 -- support. Just relax the test requirements for them. -select case when typbyval then 'require' else 'allow' end guc_value -from pg_type where oid = 'int8'::regtype +select case when setting::bool then 'require' else 'allow' end guc_value +from pg_settings where name = 'timescaledb.debug_have_int128' \gset set timescaledb.debug_require_vector_agg = :'guc_value'; From 2dd4b7c11f74347d2d7066fe06df81332f948e5b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:17:32 +0100 Subject: [PATCH 116/242] fix --- tsl/test/expected/vector_agg_functions.out | 2 +- tsl/test/sql/vector_agg_functions.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index b1f90506bf4..4e03e74eab2 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -109,7 +109,7 @@ from pg_type where oid = 'int8'::regtype set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. --- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 243cfafc0a6..daa4c8df02c 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -93,7 +93,7 @@ from pg_type where oid = 'int8'::regtype set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. -set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', From 206b7b7506af910f554176022092258daf2ce450 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:21:52 +0100 Subject: [PATCH 117/242] test --- tsl/test/expected/vector_agg_functions.out | 6 +++--- tsl/test/sql/vector_agg_functions.sql | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 4e03e74eab2..5f7d637af6f 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -103,13 +103,13 @@ select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; -- We can't vectorize some aggregate functions on platforms withouth int128 -- support. Just relax the test requirements for them. -select case when typbyval then 'require' else 'allow' end guc_value -from pg_type where oid = 'int8'::regtype +select case when setting::bool then 'require' else 'allow' end guc_value +from pg_settings where name = 'timescaledb.debug_have_int128' \gset set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 6b3cba795a1..fdc66addc80 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -137,7 +137,8 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's']) with ordinality as grouping(grouping, n) + 's', + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) From d5ad761d2904a287214173fbd0ea3f2a91bb89af Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:52:54 +0100 Subject: [PATCH 118/242] fixes --- tsl/src/nodes/vector_agg/plan.c | 10 ++++++++++ tsl/test/expected/vector_agg_param.out | 2 ++ tsl/test/expected/vectorized_aggregation.out | 7 +++++++ tsl/test/sql/vector_agg_param.sql | 3 +++ tsl/test/sql/vectorized_aggregation.sql | 4 ++++ 5 files changed, 26 insertions(+) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 07200d786e6..74a89953cab 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -205,6 +205,16 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) custom->scan.scanrelid, decompressed_var->varno); + if (decompressed_var->varattno <= 0) + { + /* Can't work with special attributes like tableoid. */ + if (out_is_segmentby) + { + *out_is_segmentby = false; + } + return false; + } + /* * Now, we have to translate the decompressed varno into the compressed * column index, to check if the column supports bulk decompression. diff --git a/tsl/test/expected/vector_agg_param.out b/tsl/test/expected/vector_agg_param.out index 6835cc971e3..2f230b6cff4 100644 --- a/tsl/test/expected/vector_agg_param.out +++ b/tsl/test/expected/vector_agg_param.out @@ -21,6 +21,8 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; (1 row) analyze pvagg; +-- Uncomment to generate reference +set timescaledb.enable_vectorized_aggregation to off; explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; QUERY PLAN diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 12ed14e3e84..10896f9a4b9 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -3292,3 +3292,10 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND (75 rows) RESET max_parallel_workers_per_gather; +-- Can't group by a system column +SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; + sum +------- + 82620 +(1 row) + diff --git a/tsl/test/sql/vector_agg_param.sql b/tsl/test/sql/vector_agg_param.sql index 3c31b8ccf0a..1be5bd71495 100644 --- a/tsl/test/sql/vector_agg_param.sql +++ b/tsl/test/sql/vector_agg_param.sql @@ -18,6 +18,9 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; analyze pvagg; +-- Uncomment to generate reference +--set timescaledb.enable_vectorized_aggregation to off; + explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index c8844932a93..bafecd6b544 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -403,3 +403,7 @@ SET max_parallel_workers_per_gather = 0; SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND int_value > 1000; RESET max_parallel_workers_per_gather; + + +-- Can't group by a system column +SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; From c6eb880bd0033dcd8602baedfcef1abbc29d9f60 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:56:06 +0100 Subject: [PATCH 119/242] copy --- tsl/src/nodes/vector_agg/plan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 74a89953cab..44d9631d7d5 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -82,7 +82,7 @@ resolve_outer_special_vars_mutator(Node *node, void *context) * This is already the uncompressed chunk var. We can see it referenced * by expressions in the output targetlist of DecompressChunk node. */ - return (Node *) var; + return (Node *) copyObject(var); } if (var->varno == OUTER_VAR) From 0c59d9ab78d7059e8e264ea00745b6002c3b3086 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 13 Nov 2024 23:01:18 +0100 Subject: [PATCH 120/242] fix --- tsl/test/expected/vector_agg_param.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/test/expected/vector_agg_param.out b/tsl/test/expected/vector_agg_param.out index 2f230b6cff4..a73bea2b5d3 100644 --- a/tsl/test/expected/vector_agg_param.out +++ b/tsl/test/expected/vector_agg_param.out @@ -22,7 +22,7 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; analyze pvagg; -- Uncomment to generate reference -set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.enable_vectorized_aggregation to off; explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; QUERY PLAN From e71a0154d04215a5f3f8fe6f613c788adedb3e30 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:49:17 +0100 Subject: [PATCH 121/242] fixes for pg16 --- tsl/src/nodes/vector_agg/plan.c | 30 +++++++++++++++++++------ tsl/test/expected/vector_agg_param.out | 31 ++------------------------ tsl/test/sql/vector_agg_param.sql | 5 ++--- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 44d9631d7d5..2dc0d167a5b 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -364,7 +364,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(resolved_targetlist, offset); + TargetEntry *entry = list_nth_node(TargetEntry, resolved_targetlist, offset); bool is_segmentby = false; if (!is_vector_var(custom, entry->expr, &is_segmentby)) @@ -559,19 +559,35 @@ try_insert_vector_agg_node(Plan *plan) return plan; } - /* Now check the aggregate functions themselves. */ + /* Now check the output targetlist. */ ListCell *lc; foreach (lc, resolved_targetlist) { TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); - if (!IsA(target_entry->expr, Aggref)) + if (IsA(target_entry->expr, Aggref)) { - continue; + Aggref *aggref = castNode(Aggref, target_entry->expr); + if (!can_vectorize_aggref(aggref, custom)) + { + /* Aggregate function not vectorizable. */ + return plan; + } } - - Aggref *aggref = castNode(Aggref, target_entry->expr); - if (!can_vectorize_aggref(aggref, custom)) + else if (IsA(target_entry->expr, Var)) + { + if (!is_vector_var(custom, target_entry->expr, NULL)) + { + /* Variable not vectorizable. */ + return plan; + } + } + else { + /* + * Sometimes the plan can require this node to perform a projection, + * e.g. we can see a nested loop param in its output targetlist. We + * can't handle this case currently. + */ return plan; } } diff --git a/tsl/test/expected/vector_agg_param.out b/tsl/test/expected/vector_agg_param.out index a73bea2b5d3..1ef408e32e5 100644 --- a/tsl/test/expected/vector_agg_param.out +++ b/tsl/test/expected/vector_agg_param.out @@ -96,35 +96,8 @@ select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from p 2 | 2001996 (3 rows) -explain (verbose, costs off) -select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Nested Loop - Output: x.x, (sum(_hyper_1_1_chunk.a)) - -> Function Scan on pg_catalog.unnest x - Output: x.x - Function Call: unnest('{0,1,2}'::integer[]) - -> Finalize GroupAggregate - Output: sum(_hyper_1_1_chunk.a), (x.x) - Group Key: (x.x) - -> Append - -> Partial GroupAggregate - Output: (x.x), PARTIAL sum(_hyper_1_1_chunk.a) - Group Key: x.x - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk - Output: x.x, _hyper_1_1_chunk.a - -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk - Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a - -> Partial GroupAggregate - Output: (x.x), PARTIAL sum(_hyper_1_2_chunk.a) - Group Key: x.x - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk - Output: x.x, _hyper_1_2_chunk.a - -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk - Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a -(23 rows) - +-- The plan for this query differs after PG16, x is not used as grouping key but +-- just added into the output targetlist of partial aggregation nodes. select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; x | sum ---+--------- diff --git a/tsl/test/sql/vector_agg_param.sql b/tsl/test/sql/vector_agg_param.sql index 1be5bd71495..244718ef27f 100644 --- a/tsl/test/sql/vector_agg_param.sql +++ b/tsl/test/sql/vector_agg_param.sql @@ -32,9 +32,8 @@ select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from p select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; -explain (verbose, costs off) -select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; - +-- The plan for this query differs after PG16, x is not used as grouping key but +-- just added into the output targetlist of partial aggregation nodes. select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; From d032b272a357874b4471ad7486e30c2212ed933b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:15:55 +0100 Subject: [PATCH 122/242] more edge cases --- tsl/test/expected/vector_agg_functions.out | 44 +++++++++++++--------- tsl/test/sql/vector_agg_functions.sql | 6 ++- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index f200a5113df..425e03816c2 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -77,7 +77,7 @@ select count(compress_chunk(x)) from show_chunks('aggfns') x; vacuum freeze analyze aggfns; create table edges(t int, s int, ss int, f1 int); -select create_hypertable('edges', 't'); +select create_hypertable('edges', 't', chunk_time_interval => 100000); NOTICE: adding not-null constraint to column "t" create_hypertable -------------------- @@ -87,13 +87,14 @@ NOTICE: adding not-null constraint to column "t" alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); NOTICE: default order by for hypertable "edges" is set to "t DESC" insert into edges select - s * 10000 + f1 as t, + s * 1000 + f1 as t, s, s, f1 from generate_series(0, 12) s, lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 ; +insert into edges select 200000 t, 111 s, 111 ss, 1 f1; select count(compress_chunk(x)) from show_chunks('edges') x; count ------- @@ -4516,23 +4517,30 @@ select s, sum(cint2) from aggfns where cint2 is null group by s order by sum(cin -- Test edge cases for various batch sizes and the filter matching around batch -- end. +select count(*) from edges; + count +------- + 7720 +(1 row) + select s, count(*) from edges group by 1 order by 1; - s | count -----+------- - 0 | 61 - 1 | 62 - 2 | 63 - 3 | 64 - 4 | 65 - 5 | 130 - 6 | 131 - 7 | 132 - 8 | 133 - 9 | 134 - 10 | 2247 - 11 | 2248 - 12 | 2249 -(13 rows) + s | count +-----+------- + 0 | 61 + 1 | 62 + 2 | 63 + 3 | 64 + 4 | 65 + 5 | 130 + 6 | 131 + 7 | 132 + 8 | 133 + 9 | 134 + 10 | 2247 + 11 | 2248 + 12 | 2249 + 111 | 1 +(14 rows) select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; s | count | min diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 92ec02a22fb..06c2f5262f1 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -71,16 +71,17 @@ vacuum freeze analyze aggfns; create table edges(t int, s int, ss int, f1 int); -select create_hypertable('edges', 't'); +select create_hypertable('edges', 't', chunk_time_interval => 100000); alter table edges set (timescaledb.compress, timescaledb.compress_segmentby='s'); insert into edges select - s * 10000 + f1 as t, + s * 1000 + f1 as t, s, s, f1 from generate_series(0, 12) s, lateral generate_series(0, 60 + s + (s / 5::int) * 64 + (s / 10::int) * 2048) f1 ; +insert into edges select 200000 t, 111 s, 111 ss, 1 f1; select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; @@ -153,6 +154,7 @@ order by explain, condition.n, variable, function, grouping.n -- Test edge cases for various batch sizes and the filter matching around batch -- end. +select count(*) from edges; select s, count(*) from edges group by 1 order by 1; select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; From 8d9cf38b4ad3acac87a20ee40a63ecdc58440462 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:34:43 +0100 Subject: [PATCH 123/242] import the vector var resolution changes --- .../nodes/vector_agg/grouping_policy_batch.c | 15 +- .../vector_agg/hash_table_functions_impl.c | 6 +- tsl/src/nodes/vector_agg/plan.c | 130 +++++++++++++----- 3 files changed, 103 insertions(+), 48 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index 85c915014a0..a071f62a45d 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -167,15 +167,16 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc /* * Scalar argument, or count(*). Have to also count the valid rows in * the batch. - */ - const int n = arrow_num_valid(filter, batch_state->total_batch_rows); - - /* + * * The batches that are fully filtered out by vectorized quals should - * have been skipped by the caller. + * have been skipped by the caller, but we also have to check for the + * case when no rows match the aggregate FILTER clause. */ - Assert(n > 0); - agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + const int n = arrow_num_valid(filter, batch_state->total_batch_rows); + if (n > 0) + { + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + } } } diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 1bc08a1f379..3843a7df797 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -155,15 +155,15 @@ FUNCTION_NAME(fill_offsets_impl)( * when all the batch and key rows are valid. */ #define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME##_nofilter, (COND) && (config.batch_filter == NULL)) \ + X(NAME##_nofilter, (COND) && (config.batch_filter == NULL)) \ X(NAME##_filter, (COND) && (config.batch_filter != NULL)) #define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && config.single_key.buffers[0] == NULL) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && config.single_key.buffers[0] == NULL) \ APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && config.single_key.buffers[0] != NULL) #define APPLY_FOR_SCALARS(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_noscalar, (COND) && !config.have_scalar_columns) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_noscalar, (COND) && !config.have_scalar_columns) \ APPLY_FOR_BATCH_FILTER(X, NAME##_scalar, (COND) && config.have_scalar_columns) #define APPLY_FOR_TYPE(X, NAME, COND) \ diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index ecd7d4a9a65..457c42679e1 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -75,29 +75,44 @@ resolve_outer_special_vars_mutator(Node *node, void *context) return expression_tree_mutator(node, resolve_outer_special_vars_mutator, context); } - Var *aggregated_var = castNode(Var, node); - Ensure(aggregated_var->varno == OUTER_VAR, - "encountered unexpected varno %d as an aggregate argument", - aggregated_var->varno); - + Var *var = castNode(Var, node); CustomScan *custom = castNode(CustomScan, context); - TargetEntry *decompress_chunk_tentry = - castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, aggregated_var->varattno - 1)); - Expr *decompressed_expr = decompress_chunk_tentry->expr; - if (IsA(decompressed_expr, Var) && castNode(Var, decompressed_expr)->varno == INDEX_VAR) + if ((Index) var->varno == (Index) custom->scan.scanrelid) + { + /* + * This is already the uncompressed chunk var. We can see it referenced + * by expressions in the output targetlist of DecompressChunk node. + */ + return (Node *) copyObject(var); + } + + if (var->varno == OUTER_VAR) + { + /* + * Reference into the output targetlist of the DecompressChunk node. + */ + TargetEntry *decompress_chunk_tentry = + castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, var->varattno - 1)); + + return resolve_outer_special_vars_mutator((Node *) decompress_chunk_tentry->expr, context); + } + + if (var->varno == INDEX_VAR) { /* * This is a reference into the custom scan targetlist, we have to resolve * it as well. */ - TargetEntry *custom_scan_tentry = - castNode(TargetEntry, - list_nth(custom->custom_scan_tlist, - castNode(Var, decompressed_expr)->varattno - 1)); - decompressed_expr = custom_scan_tentry->expr; - } - Assert(!IsA(decompressed_expr, Var) || castNode(Var, decompressed_expr)->varno > 0); - return (Node *) copyObject(decompressed_expr); + var = castNode(Var, + castNode(TargetEntry, list_nth(custom->custom_scan_tlist, var->varattno - 1)) + ->expr); + Assert(var->varno > 0); + + return (Node *) copyObject(var); + } + + Ensure(false, "encountered unexpected varno %d as an aggregate argument", var->varno); + return node; } /* @@ -116,20 +131,20 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) * node. */ static Plan * -vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) +vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_targetlist) { CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); vector_agg->custom_plans = list_make1(decompress_chunk); vector_agg->methods = &scan_methods; + vector_agg->custom_scan_tlist = resolved_targetlist; + /* * Note that this is being called from the post-planning hook, and therefore * after set_plan_refs(). The meaning of output targetlists is different from * the previous planning stages, and they contain special varnos referencing * the scan targetlists. */ - vector_agg->custom_scan_tlist = - resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); vector_agg->scan.plan.targetlist = build_trivial_custom_output_targetlist(vector_agg->custom_scan_tlist); @@ -182,13 +197,30 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) Var *decompressed_var = castNode(Var, expr); + /* + * This must be called after resolve_outer_special_vars(), so we should only + * see the uncompressed chunk variables here. + */ + Ensure((Index) decompressed_var->varno == (Index) custom->scan.scanrelid, + "expected scan varno %d got %d", + custom->scan.scanrelid, + decompressed_var->varno); + + if (decompressed_var->varattno <= 0) + { + /* Can't work with special attributes like tableoid. */ + if (out_is_segmentby) + { + *out_is_segmentby = false; + } + return false; + } + /* * Now, we have to translate the decompressed varno into the compressed * column index, to check if the column supports bulk decompression. */ List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); - List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); - List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); int compressed_column_index = 0; for (; compressed_column_index < list_length(decompression_map); compressed_column_index++) { @@ -219,6 +251,8 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) } } Ensure(compressed_column_index < list_length(decompression_map), "compressed column not found"); + + List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); Assert(list_length(decompression_map) == list_length(bulk_decompression_column)); const bool bulk_decompression_enabled_for_column = list_nth_int(bulk_decompression_column, compressed_column_index); @@ -235,6 +269,8 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) /* * Check if this column is a segmentby. */ + List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); + Assert(list_length(is_segmentby_column) == list_length(decompression_map)); const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); if (out_is_segmentby) { @@ -319,7 +355,7 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) * Whether we can perform vectorized aggregation with a given grouping. */ static bool -can_vectorize_grouping(Agg *agg, CustomScan *custom) +can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) { /* * We support vectorized aggregation without grouping. @@ -330,7 +366,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) } /* FIXME */ - List *aggregated_tlist_resolved = resolve_outer_special_vars(agg->plan.targetlist, custom); + List *aggregated_tlist_resolved = resolved_targetlist; /* * We support hashed vectorized grouping by one fixed-size by-value @@ -558,7 +594,14 @@ try_insert_vector_agg_node(Plan *plan) return plan; } - if (!can_vectorize_grouping(agg, custom)) + /* + * To make it easier to examine the variables participating in the aggregation, + * the subsequent checks are performed on the aggregated targetlist with + * all variables resolved to uncompressed chunk variables. + */ + List *resolved_targetlist = resolve_outer_special_vars(agg->plan.targetlist, custom); + + if (!can_vectorize_grouping(agg, custom, resolved_targetlist)) { /* No GROUP BY support for now. */ return plan; @@ -583,9 +626,6 @@ try_insert_vector_agg_node(Plan *plan) List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); - /* FIXME */ - List *aggregated_tlist_resolved = resolve_outer_special_vars(agg->plan.targetlist, custom); - int maxattno = 0; for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); compressed_column_index++) @@ -667,21 +707,35 @@ try_insert_vector_agg_node(Plan *plan) // is_vector_var); } - /* Now check the aggregate functions themselves. */ + /* Now check the output targetlist. */ ListCell *lc; - foreach (lc, aggregated_tlist_resolved) + foreach (lc, resolved_targetlist) { TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); - if (!IsA(target_entry->expr, Aggref)) + if (IsA(target_entry->expr, Aggref)) { - continue; + Aggref *aggref = castNode(Aggref, target_entry->expr); + if (!can_vectorize_aggref(aggref, custom, &vqi)) + { + /* Aggregate function not vectorizable. */ + return plan; + } } - - Aggref *aggref = castNode(Aggref, target_entry->expr); - // fprintf(stderr, "the final aggref is:\n"); - // my_print(aggref); - if (!can_vectorize_aggref(aggref, custom, &vqi)) + else if (IsA(target_entry->expr, Var)) + { + if (!is_vector_var(custom, target_entry->expr, NULL)) + { + /* Variable not vectorizable. */ + return plan; + } + } + else { + /* + * Sometimes the plan can require this node to perform a projection, + * e.g. we can see a nested loop param in its output targetlist. We + * can't handle this case currently. + */ return plan; } } @@ -690,5 +744,5 @@ try_insert_vector_agg_node(Plan *plan) * Finally, all requirements are satisfied and we can vectorize this partial * aggregation node. */ - return vector_agg_plan_create(agg, custom); + return vector_agg_plan_create(agg, custom, resolved_targetlist); } From 4ca989bae8baab71592c88dcbe8c9a9e850b02f6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:47:06 +0100 Subject: [PATCH 124/242] test --- tsl/test/expected/vector_agg_functions.out | 5 ++++- tsl/test/sql/vector_agg_functions.sql | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 425e03816c2..1d0e5c100f2 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -103,9 +103,12 @@ select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; -- We can't vectorize some aggregate functions on platforms withouth int128 --- support. Just relax the test requirements for them. +-- support. Just relax the test requirements for them. I don't want to disable +-- this test in release builds, and don't want to have the guc in release builds, +-- so we'll assume we have int128 in all release builds. select case when setting::bool then 'require' else 'allow' end guc_value from pg_settings where name = 'timescaledb.debug_have_int128' +union select 'require' guc_value \gset set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 06c2f5262f1..6b35dbbc2d9 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -86,9 +86,12 @@ select count(compress_chunk(x)) from show_chunks('edges') x; vacuum freeze analyze edges; -- We can't vectorize some aggregate functions on platforms withouth int128 --- support. Just relax the test requirements for them. +-- support. Just relax the test requirements for them. I don't want to disable +-- this test in release builds, and don't want to have the guc in release builds, +-- so we'll assume we have int128 in all release builds. select case when setting::bool then 'require' else 'allow' end guc_value from pg_settings where name = 'timescaledb.debug_have_int128' +union select 'require' guc_value \gset set timescaledb.debug_require_vector_agg = :'guc_value'; From c2ac4db0c122d28b7653ab132466f83b38788f8f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:19:44 +0100 Subject: [PATCH 125/242] simplified output key creation --- tsl/src/nodes/vector_agg/exec.c | 43 +++++--- tsl/src/nodes/vector_agg/function/functions.c | 51 +++++++++- .../nodes/vector_agg/grouping_policy_hash.c | 50 ++++------ .../nodes/vector_agg/grouping_policy_hash.h | 31 +++--- tsl/src/nodes/vector_agg/hash_serialized.c | 97 ++++++++++++------- tsl/src/nodes/vector_agg/hash_single_helper.c | 24 +++++ tsl/src/nodes/vector_agg/hash_single_text.c | 10 +- .../vector_agg/hash_table_functions_impl.c | 11 ++- .../nodes/vector_agg/single_fixed_key_impl.c | 3 +- tsl/test/expected/vector_agg_grouping.out | 38 ++++---- tsl/test/sql/vector_agg_grouping.sql | 2 +- 11 files changed, 225 insertions(+), 135 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hash_single_helper.c diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index d68392ffae9..63a158adfa0 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -177,23 +177,34 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) col->typid = desc->typid; col->value_bytes = desc->value_bytes; col->by_value = desc->by_value; - switch (desc->typalign) + if (col->value_bytes == -1) { - case TYPALIGN_CHAR: - col->alignment_bytes = 1; - break; - case TYPALIGN_SHORT: - col->alignment_bytes = ALIGNOF_SHORT; - break; - case TYPALIGN_INT: - col->alignment_bytes = ALIGNOF_INT; - break; - case TYPALIGN_DOUBLE: - col->alignment_bytes = ALIGNOF_DOUBLE; - break; - default: - Assert(false); - col->alignment_bytes = 1; + /* + * long varlena requires 4 byte alignment, not sure why text has 'i' + * typalign in pg catalog. + */ + col->alignment_bytes = 4; + } + else + { + switch (desc->typalign) + { + case TYPALIGN_CHAR: + col->alignment_bytes = 1; + break; + case TYPALIGN_SHORT: + col->alignment_bytes = ALIGNOF_SHORT; + break; + case TYPALIGN_INT: + col->alignment_bytes = ALIGNOF_INT; + break; + case TYPALIGN_DOUBLE: + col->alignment_bytes = ALIGNOF_DOUBLE; + break; + default: + Assert(false); + col->alignment_bytes = 1; + } } } } diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index 60411c8c86d..bb6ef7cf074 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -52,10 +52,10 @@ count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, state->count += n; } -static void -count_star_many_scalar(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, - int start_row, int end_row, Datum constvalue, bool constisnull, - MemoryContext agg_extra_mctx) +static pg_attribute_always_inline void +count_star_many_scalar_impl(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) { CountState *states = (CountState *) agg_states; for (int row = start_row; row < end_row; row++) @@ -67,6 +67,49 @@ count_star_many_scalar(void *restrict agg_states, const uint32 *offsets, const u } } +static pg_noinline void +count_star_many_scalar_nofilter(void *restrict agg_states, const uint32 *offsets, int start_row, + int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) +{ + count_star_many_scalar_impl(agg_states, + offsets, + NULL, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); +} + +static void +count_star_many_scalar(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) +{ + if (filter == NULL) + { + count_star_many_scalar_nofilter(agg_states, + offsets, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); + } + else + { + count_star_many_scalar_impl(agg_states, + offsets, + filter, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); + } +} + VectorAggFunctions count_star_agg = { .state_bytes = sizeof(CountState), .agg_init = count_init, diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index da96f9f1123..6e854669804 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -31,11 +31,11 @@ #define DEBUG_LOG(...) #endif -extern HashTableFunctions single_fixed_2_functions; -extern HashTableFunctions single_fixed_4_functions; -extern HashTableFunctions single_fixed_8_functions; -extern HashTableFunctions single_text_functions; -extern HashTableFunctions serialized_functions; +extern HashingStrategy single_fixed_2_strategy; +extern HashingStrategy single_fixed_4_strategy; +extern HashingStrategy single_fixed_8_strategy; +extern HashingStrategy single_text_strategy; +extern HashingStrategy serialized_strategy; static const GroupingPolicy grouping_policy_hash_functions; @@ -73,17 +73,17 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr switch (g->value_bytes) { case 8: - policy->functions = single_fixed_8_functions; + policy->strategy = single_fixed_8_strategy; break; case 4: - policy->functions = single_fixed_4_functions; + policy->strategy = single_fixed_4_strategy; break; case 2: - policy->functions = single_fixed_2_functions; + policy->strategy = single_fixed_2_strategy; break; case -1: Assert(g->typid == TEXTOID); - policy->functions = single_text_functions; + policy->strategy = single_text_strategy; break; default: Assert(false); @@ -92,11 +92,10 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr } else { - policy->functions = serialized_functions; + policy->strategy = serialized_strategy; } - policy->table = - policy->functions.create(CurrentMemoryContext, policy->num_agg_state_rows, NULL); + policy->strategy.init(&policy->strategy, policy); return &policy->funcs; } @@ -110,7 +109,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; - policy->functions.reset(policy->table); + policy->strategy.reset(policy->table); /* * Have to reset this because it's in the key body context which is also @@ -238,7 +237,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * Match rows to aggregation states using a hash table. */ Assert((size_t) end_row <= policy->num_key_index_for_row); - policy->functions.fill_offsets(policy, batch_state, start_row, end_row); + policy->strategy.fill_offsets(policy, batch_state, start_row, end_row); /* * Process the aggregate function states. @@ -361,7 +360,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * Call the per-batch initialization function of the hashing strategy, if * it has one. */ - if (policy->functions.prepare_for_batch) + if (policy->strategy.prepare_for_batch) { /* * Remember which aggregation states have already existed, and which we @@ -369,7 +368,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) */ const uint32 first_initialized_key_index = policy->last_used_key_index; - policy->functions.prepare_for_batch(policy, batch_state); + policy->strategy.prepare_for_batch(policy, batch_state); if (policy->last_used_key_index > first_initialized_key_index) { @@ -472,7 +471,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - return policy->functions.get_size_bytes(policy->table) > 128 * 1024; + return policy->strategy.get_size_bytes(policy->table) > 128 * 1024; } static bool @@ -524,20 +523,9 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) &aggregated_slot->tts_isnull[agg_def->output_offset]); } - const int num_key_columns = policy->num_grouping_columns; - for (int i = 0; i < num_key_columns; i++) - { - const GroupingColumn *col = &policy->grouping_columns[i]; - aggregated_slot->tts_values[col->output_offset] = - gp_hash_output_keys(policy, current_key)[i]; - aggregated_slot->tts_isnull[col->output_offset] = - !byte_bitmap_row_is_valid(gp_hash_key_validity_bitmap(policy, current_key), i); - } + policy->strategy.emit_key(policy, current_key, aggregated_slot); - DEBUG_PRINT("%p: output key index %d valid %lx\n", - policy, - current_key, - gp_hash_key_validity_bitmap(policy, current_key)[0]); + DEBUG_PRINT("%p: output key index %d\n", policy, current_key); return true; } @@ -546,7 +534,7 @@ static char * gp_hash_explain(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - return psprintf("hashed with %s key", policy->functions.explain_name); + return psprintf("hashed with %s key", policy->strategy.explain_name); } static const GroupingPolicy grouping_policy_hash_functions = { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 204a508765b..67abf266b45 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -15,17 +15,21 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; -typedef struct +typedef struct HashingStrategy HashingStrategy; + +typedef struct HashingStrategy { char *explain_name; - void *(*create)(MemoryContext context, uint32 initial_rows, void *data); + void (*init)(HashingStrategy *strategy, GroupingPolicyHash *policy); void (*reset)(void *table); uint32 (*get_num_keys)(void *table); uint64 (*get_size_bytes)(void *table); void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row); -} HashTableFunctions; + void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot); +} HashingStrategy; /* * Hash grouping policy. @@ -74,7 +78,7 @@ typedef struct GroupingPolicyHash * unique integer index. */ void *table; - HashTableFunctions functions; + HashingStrategy strategy; /* * Temporary key storages. Some hashing strategies need to put the key in a @@ -172,22 +176,9 @@ typedef struct GroupingPolicyHash static inline Datum * gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) { - Assert(key_index != 0); - - const size_t null_bitmap_bytes = (policy->num_grouping_columns + 7) / 8; - const size_t key_bytes = sizeof(Datum) * policy->num_grouping_columns; - const size_t serialized_key_bytes = TYPEALIGN(8, null_bitmap_bytes + key_bytes); - /* Bitmap goes to the end. */ - return (Datum *) (serialized_key_bytes * key_index + (uint8 *) policy->output_keys); -} - -static inline uint8 * -gp_hash_key_validity_bitmap(GroupingPolicyHash *policy, int key_index) -{ - Assert(key_index != 0); - - const size_t null_bitmap_bytes = (policy->num_grouping_columns + 7) / 8; - return ((uint8 *) gp_hash_output_keys(policy, key_index + 1)) - null_bitmap_bytes; + Assert(key_index > 0); + // Assert((size_t) key_index < policy->num_output_keys); + return key_index + (Datum *) policy->output_keys; } static pg_attribute_always_inline bool diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 775e6a5e6f5..1aae1a8be25 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -88,6 +88,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * { /* Short varlena, unaligned. */ total_bytes = value_bytes + VARHDRSZ_SHORT; + num_bytes += total_bytes; } else { @@ -95,8 +96,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * total_bytes = value_bytes + VARHDRSZ; num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; } - - num_bytes += total_bytes; } } @@ -127,16 +126,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * serialized_key_validity_bitmap = &serialized_key_storage[num_bytes - bitmap_bytes]; - /* - * We will also fill the output key values in Postgres format. They can go - * straight into the next unused key space, if this key is discarded they - * will just be overwritten later. - */ - uint8 *restrict output_key_validity_bitmap = - gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1); - Datum *restrict output_key_datums = - gp_hash_output_keys(policy, policy->last_used_key_index + 1); - /* * Loop through the grouping columns again and build the actual key. */ @@ -159,10 +148,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * column_values->output_value, def->value_bytes); - memcpy(&output_key_datums[column_index], - column_values->output_value, - def->value_bytes); - offset += def->value_bytes; } else @@ -173,9 +158,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * DatumGetPointer(*column_values->output_value), VARSIZE_ANY(*column_values->output_value)); - output_key_datums[column_index] = - PointerGetDatum(&serialized_key_storage[offset]); - offset += VARSIZE_ANY(*column_values->output_value); } } @@ -198,10 +180,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * memcpy(&serialized_key_storage[offset], ((char *) column_values->buffers[1]) + column_values->decompression_type * row, column_values->decompression_type); - memcpy(&output_key_datums[column_index], - ((char *) column_values->buffers[1]) + column_values->decompression_type * row, - column_values->decompression_type); - offset += column_values->decompression_type; continue; @@ -216,11 +194,9 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; - void *datum_start; if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { /* Short varlena, unaligned. */ - datum_start = &serialized_key_storage[offset]; const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); offset += VARHDRSZ_SHORT; @@ -229,15 +205,14 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * { /* Long varlena, requires alignment. */ offset = TYPEALIGN(4, offset); - datum_start = &serialized_key_storage[offset]; const int32 total_bytes = value_bytes + VARHDRSZ; SET_VARSIZE(&serialized_key_storage[offset], total_bytes); offset += VARHDRSZ; } - output_key_datums[column_index] = PointerGetDatum(datum_start); memcpy(&serialized_key_storage[offset], &((uint8 *) column_values->buffers[2])[start], value_bytes); + offset += value_bytes; } @@ -251,14 +226,6 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * offset += bitmap_bytes; Assert(offset == num_bytes); - /* - * The output keys also have a validity bitmap, copy it there. - */ - for (size_t i = 0; i < bitmap_bytes; i++) - { - output_key_validity_bitmap[i] = serialized_key_validity_bitmap[i]; - } - DEBUG_PRINT("key is %d bytes: ", offset); for (size_t i = 0; i < offset; i++) { @@ -288,6 +255,9 @@ serialized_store_key(GroupingPolicyHash *restrict policy, text *key) Assert(policy->tmp_key_storage == (void *) key); policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; + + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(key); + return key; } @@ -297,6 +267,63 @@ serialized_destroy_key(text *key) /* Noop, the memory will be reused by the subsequent key. */ } +static void +serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) +{ + const int num_key_columns = policy->num_grouping_columns; + const Datum serialized_key_datum = gp_hash_output_keys(policy, current_key)[0]; + const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); + const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); + const uint8 *restrict ptr = serialized_key; + const int bitmap_bytes = (num_key_columns + 7) / 8; + Assert(bitmap_bytes <= key_data_bytes); + const uint8 *restrict key_validity_bitmap = &serialized_key[key_data_bytes - bitmap_bytes]; + + DEBUG_PRINT("emit key #%d, without header %d bytes: ", current_key, key_data_bytes); + for (int i = 0; i < key_data_bytes; i++) + { + DEBUG_PRINT("%.2x.", ptr[i]); + } + DEBUG_PRINT("\n"); + + for (int column_index = 0; column_index < num_key_columns; column_index++) + { + const GroupingColumn *col = &policy->grouping_columns[column_index]; + const bool isnull = !byte_bitmap_row_is_valid(key_validity_bitmap, column_index); + + aggregated_slot->tts_isnull[col->output_offset] = isnull; + + if (isnull) + { + continue; + } + + Datum *output = &aggregated_slot->tts_values[col->output_offset]; + if (col->by_value) + { + *output = 0; + memcpy(output, ptr, col->value_bytes); + ptr += col->value_bytes; + } + else + { + if (VARATT_IS_SHORT(ptr)) + { + *output = PointerGetDatum(ptr); + ptr += VARSIZE_SHORT(ptr); + } + else + { + ptr = (const uint8 *) TYPEALIGN(4, ptr); + *output = PointerGetDatum(ptr); + ptr += VARSIZE(ptr); + } + } + } + + Assert(ptr == key_validity_bitmap); +} + #define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized #define KEY_HASH(X) hash_bytes_view((BytesView){ .len = VARSIZE_4B(X), .data = (uint8 *) (X) }) diff --git a/tsl/src/nodes/vector_agg/hash_single_helper.c b/tsl/src/nodes/vector_agg/hash_single_helper.c new file mode 100644 index 00000000000..f5eb0f05c37 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_helper.c @@ -0,0 +1,24 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) + +static void +FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + Assert(policy->num_grouping_columns == 1); + + const GroupingColumn *col = &policy->grouping_columns[0]; + aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[0]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; +} + +#undef FUNCTION_NAME_HELPER2 +#undef FUNCTION_NAME_HELPER +#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 5a4a775afb1..8f43d955251 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -31,8 +31,7 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) static pg_attribute_always_inline void single_text_get_key(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) { - GroupingPolicyHash *policy = config.policy; - Assert(policy->num_grouping_columns == 1); + Assert(config.policy->num_grouping_columns == 1); BytesView *restrict key = (BytesView *) key_ptr; @@ -59,9 +58,6 @@ single_text_get_key(HashingConfig config, int row, void *restrict key_ptr, bool pg_unreachable(); } - *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1) = - *valid; - DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", policy, row, @@ -243,7 +239,6 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * { policy->null_key_index = ++policy->last_used_key_index; gp_hash_output_keys(policy, policy->null_key_index)[0] = PointerGetDatum(NULL); - *(uint64 *restrict) gp_hash_key_validity_bitmap(policy, policy->null_key_index) = false; } policy->use_key_index_for_dict = true; @@ -324,4 +319,7 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #define STORE_HASH #define CTYPE BytesView #define HAVE_PREPARE_FUNCTION + +#include "hash_single_helper.c" + #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 3843a7df797..0b6c8f593f5 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -238,12 +238,19 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba FUNCTION_NAME(dispatch_for_config)(config, start_row, end_row); } -HashTableFunctions FUNCTION_NAME(functions) = { - .create = (void *(*) (MemoryContext, uint32, void *) ) FUNCTION_NAME(create), +static void +FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) +{ + policy->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); +} + +HashingStrategy FUNCTION_NAME(strategy) = { + .init = FUNCTION_NAME(init), .reset = (void (*)(void *)) FUNCTION_NAME(reset), .get_num_keys = FUNCTION_NAME(get_num_keys), .get_size_bytes = FUNCTION_NAME(get_size_bytes), .fill_offsets = FUNCTION_NAME(fill_offsets), + .emit_key = FUNCTION_NAME(emit_key), .explain_name = EXPLAIN_NAME, #ifdef HAVE_PREPARE_FUNCTION .prepare_for_batch = FUNCTION_NAME(prepare_for_batch), diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 966eb47158c..e80a6c8311d 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -32,7 +32,6 @@ FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict key_ptr, bo } gp_hash_output_keys(policy, policy->last_used_key_index + 1)[0] = CTYPE_TO_DATUM(*key); - gp_hash_key_validity_bitmap(policy, policy->last_used_key_index + 1)[0] = *valid; } static pg_attribute_always_inline CTYPE @@ -50,3 +49,5 @@ FUNCTION_NAME(destroy_key)(CTYPE key) #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER #undef FUNCTION_NAME + +#include "hash_single_helper.c" diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index 16075bd2539..7e8c1bca431 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -47,7 +47,7 @@ select *, ss::text as x from ( -- null in entire batch when s = 2 then null -- null for some rows - when s = 3 and t % 1053 = 0 then null + when s = 3 and t % 1051 = 0 then null -- for some rows same as default when s = 4 and t % 1057 = 0 then 11 -- not null for entire batch @@ -666,7 +666,7 @@ select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; 8 | -16382 3 | -16381 9 | -16375 - | -16100 + | -16295 (10 rows) select count(*) from agggroup where cint2 > 0; @@ -753,10 +753,10 @@ select s, cint2, count(*) from agggroup where cint2 > 0 group by s, cint2 order select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by count(*), s, ss limit 10; s | ss | count ---+----+------- - 3 | | 7 + 3 | | 9 4 | 11 | 9 2 | 11 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -768,10 +768,10 @@ select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by cou select s, x, count(*) from agggroup where cint2 > 0 group by s, x order by count(*), s, x limit 10; s | x | count ---+----+------- - 3 | | 7 + 3 | | 9 4 | 11 | 9 2 | 11 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -798,10 +798,10 @@ select ss, cint2, x, count(*) from agggroup where cint2 > 0 group by ss, cint2, select ss, s, count(*) from agggroup where cint2 > 0 group by ss, s order by count(*), ss, s limit 10; ss | s | count ----+---+------- - | 3 | 7 11 | 4 | 9 + | 3 | 9 11 | 2 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -843,8 +843,8 @@ select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; x | count ----+------- - | 7 - 3 | 9886 + | 9 + 3 | 9884 6 | 9890 4 | 9897 8 | 9898 @@ -939,10 +939,10 @@ select s, cint2, count(cint2) from agggroup where cint2 > 0 group by s, cint2 or select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by count(cint2), s, ss limit 10; s | ss | count ---+----+------- - 3 | | 7 + 3 | | 9 4 | 11 | 9 2 | 11 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -954,10 +954,10 @@ select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by select s, x, count(cint2) from agggroup where cint2 > 0 group by s, x order by count(cint2), s, x limit 10; s | x | count ---+----+------- - 3 | | 7 + 3 | | 9 4 | 11 | 9 2 | 11 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -984,10 +984,10 @@ select ss, cint2, x, count(cint2) from agggroup where cint2 > 0 group by ss, cin select ss, s, count(cint2) from agggroup where cint2 > 0 group by ss, s order by count(cint2), ss, s limit 10; ss | s | count ----+---+------- - | 3 | 7 11 | 4 | 9 + | 3 | 9 11 | 2 | 9868 - 3 | 3 | 9886 + 3 | 3 | 9884 6 | 6 | 9890 4 | 4 | 9897 8 | 8 | 9898 @@ -1029,8 +1029,8 @@ select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; x | count ----+------- - | 7 - 3 | 9886 + | 9 + 3 | 9884 6 | 9890 4 | 9897 8 | 9898 @@ -1224,7 +1224,7 @@ select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2 6 | 3 0 | 4 4 | 4 - | 3667 + | 4895 (10 rows) select count(*) from agggroup where cint2 is null; diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index 6b79a3e4adb..2ec80ec1120 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -46,7 +46,7 @@ select *, ss::text as x from ( -- null in entire batch when s = 2 then null -- null for some rows - when s = 3 and t % 1053 = 0 then null + when s = 3 and t % 1051 = 0 then null -- for some rows same as default when s = 4 and t % 1057 = 0 then 11 -- not null for entire batch From 3b03a5c9138f9eb9e5dbd19af9664f9a0ed135c0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:28:08 +0100 Subject: [PATCH 126/242] fixes --- tsl/test/expected/vector_agg_functions.out | 6 ++++-- tsl/test/sql/vector_agg_functions.sql | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index 6a04f131ef4..bffb8d7af7d 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -108,7 +108,8 @@ vacuum freeze analyze edges; -- so we'll assume we have int128 in all release builds. select case when setting::bool then 'require' else 'allow' end guc_value from pg_settings where name = 'timescaledb.debug_have_int128' -union select 'require' guc_value +union all select 'require' guc_value +limit 1 \gset set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies @@ -156,7 +157,8 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's']) with ordinality as grouping(grouping, n) + 's', + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 4dc8938182a..2876a303fba 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -91,7 +91,8 @@ vacuum freeze analyze edges; -- so we'll assume we have int128 in all release builds. select case when setting::bool then 'require' else 'allow' end guc_value from pg_settings where name = 'timescaledb.debug_have_int128' -union select 'require' guc_value +union all select 'require' guc_value +limit 1 \gset set timescaledb.debug_require_vector_agg = :'guc_value'; @@ -141,7 +142,8 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's']) with ordinality as grouping(grouping, n) + 's', + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) From 9bca9721de6dd219821fa847d00e89110582f8c9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:28:35 +0100 Subject: [PATCH 127/242] benchmark hash grouping (2024-11-14 no. 8) From b8776f8f08606c5cdbc5784970a61029f41943d0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:21:19 +0100 Subject: [PATCH 128/242] abbreviated keys :o --- tsl/src/nodes/vector_agg/hash_serialized.c | 13 ++++--- .../nodes/vector_agg/hash_single_fixed_2.c | 7 ++-- .../nodes/vector_agg/hash_single_fixed_4.c | 7 ++-- .../nodes/vector_agg/hash_single_fixed_8.c | 7 ++-- tsl/src/nodes/vector_agg/hash_single_text.c | 25 +++++++------ .../vector_agg/hash_table_functions_impl.c | 35 ++++++++++--------- .../nodes/vector_agg/single_fixed_key_impl.c | 25 ++++++------- 7 files changed, 67 insertions(+), 52 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 1aae1a8be25..1e35e53b962 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -19,11 +19,13 @@ #include "nodes/vector_agg/exec.h" static pg_attribute_always_inline void -serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) +serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, + void *restrict abbrev_key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = config.policy; - text **restrict key = (text **) key_ptr; + text **restrict full_key = (text **) full_key_ptr; + text **restrict abbrev_key = (text **) abbrev_key_ptr; const int num_columns = config.num_grouping_columns; @@ -235,7 +237,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * SET_VARSIZE(serialized_key_storage, offset); - *key = (text *) serialized_key_storage; + *full_key = (text *) serialized_key_storage; /* * The multi-column key is always considered non-null, and the null flags @@ -243,6 +245,8 @@ serialized_get_key(HashingConfig config, int row, void *restrict key_ptr, bool * * key. */ *valid = true; + + *abbrev_key = *full_key; } static pg_attribute_always_inline text * @@ -331,5 +335,6 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl (VARSIZE_4B(a) == VARSIZE_4B(b) && \ memcmp(VARDATA_4B(a), VARDATA_4B(b), VARSIZE_4B(a) - VARHDRSZ) == 0) #define STORE_HASH -#define CTYPE text * +#define FULL_KEY_TYPE text * +#define ABBREV_KEY_TYPE text * #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 3799d4dae9b..7453fb07291 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -21,9 +21,10 @@ #define KEY_BYTES 2 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CTYPE int16 -#define DATUM_TO_CTYPE DatumGetInt16 -#define CTYPE_TO_DATUM Int16GetDatum +#define FULL_KEY_TYPE int16 +#define ABBREV_KEY_TYPE int16 +#define DATUM_TO_FULL_KEY DatumGetInt16 +#define FULL_KEY_TO_DATUM Int16GetDatum #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index e4982c9e11b..fb5d7b1c6d8 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -21,9 +21,10 @@ #define KEY_BYTES 4 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CTYPE int32 -#define DATUM_TO_CTYPE DatumGetInt32 -#define CTYPE_TO_DATUM Int32GetDatum +#define FULL_KEY_TYPE int32 +#define ABBREV_KEY_TYPE int32 +#define DATUM_TO_FULL_KEY DatumGetInt32 +#define FULL_KEY_TO_DATUM Int32GetDatum #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index f191cbfe9ff..45e000ad409 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -21,9 +21,10 @@ #define KEY_BYTES 8 #define KEY_HASH hash64 #define KEY_EQUAL(a, b) a == b -#define CTYPE int64 -#define DATUM_TO_CTYPE DatumGetInt64 -#define CTYPE_TO_DATUM Int64GetDatum +#define FULL_KEY_TYPE int64 +#define ABBREV_KEY_TYPE int64 +#define DATUM_TO_FULL_KEY DatumGetInt64 +#define FULL_KEY_TO_DATUM Int64GetDatum #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 8f43d955251..eeab9292871 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -29,28 +29,30 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) +single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, + void *restrict abbrev_key_ptr, bool *restrict valid) { Assert(config.policy->num_grouping_columns == 1); - BytesView *restrict key = (BytesView *) key_ptr; + BytesView *restrict full_key = (BytesView *) full_key_ptr; + BytesView *restrict abbrev_key = (BytesView *) abbrev_key_ptr; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { /* Already stored. */ - key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); - key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); + full_key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); + full_key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); *valid = !*config.single_key.output_isnull; } else if (config.single_key.decompression_type == DT_ArrowText) { - *key = get_bytes_view(&config.single_key, row); + *full_key = get_bytes_view(&config.single_key, row); *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } else if (config.single_key.decompression_type == DT_ArrowTextDict) { const int16 index = ((int16 *) config.single_key.buffers[3])[row]; - *key = get_bytes_view(&config.single_key, index); + *full_key = get_bytes_view(&config.single_key, index); *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } else @@ -62,12 +64,14 @@ single_text_get_key(HashingConfig config, int row, void *restrict key_ptr, bool policy, row, policy->last_used_key_index + 1, - key->len); - for (size_t i = 0; i < key->len; i++) + full_key->len); + for (size_t i = 0; i < full_key->len; i++) { - DEBUG_PRINT("%.2x.", key->data[i]); + DEBUG_PRINT("%.2x.", full_key->data[i]); } DEBUG_PRINT("\n"); + + *abbrev_key = *full_key; } static pg_attribute_always_inline BytesView @@ -317,7 +321,8 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #define KEY_HASH(X) hash_bytes_view(X) #define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) #define STORE_HASH -#define CTYPE BytesView +#define FULL_KEY_TYPE BytesView +#define ABBREV_KEY_TYPE BytesView #define HAVE_PREPARE_FUNCTION #include "hash_single_helper.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 0b6c8f593f5..1aa50a6e31d 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -16,7 +16,7 @@ */ typedef struct { - CTYPE key; + ABBREV_KEY_TYPE abbrev_key; #ifdef STORE_HASH /* @@ -33,8 +33,8 @@ typedef struct #define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) -#define SH_KEY_TYPE CTYPE -#define SH_KEY key +#define SH_KEY_TYPE FULL_KEY_TYPE +#define SH_KEY abbrev_key #define SH_HASH_KEY(tb, key) KEY_HASH(key) #define SH_EQUAL(tb, a, b) KEY_EQUAL(a, b) #define SH_SCOPE static inline @@ -77,7 +77,7 @@ FUNCTION_NAME(fill_offsets_impl)( struct FUNCTION_NAME(hash) *restrict table = policy->table; - CTYPE previous_key; + ABBREV_KEY_TYPE prev_abbrev_key; uint32 previous_key_index = 0; for (int row = start_row; row < end_row; row++) { @@ -89,8 +89,9 @@ FUNCTION_NAME(fill_offsets_impl)( } bool key_valid = false; - CTYPE key = { 0 }; - FUNCTION_NAME(get_key)(config, row, &key, &key_valid); + FULL_KEY_TYPE full_key = { 0 }; + ABBREV_KEY_TYPE abbrev_key = { 0 }; + FUNCTION_NAME(get_key)(config, row, &full_key, &abbrev_key, &key_valid); if (unlikely(!key_valid)) { @@ -101,11 +102,11 @@ FUNCTION_NAME(fill_offsets_impl)( } indexes[row] = policy->null_key_index; DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); - FUNCTION_NAME(destroy_key)(key); + FUNCTION_NAME(destroy_key)(full_key); continue; } - if (likely(previous_key_index != 0) && KEY_EQUAL(key, previous_key)) + if (likely(previous_key_index != 0) && KEY_EQUAL(abbrev_key, prev_abbrev_key)) { /* * In real data sets, we often see consecutive rows with the @@ -116,7 +117,7 @@ FUNCTION_NAME(fill_offsets_impl)( * for that case. */ indexes[row] = previous_key_index; - FUNCTION_NAME(destroy_key)(key); + FUNCTION_NAME(destroy_key)(full_key); policy->stat_consecutive_keys++; DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; @@ -126,26 +127,26 @@ FUNCTION_NAME(fill_offsets_impl)( * Find the key using the hash table. */ bool found = false; - FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, key, &found); + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, abbrev_key, &found); if (!found) { /* * New key, have to store it persistently. */ const int index = ++policy->last_used_key_index; - entry->key = FUNCTION_NAME(store_key)(policy, key); + entry->abbrev_key = FUNCTION_NAME(store_key)(policy, abbrev_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } else { DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); - FUNCTION_NAME(destroy_key)(key); + FUNCTION_NAME(destroy_key)(full_key); } indexes[row] = entry->key_index; previous_key_index = entry->key_index; - previous_key = entry->key; + prev_abbrev_key = entry->abbrev_key; } } @@ -169,7 +170,7 @@ FUNCTION_NAME(fill_offsets_impl)( #define APPLY_FOR_TYPE(X, NAME, COND) \ APPLY_FOR_VALIDITY(X, \ NAME##_byval, \ - (COND) && config.single_key.decompression_type == sizeof(CTYPE)) \ + (COND) && config.single_key.decompression_type == sizeof(FULL_KEY_TYPE)) \ APPLY_FOR_VALIDITY(X, \ NAME##_text, \ (COND) && config.single_key.decompression_type == DT_ArrowText) \ @@ -264,9 +265,9 @@ HashingStrategy FUNCTION_NAME(strategy) = { #undef KEY_EQUAL #undef STORE_HASH #undef CHECK_PREVIOUS_KEY -#undef CTYPE -#undef DATUM_TO_CTYPE -#undef CTYPE_TO_DATUM +#undef FULL_KEY_TYPE +#undef DATUM_TO_FULL_KEY +#undef FULL_KEY_TO_DATUM #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index e80a6c8311d..fb68857dd37 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -9,39 +9,40 @@ #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict key_ptr, bool *restrict valid) +FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict full_key_ptr, + void *restrict abbrev_key_ptr, bool *restrict valid) { - GroupingPolicyHash *policy = config.policy; - - CTYPE *restrict key = (CTYPE *) key_ptr; + FULL_KEY_TYPE *restrict full_key = (FULL_KEY_TYPE *) full_key_ptr; + ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { - *key = DATUM_TO_CTYPE(*config.single_key.output_value); + *full_key = DATUM_TO_FULL_KEY(*config.single_key.output_value); *valid = !*config.single_key.output_isnull; } - else if (config.single_key.decompression_type == sizeof(CTYPE)) + else if (config.single_key.decompression_type == sizeof(FULL_KEY_TYPE)) { - const CTYPE *values = config.single_key.buffers[1]; + const FULL_KEY_TYPE *values = config.single_key.buffers[1]; *valid = arrow_row_is_valid(config.single_key.buffers[0], row); - *key = values[row]; + *full_key = values[row]; } else { pg_unreachable(); } - gp_hash_output_keys(policy, policy->last_used_key_index + 1)[0] = CTYPE_TO_DATUM(*key); + *abbrev_key = *full_key; } -static pg_attribute_always_inline CTYPE -FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, CTYPE key) +static pg_attribute_always_inline FULL_KEY_TYPE +FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE key) { + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(key); return key; } static pg_attribute_always_inline void -FUNCTION_NAME(destroy_key)(CTYPE key) +FUNCTION_NAME(destroy_key)(FULL_KEY_TYPE key) { /* Noop for fixed-size keys. */ } From 5aac91fbd30dd93ca788ce72d79cc4efa8f5bfc3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:37:31 +0100 Subject: [PATCH 129/242] abbreviated key for integers --- tsl/src/nodes/vector_agg/hash64.h | 24 ++++++++++++++++++- tsl/src/nodes/vector_agg/hash_serialized.c | 10 ++++---- .../nodes/vector_agg/hash_single_fixed_2.c | 5 ++-- .../nodes/vector_agg/hash_single_fixed_4.c | 6 +++-- .../nodes/vector_agg/hash_single_fixed_8.c | 5 ++-- tsl/src/nodes/vector_agg/hash_single_text.c | 10 ++++---- .../vector_agg/hash_table_functions_impl.c | 2 +- .../nodes/vector_agg/single_fixed_key_impl.c | 11 +++++---- 8 files changed, 51 insertions(+), 22 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash64.h b/tsl/src/nodes/vector_agg/hash64.h index 4d988ac6eb4..ca792476486 100644 --- a/tsl/src/nodes/vector_agg/hash64.h +++ b/tsl/src/nodes/vector_agg/hash64.h @@ -11,7 +11,7 @@ * implementations. */ -#ifdef USE_SSE42_CRC32C +#ifdef USE_SSE42_CRC32Ceeeeeeeee #include static pg_attribute_always_inline uint64 hash64(uint64 x) @@ -33,4 +33,26 @@ hash64(uint64 x) x ^= x >> 31; return x; } + +static pg_attribute_always_inline uint32 +hash32(uint32 x) +{ + x ^= x >> 16; + x *= 0x7feb352d; + x ^= x >> 15; + x *= 0x846ca68b; + x ^= x >> 16; + return x; +} + +static pg_attribute_always_inline uint16 +hash16(uint16 x) +{ + x ^= x >> 8; + x *= 0x88b5U; + x ^= x >> 7; + x *= 0xdb2dU; + x ^= x >> 9; + return x; +} #endif diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 1e35e53b962..71dba600050 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -250,23 +250,23 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } static pg_attribute_always_inline text * -serialized_store_key(GroupingPolicyHash *restrict policy, text *key) +serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, text *abbrev_key) { /* * We will store this key so we have to consume the temporary storage that * was used for it. The subsequent keys will need to allocate new memory. */ - Assert(policy->tmp_key_storage == (void *) key); + Assert(policy->tmp_key_storage == (void *) full_key); policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(key); + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(abbrev_key); - return key; + return abbrev_key; } static pg_attribute_always_inline void -serialized_destroy_key(text *key) +serialized_destroy_key(const text *key) { /* Noop, the memory will be reused by the subsequent key. */ } diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 7453fb07291..59bd91e5c39 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -19,13 +19,14 @@ #define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 #define KEY_BYTES 2 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b #define FULL_KEY_TYPE int16 #define ABBREV_KEY_TYPE int16 #define DATUM_TO_FULL_KEY DatumGetInt16 #define FULL_KEY_TO_DATUM Int16GetDatum +#define ABBREVIATE(X) hash16(X) #include "single_fixed_key_impl.c" +#define KEY_HASH(X) (X) +#define KEY_EQUAL(a, b) a == b #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index fb5d7b1c6d8..65044e563b9 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -19,13 +19,15 @@ #define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 #define KEY_BYTES 4 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b #define FULL_KEY_TYPE int32 #define ABBREV_KEY_TYPE int32 #define DATUM_TO_FULL_KEY DatumGetInt32 #define FULL_KEY_TO_DATUM Int32GetDatum +#define ABBREVIATE(X) hash32(X) #include "single_fixed_key_impl.c" +#define KEY_HASH(X) (X) +#define KEY_EQUAL(a, b) a == b + #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index 45e000ad409..a47946355cb 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -19,13 +19,14 @@ #define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 #define KEY_BYTES 8 -#define KEY_HASH hash64 -#define KEY_EQUAL(a, b) a == b #define FULL_KEY_TYPE int64 #define ABBREV_KEY_TYPE int64 #define DATUM_TO_FULL_KEY DatumGetInt64 #define FULL_KEY_TO_DATUM Int64GetDatum +#define ABBREVIATE(X) hash64(X) #include "single_fixed_key_impl.c" +#define KEY_HASH(X) (X) +#define KEY_EQUAL(a, b) a == b #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index eeab9292871..bb72b3815f6 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -75,15 +75,15 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } static pg_attribute_always_inline BytesView -single_text_store_key(GroupingPolicyHash *restrict policy, BytesView key) +single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, BytesView abbrev_key) { - const int total_bytes = key.len + VARHDRSZ; + const int total_bytes = full_key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); - memcpy(VARDATA(stored), key.data, key.len); - key.data = (uint8 *) VARDATA(stored); + memcpy(VARDATA(stored), full_key.data, full_key.len); + full_key.data = (uint8 *) VARDATA(stored); gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); - return key; + return full_key; } static pg_attribute_always_inline void diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 1aa50a6e31d..3f4f37e7dfb 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -134,7 +134,7 @@ FUNCTION_NAME(fill_offsets_impl)( * New key, have to store it persistently. */ const int index = ++policy->last_used_key_index; - entry->abbrev_key = FUNCTION_NAME(store_key)(policy, abbrev_key); + entry->abbrev_key = FUNCTION_NAME(store_key)(policy, full_key, abbrev_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index fb68857dd37..b599d22e160 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -31,14 +31,15 @@ FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict full_key_pt pg_unreachable(); } - *abbrev_key = *full_key; + *abbrev_key = ABBREVIATE(*full_key); } static pg_attribute_always_inline FULL_KEY_TYPE -FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE key) +FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE full_key, + ABBREV_KEY_TYPE abbrev_key) { - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(key); - return key; + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(full_key); + return abbrev_key; } static pg_attribute_always_inline void @@ -51,4 +52,6 @@ FUNCTION_NAME(destroy_key)(FULL_KEY_TYPE key) #undef FUNCTION_NAME_HELPER #undef FUNCTION_NAME +#undef ABBREVIATE + #include "hash_single_helper.c" From 6daa0a456ad56449f7b5eb74f59d80f6e07eccb8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:50:54 +0100 Subject: [PATCH 130/242] abbreviated keys for ints are slightly slower --- tsl/src/nodes/vector_agg/hash64.h | 25 +++++++++++-------- .../nodes/vector_agg/hash_single_fixed_2.c | 5 ++-- .../nodes/vector_agg/hash_single_fixed_4.c | 5 ++-- .../nodes/vector_agg/hash_single_fixed_8.c | 5 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash64.h b/tsl/src/nodes/vector_agg/hash64.h index ca792476486..9f7fdcb1ce8 100644 --- a/tsl/src/nodes/vector_agg/hash64.h +++ b/tsl/src/nodes/vector_agg/hash64.h @@ -11,20 +11,11 @@ * implementations. */ -#ifdef USE_SSE42_CRC32Ceeeeeeeee -#include -static pg_attribute_always_inline uint64 -hash64(uint64 x) -{ - return _mm_crc32_u64(~0ULL, x); -} - -#else /* * When we don't have the crc32 instruction, use the SplitMix64 finalizer. */ static pg_attribute_always_inline uint64 -hash64(uint64 x) +hash64_splitmix(uint64 x) { x ^= x >> 30; x *= 0xbf58476d1ce4e5b9U; @@ -34,6 +25,19 @@ hash64(uint64 x) return x; } +#ifdef USE_SSE42_CRC32C +#include +static pg_attribute_always_inline uint64 +hash64_crc(uint64 x) +{ + return _mm_crc32_u64(~0ULL, x); +} + +#define HASH64 hash64_crc +#else +#define HASH64 hash64_splitmix +#endif + static pg_attribute_always_inline uint32 hash32(uint32 x) { @@ -55,4 +59,3 @@ hash16(uint16 x) x ^= x >> 9; return x; } -#endif diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 59bd91e5c39..6998771c761 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -23,10 +23,11 @@ #define ABBREV_KEY_TYPE int16 #define DATUM_TO_FULL_KEY DatumGetInt16 #define FULL_KEY_TO_DATUM Int16GetDatum -#define ABBREVIATE(X) hash16(X) + +#define ABBREVIATE(X) (X) +#define KEY_HASH(X) hash64_crc(X) #include "single_fixed_key_impl.c" -#define KEY_HASH(X) (X) #define KEY_EQUAL(a, b) a == b #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index 65044e563b9..2880f9655b8 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -23,11 +23,12 @@ #define ABBREV_KEY_TYPE int32 #define DATUM_TO_FULL_KEY DatumGetInt32 #define FULL_KEY_TO_DATUM Int32GetDatum -#define ABBREVIATE(X) hash32(X) + +#define ABBREVIATE(X) (X) +#define KEY_HASH(X) hash64_crc(X) #include "single_fixed_key_impl.c" -#define KEY_HASH(X) (X) #define KEY_EQUAL(a, b) a == b #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index a47946355cb..3d0973d6cc8 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -23,10 +23,11 @@ #define ABBREV_KEY_TYPE int64 #define DATUM_TO_FULL_KEY DatumGetInt64 #define FULL_KEY_TO_DATUM Int64GetDatum -#define ABBREVIATE(X) hash64(X) + +#define ABBREVIATE(X) (X) +#define KEY_HASH(X) hash64_crc(X) #include "single_fixed_key_impl.c" -#define KEY_HASH(X) (X) #define KEY_EQUAL(a, b) a == b #include "hash_table_functions_impl.c" From ed795c13c1c4109845f373a6a2016f0761259303 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:19:56 +0100 Subject: [PATCH 131/242] umash --- scripts/clang_format_all.sh | 2 +- tsl/src/import/CMakeLists.txt | 4 +- tsl/src/import/umash.c | 1554 +++++++++++++++++ tsl/src/import/umash.h | 286 +++ .../nodes/vector_agg/grouping_policy_hash.h | 3 + tsl/src/nodes/vector_agg/hash_serialized.c | 28 +- tsl/src/nodes/vector_agg/hash_single_text.c | 26 +- .../vector_agg/hash_table_functions_impl.c | 10 +- 8 files changed, 1889 insertions(+), 24 deletions(-) create mode 100644 tsl/src/import/umash.c create mode 100644 tsl/src/import/umash.h diff --git a/scripts/clang_format_all.sh b/scripts/clang_format_all.sh index ea1bb03e8b8..5828d39b855 100755 --- a/scripts/clang_format_all.sh +++ b/scripts/clang_format_all.sh @@ -5,5 +5,5 @@ SCRIPT_DIR=$(cd "$(dirname $0)" || exit; pwd) BASE_DIR=$(dirname $SCRIPT_DIR) find ${BASE_DIR} \( -path "${BASE_DIR}/src/*" -or -path "${BASE_DIR}/test/*" -or -path "${BASE_DIR}/tsl/*" \) \ - -and -not \( -path "*/.*" -or -path "*CMake*" \) \ + -and -not \( -path "*/.*" -or -path "*CMake*" -or -path "${BASE_DIR}/tsl/src/import/*" \) \ -and \( -name '*.c' -or -name '*.h' \) -print0 | xargs -0 ${SCRIPT_DIR}/clang_format_wrapper.sh -style=file -i diff --git a/tsl/src/import/CMakeLists.txt b/tsl/src/import/CMakeLists.txt index ccac900c3ee..32e5a008652 100644 --- a/tsl/src/import/CMakeLists.txt +++ b/tsl/src/import/CMakeLists.txt @@ -1,2 +1,2 @@ -set(SOURCES "") -target_sources(${PROJECT_NAME} PRIVATE ${SOURCES}) +set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) +target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/import/umash.c b/tsl/src/import/umash.c new file mode 100644 index 00000000000..685bc659c98 --- /dev/null +++ b/tsl/src/import/umash.c @@ -0,0 +1,1554 @@ +#include "umash.h" + +/* + * UMASH is distributed under the MIT license. + * + * SPDX-License-Identifier: MIT + * + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * Copyright 2022 Dougall Johnson + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(UMASH_TEST_ONLY) && !defined(NDEBUG) +#define NDEBUG +#endif + +/** + * -DUMASH_LONG_INPUTS=0 to disable the routine specialised for long + * inputs, and -DUMASH_LONG_INPUTS=1 to enable it. If the variable + * isn't defined, we try to probe for `umash_long.inc`: that's where + * the long input routines are defined. + */ +#ifndef UMASH_LONG_INPUTS +#ifdef __has_include +#if __has_include("umash_long.inc") +#define UMASH_LONG_INPUTS 1 +#endif /* __has_include() */ +#endif /* __has_include */ + +#ifndef UMASH_LONG_INPUTS +#define UMASH_LONG_INPUTS 0 +#endif /* !UMASH_LONG_INPUTS */ +#endif /* !UMASH_LONG_INPUTS */ + +/* + * Default to dynamically dispatching implementations on x86-64 + * (there's nothing to dispatch on aarch64). + */ +#ifndef UMASH_DYNAMIC_DISPATCH +#ifdef __x86_64__ +#define UMASH_DYNAMIC_DISPATCH 1 +#else +#define UMASH_DYNAMIC_DISPATCH 0 +#endif +#endif + +/* + * Enable inline assembly by default when building with recent GCC or + * compatible compilers. It should always be safe to disable this + * option, although there may be a performance cost. + */ +#ifndef UMASH_INLINE_ASM + +#if defined(__clang__) +/* + * We need clang 8+ for output flags, and 10+ for relaxed vector + * constraints. + */ +#if __clang_major__ >= 10 +#define UMASH_INLINE_ASM 1 +#else +#define UMASH_INLINE_ASM 0 +#endif /* __clang_major__ */ + +#elif defined(__GNUC__) +#if __GNUC__ >= 6 +#define UMASH_INLINE_ASM 1 +#else +#define UMASH_INLINE_ASM 0 +#endif /* __GNUC__ */ + +#else +#define UMASH_INLINE_ASM 0 +#endif + +#endif + +#include +#include + +#ifdef __PCLMUL__ +/* If we have access to x86 PCLMUL (and some basic SSE). */ +#include + +/* We only use 128-bit vector, as pairs of 64-bit integers. */ +typedef __m128i v128; + +#define V128_ZERO { 0 }; + +static inline v128 +v128_create(uint64_t lo, uint64_t hi) +{ + return _mm_set_epi64x(hi, lo); +} + +/* Shift each 64-bit lane left by one bit. */ +static inline v128 +v128_shift(v128 x) +{ + return _mm_add_epi64(x, x); +} + +/* Computes the 128-bit carryless product of x and y. */ +static inline v128 +v128_clmul(uint64_t x, uint64_t y) +{ + return _mm_clmulepi64_si128(_mm_cvtsi64_si128(x), _mm_cvtsi64_si128(y), 0); +} + +/* Computes the 128-bit carryless product of the high and low halves of x. */ +static inline v128 +v128_clmul_cross(v128 x) +{ + return _mm_clmulepi64_si128(x, x, 1); +} + +#elif defined(__ARM_FEATURE_CRYPTO) + +#include + +typedef uint64x2_t v128; + +#define V128_ZERO { 0 }; + +static inline v128 +v128_create(uint64_t lo, uint64_t hi) +{ + return vcombine_u64(vcreate_u64(lo), vcreate_u64(hi)); +} + +static inline v128 +v128_shift(v128 x) +{ + return vshlq_n_u64(x, 1); +} + +static inline v128 +v128_clmul(uint64_t x, uint64_t y) +{ + return vreinterpretq_u64_p128(vmull_p64(x, y)); +} + +static inline v128 +v128_clmul_cross(v128 x) +{ + v128 swapped = vextq_u64(x, x, 1); +#if UMASH_INLINE_ASM + /* Keep the result out of GPRs. */ + __asm__("" : "+w"(swapped)); +#endif + + return v128_clmul(vgetq_lane_u64(x, 0), vgetq_lane_u64(swapped, 0)); +} + +#else + +#error \ + "Unsupported platform: umash requires CLMUL (-mpclmul) on x86-64, or crypto (-march=...+crypto) extensions on aarch64." +#endif + +/* + * #define UMASH_STAP_PROBE=1 to insert probe points in public UMASH + * functions. + * + * This functionality depends on Systemtap's SDT header file. + */ +#if defined(UMASH_STAP_PROBE) && UMASH_STAP_PROBE +#include +#else +#define DTRACE_PROBE1(lib, name, a0) +#define DTRACE_PROBE2(lib, name, a0, a1) +#define DTRACE_PROBE3(lib, name, a0, a1, a2) +#define DTRACE_PROBE4(lib, name, a0, a1, a2, a3) +#endif + +/* + * #define UMASH_SECTION="special_section" to emit all UMASH symbols + * in the `special_section` ELF section. + */ +#if defined(UMASH_SECTION) && defined(__GNUC__) +#define FN __attribute__((__section__(UMASH_SECTION))) +#else +#define FN +#endif + +/* + * Defining UMASH_TEST_ONLY switches to a debug build with internal + * symbols exposed. + */ +#ifdef UMASH_TEST_ONLY +#define TEST_DEF FN +#include "t/umash_test_only.h" +#else +#define TEST_DEF static FN +#endif + +#ifdef __GNUC__ +#define LIKELY(X) __builtin_expect(!!(X), 1) +#define UNLIKELY(X) __builtin_expect(!!(X), 0) +#define HOT __attribute__((__hot__)) +#define COLD __attribute__((__cold__)) +#else +#define LIKELY(X) X +#define UNLIKELY(X) X +#define HOT +#define COLD +#endif + +#define ARRAY_SIZE(ARR) (sizeof(ARR) / sizeof(ARR[0])) + +#define BLOCK_SIZE (sizeof(uint64_t) * UMASH_OH_PARAM_COUNT) + +/* + * We derive independent short hashes by offsetting the constant array + * by four u64s. In theory, any positive even number works, but this + * is the constant we used in an earlier incarnation, and it works. + */ +#define OH_SHORT_HASH_SHIFT 4 + +/* Incremental UMASH consumes 16 bytes at a time. */ +#define INCREMENTAL_GRANULARITY 16 + +/** + * Modular arithmetic utilities. + * + * The code below uses GCC extensions. It should be possible to add + * support for other compilers. + */ + +#if !defined(__x86_64__) || !UMASH_INLINE_ASM +static inline void +mul128(uint64_t x, uint64_t y, uint64_t *hi, uint64_t *lo) +{ + __uint128_t product = x; + + product *= y; + *hi = product >> 64; + *lo = product; + return; +} +#else +static inline void +mul128(uint64_t x, uint64_t y, uint64_t *hi, uint64_t *lo) +{ + uint64_t mulhi, mullo; + + __asm__("mul %3" : "=a"(mullo), "=d"(mulhi) : "%a"(x), "r"(y) : "cc"); + *hi = mulhi; + *lo = mullo; + return; +} +#endif + +TEST_DEF inline uint64_t +add_mod_fast(uint64_t x, uint64_t y) +{ + unsigned long long sum; + + /* If `sum` overflows, `sum + 8` does not. */ + return (__builtin_uaddll_overflow(x, y, &sum) ? sum + 8 : sum); +} + +static FN COLD uint64_t +add_mod_slow_slow_path(uint64_t sum, uint64_t fixup) +{ + /* Reduce sum, mod 2**64 - 8. */ + sum = (sum >= (uint64_t)-8) ? sum + 8 : sum; + /* sum < 2**64 - 8, so this doesn't overflow. */ + sum += fixup; + /* Reduce again. */ + sum = (sum >= (uint64_t)-8) ? sum + 8 : sum; + return sum; +} + +TEST_DEF inline uint64_t +add_mod_slow(uint64_t x, uint64_t y) +{ + unsigned long long sum; + uint64_t fixup = 0; + + /* x + y \equiv sum + fixup */ + if (__builtin_uaddll_overflow(x, y, &sum)) + fixup = 8; + + /* + * We must ensure `sum + fixup < 2**64 - 8`. + * + * We want a conditional branch here, but not in the + * overflowing add: overflows happen roughly half the time on + * pseudorandom inputs, but `sum < 2**64 - 16` is almost + * always true, for pseudorandom `sum`. + */ + if (LIKELY(sum < (uint64_t)-16)) + return sum + fixup; + +#ifdef UMASH_INLINE_ASM + /* + * Some compilers like to compile the likely branch above with + * conditional moves or predication. Insert a compiler barrier + * in the slow path here to force a branch. + */ + __asm__("" : "+r"(sum)); +#endif + return add_mod_slow_slow_path(sum, fixup); +} + +TEST_DEF inline uint64_t +mul_mod_fast(uint64_t m, uint64_t x) +{ + uint64_t hi, lo; + + mul128(m, x, &hi, &lo); + return add_mod_fast(lo, 8 * hi); +} + +TEST_DEF inline uint64_t +horner_double_update(uint64_t acc, uint64_t m0, uint64_t m1, uint64_t x, uint64_t y) +{ + + acc = add_mod_fast(acc, x); + return add_mod_slow(mul_mod_fast(m0, acc), mul_mod_fast(m1, y)); +} + +/** + * Salsa20 stream generator, used to derive struct umash_param. + * + * Slightly prettified version of D. J. Bernstein's public domain NaCL + * (version 20110121), without paying any attention to constant time + * execution or any other side-channel. + */ +static inline uint32_t +rotate(uint32_t u, int c) +{ + + return (u << c) | (u >> (32 - c)); +} + +static inline uint32_t +load_littleendian(const void *buf) +{ + uint32_t ret = 0; + uint8_t x[4]; + + memcpy(x, buf, sizeof(x)); + for (size_t i = 0; i < 4; i++) + ret |= (uint32_t)x[i] << (8 * i); + + return ret; +} + +static inline void +store_littleendian(void *dst, uint32_t u) +{ + + for (size_t i = 0; i < 4; i++) { + uint8_t lo = u; + + memcpy(dst, &lo, 1); + u >>= 8; + dst = (char *)dst + 1; + } + + return; +} + +static FN void +core_salsa20(char *out, const uint8_t in[static 16], const uint8_t key[static 32], + const uint8_t constant[16]) +{ + enum { ROUNDS = 20 }; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + + j0 = x0 = load_littleendian(constant + 0); + j1 = x1 = load_littleendian(key + 0); + j2 = x2 = load_littleendian(key + 4); + j3 = x3 = load_littleendian(key + 8); + j4 = x4 = load_littleendian(key + 12); + j5 = x5 = load_littleendian(constant + 4); + j6 = x6 = load_littleendian(in + 0); + j7 = x7 = load_littleendian(in + 4); + j8 = x8 = load_littleendian(in + 8); + j9 = x9 = load_littleendian(in + 12); + j10 = x10 = load_littleendian(constant + 8); + j11 = x11 = load_littleendian(key + 16); + j12 = x12 = load_littleendian(key + 20); + j13 = x13 = load_littleendian(key + 24); + j14 = x14 = load_littleendian(key + 28); + j15 = x15 = load_littleendian(constant + 12); + + for (size_t i = 0; i < ROUNDS; i += 2) { + x4 ^= rotate(x0 + x12, 7); + x8 ^= rotate(x4 + x0, 9); + x12 ^= rotate(x8 + x4, 13); + x0 ^= rotate(x12 + x8, 18); + x9 ^= rotate(x5 + x1, 7); + x13 ^= rotate(x9 + x5, 9); + x1 ^= rotate(x13 + x9, 13); + x5 ^= rotate(x1 + x13, 18); + x14 ^= rotate(x10 + x6, 7); + x2 ^= rotate(x14 + x10, 9); + x6 ^= rotate(x2 + x14, 13); + x10 ^= rotate(x6 + x2, 18); + x3 ^= rotate(x15 + x11, 7); + x7 ^= rotate(x3 + x15, 9); + x11 ^= rotate(x7 + x3, 13); + x15 ^= rotate(x11 + x7, 18); + x1 ^= rotate(x0 + x3, 7); + x2 ^= rotate(x1 + x0, 9); + x3 ^= rotate(x2 + x1, 13); + x0 ^= rotate(x3 + x2, 18); + x6 ^= rotate(x5 + x4, 7); + x7 ^= rotate(x6 + x5, 9); + x4 ^= rotate(x7 + x6, 13); + x5 ^= rotate(x4 + x7, 18); + x11 ^= rotate(x10 + x9, 7); + x8 ^= rotate(x11 + x10, 9); + x9 ^= rotate(x8 + x11, 13); + x10 ^= rotate(x9 + x8, 18); + x12 ^= rotate(x15 + x14, 7); + x13 ^= rotate(x12 + x15, 9); + x14 ^= rotate(x13 + x12, 13); + x15 ^= rotate(x14 + x13, 18); + } + + x0 += j0; + x1 += j1; + x2 += j2; + x3 += j3; + x4 += j4; + x5 += j5; + x6 += j6; + x7 += j7; + x8 += j8; + x9 += j9; + x10 += j10; + x11 += j11; + x12 += j12; + x13 += j13; + x14 += j14; + x15 += j15; + + store_littleendian(out + 0, x0); + store_littleendian(out + 4, x1); + store_littleendian(out + 8, x2); + store_littleendian(out + 12, x3); + store_littleendian(out + 16, x4); + store_littleendian(out + 20, x5); + store_littleendian(out + 24, x6); + store_littleendian(out + 28, x7); + store_littleendian(out + 32, x8); + store_littleendian(out + 36, x9); + store_littleendian(out + 40, x10); + store_littleendian(out + 44, x11); + store_littleendian(out + 48, x12); + store_littleendian(out + 52, x13); + store_littleendian(out + 56, x14); + store_littleendian(out + 60, x15); + return; +} + +TEST_DEF void +salsa20_stream( + void *dst, size_t len, const uint8_t nonce[static 8], const uint8_t key[static 32]) +{ + static const uint8_t sigma[16] = "expand 32-byte k"; + uint8_t in[16]; + + if (len == 0) + return; + + memcpy(in, nonce, 8); + memset(in + 8, 0, 8); + + while (len >= 64) { + unsigned int u; + + core_salsa20(dst, in, key, sigma); + u = 1; + for (size_t i = 8; i < 16; i++) { + u += in[i]; + in[i] = u; + u >>= 8; + } + + dst = (char *)dst + 64; + len -= 64; + } + + if (len > 0) { + char block[64]; + + core_salsa20(block, in, key, sigma); + memcpy(dst, block, len); + } + + return; +} + +#if defined(UMASH_TEST_ONLY) || UMASH_LONG_INPUTS +#include "umash_long.inc" +#endif + +/** + * OH block compression. + */ +TEST_DEF struct umash_oh +oh_varblock(const uint64_t *params, uint64_t tag, const void *block, size_t n_bytes) +{ + struct umash_oh ret; + v128 acc = V128_ZERO; + + /* The final block processes `remaining > 0` bytes. */ + size_t remaining = 1 + ((n_bytes - 1) % sizeof(v128)); + size_t end_full_pairs = (n_bytes - remaining) / sizeof(uint64_t); + const void *last_ptr = (const char *)block + n_bytes - sizeof(v128); + size_t i; + + for (i = 0; i < end_full_pairs; i += 2) { + v128 x, k; + + memcpy(&x, block, sizeof(x)); + block = (const char *)block + sizeof(x); + + memcpy(&k, ¶ms[i], sizeof(k)); + x ^= k; + acc ^= v128_clmul_cross(x); + } + + memcpy(&ret, &acc, sizeof(ret)); + + /* Compress the final (potentially partial) pair. */ + { + uint64_t x, y, enh_hi, enh_lo; + + memcpy(&x, last_ptr, sizeof(x)); + last_ptr = (const char *)last_ptr + sizeof(x); + memcpy(&y, last_ptr, sizeof(y)); + + x += params[i]; + y += params[i + 1]; + mul128(x, y, &enh_hi, &enh_lo); + enh_hi += tag; + + ret.bits[0] ^= enh_lo; + ret.bits[1] ^= enh_hi ^ enh_lo; + } + + return ret; +} + +TEST_DEF void +oh_varblock_fprint(struct umash_oh dst[static restrict 2], + const uint64_t *restrict params, uint64_t tag, const void *restrict block, + size_t n_bytes) +{ + v128 acc = V128_ZERO; /* Base umash */ + v128 acc_shifted = V128_ZERO; /* Accumulates shifted values */ + v128 lrc; + /* The final block processes `remaining > 0` bytes. */ + size_t remaining = 1 + ((n_bytes - 1) % sizeof(v128)); + size_t end_full_pairs = (n_bytes - remaining) / sizeof(uint64_t); + const void *last_ptr = (const char *)block + n_bytes - sizeof(v128); + size_t i; + + lrc = v128_create(params[UMASH_OH_PARAM_COUNT], params[UMASH_OH_PARAM_COUNT + 1]); + for (i = 0; i < end_full_pairs; i += 2) { + v128 x, k; + + memcpy(&x, block, sizeof(x)); + block = (const char *)block + sizeof(x); + + memcpy(&k, ¶ms[i], sizeof(k)); + + x ^= k; + lrc ^= x; + + x = v128_clmul_cross(x); + + acc ^= x; + if (i + 2 >= end_full_pairs) + break; + + acc_shifted ^= x; + acc_shifted = v128_shift(acc_shifted); + } + + /* + * Update the LRC for the last chunk before treating it + * specially. + */ + { + v128 x, k; + + memcpy(&x, last_ptr, sizeof(x)); + memcpy(&k, ¶ms[end_full_pairs], sizeof(k)); + + lrc ^= x ^ k; + } + + acc_shifted ^= acc; + acc_shifted = v128_shift(acc_shifted); + + acc_shifted ^= v128_clmul_cross(lrc); + + memcpy(&dst[0], &acc, sizeof(dst[0])); + memcpy(&dst[1], &acc_shifted, sizeof(dst[1])); + + { + uint64_t x, y, kx, ky, enh_hi, enh_lo; + + memcpy(&x, last_ptr, sizeof(x)); + last_ptr = (const char *)last_ptr + sizeof(x); + memcpy(&y, last_ptr, sizeof(y)); + + kx = x + params[end_full_pairs]; + ky = y + params[end_full_pairs + 1]; + + mul128(kx, ky, &enh_hi, &enh_lo); + enh_hi += tag; + + enh_hi ^= enh_lo; + dst[0].bits[0] ^= enh_lo; + dst[0].bits[1] ^= enh_hi; + + dst[1].bits[0] ^= enh_lo; + dst[1].bits[1] ^= enh_hi; + } + + return; +} + +/** + * Returns `then` if `cond` is true, `otherwise` if false. + * + * This noise helps compiler emit conditional moves. + */ +static inline const void * +select_ptr(bool cond, const void *then, const void *otherwise) +{ + const char *ret; + +#if UMASH_INLINE_ASM + /* Force strict evaluation of both arguments. */ + __asm__("" ::"r"(then), "r"(otherwise)); +#endif + + ret = (cond) ? then : otherwise; + +#if UMASH_INLINE_ASM + /* And also force the result to be materialised with a blackhole. */ + __asm__("" : "+r"(ret)); +#endif + return ret; +} + +/** + * Short UMASH (<= 8 bytes). + */ +TEST_DEF inline uint64_t +vec_to_u64(const void *data, size_t n_bytes) +{ + const char zeros[2] = { 0 }; + uint32_t hi, lo; + + /* + * If there are at least 4 bytes to read, read the first 4 in + * `lo`, and the last 4 in `hi`. This covers the whole range, + * since `n_bytes` is at most 8. + */ + if (LIKELY(n_bytes >= sizeof(lo))) { + memcpy(&lo, data, sizeof(lo)); + memcpy(&hi, (const char *)data + n_bytes - sizeof(hi), sizeof(hi)); + } else { + /* 0 <= n_bytes < 4. Decode the size in binary. */ + uint16_t word; + uint8_t byte; + + /* + * If the size is odd, load the first byte in `byte`; + * otherwise, load in a zero. + */ + memcpy(&byte, select_ptr(n_bytes & 1, data, zeros), 1); + lo = byte; + + /* + * If the size is 2 or 3, load the last two bytes in `word`; + * otherwise, load in a zero. + */ + memcpy(&word, + select_ptr(n_bytes & 2, (const char *)data + n_bytes - 2, zeros), 2); + /* + * We have now read `bytes[0 ... n_bytes - 1]` + * exactly once without overwriting any data. + */ + hi = word; + } + + /* + * Mix `hi` with the `lo` bits: SplitMix64 seems to have + * trouble with the top 4 bits. + */ + return ((uint64_t)hi << 32) | (lo + hi); +} + +TEST_DEF uint64_t +umash_short(const uint64_t *params, uint64_t seed, const void *data, size_t n_bytes) +{ + uint64_t h; + + seed += params[n_bytes]; + h = vec_to_u64(data, n_bytes); + h ^= h >> 30; + h *= 0xbf58476d1ce4e5b9ULL; + h = (h ^ seed) ^ (h >> 27); + h *= 0x94d049bb133111ebULL; + h ^= h >> 31; + return h; +} + +static FN struct umash_fp +umash_fp_short(const uint64_t *params, uint64_t seed, const void *data, size_t n_bytes) +{ + struct umash_fp ret; + uint64_t h; + + ret.hash[0] = seed + params[n_bytes]; + ret.hash[1] = seed + params[n_bytes + OH_SHORT_HASH_SHIFT]; + + h = vec_to_u64(data, n_bytes); + h ^= h >> 30; + h *= 0xbf58476d1ce4e5b9ULL; + h ^= h >> 27; + +#define TAIL(i) \ + do { \ + ret.hash[i] ^= h; \ + ret.hash[i] *= 0x94d049bb133111ebULL; \ + ret.hash[i] ^= ret.hash[i] >> 31; \ + } while (0) + + TAIL(0); + TAIL(1); +#undef TAIL + + return ret; +} + +/** + * Rotates `x` left by `n` bits. + */ +static inline uint64_t +rotl64(uint64_t x, int n) +{ + + return (x << n) | (x >> (64 - n)); +} + +TEST_DEF inline uint64_t +finalize(uint64_t x) +{ + + return (x ^ rotl64(x, 8)) ^ rotl64(x, 33); +} + +TEST_DEF uint64_t +umash_medium(const uint64_t multipliers[static 2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + uint64_t enh_hi, enh_lo; + + { + uint64_t x, y; + + memcpy(&x, data, sizeof(x)); + memcpy(&y, (const char *)data + n_bytes - sizeof(y), sizeof(y)); + x += oh[0]; + y += oh[1]; + + mul128(x, y, &enh_hi, &enh_lo); + enh_hi += seed ^ n_bytes; + } + + enh_hi ^= enh_lo; + return finalize(horner_double_update( + /*acc=*/0, multipliers[0], multipliers[1], enh_lo, enh_hi)); +} + +static FN struct umash_fp +umash_fp_medium(const uint64_t multipliers[static 2][2], const uint64_t *oh, + uint64_t seed, const void *data, size_t n_bytes) +{ + struct umash_fp ret; + const uint64_t offset = seed ^ n_bytes; + uint64_t enh_hi, enh_lo; + union { + v128 v; + uint64_t u64[2]; + } mixed_lrc; + uint64_t lrc[2] = { oh[UMASH_OH_PARAM_COUNT], oh[UMASH_OH_PARAM_COUNT + 1] }; + uint64_t x, y; + uint64_t a, b; + + /* Expand the 9-16 bytes to 16. */ + memcpy(&x, data, sizeof(x)); + memcpy(&y, (const char *)data + n_bytes - sizeof(y), sizeof(y)); + + a = oh[0]; + b = oh[1]; + + lrc[0] ^= x ^ a; + lrc[1] ^= y ^ b; + mixed_lrc.v = v128_clmul(lrc[0], lrc[1]); + + a += x; + b += y; + + mul128(a, b, &enh_hi, &enh_lo); + enh_hi += offset; + enh_hi ^= enh_lo; + + ret.hash[0] = finalize(horner_double_update( + /*acc=*/0, multipliers[0][0], multipliers[0][1], enh_lo, enh_hi)); + + ret.hash[1] = finalize(horner_double_update(/*acc=*/0, multipliers[1][0], + multipliers[1][1], enh_lo ^ mixed_lrc.u64[0], enh_hi ^ mixed_lrc.u64[1])); + + return ret; +} + +TEST_DEF uint64_t +umash_long(const uint64_t multipliers[static 2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + uint64_t acc = 0; + + /* + * umash_long.inc defines this variable when the long input + * routine is enabled. + */ +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes >= UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + size_t n_block = n_bytes / BLOCK_SIZE; + const void *remaining; + + n_bytes %= BLOCK_SIZE; + remaining = (const char *)data + (n_block * BLOCK_SIZE); + acc = umash_multiple_blocks(acc, multipliers, oh, seed, data, n_block); + + data = remaining; + if (n_bytes == 0) + goto finalize; + + goto last_block; + } +#else + /* Avoid warnings about the unused labels. */ + if (0) { + goto last_block; + goto finalize; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + struct umash_oh compressed; + + compressed = oh_varblock(oh, seed, data, BLOCK_SIZE); + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + + acc = horner_double_update(acc, multipliers[0], multipliers[1], + compressed.bits[0], compressed.bits[1]); + } + +last_block: + /* Do the final block. */ + { + struct umash_oh compressed; + + seed ^= (uint8_t)n_bytes; + compressed = oh_varblock(oh, seed, data, n_bytes); + acc = horner_double_update(acc, multipliers[0], multipliers[1], + compressed.bits[0], compressed.bits[1]); + } + +finalize: + return finalize(acc); +} + +TEST_DEF struct umash_fp +umash_fp_long(const uint64_t multipliers[static 2][2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + struct umash_oh compressed[2]; + struct umash_fp ret; + uint64_t acc[2] = { 0, 0 }; + +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes >= UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + struct umash_fp poly = { .hash = { 0, 0 } }; + size_t n_block = n_bytes / BLOCK_SIZE; + const void *remaining; + + n_bytes %= BLOCK_SIZE; + remaining = (const char *)data + (n_block * BLOCK_SIZE); + poly = umash_fprint_multiple_blocks( + poly, multipliers, oh, seed, data, n_block); + + acc[0] = poly.hash[0]; + acc[1] = poly.hash[1]; + + data = remaining; + if (n_bytes == 0) + goto finalize; + + goto last_block; + } +#else + /* Avoid warnings about the unused labels. */ + if (0) { + goto last_block; + goto finalize; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + oh_varblock_fprint(compressed, oh, seed, data, BLOCK_SIZE); + +#define UPDATE(i) \ + acc[i] = horner_double_update(acc[i], multipliers[i][0], multipliers[i][1], \ + compressed[i].bits[0], compressed[i].bits[1]) + + UPDATE(0); + UPDATE(1); +#undef UPDATE + + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + } + +last_block: + oh_varblock_fprint(compressed, oh, seed ^ (uint8_t)n_bytes, data, n_bytes); + +#define FINAL(i) \ + do { \ + acc[i] = horner_double_update(acc[i], multipliers[i][0], \ + multipliers[i][1], compressed[i].bits[0], compressed[i].bits[1]); \ + } while (0) + + FINAL(0); + FINAL(1); +#undef FINAL + +finalize: + ret.hash[0] = finalize(acc[0]); + ret.hash[1] = finalize(acc[1]); + return ret; +} + +static FN bool +value_is_repeated(const uint64_t *values, size_t n, uint64_t needle) +{ + + for (size_t i = 0; i < n; i++) { + if (values[i] == needle) + return true; + } + + return false; +} + +FN bool +umash_params_prepare(struct umash_params *params) +{ + static const uint64_t modulo = (1UL << 61) - 1; + /* + * The polynomial parameters have two redundant fields (for + * the pre-squared multipliers). Use them as our source of + * extra entropy if needed. + */ + uint64_t buf[] = { params->poly[0][0], params->poly[1][0] }; + size_t buf_idx = 0; + +#define GET_RANDOM(DST) \ + do { \ + if (buf_idx >= ARRAY_SIZE(buf)) \ + return false; \ + \ + (DST) = buf[buf_idx++]; \ + } while (0) + + /* Check the polynomial multipliers: we don't want 0s. */ + for (size_t i = 0; i < ARRAY_SIZE(params->poly); i++) { + uint64_t f = params->poly[i][1]; + + while (true) { + /* + * Zero out bits and use rejection sampling to + * guarantee uniformity. + */ + f &= (1UL << 61) - 1; + if (f != 0 && f < modulo) + break; + + GET_RANDOM(f); + } + + /* We can work in 2**64 - 8 and reduce after the fact. */ + params->poly[i][0] = mul_mod_fast(f, f) % modulo; + params->poly[i][1] = f; + } + + /* Avoid repeated OH noise values. */ + for (size_t i = 0; i < ARRAY_SIZE(params->oh); i++) { + while (value_is_repeated(params->oh, i, params->oh[i])) + GET_RANDOM(params->oh[i]); + } + + return true; +} + +FN void +umash_params_derive(struct umash_params *params, uint64_t bits, const void *key) +{ + uint8_t umash_key[32] = "Do not use UMASH VS adversaries."; + + if (key != NULL) + memcpy(umash_key, key, sizeof(umash_key)); + + while (true) { + uint8_t nonce[8]; + + for (size_t i = 0; i < 8; i++) + nonce[i] = bits >> (8 * i); + + salsa20_stream(params, sizeof(*params), nonce, umash_key); + if (umash_params_prepare(params)) + return; + + /* + * This should practically never fail, so really + * shouldn't happen multiple times. If it does, an + * infinite loop is as good as anything else. + */ + bits++; + } +} + +/* + * Updates the polynomial state at the end of a block. + */ +static FN void +sink_update_poly(struct umash_sink *sink) +{ + uint64_t oh0, oh1; + + oh0 = sink->oh_acc.bits[0]; + oh1 = sink->oh_acc.bits[1]; + sink->poly_state[0].acc = horner_double_update(sink->poly_state[0].acc, + sink->poly_state[0].mul[0], sink->poly_state[0].mul[1], oh0, oh1); + + sink->oh_acc = (struct umash_oh) { .bits = { 0 } }; + if (sink->hash_wanted == 0) + return; + + oh0 = sink->oh_twisted.acc.bits[0]; + oh1 = sink->oh_twisted.acc.bits[1]; + sink->poly_state[1].acc = horner_double_update(sink->poly_state[1].acc, + sink->poly_state[1].mul[0], sink->poly_state[1].mul[1], oh0, oh1); + + sink->oh_twisted = + (struct umash_twisted_oh) { .lrc = { sink->oh[UMASH_OH_PARAM_COUNT], + sink->oh[UMASH_OH_PARAM_COUNT + 1] } }; + return; +} + +/* + * Updates the OH state with 16 bytes of data. If `final` is true, we + * are definitely consuming the last chunk in the input. + */ +static FN void +sink_consume_buf( + struct umash_sink *sink, const char buf[static INCREMENTAL_GRANULARITY], bool final) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + const size_t param = sink->oh_iter; + const uint64_t k0 = sink->oh[param]; + const uint64_t k1 = sink->oh[param + 1]; + uint64_t x, y; + + /* Use GPR loads to avoid forwarding stalls. */ + memcpy(&x, buf, sizeof(x)); + memcpy(&y, buf + sizeof(x), sizeof(y)); + + /* All but the last 16-byte chunk of each block goes through PH. */ + if (sink->oh_iter < UMASH_OH_PARAM_COUNT - 2 && !final) { + v128 acc, h, twisted_acc, prev; + uint64_t m0, m1; + + m0 = x ^ k0; + m1 = y ^ k1; + + memcpy(&acc, &sink->oh_acc, sizeof(acc)); + h = v128_clmul(m0, m1); + acc ^= h; + memcpy(&sink->oh_acc, &acc, sizeof(acc)); + + if (sink->hash_wanted == 0) + goto next; + + sink->oh_twisted.lrc[0] ^= m0; + sink->oh_twisted.lrc[1] ^= m1; + + memcpy(&twisted_acc, &sink->oh_twisted.acc, sizeof(twisted_acc)); + memcpy(&prev, sink->oh_twisted.prev, sizeof(prev)); + + twisted_acc ^= prev; + twisted_acc = v128_shift(twisted_acc); + memcpy(&sink->oh_twisted.acc, &twisted_acc, sizeof(twisted_acc)); + memcpy(&sink->oh_twisted.prev, &h, sizeof(h)); + } else { + /* The last chunk is combined with the size tag with ENH. */ + uint64_t tag = sink->seed ^ (uint8_t)(sink->block_size + sink->bufsz); + uint64_t enh_hi, enh_lo; + + mul128(x + k0, y + k1, &enh_hi, &enh_lo); + enh_hi += tag; + enh_hi ^= enh_lo; + + if (sink->hash_wanted != 0) { + union { + v128 vec; + uint64_t h[2]; + } lrc_hash; + uint64_t lrc0, lrc1; + uint64_t oh0, oh1; + uint64_t oh_twisted0, oh_twisted1; + + lrc0 = sink->oh_twisted.lrc[0] ^ x ^ k0; + lrc1 = sink->oh_twisted.lrc[1] ^ y ^ k1; + lrc_hash.vec = v128_clmul(lrc0, lrc1); + + oh_twisted0 = sink->oh_twisted.acc.bits[0]; + oh_twisted1 = sink->oh_twisted.acc.bits[1]; + + oh0 = sink->oh_acc.bits[0]; + oh1 = sink->oh_acc.bits[1]; + oh0 ^= oh_twisted0; + oh0 <<= 1; + oh1 ^= oh_twisted1; + oh1 <<= 1; + + oh0 ^= lrc_hash.h[0]; + oh1 ^= lrc_hash.h[1]; + sink->oh_twisted.acc.bits[0] = oh0 ^ enh_lo; + sink->oh_twisted.acc.bits[1] = oh1 ^ enh_hi; + } + + sink->oh_acc.bits[0] ^= enh_lo; + sink->oh_acc.bits[1] ^= enh_hi; + } + +next: + memmove(&sink->buf, buf, buf_begin); + sink->block_size += sink->bufsz; + sink->bufsz = 0; + sink->oh_iter += 2; + + if (sink->oh_iter == UMASH_OH_PARAM_COUNT || final) { + sink_update_poly(sink); + sink->block_size = 0; + sink->oh_iter = 0; + } + + return; +} + +/** + * Hashes full 256-byte blocks into a sink that just dumped its OH + * state in the toplevel polynomial hash and reset the block state. + */ +static FN size_t +block_sink_update(struct umash_sink *sink, const void *data, size_t n_bytes) +{ + size_t consumed = 0; + + assert(n_bytes >= BLOCK_SIZE); + assert(sink->bufsz == 0); + assert(sink->block_size == 0); + assert(sink->oh_iter == 0); + +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes > UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + /* + * We leave the last block (partial or not) for the + * caller: incremental hashing must save some state + * at the end of a block. + */ + size_t n_blocks = (n_bytes - 1) / BLOCK_SIZE; + + if (sink->hash_wanted != 0) { + const uint64_t multipliers[2][2] = { + [0][0] = sink->poly_state[0].mul[0], + [0][1] = sink->poly_state[0].mul[1], + [1][0] = sink->poly_state[1].mul[0], + [1][1] = sink->poly_state[1].mul[1], + }; + struct umash_fp poly = { + .hash[0] = sink->poly_state[0].acc, + .hash[1] = sink->poly_state[1].acc, + }; + + poly = umash_fprint_multiple_blocks( + poly, multipliers, sink->oh, sink->seed, data, n_blocks); + + sink->poly_state[0].acc = poly.hash[0]; + sink->poly_state[1].acc = poly.hash[1]; + } else { + sink->poly_state[0].acc = umash_multiple_blocks( + sink->poly_state[0].acc, sink->poly_state[0].mul, sink->oh, + sink->seed, data, n_blocks); + } + + return n_blocks * BLOCK_SIZE; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + /* + * Is this worth unswitching? Not obviously, given + * the amount of work in one OH block. + */ + if (sink->hash_wanted != 0) { + struct umash_oh hashes[2]; + + oh_varblock_fprint( + hashes, sink->oh, sink->seed, data, BLOCK_SIZE); + sink->oh_acc = hashes[0]; + sink->oh_twisted.acc = hashes[1]; + } else { + sink->oh_acc = + oh_varblock(sink->oh, sink->seed, data, BLOCK_SIZE); + } + + sink_update_poly(sink); + consumed += BLOCK_SIZE; + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + } + + return consumed; +} + +FN void +umash_sink_update(struct umash_sink *sink, const void *data, size_t n_bytes) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + size_t remaining = INCREMENTAL_GRANULARITY - sink->bufsz; + + DTRACE_PROBE4(libumash, umash_sink_update, sink, remaining, data, n_bytes); + + if (n_bytes < remaining) { + memcpy(&sink->buf[buf_begin + sink->bufsz], data, n_bytes); + sink->bufsz += n_bytes; + return; + } + + memcpy(&sink->buf[buf_begin + sink->bufsz], data, remaining); + data = (const char *)data + remaining; + n_bytes -= remaining; + /* We know we're hashing at least 16 bytes. */ + sink->large_umash = true; + sink->bufsz = INCREMENTAL_GRANULARITY; + + /* + * We can't compress a 16-byte buffer until we know whether + * data is coming: the last 16-byte chunk goes to `NH` instead + * of `PH`. We could try to detect when the buffer is the + * last chunk in a block and immediately go to `NH`, but it + * seems more robust to always let the stores settle before we + * read them, just in case the combination is bad for forwarding. + */ + if (n_bytes == 0) + return; + + sink_consume_buf(sink, sink->buf + buf_begin, /*final=*/false); + + while (n_bytes > INCREMENTAL_GRANULARITY) { + size_t consumed; + + if (sink->oh_iter == 0 && n_bytes > BLOCK_SIZE) { + consumed = block_sink_update(sink, data, n_bytes); + assert(consumed >= BLOCK_SIZE); + + /* + * Save the tail of the data we just consumed + * in `sink->buf[0 ... buf_begin - 1]`: the + * final digest may need those bytes for its + * redundant read. + */ + memcpy(sink->buf, + (const char *)data + (consumed - INCREMENTAL_GRANULARITY), + buf_begin); + } else { + consumed = INCREMENTAL_GRANULARITY; + sink->bufsz = INCREMENTAL_GRANULARITY; + sink_consume_buf(sink, data, /*final=*/false); + } + + n_bytes -= consumed; + data = (const char *)data + consumed; + } + + memcpy(&sink->buf[buf_begin], data, n_bytes); + sink->bufsz = n_bytes; + return; +} + +FN uint64_t +umash_full(const struct umash_params *params, uint64_t seed, int which, const void *data, + size_t n_bytes) +{ + + DTRACE_PROBE4(libumash, umash_full, params, which, data, n_bytes); + + /* + * We don't (yet) implement code that only evaluates the + * second hash. We don't currently use that logic, and it's + * about to become a bit more complex, so let's just go for a + * full fingerprint and take what we need. + * + * umash_full is also rarely used that way: usually we want + * either the main hash, or the full fingerprint. + */ + if (UNLIKELY(which != 0)) { + struct umash_fp fp; + + fp = umash_fprint(params, seed, data, n_bytes); + return fp.hash[1]; + } + + /* + * It's not that short inputs are necessarily more likely, but + * we want to make sure they fall through correctly to + * minimise latency. + */ + if (LIKELY(n_bytes <= sizeof(v128))) { + if (LIKELY(n_bytes <= sizeof(uint64_t))) + return umash_short(params->oh, seed, data, n_bytes); + + return umash_medium(params->poly[0], params->oh, seed, data, n_bytes); + } + + return umash_long(params->poly[0], params->oh, seed, data, n_bytes); +} + +FN struct umash_fp +umash_fprint( + const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes) +{ + + DTRACE_PROBE3(libumash, umash_fprint, params, data, n_bytes); + if (LIKELY(n_bytes <= sizeof(v128))) { + if (LIKELY(n_bytes <= sizeof(uint64_t))) + return umash_fp_short(params->oh, seed, data, n_bytes); + + return umash_fp_medium(params->poly, params->oh, seed, data, n_bytes); + } + + return umash_fp_long(params->poly, params->oh, seed, data, n_bytes); +} + +FN void +umash_init(struct umash_state *state, const struct umash_params *params, uint64_t seed, + int which) +{ + + which = (which == 0) ? 0 : 1; + DTRACE_PROBE3(libumash, umash_init, state, params, which); + + state->sink = (struct umash_sink) { + .poly_state[0] = { + .mul = { + params->poly[0][0], + params->poly[0][1], + }, + }, + .poly_state[1]= { + .mul = { + params->poly[1][0], + params->poly[1][1], + }, + }, + .oh = params->oh, + .hash_wanted = which, + .oh_twisted.lrc = { params->oh[UMASH_OH_PARAM_COUNT], + params->oh[UMASH_OH_PARAM_COUNT + 1] }, + .seed = seed, + }; + + return; +} + +FN void +umash_fp_init( + struct umash_fp_state *state, const struct umash_params *params, uint64_t seed) +{ + + DTRACE_PROBE2(libumash, umash_fp_init, state, params); + + state->sink = (struct umash_sink) { + .poly_state[0] = { + .mul = { + params->poly[0][0], + params->poly[0][1], + }, + }, + .poly_state[1]= { + .mul = { + params->poly[1][0], + params->poly[1][1], + }, + }, + .oh = params->oh, + .hash_wanted = 2, + .oh_twisted.lrc = { params->oh[UMASH_OH_PARAM_COUNT], + params->oh[UMASH_OH_PARAM_COUNT + 1] }, + .seed = seed, + }; + + return; +} + +/** + * Pumps any last block out of the incremental state. + */ +static FN void +digest_flush(struct umash_sink *sink) +{ + + if (sink->bufsz > 0) + sink_consume_buf(sink, &sink->buf[sink->bufsz], /*final=*/true); + return; +} + +/** + * Finalizes a digest out of `sink`'s current state. + * + * The `sink` must be `digest_flush`ed if it is a `large_umash`. + * + * @param index 0 to return the first (only, if hashing) value, 1 for the + * second independent value for fingerprinting. + */ +static FN uint64_t +digest(const struct umash_sink *sink, int index) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + const size_t shift = (index == 0) ? 0 : OH_SHORT_HASH_SHIFT; + + if (sink->large_umash) + return finalize(sink->poly_state[index].acc); + + if (sink->bufsz <= sizeof(uint64_t)) + return umash_short( + &sink->oh[shift], sink->seed, &sink->buf[buf_begin], sink->bufsz); + + return umash_medium(sink->poly_state[index].mul, sink->oh, sink->seed, + &sink->buf[buf_begin], sink->bufsz); +} + +static FN struct umash_fp +fp_digest_sink(const struct umash_sink *sink) +{ + struct umash_sink copy; + struct umash_fp ret; + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + + if (sink->large_umash) { + copy = *sink; + digest_flush(©); + sink = © + } else if (sink->bufsz <= sizeof(uint64_t)) { + return umash_fp_short( + sink->oh, sink->seed, &sink->buf[buf_begin], sink->bufsz); + } else { + const struct umash_params *params; + + /* + * Back out the params struct from our pointer to its + * `oh` member. + */ + params = (const void *)((const char *)sink->oh - + __builtin_offsetof(struct umash_params, oh)); + return umash_fp_medium(params->poly, sink->oh, sink->seed, + &sink->buf[buf_begin], sink->bufsz); + } + + for (size_t i = 0; i < ARRAY_SIZE(ret.hash); i++) + ret.hash[i] = digest(sink, i); + + return ret; +} + +FN uint64_t +umash_digest(const struct umash_state *state) +{ + struct umash_sink copy; + const struct umash_sink *sink = &state->sink; + + DTRACE_PROBE1(libumash, umash_digest, state); + + if (sink->hash_wanted == 1) { + struct umash_fp fp; + + fp = fp_digest_sink(sink); + return fp.hash[1]; + } + + if (sink->large_umash) { + copy = *sink; + digest_flush(©); + sink = © + } + + return digest(sink, 0); +} + +FN struct umash_fp +umash_fp_digest(const struct umash_fp_state *state) +{ + + DTRACE_PROBE1(libumash, umash_fp_digest, state); + return fp_digest_sink(&state->sink); +} diff --git a/tsl/src/import/umash.h b/tsl/src/import/umash.h new file mode 100644 index 00000000000..fcb742cd2d5 --- /dev/null +++ b/tsl/src/import/umash.h @@ -0,0 +1,286 @@ +#ifndef UMASH_H +#define UMASH_H +#include +#include +#include + +/** + * # UMASH: a non-cryptographic hash function with collision bounds + * + * SPDX-License-Identifier: MIT + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * + * UMASH is a fast (9-22 ns latency for inputs of 1-64 bytes and 22 + * GB/s peak throughput, on a 2.5 GHz Intel 8175M) 64-bit hash + * function with mathematically proven collision bounds: it is + * [ceil(s / 4096) * 2^{-55}]-almost-universal for inputs of s or + * fewer bytes. + * + * When that's not enough, UMASH can also generate a pair of 64-bit + * hashes in a single traversal. The resulting fingerprint reduces + * the collision probability to less than [ceil(s / 2^{26})^2 * 2^{-83}]; + * the probability that two distinct inputs receive the same + * fingerprint is less 2^{-83} for inputs up to 64 MB, and less than + * 2^{-70} as long as the inputs are shorter than 5 GB each. This + * expectation is taken over the randomly generated `umash_params`. + * If an attacker can infer the contents of these parameters, the + * bounds do not apply. + * + * ## Initialisation + * + * In order to use `UMASH`, one must first generate a `struct + * umash_params`; each such param defines a distinct `UMASH` function + * (a pair of such functions, in fact). Ideally, one would fill + * a struct with random bytes and call`umash_params_prepare`. + * + * - `umash_params_prepare`: attempts to convert the contents of + * randomly filled `struct umash_params` into a valid UMASH + * parameter struct (key). When the input consists of uniformly + * generated random bytes, the probability of failure is + * astronomically small. + * + * - `umash_params_derive`: deterministically constructs a `struct + * umash_params` from a 64-bit seed and an optional 32-byte secret. + * The seed and secret are expanded into random bytes with Salsa20; + * the resulting `umash_params` should be practically random, as + * long the seed or secret are unknown. + * + * ## Batch hashing and fingerprinting + * + * Once we have a `struct umash_params`, we can use `umash_full` or + * `umash_fprint` like regular hash functions. + * + * - `umash_full` can compute either of the two UMASH functions + * described by a `struct umash_params`. Its `seed` argument will + * change the output, but is not associated with any collision + * bound. + * + * - `umash_fprint` computes both `UMASH` functions described by a + * `struct umash_params`. `umash_fp::hash[0]` corresponds to + * calling `umash_full` with the same arguments and `which = 0`; + * `umash_fp::hash[1]` corresponds to `which = 1`. + * + * ## Incremental hashing and fingerprinting + * + * We can also compute UMASH values by feeding bytes incrementally. + * The result is guaranteed to the same as if we had buffered all the + * bytes and called `umash_full` or `umash_fprint`. + * + * - `umash_init` initialises a `struct umash_state` with the same + * parameters one would pass to `umash_full`. + * + * - `umash_digest` computes the value `umash_full` would return + * were it passed the arguments that were given to `umash_init`, + * and the bytes "fed" into the `umash_state`. + * + * - `umash_fp_init` initialises a `struct umash_fp_state` with the + * same parameters one would pass to `umash_fprint`. + * + * - `umash_fp_digest` computes the value `umash_fprint` would return + * for the bytes "fed" into the `umash_fp_state`. + * + * In both cases, one passes a pointer to `struct umash_state::sink` + * or `struct umash_fp_state::sink` to callees that wish to feed bytes + * into the `umash_state` or `umash_fp_state`. + * + * - `umash_sink_update` feeds a byte range to the `umash_sink` + * initialised by calling `umash_init` or `umash_fp_init`. The sink + * does not take ownership of anything and the input bytes may be + * overwritten or freed as soon as `umash_sink_update` returns. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { UMASH_OH_PARAM_COUNT = 32, UMASH_OH_TWISTING_COUNT = 2 }; + +/** + * A single UMASH params struct stores the parameters for a pair of + * independent `UMASH` functions. + */ +struct umash_params { + /* + * Each uint64_t[2] array consists of {f^2, f}, where f is a + * random multiplier in mod 2**61 - 1. + */ + uint64_t poly[2][2]; + /* + * The second (twisted) OH function uses an additional + * 128-bit constant stored in the last two elements. + */ + uint64_t oh[UMASH_OH_PARAM_COUNT + UMASH_OH_TWISTING_COUNT]; +}; + +/** + * A fingerprint consists of two independent `UMASH` hash values. + */ +struct umash_fp { + uint64_t hash[2]; +}; + +/** + * This struct holds the state for incremental UMASH hashing or + * fingerprinting. + * + * A sink owns no allocation, and simply borrows a pointer to its + * `umash_params`. It can be byte-copied to snapshot its state. + * + * The layout works best with alignment to 64 bytes, but does not + * require it. + */ +struct umash_sink { + /* + * We incrementally maintain two states when fingerprinting. + * When hashing, only the first `poly_state` and `oh_acc` + * entries are active. + */ + struct { + uint64_t mul[2]; /* Multiplier, and multiplier^2. */ + uint64_t acc; /* Current Horner accumulator. */ + } poly_state[2]; + + /* + * We write new bytes to the second half, and keep the previous + * 16 byte chunk in the first half. + * + * We may temporarily have a full 16-byte buffer in the second half: + * we must know if the first 16 byte chunk is the first of many, or + * the whole input. + */ + char buf[2 * 16]; + + /* The next 64 bytes are accessed in the `OH` inner loop. */ + + /* key->oh. */ + const uint64_t *oh; + + /* oh_iter tracks where we are in the inner loop, times 2. */ + uint32_t oh_iter; + uint8_t bufsz; /* Write pointer in `buf + 16`. */ + uint8_t block_size; /* Current OH block size, excluding `bufsz`. */ + bool large_umash; /* True once we definitely have >= 16 bytes. */ + /* + * 0 if we're computing the first umash, 1 for the second, and + * 2 for a fingerprint. + * + * In practice, we treat 1 and 2 the same (always compute a + * full fingerprint), and return only the second half if we + * only want that half. + */ + uint8_t hash_wanted; + + /* Accumulators for the current OH value. */ + struct umash_oh { + uint64_t bits[2]; + } oh_acc; + struct umash_twisted_oh { + uint64_t lrc[2]; + uint64_t prev[2]; + struct umash_oh acc; + } oh_twisted; + + uint64_t seed; +}; + +/** + * The `umash_state` struct wraps a sink in a type-safe interface: we + * don't want to try and extract a fingerprint from a sink configured + * for hashing. + */ +struct umash_state { + struct umash_sink sink; +}; + +/** + * Similarly, the `umash_fp_state` struct wraps a sink from which we + * should extract a fingerprint. + */ +struct umash_fp_state { + struct umash_sink sink; +}; + +/** + * Converts a `umash_params` struct filled with random values into + * something usable by the UMASH functions below. + * + * When it succeeds, this function is idempotent. Failure happens + * with probability < 2**-110 is `params` is filled with uniformly + * distributed random bits. That's an astronomically unlikely event, + * and most likely signals an issue with the caller's (pseudo-)random + * number generator. + * + * @return false on failure, probably because the input was not random. + */ +bool umash_params_prepare(struct umash_params *params); + +/** + * Deterministically derives a `umash_params` struct from `bits` and + * `key`. The `bits` values do not have to be particularly well + * distributed, and can be generated sequentially. + * + * @param key a pointer to exactly 32 secret bytes. NULL will be + * replaced with "Do not use UMASH VS adversaries.", the default + * UMASH secret. + */ +void umash_params_derive(struct umash_params *, uint64_t bits, const void *key); + +/** + * Updates a `umash_sink` to take into account `data[0 ... n_bytes)`. + */ +void umash_sink_update(struct umash_sink *, const void *data, size_t n_bytes); + +/** + * Computes the UMASH hash of `data[0 ... n_bytes)`. + * + * Randomly generated `param` lead to independent UMASH values and + * associated worst-case collision bounds; changing the `seed` comes + * with no guarantee. + * + * @param which 0 to compute the first UMASH defined by `params`, 1 + * for the second. + */ +uint64_t umash_full(const struct umash_params *params, uint64_t seed, int which, + const void *data, size_t n_bytes); + +/** + * Computes the UMASH fingerprint of `data[0 ... n_bytes)`. + * + * Randomly generated `param` lead to independent UMASH values and + * associated worst-case collision bounds; changing the `seed` comes + * with no guarantee. + */ +struct umash_fp umash_fprint( + const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes); + +/** + * Prepares a `umash_state` for computing the `which`th UMASH function in + * `params`. + */ +void umash_init( + struct umash_state *, const struct umash_params *params, uint64_t seed, int which); + +/** + * Returns the UMASH value for the bytes that have been + * `umash_sink_update`d into the state. + */ +uint64_t umash_digest(const struct umash_state *); + +/** + * Prepares a `umash_fp_state` for computing the UMASH fingerprint in + * `params`. + */ +void umash_fp_init( + struct umash_fp_state *, const struct umash_params *params, uint64_t seed); + +/** + * Returns the UMASH fingerprint for the bytes that have been + * `umash_sink_update`d into the state. + */ +struct umash_fp umash_fp_digest(const struct umash_fp_state *); + +#ifdef __cplusplus +} +#endif +#endif /* !UMASH_H */ diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 67abf266b45..1d8085093f6 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -17,6 +17,8 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; typedef struct HashingStrategy HashingStrategy; +struct umash_params; + typedef struct HashingStrategy { char *explain_name; @@ -79,6 +81,7 @@ typedef struct GroupingPolicyHash */ void *table; HashingStrategy strategy; + struct umash_params *umash_params; /* * Temporary key storages. Some hashing strategies need to put the key in a diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 71dba600050..1cc9dc817bd 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -18,6 +18,13 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "import/umash.h" + +#define UMASH +#define ABBREV_KEY_TYPE struct umash_fp +#define KEY_HASH(X) (X.hash[0]) +#define KEY_EQUAL(a, b) (a.hash[0] == b.hash[0] && a.hash[1] == b.hash[1]) + static pg_attribute_always_inline void serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, void *restrict abbrev_key_ptr, bool *restrict valid) @@ -25,7 +32,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, GroupingPolicyHash *policy = config.policy; text **restrict full_key = (text **) full_key_ptr; - text **restrict abbrev_key = (text **) abbrev_key_ptr; + ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; const int num_columns = config.num_grouping_columns; @@ -246,11 +253,15 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, */ *valid = true; - *abbrev_key = *full_key; + *abbrev_key = umash_fprint(config.policy->umash_params, + /* seed = */ -1ull, + serialized_key_storage, + num_bytes); } -static pg_attribute_always_inline text * -serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, text *abbrev_key) +static pg_attribute_always_inline ABBREV_KEY_TYPE +serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, + ABBREV_KEY_TYPE abbrev_key) { /* * We will store this key so we have to consume the temporary storage that @@ -260,7 +271,7 @@ serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, text * policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(abbrev_key); + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(full_key); return abbrev_key; } @@ -330,11 +341,6 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl #define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized -#define KEY_HASH(X) hash_bytes_view((BytesView){ .len = VARSIZE_4B(X), .data = (uint8 *) (X) }) -#define KEY_EQUAL(a, b) \ - (VARSIZE_4B(a) == VARSIZE_4B(b) && \ - memcmp(VARDATA_4B(a), VARDATA_4B(b), VARSIZE_4B(a) - VARHDRSZ) == 0) -#define STORE_HASH #define FULL_KEY_TYPE text * -#define ABBREV_KEY_TYPE text * + #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index bb72b3815f6..2e05e2a8e7b 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -18,6 +18,11 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "import/umash.h" + +#define UMASH +#define ABBREV_KEY_TYPE struct umash_fp + static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) { @@ -35,7 +40,7 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, Assert(config.policy->num_grouping_columns == 1); BytesView *restrict full_key = (BytesView *) full_key_ptr; - BytesView *restrict abbrev_key = (BytesView *) abbrev_key_ptr; + ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { @@ -71,11 +76,15 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } DEBUG_PRINT("\n"); - *abbrev_key = *full_key; + *abbrev_key = umash_fprint(config.policy->umash_params, + /* seed = */ -1ull, + full_key->data, + full_key->len); } -static pg_attribute_always_inline BytesView -single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, BytesView abbrev_key) +static pg_attribute_always_inline ABBREV_KEY_TYPE +single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, + ABBREV_KEY_TYPE abbrev_key) { const int total_bytes = full_key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); @@ -83,7 +92,7 @@ single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, B memcpy(VARDATA(stored), full_key.data, full_key.len); full_key.data = (uint8 *) VARDATA(stored); gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); - return full_key; + return abbrev_key; } static pg_attribute_always_inline void @@ -318,13 +327,12 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #define EXPLAIN_NAME "single text" #define KEY_VARIANT single_text -#define KEY_HASH(X) hash_bytes_view(X) -#define KEY_EQUAL(a, b) (a.len == b.len && memcmp(a.data, b.data, a.len) == 0) -#define STORE_HASH #define FULL_KEY_TYPE BytesView -#define ABBREV_KEY_TYPE BytesView #define HAVE_PREPARE_FUNCTION #include "hash_single_helper.c" +#define KEY_HASH(X) (X.hash[0]) +#define KEY_EQUAL(a, b) (a.hash[0] == b.hash[0] && a.hash[1] == b.hash[1]) + #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 3f4f37e7dfb..8a3c67d4cf5 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -4,6 +4,8 @@ * LICENSE-TIMESCALE for a copy of the license. */ +#include "import/umash.h" + #define FUNCTION_NAME_HELPER2(X, Y) X##_##Y #define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) @@ -33,7 +35,7 @@ typedef struct #define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) -#define SH_KEY_TYPE FULL_KEY_TYPE +#define SH_KEY_TYPE ABBREV_KEY_TYPE #define SH_KEY abbrev_key #define SH_HASH_KEY(tb, key) KEY_HASH(key) #define SH_EQUAL(tb, a, b) KEY_EQUAL(a, b) @@ -243,6 +245,10 @@ static void FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) { policy->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); +#ifdef UMASH + policy->umash_params = palloc0(sizeof(struct umash_params)); + umash_params_derive(policy->umash_params, 0xabcdef1234567890ull, NULL); +#endif } HashingStrategy FUNCTION_NAME(strategy) = { @@ -266,8 +272,10 @@ HashingStrategy FUNCTION_NAME(strategy) = { #undef STORE_HASH #undef CHECK_PREVIOUS_KEY #undef FULL_KEY_TYPE +#undef ABBREV_KEY_TYPE #undef DATUM_TO_FULL_KEY #undef FULL_KEY_TO_DATUM +#undef UMASH #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER From d5cb87dac0e4b8f221448a724ccaa46fb822179d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:20:07 +0100 Subject: [PATCH 132/242] benchmark hash grouping with umash abbreviated keys (2024-11-15 no. 9) From 40824ef4ecf9dfe403c67cb49f707c7922a12dde Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 15 Nov 2024 12:22:22 +0100 Subject: [PATCH 133/242] fix compilation w/o crc --- tsl/src/nodes/vector_agg/hash_single_fixed_2.c | 2 +- tsl/src/nodes/vector_agg/hash_single_fixed_4.c | 2 +- tsl/src/nodes/vector_agg/hash_single_fixed_8.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 6998771c761..0e66f9275ac 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -25,7 +25,7 @@ #define FULL_KEY_TO_DATUM Int16GetDatum #define ABBREVIATE(X) (X) -#define KEY_HASH(X) hash64_crc(X) +#define KEY_HASH(X) HASH64(X) #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index 2880f9655b8..1b16bc4ac5f 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -25,7 +25,7 @@ #define FULL_KEY_TO_DATUM Int32GetDatum #define ABBREVIATE(X) (X) -#define KEY_HASH(X) hash64_crc(X) +#define KEY_HASH(X) HASH64(X) #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index 3d0973d6cc8..876bd9a7a09 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -25,7 +25,7 @@ #define FULL_KEY_TO_DATUM Int64GetDatum #define ABBREVIATE(X) (X) -#define KEY_HASH(X) hash64_crc(X) +#define KEY_HASH(X) HASH64(X) #include "single_fixed_key_impl.c" From 47d384cb3551536075d67d591eeac6dce60c36bf Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 15 Nov 2024 14:50:51 +0100 Subject: [PATCH 134/242] shorter abbreviated umash key --- .github/gh_matrix_builder.py | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 11 ++++++++- tsl/src/nodes/vector_agg/hash_serialized.c | 22 ++++++++++++------ tsl/src/nodes/vector_agg/hash_single_text.c | 23 ++++++++++++------- .../vector_agg/hash_table_functions_impl.c | 8 +++---- 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/.github/gh_matrix_builder.py b/.github/gh_matrix_builder.py index 6d9a8606a40..2ea58bf5437 100755 --- a/.github/gh_matrix_builder.py +++ b/.github/gh_matrix_builder.py @@ -78,7 +78,7 @@ def build_debug_config(overrides): "ignored_tests": default_ignored_tests, "name": "Debug", "os": "ubuntu-22.04", - "pg_extra_args": "--enable-debug --enable-cassert --with-llvm LLVM_CONFIG=llvm-config-14", + "pg_extra_args": "CFLAGS=-march=native --enable-debug --enable-cassert --with-llvm LLVM_CONFIG=llvm-config-14", "pg_extensions": "postgres_fdw test_decoding pageinspect pgstattuple", "pginstallcheck": True, "tsdb_build_args": "-DWARNINGS_AS_ERRORS=ON -DREQUIRE_ALL_TESTS=ON", diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 6e854669804..774e36a4a81 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -464,6 +464,15 @@ gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + if (policy->last_used_key_index > UINT32_MAX - GLOBAL_MAX_ROWS_PER_COMPRESSION) + { + /* + * The max valid key index is UINT32_MAX, so we have to spill if the next + * batch can possibly lead to key index overflow. + */ + return true; + } + /* * Don't grow the hash table cardinality too much, otherwise we become bound * by memory reads. In general, when this first stage of grouping doesn't @@ -471,7 +480,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - return policy->strategy.get_size_bytes(policy->table) > 128 * 1024; + return policy->strategy.get_size_bytes(policy->table) > 512 * 1024; } static bool diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 1cc9dc817bd..6049f3dbb4f 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -20,10 +20,16 @@ #include "import/umash.h" +struct abbrev_key +{ + uint32 hash; + uint64 rest; +} pg_attribute_packed; + #define UMASH -#define ABBREV_KEY_TYPE struct umash_fp -#define KEY_HASH(X) (X.hash[0]) -#define KEY_EQUAL(a, b) (a.hash[0] == b.hash[0] && a.hash[1] == b.hash[1]) +#define ABBREV_KEY_TYPE struct abbrev_key +#define KEY_HASH(X) (X.hash) +#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) static pg_attribute_always_inline void serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, @@ -253,10 +259,12 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, */ *valid = true; - *abbrev_key = umash_fprint(config.policy->umash_params, - /* seed = */ -1ull, - serialized_key_storage, - num_bytes); + struct umash_fp fp = umash_fprint(config.policy->umash_params, + /* seed = */ -1ull, + serialized_key_storage, + num_bytes); + abbrev_key->hash = fp.hash[0] & (~(uint32) 0); + abbrev_key->rest = fp.hash[1]; } static pg_attribute_always_inline ABBREV_KEY_TYPE diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 2e05e2a8e7b..cdac9262ea8 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -20,8 +20,16 @@ #include "import/umash.h" +struct abbrev_key +{ + uint32 hash; + uint64 rest; +} __attribute__((packed)); + #define UMASH -#define ABBREV_KEY_TYPE struct umash_fp +#define ABBREV_KEY_TYPE struct abbrev_key +#define KEY_HASH(X) (X.hash) +#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) @@ -76,10 +84,12 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } DEBUG_PRINT("\n"); - *abbrev_key = umash_fprint(config.policy->umash_params, - /* seed = */ -1ull, - full_key->data, - full_key->len); + struct umash_fp fp = umash_fprint(config.policy->umash_params, + /* seed = */ -1ull, + full_key->data, + full_key->len); + abbrev_key->hash = fp.hash[0] & (~ (uint32) 0); + abbrev_key->rest = fp.hash[1]; } static pg_attribute_always_inline ABBREV_KEY_TYPE @@ -332,7 +342,4 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #include "hash_single_helper.c" -#define KEY_HASH(X) (X.hash[0]) -#define KEY_EQUAL(a, b) (a.hash[0] == b.hash[0] && a.hash[1] == b.hash[1]) - #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 8a3c67d4cf5..ddc295a643d 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -18,6 +18,9 @@ */ typedef struct { + /* Key index 0 is invalid. */ + uint32 key_index; + ABBREV_KEY_TYPE abbrev_key; #ifdef STORE_HASH @@ -27,12 +30,9 @@ typedef struct */ uint32 hash; #endif - - /* Key index 0 is invalid. */ - uint32 key_index; } FUNCTION_NAME(entry); -#define SH_FILLFACTOR (0.5) +// #define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) #define SH_KEY_TYPE ABBREV_KEY_TYPE From 0c19ff76ce5f33e24ff47b0d6266f275900ce524 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:02:40 +0100 Subject: [PATCH 135/242] don't use bitwise operations on bool --- tsl/src/compression/algorithms/dictionary.c | 2 +- tsl/src/nodes/decompress_chunk/vector_predicates.h | 4 ++-- tsl/src/nodes/vector_agg/function/int24_sum_single.c | 4 ++-- .../nodes/vector_agg/function/minmax_arithmetic_single.c | 2 +- tsl/src/nodes/vector_agg/function/sum_float_single.c | 6 +++--- tsl/src/nodes/vector_agg/grouping_policy_hash.h | 3 ++- tsl/src/nodes/vector_agg/hash_single_text.c | 7 ++++--- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/tsl/src/compression/algorithms/dictionary.c b/tsl/src/compression/algorithms/dictionary.c index a090447c933..d01dec6c703 100644 --- a/tsl/src/compression/algorithms/dictionary.c +++ b/tsl/src/compression/algorithms/dictionary.c @@ -449,7 +449,7 @@ tsl_text_dictionary_decompress_all(Datum compressed, Oid element_type, MemoryCon bool have_incorrect_index = false; for (uint32 i = 0; i < n_notnull; i++) { - have_incorrect_index |= indices[i] >= (int16) header->num_distinct; + have_incorrect_index = have_incorrect_index || indices[i] >= (int16) header->num_distinct; } CheckCompressedData(!have_incorrect_index); diff --git a/tsl/src/nodes/decompress_chunk/vector_predicates.h b/tsl/src/nodes/decompress_chunk/vector_predicates.h index 0fd3fa6f005..cace90dbc44 100644 --- a/tsl/src/nodes/decompress_chunk/vector_predicates.h +++ b/tsl/src/nodes/decompress_chunk/vector_predicates.h @@ -32,8 +32,8 @@ get_vector_qual_summary(uint64 *restrict qual_result, size_t n_rows) bool all_rows_pass = true; for (size_t i = 0; i < n_rows / 64; i++) { - any_rows_pass |= (qual_result[i] != 0); - all_rows_pass &= (~qual_result[i] == 0); + any_rows_pass = any_rows_pass || (qual_result[i] != 0); + all_rows_pass = all_rows_pass && (~qual_result[i] == 0); } if (n_rows % 64 != 0) diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index 05a6639e93f..95320240e75 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -39,7 +39,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui { const bool row_ok = arrow_row_is_valid(filter, row); batch_sum += values[row] * row_ok; - have_result |= row_ok; + have_result = have_result || row_ok; } if (unlikely(pg_add_s64_overflow(state->result, batch_sum, &state->result))) @@ -48,7 +48,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("bigint out of range"))); } - state->isvalid |= have_result; + state->isvalid = state->isvalid || have_result; } static pg_attribute_always_inline void diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index e4b94abdf21..e64dab8e20c 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -30,7 +30,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui isnan((double) new_value)); outer_result = do_replace ? new_value : outer_result; - outer_isvalid |= do_replace; + outer_isvalid = outer_isvalid || do_replace; } state->isvalid = outer_isvalid; diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index dd97b639d89..e6f607bf534 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -54,7 +54,7 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui } u = { .f = values[row] }; \ u.m &= row_valid ? ~(MASKTYPE) 0 : (MASKTYPE) 0; \ *dest += u.f; \ - *have_result |= row_valid; + *have_result = *have_result || row_valid; INNER_LOOP } @@ -70,13 +70,13 @@ FUNCTION_NAME(vector_impl)(void *agg_state, int n, const CTYPE *values, const ui for (int i = 1; i < UNROLL_SIZE; i++) { sum_accu[0] += sum_accu[i]; - have_result_accu[0] |= have_result_accu[i]; + have_result_accu[0] = have_result_accu[0] || have_result_accu[i]; } #undef UNROLL_SIZE #undef INNER_LOOP FloatSumState *state = (FloatSumState *) agg_state; - state->isvalid |= have_result_accu[0]; + state->isvalid = state->isvalid || have_result_accu[0]; state->result += sum_accu[0]; } diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 1d8085093f6..cb4c07a97c4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -249,7 +249,8 @@ build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_sta for (int i = 0; i < policy->num_grouping_columns; i++) { - config.have_scalar_columns |= + config.have_scalar_columns = + config.have_scalar_columns || (policy->grouping_column_values[i].decompression_type == DT_Scalar || policy->grouping_column_values[i].buffers[0] != NULL); } diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index cdac9262ea8..faaf419e6bb 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -88,7 +88,7 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, /* seed = */ -1ull, full_key->data, full_key->len); - abbrev_key->hash = fp.hash[0] & (~ (uint32) 0); + abbrev_key->hash = fp.hash[0] & (~(uint32) 0); abbrev_key->rest = fp.hash[1]; } @@ -175,7 +175,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * for (int inner = 0; inner < INNER_MAX; inner++) \ { \ const int16 index = ((int16 *) config.single_key.buffers[3])[outer * 64 + inner]; \ - tmp[index] |= (word & (1ull << inner)); \ + tmp[index] = tmp[index] || (word & (1ull << inner)); \ } INNER_LOOP(64) @@ -226,7 +226,8 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * const size_t batch_words = (batch_rows + 63) / 64; for (size_t i = 0; i < batch_words; i++) { - have_null_key |= + have_null_key = + have_null_key || (row_filter[i] & (~((uint64 *) config.single_key.buffers[0])[i])) != 0; } } From 010d5432f7abd4191d08c6a5c1009ee343fbc9d8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:42:25 +0100 Subject: [PATCH 136/242] incremental umash digest -- throughput much lower --- .../nodes/vector_agg/grouping_policy_hash.h | 2 +- tsl/src/nodes/vector_agg/hash_serialized.c | 145 ++++++++++++------ tsl/src/nodes/vector_agg/hash_single_text.c | 8 +- .../vector_agg/hash_table_functions_impl.c | 2 +- .../nodes/vector_agg/single_fixed_key_impl.c | 5 +- 5 files changed, 108 insertions(+), 54 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index cb4c07a97c4..c835fe9c1c9 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -225,7 +225,7 @@ typedef struct HashingConfig const CompressedColumnValues *grouping_column_values; bool have_scalar_columns; - GroupingPolicyHash *policy; + GroupingPolicyHash *restrict policy; uint32 *restrict result_key_indexes; } HashingConfig; diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 6049f3dbb4f..7b15b7e86b8 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -35,13 +35,103 @@ static pg_attribute_always_inline void serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, void *restrict abbrev_key_ptr, bool *restrict valid) { - GroupingPolicyHash *policy = config.policy; + *(text **) full_key_ptr = NULL; - text **restrict full_key = (text **) full_key_ptr; ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; const int num_columns = config.num_grouping_columns; + /* + * Loop through the grouping columns again and build the actual fingerprint. + */ + struct umash_fp_state fp_state; + umash_fp_init(&fp_state, config.policy->umash_params, /* seed = */ -1ull); + + for (int column_index = 0; column_index < num_columns; column_index++) + { + const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; + + if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) + { + const bool is_valid = !*column_values->output_isnull; + umash_sink_update(&fp_state.sink, &is_valid, sizeof(is_valid)); + if (is_valid) + { + const GroupingColumn *def = &config.policy->grouping_columns[column_index]; + if (def->by_value) + { + umash_sink_update(&fp_state.sink, + column_values->output_value, + def->value_bytes); + } + else + { + const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); + umash_sink_update(&fp_state.sink, + &value_bytes, sizeof(value_bytes)); + umash_sink_update(&fp_state.sink, + VARDATA_ANY(DatumGetPointer(*column_values->output_value)), + value_bytes); + } + } + continue; + } + + const bool is_valid = + !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); + + umash_sink_update(&fp_state.sink, &is_valid, sizeof(is_valid)); + + if (!is_valid) + { + continue; + } + + if (column_values->decompression_type > 0) + { + umash_sink_update(&fp_state.sink, + ((char *) column_values->buffers[1]) + + column_values->decompression_type * row, + column_values->decompression_type); + + continue; + } + + Assert(column_values->decompression_type == DT_ArrowText || + column_values->decompression_type == DT_ArrowTextDict); + + const uint32 data_row = column_values->decompression_type == DT_ArrowTextDict ? + ((int16 *) column_values->buffers[3])[row] : + row; + const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; + + umash_sink_update(&fp_state.sink, + &value_bytes, + sizeof(value_bytes)); + + umash_sink_update(&fp_state.sink, + &((uint8 *) column_values->buffers[2])[start], + value_bytes); + } + + /* + * The multi-column key is always considered non-null, and the null flags + * for the individual columns are stored in a bitmap that is part of the + * key. + */ + *valid = true; + + struct umash_fp fp = umash_fp_digest(&fp_state); + abbrev_key->hash = fp.hash[0] & (~(uint32) 0); + abbrev_key->rest = fp.hash[1]; +} + +static pg_attribute_always_inline ABBREV_KEY_TYPE +serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_TYPE abbrev_key) +{ + const int num_columns = config.num_grouping_columns; + size_t bitmap_bytes = (num_columns + 7) / 8; uint8 *restrict serialized_key_validity_bitmap; @@ -119,23 +209,13 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, */ num_bytes += bitmap_bytes; - /* - * Use temporary storage for the new key, reallocate if it's too small. - */ - if (num_bytes > policy->num_tmp_key_storage_bytes) - { - if (policy->tmp_key_storage != NULL) - { - pfree(policy->tmp_key_storage); - } - policy->tmp_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); - policy->num_tmp_key_storage_bytes = num_bytes; - } - uint8 *restrict serialized_key_storage = policy->tmp_key_storage; + uint8 *restrict serialized_key_storage = + MemoryContextAlloc(config.policy->key_body_mctx, num_bytes); /* * Have to memset the key with zeros, so that the alignment bytes are zeroed * out. + * FIXME no alignment anymore, remove? */ memset(serialized_key_storage, 0, num_bytes); @@ -212,6 +292,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { /* Short varlena, unaligned. */ + /* FIXME only storing new keys now, remove? */ const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); offset += VARHDRSZ_SHORT; @@ -241,7 +322,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, offset += bitmap_bytes; Assert(offset == num_bytes); - DEBUG_PRINT("key is %d bytes: ", offset); + DEBUG_PRINT("new key is %d bytes: ", offset); for (size_t i = 0; i < offset; i++) { DEBUG_PRINT("%.2x.", serialized_key_storage[i]); @@ -250,36 +331,8 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, SET_VARSIZE(serialized_key_storage, offset); - *full_key = (text *) serialized_key_storage; - - /* - * The multi-column key is always considered non-null, and the null flags - * for the individual columns are stored in a bitmap that is part of the - * key. - */ - *valid = true; - - struct umash_fp fp = umash_fprint(config.policy->umash_params, - /* seed = */ -1ull, - serialized_key_storage, - num_bytes); - abbrev_key->hash = fp.hash[0] & (~(uint32) 0); - abbrev_key->rest = fp.hash[1]; -} - -static pg_attribute_always_inline ABBREV_KEY_TYPE -serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, - ABBREV_KEY_TYPE abbrev_key) -{ - /* - * We will store this key so we have to consume the temporary storage that - * was used for it. The subsequent keys will need to allocate new memory. - */ - Assert(policy->tmp_key_storage == (void *) full_key); - policy->tmp_key_storage = NULL; - policy->num_tmp_key_storage_bytes = 0; - - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(full_key); + gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = + PointerGetDatum(serialized_key_storage); return abbrev_key; } diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index faaf419e6bb..9e69cfdab23 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -93,15 +93,15 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } static pg_attribute_always_inline ABBREV_KEY_TYPE -single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, - ABBREV_KEY_TYPE abbrev_key) +single_text_store_key(HashingConfig config, int row, BytesView full_key, ABBREV_KEY_TYPE abbrev_key) { const int total_bytes = full_key.len + VARHDRSZ; - text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); + text *restrict stored = (text *) MemoryContextAlloc(config.policy->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), full_key.data, full_key.len); full_key.data = (uint8 *) VARDATA(stored); - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); + gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = + PointerGetDatum(stored); return abbrev_key; } diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index ddc295a643d..e51778e2e8e 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -136,7 +136,7 @@ FUNCTION_NAME(fill_offsets_impl)( * New key, have to store it persistently. */ const int index = ++policy->last_used_key_index; - entry->abbrev_key = FUNCTION_NAME(store_key)(policy, full_key, abbrev_key); + entry->abbrev_key = FUNCTION_NAME(store_key)(config, row, full_key, abbrev_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index b599d22e160..e6ebf28aa2d 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -35,10 +35,11 @@ FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict full_key_pt } static pg_attribute_always_inline FULL_KEY_TYPE -FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE full_key, +FUNCTION_NAME(store_key)(HashingConfig config, int row, FULL_KEY_TYPE full_key, ABBREV_KEY_TYPE abbrev_key) { - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(full_key); + gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = + FULL_KEY_TO_DATUM(full_key); return abbrev_key; } From 3da89a0657d0c46ec938b8c2968ed8c27c3a9058 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:43:45 +0100 Subject: [PATCH 137/242] revert incremental umash digest --- tsl/src/nodes/vector_agg/hash_serialized.c | 145 ++++++------------ tsl/src/nodes/vector_agg/hash_single_text.c | 8 +- .../vector_agg/hash_table_functions_impl.c | 2 +- .../nodes/vector_agg/single_fixed_key_impl.c | 5 +- 4 files changed, 53 insertions(+), 107 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 7b15b7e86b8..6049f3dbb4f 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -35,103 +35,13 @@ static pg_attribute_always_inline void serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, void *restrict abbrev_key_ptr, bool *restrict valid) { - *(text **) full_key_ptr = NULL; + GroupingPolicyHash *policy = config.policy; + text **restrict full_key = (text **) full_key_ptr; ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; const int num_columns = config.num_grouping_columns; - /* - * Loop through the grouping columns again and build the actual fingerprint. - */ - struct umash_fp_state fp_state; - umash_fp_init(&fp_state, config.policy->umash_params, /* seed = */ -1ull); - - for (int column_index = 0; column_index < num_columns; column_index++) - { - const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; - - if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) - { - const bool is_valid = !*column_values->output_isnull; - umash_sink_update(&fp_state.sink, &is_valid, sizeof(is_valid)); - if (is_valid) - { - const GroupingColumn *def = &config.policy->grouping_columns[column_index]; - if (def->by_value) - { - umash_sink_update(&fp_state.sink, - column_values->output_value, - def->value_bytes); - } - else - { - const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); - umash_sink_update(&fp_state.sink, - &value_bytes, sizeof(value_bytes)); - umash_sink_update(&fp_state.sink, - VARDATA_ANY(DatumGetPointer(*column_values->output_value)), - value_bytes); - } - } - continue; - } - - const bool is_valid = - !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); - - umash_sink_update(&fp_state.sink, &is_valid, sizeof(is_valid)); - - if (!is_valid) - { - continue; - } - - if (column_values->decompression_type > 0) - { - umash_sink_update(&fp_state.sink, - ((char *) column_values->buffers[1]) + - column_values->decompression_type * row, - column_values->decompression_type); - - continue; - } - - Assert(column_values->decompression_type == DT_ArrowText || - column_values->decompression_type == DT_ArrowTextDict); - - const uint32 data_row = column_values->decompression_type == DT_ArrowTextDict ? - ((int16 *) column_values->buffers[3])[row] : - row; - const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; - const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; - - umash_sink_update(&fp_state.sink, - &value_bytes, - sizeof(value_bytes)); - - umash_sink_update(&fp_state.sink, - &((uint8 *) column_values->buffers[2])[start], - value_bytes); - } - - /* - * The multi-column key is always considered non-null, and the null flags - * for the individual columns are stored in a bitmap that is part of the - * key. - */ - *valid = true; - - struct umash_fp fp = umash_fp_digest(&fp_state); - abbrev_key->hash = fp.hash[0] & (~(uint32) 0); - abbrev_key->rest = fp.hash[1]; -} - -static pg_attribute_always_inline ABBREV_KEY_TYPE -serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_TYPE abbrev_key) -{ - const int num_columns = config.num_grouping_columns; - size_t bitmap_bytes = (num_columns + 7) / 8; uint8 *restrict serialized_key_validity_bitmap; @@ -209,13 +119,23 @@ serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_T */ num_bytes += bitmap_bytes; - uint8 *restrict serialized_key_storage = - MemoryContextAlloc(config.policy->key_body_mctx, num_bytes); + /* + * Use temporary storage for the new key, reallocate if it's too small. + */ + if (num_bytes > policy->num_tmp_key_storage_bytes) + { + if (policy->tmp_key_storage != NULL) + { + pfree(policy->tmp_key_storage); + } + policy->tmp_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); + policy->num_tmp_key_storage_bytes = num_bytes; + } + uint8 *restrict serialized_key_storage = policy->tmp_key_storage; /* * Have to memset the key with zeros, so that the alignment bytes are zeroed * out. - * FIXME no alignment anymore, remove? */ memset(serialized_key_storage, 0, num_bytes); @@ -292,7 +212,6 @@ serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_T if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { /* Short varlena, unaligned. */ - /* FIXME only storing new keys now, remove? */ const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); offset += VARHDRSZ_SHORT; @@ -322,7 +241,7 @@ serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_T offset += bitmap_bytes; Assert(offset == num_bytes); - DEBUG_PRINT("new key is %d bytes: ", offset); + DEBUG_PRINT("key is %d bytes: ", offset); for (size_t i = 0; i < offset; i++) { DEBUG_PRINT("%.2x.", serialized_key_storage[i]); @@ -331,8 +250,36 @@ serialized_store_key(HashingConfig config, int row, text *full_key, ABBREV_KEY_T SET_VARSIZE(serialized_key_storage, offset); - gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = - PointerGetDatum(serialized_key_storage); + *full_key = (text *) serialized_key_storage; + + /* + * The multi-column key is always considered non-null, and the null flags + * for the individual columns are stored in a bitmap that is part of the + * key. + */ + *valid = true; + + struct umash_fp fp = umash_fprint(config.policy->umash_params, + /* seed = */ -1ull, + serialized_key_storage, + num_bytes); + abbrev_key->hash = fp.hash[0] & (~(uint32) 0); + abbrev_key->rest = fp.hash[1]; +} + +static pg_attribute_always_inline ABBREV_KEY_TYPE +serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, + ABBREV_KEY_TYPE abbrev_key) +{ + /* + * We will store this key so we have to consume the temporary storage that + * was used for it. The subsequent keys will need to allocate new memory. + */ + Assert(policy->tmp_key_storage == (void *) full_key); + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(full_key); return abbrev_key; } diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index 9e69cfdab23..faaf419e6bb 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -93,15 +93,15 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } static pg_attribute_always_inline ABBREV_KEY_TYPE -single_text_store_key(HashingConfig config, int row, BytesView full_key, ABBREV_KEY_TYPE abbrev_key) +single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, + ABBREV_KEY_TYPE abbrev_key) { const int total_bytes = full_key.len + VARHDRSZ; - text *restrict stored = (text *) MemoryContextAlloc(config.policy->key_body_mctx, total_bytes); + text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), full_key.data, full_key.len); full_key.data = (uint8 *) VARDATA(stored); - gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = - PointerGetDatum(stored); + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); return abbrev_key; } diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index e51778e2e8e..ddc295a643d 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -136,7 +136,7 @@ FUNCTION_NAME(fill_offsets_impl)( * New key, have to store it persistently. */ const int index = ++policy->last_used_key_index; - entry->abbrev_key = FUNCTION_NAME(store_key)(config, row, full_key, abbrev_key); + entry->abbrev_key = FUNCTION_NAME(store_key)(policy, full_key, abbrev_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index e6ebf28aa2d..b599d22e160 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -35,11 +35,10 @@ FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict full_key_pt } static pg_attribute_always_inline FULL_KEY_TYPE -FUNCTION_NAME(store_key)(HashingConfig config, int row, FULL_KEY_TYPE full_key, +FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE full_key, ABBREV_KEY_TYPE abbrev_key) { - gp_hash_output_keys(config.policy, config.policy->last_used_key_index)[0] = - FULL_KEY_TO_DATUM(full_key); + gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(full_key); return abbrev_key; } From dc2ec93a0a0255ad9451e8007e6767a02c21739f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:06:51 +0100 Subject: [PATCH 138/242] inline array construction --- tsl/src/nodes/vector_agg/exec.c | 32 +++++++++++++++++++ .../function/float48_accum_single.c | 24 +++++++------- .../function/int24_avg_accum_templates.c | 16 ++++++---- tsl/src/nodes/vector_agg/hash_serialized.c | 3 ++ 4 files changed, 57 insertions(+), 18 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 63a158adfa0..7d5f7cadf30 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -55,6 +55,25 @@ get_input_offset(DecompressChunkState *decompress_state, Var *var) return index; } +static int +grouping_column_comparator(const void *a_ptr, const void *b_ptr) +{ + const GroupingColumn *a = (GroupingColumn *) a_ptr; + const GroupingColumn *b = (GroupingColumn *) b_ptr; + + if (a->value_bytes == b->value_bytes) + { + return 0; + } + + if (a->value_bytes > b->value_bytes) + { + return -1; + } + + return 1; +} + static void vector_agg_begin(CustomScanState *node, EState *estate, int eflags) { @@ -209,6 +228,19 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } } + /* + * Sort grouping columns by descending column size, variable size last. This + * helps improve branch predictability and key packing when we use hashed + * serialized multi-column keys. + */ + qsort(vector_agg_state->grouping_columns, + vector_agg_state->num_grouping_columns, + sizeof(GroupingColumn), + grouping_column_comparator); + + /* + * Determine which grouping policy we are going to use. + */ bool all_segmentby = true; for (int i = 0; i < vector_agg_state->num_grouping_columns; i++) { diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index deb2998d784..9c27d8f6da3 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -69,9 +69,17 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) { FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - Datum transdatums[3] = { - Float8GetDatumFast(state->N), - Float8GetDatumFast(state->Sx), + const size_t nbytes = 3 * sizeof(float8) + ARR_OVERHEAD_NONULLS(/* ndims = */ 1); + ArrayType *result = palloc(nbytes); + SET_VARSIZE(result, nbytes); + result->ndim = 1; + result->dataoffset = 0; + result->elemtype = FLOAT8OID; + ARR_DIMS(result)[0] = 3; + ARR_LBOUND(result)[0] = 1; + ((Datum *) ARR_DATA_PTR(result))[0] = Float8GetDatumFast(state->N); + ((Datum *) ARR_DATA_PTR(result))[1] = Float8GetDatumFast(state->Sx); + ((Datum *) ARR_DATA_PTR(result))[2] = /* * Sxx should be NaN if any of the inputs are infinite or NaN. This is * checked by float8_combine even if it's not used for the actual @@ -81,15 +89,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) #ifdef NEED_SXX + state->Sxx #endif - ), - }; - - ArrayType *result = construct_array(transdatums, - 3, - FLOAT8OID, - sizeof(float8), - FLOAT8PASSBYVAL, - TYPALIGN_DOUBLE); + ); *out_result = PointerGetDatum(result); *out_isnull = false; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c index 518a7491aab..2e6db8952e9 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c @@ -42,13 +42,17 @@ int24_avg_accum_emit(void *agg_state, Datum *out_result, bool *out_isnull) { Int24AvgAccumState *state = (Int24AvgAccumState *) agg_state; - Datum transdatums[2] = { - Int64GetDatumFast(state->count), - Int64GetDatumFast(state->sum), - }; + const size_t nbytes = 2 * sizeof(int64) + ARR_OVERHEAD_NONULLS(/* ndims = */ 1); + ArrayType *result = palloc(nbytes); + SET_VARSIZE(result, nbytes); + result->ndim = 1; + result->dataoffset = 0; + result->elemtype = INT8OID; + ARR_DIMS(result)[0] = 2; + ARR_LBOUND(result)[0] = 1; + ((Datum *) ARR_DATA_PTR(result))[0] = Int64GetDatumFast(state->count); + ((Datum *) ARR_DATA_PTR(result))[1] = Int64GetDatumFast(state->sum); - ArrayType *result = - construct_array(transdatums, 2, INT8OID, sizeof(int64), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); *out_result = PointerGetDatum(result); *out_isnull = false; } diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 6049f3dbb4f..71f028389ed 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -324,12 +324,15 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Datum *output = &aggregated_slot->tts_values[col->output_offset]; if (col->by_value) { + Assert(col->value_bytes > 0); + Assert((size_t) col->value_bytes <= sizeof(Datum)); *output = 0; memcpy(output, ptr, col->value_bytes); ptr += col->value_bytes; } else { + Assert(col->value_bytes == -1); if (VARATT_IS_SHORT(ptr)) { *output = PointerGetDatum(ptr); From 8c95744c55b3ffd720b85c035eb71adc7ec4b40d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:22:01 +0100 Subject: [PATCH 139/242] stuff --- tsl/src/nodes/vector_agg/hash_serialized.c | 5 + tsl/test/expected/vector_agg_grouping.out | 246 ++++++++++----------- tsl/test/sql/vector_agg_grouping.sql | 2 +- 3 files changed, 129 insertions(+), 124 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 71f028389ed..6a26f654a9f 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -167,6 +167,11 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, } else { + /* + * FIXME this is not consistent with non-scalar values, add + * a test (how??? it differentiates equal keys, not equates + * different ones). + */ offset = TYPEALIGN(4, offset); memcpy(&serialized_key_storage[offset], diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index 7e8c1bca431..5601efd9474 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -103,7 +103,7 @@ from 'ss, cint2, x', 'ss, s', 'ss, x, cint2', - 't, s, ss, x, cint2, cint4, cint8', + 't, s, ss, x, cint4, cint8, cint2', 'x']) with ordinality as grouping(grouping, n) where true @@ -267,19 +267,19 @@ select ss, x, cint2, count(*) from agggroup group by ss, x, cint2 order by count 0 | 0 | -16367 | 1 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count -----+---+----+---+--------+--------+-------+------- - 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 - 2 | 0 | 0 | 0 | -5373 | 1096 | -6638 | 1 - 3 | 0 | 0 | 0 | -7109 | -15920 | 13672 | 1 - 4 | 0 | 0 | 0 | -4927 | 14299 | -8187 | 1 - 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 - 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 - 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 - 8 | 0 | 0 | 0 | -12705 | -10427 | 876 | 1 - 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 - 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+--------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 2 | 0 | 0 | 0 | 1096 | -6638 | -5373 | 1 + 3 | 0 | 0 | 0 | -15920 | 13672 | -7109 | 1 + 4 | 0 | 0 | 0 | 14299 | -8187 | -4927 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 8 | 0 | 0 | 0 | -10427 | 876 | -12705 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 (10 rows) select x, count(*) from agggroup group by x order by count(*), x limit 10; @@ -453,19 +453,19 @@ select ss, x, cint2, count(cint2) from agggroup group by ss, x, cint2 order by c 0 | 0 | -16377 | 1 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count --------+---+----+---+-------+--------+--------+------- - 1051 | 0 | 0 | 0 | | -8612 | 14327 | 0 - 2102 | 0 | 0 | 0 | | 11069 | 16047 | 0 - 3153 | 0 | 0 | 0 | | 6192 | 12700 | 0 - 4204 | 0 | 0 | 0 | | 4165 | -10102 | 0 - 5255 | 0 | 0 | 0 | | 16314 | 13418 | 0 - 6306 | 0 | 0 | 0 | | 701 | -3029 | 0 - 7357 | 0 | 0 | 0 | | 1115 | 4913 | 0 - 8408 | 0 | 0 | 0 | | 15553 | 1743 | 0 - 9459 | 0 | 0 | 0 | | -14640 | 11933 | 0 - 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 (10 rows) select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; @@ -639,19 +639,19 @@ select ss, x, cint2, min(cint2) from agggroup group by ss, x, cint2 order by min 5 | 5 | -16381 | -16381 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | min +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min -------+---+----+----+--------+--------+--------+-------- - 6194 | 0 | 0 | 0 | -16383 | -13372 | 11094 | -16383 - 17044 | 0 | 0 | 0 | -16383 | -10318 | 6326 | -16383 - 53843 | 4 | 4 | 4 | -16383 | -9008 | 4390 | -16383 - 60530 | 5 | 5 | 5 | -16383 | 6729 | 6717 | -16383 - 73208 | 6 | 6 | 6 | -16383 | -3043 | -1794 | -16383 - 74870 | 6 | 6 | 6 | -16383 | -16190 | 13646 | -16383 - 22836 | 2 | 11 | 11 | -16382 | -3080 | -15609 | -16382 - 29858 | 2 | 11 | 11 | -16382 | -14012 | -9888 | -16382 - 31516 | 2 | 11 | 11 | -16382 | 6193 | 206 | -16382 - 76781 | 7 | 7 | 7 | -16382 | 9938 | 6519 | -16382 + 6194 | 0 | 0 | 0 | -13372 | 11094 | -16383 | -16383 + 17044 | 0 | 0 | 0 | -10318 | 6326 | -16383 | -16383 + 53843 | 4 | 4 | 4 | -9008 | 4390 | -16383 | -16383 + 60530 | 5 | 5 | 5 | 6729 | 6717 | -16383 | -16383 + 73208 | 6 | 6 | 6 | -3043 | -1794 | -16383 | -16383 + 74870 | 6 | 6 | 6 | -16190 | 13646 | -16383 | -16383 + 22836 | 2 | 11 | 11 | -3080 | -15609 | -16382 | -16382 + 29858 | 2 | 11 | 11 | -14012 | -9888 | -16382 | -16382 + 31516 | 2 | 11 | 11 | 6193 | 206 | -16382 | -16382 + 76781 | 7 | 7 | 7 | 9938 | 6519 | -16382 | -16382 (10 rows) select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; @@ -825,19 +825,19 @@ select ss, x, cint2, count(*) from agggroup where cint2 > 0 group by ss, x, cint 0 | 0 | 31 | 1 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count -----+---+----+---+-------+--------+-------+------- - 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 - 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 - 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 - 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 - 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 - 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 - 14 | 0 | 0 | 0 | 4669 | -13766 | -398 | 1 - 15 | 0 | 0 | 0 | 15101 | -13009 | 14045 | 1 - 19 | 0 | 0 | 0 | 7684 | -16257 | 4566 | 1 - 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 (10 rows) select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; @@ -1011,19 +1011,19 @@ select ss, x, cint2, count(cint2) from agggroup where cint2 > 0 group by ss, x, 0 | 0 | 31 | 1 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count -----+---+----+---+-------+--------+-------+------- - 1 | 0 | 0 | 0 | 3398 | -15736 | 12910 | 1 - 5 | 0 | 0 | 0 | 4859 | 9267 | 6436 | 1 - 6 | 0 | 0 | 0 | 12177 | -5203 | 9870 | 1 - 7 | 0 | 0 | 0 | 5174 | 6620 | -781 | 1 - 9 | 0 | 0 | 0 | 2257 | -14954 | -1593 | 1 - 10 | 0 | 0 | 0 | 3923 | 10047 | -7626 | 1 - 14 | 0 | 0 | 0 | 4669 | -13766 | -398 | 1 - 15 | 0 | 0 | 0 | 15101 | -13009 | 14045 | 1 - 19 | 0 | 0 | 0 | 7684 | -16257 | 4566 | 1 - 22 | 0 | 0 | 0 | 11755 | -6345 | -8658 | 1 +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 (10 rows) select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; @@ -1197,19 +1197,19 @@ select ss, x, cint2, min(cint2) from agggroup where cint2 > 0 group by ss, x, ci 3 | 3 | 3 | 3 (10 rows) -select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | min --------+---+----+----+-------+--------+--------+----- - 11611 | 1 | 11 | 11 | 1 | -12025 | -2210 | 1 - 28649 | 2 | 11 | 11 | 1 | -1493 | -1043 | 1 - 28786 | 1 | 11 | 11 | 1 | -4190 | -2827 | 1 - 41774 | 3 | 3 | 3 | 1 | 1863 | 7650 | 1 - 41779 | 3 | 3 | 3 | 1 | 14078 | 9929 | 1 - 51152 | 5 | 5 | 5 | 1 | 9242 | -9798 | 1 - 70932 | 7 | 7 | 7 | 1 | -10344 | -13684 | 1 - 86957 | 7 | 7 | 7 | 1 | 15656 | 12597 | 1 - 89689 | 8 | 8 | 8 | 1 | 11189 | -5168 | 1 - 22147 | 1 | 11 | 11 | 2 | -9569 | 9760 | 2 +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+----+--------+--------+-------+----- + 11611 | 1 | 11 | 11 | -12025 | -2210 | 1 | 1 + 28649 | 2 | 11 | 11 | -1493 | -1043 | 1 | 1 + 28786 | 1 | 11 | 11 | -4190 | -2827 | 1 | 1 + 41774 | 3 | 3 | 3 | 1863 | 7650 | 1 | 1 + 41779 | 3 | 3 | 3 | 14078 | 9929 | 1 | 1 + 51152 | 5 | 5 | 5 | 9242 | -9798 | 1 | 1 + 70932 | 7 | 7 | 7 | -10344 | -13684 | 1 | 1 + 86957 | 7 | 7 | 7 | 15656 | 12597 | 1 | 1 + 89689 | 8 | 8 | 8 | 11189 | -5168 | 1 | 1 + 22147 | 1 | 11 | 11 | -9569 | 9760 | 2 | 2 (10 rows) select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; @@ -1372,19 +1372,19 @@ select ss, x, cint2, count(*) from agggroup where cint2 is null group by ss, x, 11 | 11 | | 38 (9 rows) -select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count --------+---+----+---+-------+--------+--------+------- - 1051 | 0 | 0 | 0 | | -8612 | 14327 | 1 - 2102 | 0 | 0 | 0 | | 11069 | 16047 | 1 - 3153 | 0 | 0 | 0 | | 6192 | 12700 | 1 - 4204 | 0 | 0 | 0 | | 4165 | -10102 | 1 - 5255 | 0 | 0 | 0 | | 16314 | 13418 | 1 - 6306 | 0 | 0 | 0 | | 701 | -3029 | 1 - 7357 | 0 | 0 | 0 | | 1115 | 4913 | 1 - 8408 | 0 | 0 | 0 | | 15553 | 1743 | 1 - 9459 | 0 | 0 | 0 | | -14640 | 11933 | 1 - 10510 | 0 | 0 | 0 | | -14725 | 6531 | 1 +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 1 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 1 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 1 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 1 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 1 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 1 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 1 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 1 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 1 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 1 (10 rows) select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; @@ -1546,19 +1546,19 @@ select ss, x, cint2, count(cint2) from agggroup where cint2 is null group by ss, 11 | 11 | | 0 (9 rows) -select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count --------+---+----+---+-------+--------+--------+------- - 1051 | 0 | 0 | 0 | | -8612 | 14327 | 0 - 2102 | 0 | 0 | 0 | | 11069 | 16047 | 0 - 3153 | 0 | 0 | 0 | | 6192 | 12700 | 0 - 4204 | 0 | 0 | 0 | | 4165 | -10102 | 0 - 5255 | 0 | 0 | 0 | | 16314 | 13418 | 0 - 6306 | 0 | 0 | 0 | | 701 | -3029 | 0 - 7357 | 0 | 0 | 0 | | 1115 | 4913 | 0 - 8408 | 0 | 0 | 0 | | 15553 | 1743 | 0 - 9459 | 0 | 0 | 0 | | -14640 | 11933 | 0 - 10510 | 0 | 0 | 0 | | -14725 | 6531 | 0 +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 (10 rows) select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; @@ -1720,19 +1720,19 @@ select ss, x, cint2, min(cint2) from agggroup where cint2 is null group by ss, x 11 | 11 | | (9 rows) -select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | min --------+---+----+---+-------+--------+--------+----- - 1051 | 0 | 0 | 0 | | -8612 | 14327 | - 2102 | 0 | 0 | 0 | | 11069 | 16047 | - 3153 | 0 | 0 | 0 | | 6192 | 12700 | - 4204 | 0 | 0 | 0 | | 4165 | -10102 | - 5255 | 0 | 0 | 0 | | 16314 | 13418 | - 6306 | 0 | 0 | 0 | | 701 | -3029 | - 7357 | 0 | 0 | 0 | | 1115 | 4913 | - 8408 | 0 | 0 | 0 | | 15553 | 1743 | - 9459 | 0 | 0 | 0 | | -14640 | 11933 | - 10510 | 0 | 0 | 0 | | -14725 | 6531 | +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+---+--------+--------+-------+----- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | + 2102 | 0 | 0 | 0 | 11069 | 16047 | | + 3153 | 0 | 0 | 0 | 6192 | 12700 | | + 4204 | 0 | 0 | 0 | 4165 | -10102 | | + 5255 | 0 | 0 | 0 | 16314 | 13418 | | + 6306 | 0 | 0 | 0 | 701 | -3029 | | + 7357 | 0 | 0 | 0 | 1115 | 4913 | | + 8408 | 0 | 0 | 0 | 15553 | 1743 | | + 9459 | 0 | 0 | 0 | -14640 | 11933 | | + 10510 | 0 | 0 | 0 | -14725 | 6531 | | (10 rows) select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; @@ -1805,8 +1805,8 @@ select ss, x, cint2, count(*) from agggroup where cint2 is null and x is null gr ----+---+-------+------- (0 rows) -select t, s, ss, x, cint2, cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by count(*), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count ---+---+----+---+-------+-------+-------+------- (0 rows) @@ -1871,8 +1871,8 @@ select ss, x, cint2, count(cint2) from agggroup where cint2 is null and x is nul ----+---+-------+------- (0 rows) -select t, s, ss, x, cint2, cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by count(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | count +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count ---+---+----+---+-------+-------+-------+------- (0 rows) @@ -1937,8 +1937,8 @@ select ss, x, cint2, min(cint2) from agggroup where cint2 is null and x is null ----+---+-------+----- (0 rows) -select t, s, ss, x, cint2, cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint2, cint4, cint8 order by min(cint2), t, s, ss, x, cint2, cint4, cint8 limit 10; - t | s | ss | x | cint2 | cint4 | cint8 | min +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min ---+---+----+---+-------+-------+-------+----- (0 rows) diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index 2ec80ec1120..68ac5a5aa91 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -100,7 +100,7 @@ from 'ss, cint2, x', 'ss, s', 'ss, x, cint2', - 't, s, ss, x, cint2, cint4, cint8', + 't, s, ss, x, cint4, cint8, cint2', 'x']) with ordinality as grouping(grouping, n) where true From 05ef083027d7eee48dfc48e9dcc64013c49c59b6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:11:40 +0100 Subject: [PATCH 140/242] move the code around --- .../nodes/vector_agg/grouping_policy_hash.c | 85 ++---------- .../nodes/vector_agg/grouping_policy_hash.h | 54 ++++---- tsl/src/nodes/vector_agg/hash_serialized.c | 63 ++++++--- .../nodes/vector_agg/hash_single_fixed_2.c | 8 +- .../nodes/vector_agg/hash_single_fixed_4.c | 9 +- .../nodes/vector_agg/hash_single_fixed_8.c | 9 +- tsl/src/nodes/vector_agg/hash_single_helper.c | 24 ---- .../hash_single_output_key_helper.c | 52 +++++++ tsl/src/nodes/vector_agg/hash_single_text.c | 130 +++++++++++++----- .../vector_agg/hash_table_functions_impl.c | 47 +++---- .../nodes/vector_agg/single_fixed_key_impl.c | 41 +++--- 11 files changed, 295 insertions(+), 227 deletions(-) delete mode 100644 tsl/src/nodes/vector_agg/hash_single_helper.c create mode 100644 tsl/src/nodes/vector_agg/hash_single_output_key_helper.c diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 774e36a4a81..9197a6710ca 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -63,9 +63,8 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->per_agg_states[i] = palloc(agg_def->func.state_bytes * policy->num_agg_state_rows); } - policy->grouping_column_values = palloc(sizeof(CompressedColumnValues) * num_grouping_columns); - - policy->key_body_mctx = policy->agg_extra_mctx; + policy->current_batch_grouping_column_values = + palloc(sizeof(CompressedColumnValues) * num_grouping_columns); if (num_grouping_columns == 1) { @@ -95,6 +94,8 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->strategy = serialized_strategy; } + policy->strategy.key_body_mctx = policy->agg_extra_mctx; + policy->strategy.init(&policy->strategy, policy); return &policy->funcs; @@ -313,28 +314,6 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } memset(policy->key_index_for_row, 0, n * sizeof(policy->key_index_for_row[0])); - /* - * Allocate enough storage for keys, given that each row of the new - * compressed batch might turn out to be a new grouping key. - * We do this here to avoid allocations in the hot loop that fills the hash - * table. - */ - const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; - if (num_possible_keys > policy->num_output_keys) - { - policy->num_output_keys = num_possible_keys * 2 + 1; - const size_t new_bytes = (char *) gp_hash_output_keys(policy, policy->num_output_keys) - - (char *) policy->output_keys; - if (policy->output_keys == NULL) - { - policy->output_keys = palloc(new_bytes); - } - else - { - policy->output_keys = repalloc(policy->output_keys, new_bytes); - } - } - /* * Allocate the temporary filter array for computing the combined results of * batch filter, aggregate filter and column validity. @@ -353,61 +332,25 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) { const GroupingColumn *def = &policy->grouping_columns[i]; const CompressedColumnValues *values = &batch_state->compressed_columns[def->input_offset]; - policy->grouping_column_values[i] = *values; + policy->current_batch_grouping_column_values[i] = *values; } /* - * Call the per-batch initialization function of the hashing strategy, if - * it has one. + * Call the per-batch initialization function of the hashing strategy. */ - if (policy->strategy.prepare_for_batch) - { - /* - * Remember which aggregation states have already existed, and which we - * have to initialize. State index zero is invalid. - */ - const uint32 first_initialized_key_index = policy->last_used_key_index; - policy->strategy.prepare_for_batch(policy, batch_state); - - if (policy->last_used_key_index > first_initialized_key_index) - { - const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; - const int num_fns = policy->num_agg_defs; - for (int i = 0; i < num_fns; i++) - { - const VectorAggDef *agg_def = &policy->agg_defs[i]; - if (policy->last_used_key_index >= policy->num_agg_state_rows) - { - policy->per_agg_states[i] = - repalloc(policy->per_agg_states[i], - new_aggstate_rows * agg_def->func.state_bytes); - } - - /* - * Initialize the aggregate function states for the newly added keys. - */ - void *first_uninitialized_state = - agg_def->func.state_bytes * (first_initialized_key_index + 1) + - (char *) policy->per_agg_states[i]; - agg_def->func.agg_init(first_uninitialized_state, - policy->last_used_key_index - first_initialized_key_index); - } - - /* - * Record the newly allocated number of rows in case we had to reallocate. - */ - if (policy->last_used_key_index >= policy->num_agg_state_rows) - { - Assert(new_aggstate_rows > policy->num_agg_state_rows); - policy->num_agg_state_rows = new_aggstate_rows; - } - } - } + policy->strategy.prepare_for_batch(policy, batch_state); + /* + * Add the batch rows to aggregate function states. + */ const uint64_t *restrict filter = batch_state->vector_qual_result; if (filter == NULL) { + /* + * We don't have a filter on this batch, so aggregate it entirely in one + * go. + */ add_one_range(policy, batch_state, 0, n); } else diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index c835fe9c1c9..157ad8fee4a 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -31,6 +31,26 @@ typedef struct HashingStrategy int start_row, int end_row); void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot); + + /* + * For each unique grouping key, we store the values of the grouping columns. + * This is stored separately from hash table keys, because they might not + * have the full column values, and also storing them contiguously here + * leads to better memory access patterns when emitting the results. + * The details of the key storage are managed by the hashing strategy. + */ + Datum *restrict output_keys; + uint64 num_output_keys; + MemoryContext key_body_mctx; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and its index is given by this value. Key index 0 is invalid. + * This is done to avoid having an "is null" flag in the hash table entries, + * to reduce the hash table size. + */ + uint32 null_key_index; + } HashingStrategy; /* @@ -73,7 +93,11 @@ typedef struct GroupingPolicyHash int num_grouping_columns; const GroupingColumn *restrict grouping_columns; - CompressedColumnValues *restrict grouping_column_values; + /* + * The values of the grouping columns picked from the compressed batch and + * arranged in the order of grouping column definitions. + */ + CompressedColumnValues *restrict current_batch_grouping_column_values; /* * The hash table we use for grouping. It matches each grouping key to its @@ -148,18 +172,6 @@ typedef struct GroupingPolicyHash */ MemoryContext agg_extra_mctx; - /* - * For each unique grouping key, we store the values of the grouping columns - * in Postgres format (i.e. Datum/isnull). They are used when emitting the - * partial aggregation results. The details of this are managed by the - * hashing strategy. - * - * FIXME - */ - void *restrict output_keys; - uint64 num_output_keys; - MemoryContext key_body_mctx; - /* * Whether we are in the mode of returning the partial aggregation results. * If we are, track the index of the last returned grouping key. @@ -176,14 +188,6 @@ typedef struct GroupingPolicyHash uint64 stat_consecutive_keys; } GroupingPolicyHash; -static inline Datum * -gp_hash_output_keys(GroupingPolicyHash *policy, int key_index) -{ - Assert(key_index > 0); - // Assert((size_t) key_index < policy->num_output_keys); - return key_index + (Datum *) policy->output_keys; -} - static pg_attribute_always_inline bool byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) { @@ -237,22 +241,22 @@ build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_sta .policy = policy, .batch_filter = batch_state->vector_qual_result, .num_grouping_columns = policy->num_grouping_columns, - .grouping_column_values = policy->grouping_column_values, + .grouping_column_values = policy->current_batch_grouping_column_values, .result_key_indexes = policy->key_index_for_row, }; Assert(policy->num_grouping_columns > 0); if (policy->num_grouping_columns == 1) { - config.single_key = policy->grouping_column_values[0]; + config.single_key = policy->current_batch_grouping_column_values[0]; } for (int i = 0; i < policy->num_grouping_columns; i++) { config.have_scalar_columns = config.have_scalar_columns || - (policy->grouping_column_values[i].decompression_type == DT_Scalar || - policy->grouping_column_values[i].buffers[0] != NULL); + (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || + policy->current_batch_grouping_column_values[i].buffers[0] != NULL); } return config; diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 6a26f654a9f..041dce3f85a 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -20,25 +20,25 @@ #include "import/umash.h" -struct abbrev_key +struct hash_table_key { uint32 hash; uint64 rest; } pg_attribute_packed; #define UMASH -#define ABBREV_KEY_TYPE struct abbrev_key +#define HASH_TABLE_KEY_TYPE struct hash_table_key #define KEY_HASH(X) (X.hash) #define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) static pg_attribute_always_inline void -serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, - void *restrict abbrev_key_ptr, bool *restrict valid) +serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = config.policy; - text **restrict full_key = (text **) full_key_ptr; - ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; + text **restrict output_key = (text **) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; const int num_columns = config.num_grouping_columns; @@ -128,7 +128,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, { pfree(policy->tmp_key_storage); } - policy->tmp_key_storage = MemoryContextAlloc(policy->key_body_mctx, num_bytes); + policy->tmp_key_storage = MemoryContextAlloc(policy->strategy.key_body_mctx, num_bytes); policy->num_tmp_key_storage_bytes = num_bytes; } uint8 *restrict serialized_key_storage = policy->tmp_key_storage; @@ -255,7 +255,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, SET_VARSIZE(serialized_key_storage, offset); - *full_key = (text *) serialized_key_storage; + *output_key = (text *) serialized_key_storage; /* * The multi-column key is always considered non-null, and the null flags @@ -268,25 +268,25 @@ serialized_get_key(HashingConfig config, int row, void *restrict full_key_ptr, /* seed = */ -1ull, serialized_key_storage, num_bytes); - abbrev_key->hash = fp.hash[0] & (~(uint32) 0); - abbrev_key->rest = fp.hash[1]; + hash_table_key->hash = fp.hash[0] & (~(uint32) 0); + hash_table_key->rest = fp.hash[1]; } -static pg_attribute_always_inline ABBREV_KEY_TYPE -serialized_store_key(GroupingPolicyHash *restrict policy, text *full_key, - ABBREV_KEY_TYPE abbrev_key) +static pg_attribute_always_inline HASH_TABLE_KEY_TYPE +serialized_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, + text *output_key, HASH_TABLE_KEY_TYPE hash_table_key) { /* * We will store this key so we have to consume the temporary storage that * was used for it. The subsequent keys will need to allocate new memory. */ - Assert(policy->tmp_key_storage == (void *) full_key); + Assert(policy->tmp_key_storage == (void *) output_key); policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(full_key); + policy->strategy.output_keys[new_key_index] = PointerGetDatum(output_key); - return abbrev_key; + return hash_table_key; } static pg_attribute_always_inline void @@ -299,7 +299,7 @@ static void serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { const int num_key_columns = policy->num_grouping_columns; - const Datum serialized_key_datum = gp_hash_output_keys(policy, current_key)[0]; + const Datum serialized_key_datum = policy->strategy.output_keys[current_key]; const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); const uint8 *restrict ptr = serialized_key; @@ -355,8 +355,35 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Assert(ptr == key_validity_bitmap); } +static void +serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + /* + * Allocate enough storage for keys, given that each row of the new + * compressed batch might turn out to be a new grouping key. + * We do this here to avoid allocations in the hot loop that fills the hash + * table. + */ + HashingStrategy *hashing = &policy->strategy; + const int n = batch_state->total_batch_rows; + const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; + if (num_possible_keys > hashing->num_output_keys) + { + hashing->num_output_keys = num_possible_keys * 2 + 1; + const size_t new_bytes = sizeof(Datum) * hashing->num_output_keys; + if (hashing->output_keys == NULL) + { + hashing->output_keys = palloc(new_bytes); + } + else + { + hashing->output_keys = repalloc(hashing->output_keys, new_bytes); + } + } +} + #define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized -#define FULL_KEY_TYPE text * +#define OUTPUT_KEY_TYPE text * #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c index 0e66f9275ac..8df1a71bffe 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_2.c @@ -19,10 +19,10 @@ #define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 #define KEY_BYTES 2 -#define FULL_KEY_TYPE int16 -#define ABBREV_KEY_TYPE int16 -#define DATUM_TO_FULL_KEY DatumGetInt16 -#define FULL_KEY_TO_DATUM Int16GetDatum +#define OUTPUT_KEY_TYPE int16 +#define HASH_TABLE_KEY_TYPE OUTPUT_KEY_TYPE +#define DATUM_TO_output_key DatumGetInt16 +#define output_key_TO_DATUM Int16GetDatum #define ABBREVIATE(X) (X) #define KEY_HASH(X) HASH64(X) diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c index 1b16bc4ac5f..29a7f79cf9f 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_4.c @@ -19,12 +19,11 @@ #define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 #define KEY_BYTES 4 -#define FULL_KEY_TYPE int32 -#define ABBREV_KEY_TYPE int32 -#define DATUM_TO_FULL_KEY DatumGetInt32 -#define FULL_KEY_TO_DATUM Int32GetDatum +#define OUTPUT_KEY_TYPE int32 +#define HASH_TABLE_KEY_TYPE int32 +#define DATUM_TO_output_key DatumGetInt32 +#define output_key_TO_DATUM Int32GetDatum -#define ABBREVIATE(X) (X) #define KEY_HASH(X) HASH64(X) #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c index 876bd9a7a09..6baedef0ad4 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hash_single_fixed_8.c @@ -19,12 +19,11 @@ #define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 #define KEY_BYTES 8 -#define FULL_KEY_TYPE int64 -#define ABBREV_KEY_TYPE int64 -#define DATUM_TO_FULL_KEY DatumGetInt64 -#define FULL_KEY_TO_DATUM Int64GetDatum +#define OUTPUT_KEY_TYPE int64 +#define HASH_TABLE_KEY_TYPE int64 +#define DATUM_TO_output_key DatumGetInt64 +#define output_key_TO_DATUM Int64GetDatum -#define ABBREVIATE(X) (X) #define KEY_HASH(X) HASH64(X) #include "single_fixed_key_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_helper.c b/tsl/src/nodes/vector_agg/hash_single_helper.c deleted file mode 100644 index f5eb0f05c37..00000000000 --- a/tsl/src/nodes/vector_agg/hash_single_helper.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file and its contents are licensed under the Timescale License. - * Please see the included NOTICE for copyright information and - * LICENSE-TIMESCALE for a copy of the license. - */ - -#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y -#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) -#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) - -static void -FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, - TupleTableSlot *aggregated_slot) -{ - Assert(policy->num_grouping_columns == 1); - - const GroupingColumn *col = &policy->grouping_columns[0]; - aggregated_slot->tts_values[col->output_offset] = gp_hash_output_keys(policy, current_key)[0]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; -} - -#undef FUNCTION_NAME_HELPER2 -#undef FUNCTION_NAME_HELPER -#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hash_single_output_key_helper.c b/tsl/src/nodes/vector_agg/hash_single_output_key_helper.c new file mode 100644 index 00000000000..1db5447abcd --- /dev/null +++ b/tsl/src/nodes/vector_agg/hash_single_output_key_helper.c @@ -0,0 +1,52 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) + +static void +FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + /* + * Allocate enough storage for keys, given that each row of the new + * compressed batch might turn out to be a new grouping key. + * We do this here to avoid allocations in the hot loop that fills the hash + * table. + */ + HashingStrategy *hashing = &policy->strategy; + const int n = batch_state->total_batch_rows; + const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; + if (num_possible_keys > hashing->num_output_keys) + { + hashing->num_output_keys = num_possible_keys * 2 + 1; + const size_t new_bytes = sizeof(Datum) * hashing->num_output_keys; + if (hashing->output_keys == NULL) + { + hashing->output_keys = palloc(new_bytes); + } + else + { + hashing->output_keys = repalloc(hashing->output_keys, new_bytes); + } + } +} + +static void +FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + HashingStrategy *hashing = &policy->strategy; + Assert(policy->num_grouping_columns == 1); + + const GroupingColumn *col = &policy->grouping_columns[0]; + aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; +} + +#undef FUNCTION_NAME_HELPER2 +#undef FUNCTION_NAME_HELPER +#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index faaf419e6bb..a3cc478328e 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -20,14 +20,14 @@ #include "import/umash.h" -struct abbrev_key +struct hash_table_key { uint32 hash; uint64 rest; } __attribute__((packed)); #define UMASH -#define ABBREV_KEY_TYPE struct abbrev_key +#define HASH_TABLE_KEY_TYPE struct hash_table_key #define KEY_HASH(X) (X.hash) #define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) @@ -42,30 +42,30 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, - void *restrict abbrev_key_ptr, bool *restrict valid) +single_text_get_key(HashingConfig config, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) { Assert(config.policy->num_grouping_columns == 1); - BytesView *restrict full_key = (BytesView *) full_key_ptr; - ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; + BytesView *restrict output_key = (BytesView *) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { /* Already stored. */ - full_key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); - full_key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); + output_key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); + output_key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); *valid = !*config.single_key.output_isnull; } else if (config.single_key.decompression_type == DT_ArrowText) { - *full_key = get_bytes_view(&config.single_key, row); + *output_key = get_bytes_view(&config.single_key, row); *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } else if (config.single_key.decompression_type == DT_ArrowTextDict) { const int16 index = ((int16 *) config.single_key.buffers[3])[row]; - *full_key = get_bytes_view(&config.single_key, index); + *output_key = get_bytes_view(&config.single_key, index); *valid = arrow_row_is_valid(config.single_key.buffers[0], row); } else @@ -77,32 +77,33 @@ single_text_get_key(HashingConfig config, int row, void *restrict full_key_ptr, policy, row, policy->last_used_key_index + 1, - full_key->len); - for (size_t i = 0; i < full_key->len; i++) + output_key->len); + for (size_t i = 0; i < output_key->len; i++) { - DEBUG_PRINT("%.2x.", full_key->data[i]); + DEBUG_PRINT("%.2x.", output_key->data[i]); } DEBUG_PRINT("\n"); struct umash_fp fp = umash_fprint(config.policy->umash_params, /* seed = */ -1ull, - full_key->data, - full_key->len); - abbrev_key->hash = fp.hash[0] & (~(uint32) 0); - abbrev_key->rest = fp.hash[1]; + output_key->data, + output_key->len); + hash_table_key->hash = fp.hash[0] & (~(uint32) 0); + hash_table_key->rest = fp.hash[1]; } -static pg_attribute_always_inline ABBREV_KEY_TYPE -single_text_store_key(GroupingPolicyHash *restrict policy, BytesView full_key, - ABBREV_KEY_TYPE abbrev_key) +static pg_attribute_always_inline HASH_TABLE_KEY_TYPE +single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, + BytesView output_key, HASH_TABLE_KEY_TYPE hash_table_key) { - const int total_bytes = full_key.len + VARHDRSZ; - text *restrict stored = (text *) MemoryContextAlloc(policy->key_body_mctx, total_bytes); + const int total_bytes = output_key.len + VARHDRSZ; + text *restrict stored = + (text *) MemoryContextAlloc(policy->strategy.key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); - memcpy(VARDATA(stored), full_key.data, full_key.len); - full_key.data = (uint8 *) VARDATA(stored); - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = PointerGetDatum(stored); - return abbrev_key; + memcpy(VARDATA(stored), output_key.data, output_key.len); + output_key.data = (uint8 *) VARDATA(stored); + policy->strategy.output_keys[new_key_index] = PointerGetDatum(stored); + return hash_table_key; } static pg_attribute_always_inline void @@ -111,12 +112,36 @@ single_text_destroy_key(BytesView key) /* Noop. */ } +/* + * We use the standard single-key key output functions. + */ +#define EXPLAIN_NAME "single text" +#define KEY_VARIANT single_text +#define OUTPUT_KEY_TYPE BytesView + +#include "hash_single_output_key_helper.c" + +/* + * We use a special batch preparation function to sometimes hash the dictionary- + * encoded column using the dictionary. + */ + +#define USE_DICT_HASHING + static pg_attribute_always_inline void single_text_dispatch_for_config(HashingConfig config, int start_row, int end_row); static void single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { + /* + * Allocate the key storage. + */ + single_text_alloc_output_keys(policy, batch_state); + + /* + * Determine whether we're going to use the dictionary for hashing. + */ policy->use_key_index_for_dict = false; Assert(policy->num_grouping_columns == 1); @@ -134,6 +159,12 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * { return; } + /* + * Remember which + * aggregation states have already existed, and which we have to + * initialize. State index zero is invalid. + */ + const uint32 first_initialized_key_index = policy->last_used_key_index; /* * Initialize the array for storing the aggregate state offsets corresponding @@ -258,15 +289,53 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * /* * The dictionary doesn't store nulls, so add the null key separately if we * have one. + * + * FIXME doesn't respect nulls last/first in GroupAggregate. Add a test. */ if (have_null_key && policy->null_key_index == 0) { policy->null_key_index = ++policy->last_used_key_index; - gp_hash_output_keys(policy, policy->null_key_index)[0] = PointerGetDatum(NULL); + policy->strategy.output_keys[policy->null_key_index] = PointerGetDatum(NULL); } policy->use_key_index_for_dict = true; + /* + * Initialize the new keys if we added any. + */ + if (policy->last_used_key_index > first_initialized_key_index) + { + const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; + const int num_fns = policy->num_agg_defs; + for (int i = 0; i < num_fns; i++) + { + const VectorAggDef *agg_def = &policy->agg_defs[i]; + if (policy->last_used_key_index >= policy->num_agg_state_rows) + { + policy->per_agg_states[i] = repalloc(policy->per_agg_states[i], + new_aggstate_rows * agg_def->func.state_bytes); + } + + /* + * Initialize the aggregate function states for the newly added keys. + */ + void *first_uninitialized_state = + agg_def->func.state_bytes * (first_initialized_key_index + 1) + + (char *) policy->per_agg_states[i]; + agg_def->func.agg_init(first_uninitialized_state, + policy->last_used_key_index - first_initialized_key_index); + } + + /* + * Record the newly allocated number of rows in case we had to reallocate. + */ + if (policy->last_used_key_index >= policy->num_agg_state_rows) + { + Assert(new_aggstate_rows > policy->num_agg_state_rows); + policy->num_agg_state_rows = new_aggstate_rows; + } + } + DEBUG_PRINT("computed the dict offsets\n"); } @@ -336,11 +405,4 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #undef APPLY_FOR_VALIDITY #undef APPLY_FOR_BATCH_FILTER -#define EXPLAIN_NAME "single text" -#define KEY_VARIANT single_text -#define FULL_KEY_TYPE BytesView -#define HAVE_PREPARE_FUNCTION - -#include "hash_single_helper.c" - #include "hash_table_functions_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index ddc295a643d..3d8907c0f4b 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -21,7 +21,7 @@ typedef struct /* Key index 0 is invalid. */ uint32 key_index; - ABBREV_KEY_TYPE abbrev_key; + HASH_TABLE_KEY_TYPE hash_table_key; #ifdef STORE_HASH /* @@ -35,8 +35,8 @@ typedef struct // #define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) -#define SH_KEY_TYPE ABBREV_KEY_TYPE -#define SH_KEY abbrev_key +#define SH_KEY_TYPE HASH_TABLE_KEY_TYPE +#define SH_KEY hash_table_key #define SH_HASH_KEY(tb, key) KEY_HASH(key) #define SH_EQUAL(tb, a, b) KEY_EQUAL(a, b) #define SH_SCOPE static inline @@ -79,7 +79,7 @@ FUNCTION_NAME(fill_offsets_impl)( struct FUNCTION_NAME(hash) *restrict table = policy->table; - ABBREV_KEY_TYPE prev_abbrev_key; + HASH_TABLE_KEY_TYPE prev_hash_table_key; uint32 previous_key_index = 0; for (int row = start_row; row < end_row; row++) { @@ -91,9 +91,9 @@ FUNCTION_NAME(fill_offsets_impl)( } bool key_valid = false; - FULL_KEY_TYPE full_key = { 0 }; - ABBREV_KEY_TYPE abbrev_key = { 0 }; - FUNCTION_NAME(get_key)(config, row, &full_key, &abbrev_key, &key_valid); + OUTPUT_KEY_TYPE output_key = { 0 }; + HASH_TABLE_KEY_TYPE hash_table_key = { 0 }; + FUNCTION_NAME(get_key)(config, row, &output_key, &hash_table_key, &key_valid); if (unlikely(!key_valid)) { @@ -104,11 +104,11 @@ FUNCTION_NAME(fill_offsets_impl)( } indexes[row] = policy->null_key_index; DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); - FUNCTION_NAME(destroy_key)(full_key); + FUNCTION_NAME(destroy_key)(output_key); continue; } - if (likely(previous_key_index != 0) && KEY_EQUAL(abbrev_key, prev_abbrev_key)) + if (likely(previous_key_index != 0) && KEY_EQUAL(hash_table_key, prev_hash_table_key)) { /* * In real data sets, we often see consecutive rows with the @@ -119,7 +119,7 @@ FUNCTION_NAME(fill_offsets_impl)( * for that case. */ indexes[row] = previous_key_index; - FUNCTION_NAME(destroy_key)(full_key); + FUNCTION_NAME(destroy_key)(output_key); policy->stat_consecutive_keys++; DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; @@ -129,26 +129,27 @@ FUNCTION_NAME(fill_offsets_impl)( * Find the key using the hash table. */ bool found = false; - FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, abbrev_key, &found); + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, hash_table_key, &found); if (!found) { /* * New key, have to store it persistently. */ - const int index = ++policy->last_used_key_index; - entry->abbrev_key = FUNCTION_NAME(store_key)(policy, full_key, abbrev_key); + const uint32 index = ++policy->last_used_key_index; + entry->hash_table_key = + FUNCTION_NAME(store_output_key)(policy, index, output_key, hash_table_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } else { DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); - FUNCTION_NAME(destroy_key)(full_key); + FUNCTION_NAME(destroy_key)(output_key); } indexes[row] = entry->key_index; previous_key_index = entry->key_index; - prev_abbrev_key = entry->abbrev_key; + prev_hash_table_key = entry->hash_table_key; } } @@ -172,7 +173,7 @@ FUNCTION_NAME(fill_offsets_impl)( #define APPLY_FOR_TYPE(X, NAME, COND) \ APPLY_FOR_VALIDITY(X, \ NAME##_byval, \ - (COND) && config.single_key.decompression_type == sizeof(FULL_KEY_TYPE)) \ + (COND) && config.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) \ APPLY_FOR_VALIDITY(X, \ NAME##_text, \ (COND) && config.single_key.decompression_type == DT_ArrowText) \ @@ -230,9 +231,10 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba HashingConfig config = build_hashing_config(policy, batch_state); -#ifdef HAVE_PREPARE_FUNCTION +#ifdef USE_DICT_HASHING if (policy->use_key_index_for_dict) { + Assert(config.single_key.decompression_type == DT_ArrowTextDict); single_text_offsets_translate(config, start_row, end_row); return; } @@ -259,9 +261,7 @@ HashingStrategy FUNCTION_NAME(strategy) = { .fill_offsets = FUNCTION_NAME(fill_offsets), .emit_key = FUNCTION_NAME(emit_key), .explain_name = EXPLAIN_NAME, -#ifdef HAVE_PREPARE_FUNCTION .prepare_for_batch = FUNCTION_NAME(prepare_for_batch), -#endif }; #undef EXPLAIN_NAME @@ -271,11 +271,12 @@ HashingStrategy FUNCTION_NAME(strategy) = { #undef KEY_EQUAL #undef STORE_HASH #undef CHECK_PREVIOUS_KEY -#undef FULL_KEY_TYPE -#undef ABBREV_KEY_TYPE -#undef DATUM_TO_FULL_KEY -#undef FULL_KEY_TO_DATUM +#undef OUTPUT_KEY_TYPE +#undef HASH_TABLE_KEY_TYPE +#undef DATUM_TO_output_key +#undef output_key_TO_DATUM #undef UMASH +#undef USE_DICT_HASHING #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index b599d22e160..23c65e3fe58 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -4,54 +4,59 @@ * LICENSE-TIMESCALE for a copy of the license. */ +#include "hash_single_output_key_helper.c" + #define FUNCTION_NAME_HELPER2(X, Y) X##_##Y #define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict full_key_ptr, - void *restrict abbrev_key_ptr, bool *restrict valid) +FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) { - FULL_KEY_TYPE *restrict full_key = (FULL_KEY_TYPE *) full_key_ptr; - ABBREV_KEY_TYPE *restrict abbrev_key = (ABBREV_KEY_TYPE *) abbrev_key_ptr; + OUTPUT_KEY_TYPE *restrict output_key = (OUTPUT_KEY_TYPE *) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; if (unlikely(config.single_key.decompression_type == DT_Scalar)) { - *full_key = DATUM_TO_FULL_KEY(*config.single_key.output_value); + *output_key = DATUM_TO_output_key(*config.single_key.output_value); *valid = !*config.single_key.output_isnull; } - else if (config.single_key.decompression_type == sizeof(FULL_KEY_TYPE)) + else if (config.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) { - const FULL_KEY_TYPE *values = config.single_key.buffers[1]; + const OUTPUT_KEY_TYPE *values = config.single_key.buffers[1]; *valid = arrow_row_is_valid(config.single_key.buffers[0], row); - *full_key = values[row]; + *output_key = values[row]; } else { pg_unreachable(); } - *abbrev_key = ABBREVIATE(*full_key); + *hash_table_key = *output_key; } -static pg_attribute_always_inline FULL_KEY_TYPE -FUNCTION_NAME(store_key)(GroupingPolicyHash *restrict policy, FULL_KEY_TYPE full_key, - ABBREV_KEY_TYPE abbrev_key) +static pg_attribute_always_inline OUTPUT_KEY_TYPE +FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, + OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) { - gp_hash_output_keys(policy, policy->last_used_key_index)[0] = FULL_KEY_TO_DATUM(full_key); - return abbrev_key; + policy->strategy.output_keys[new_key_index] = output_key_TO_DATUM(output_key); + return hash_table_key; } static pg_attribute_always_inline void -FUNCTION_NAME(destroy_key)(FULL_KEY_TYPE key) +FUNCTION_NAME(destroy_key)(OUTPUT_KEY_TYPE key) { /* Noop for fixed-size keys. */ } +static void +FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + FUNCTION_NAME(alloc_output_keys)(policy, batch_state); +} + #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER #undef FUNCTION_NAME -#undef ABBREVIATE - -#include "hash_single_helper.c" From c9d63ab391af333d1ce81448adb28c29a0a74eaa Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:12:23 +0100 Subject: [PATCH 141/242] destroy_key is a noop for all strategies anyway --- tsl/src/nodes/vector_agg/hash_serialized.c | 6 ------ tsl/src/nodes/vector_agg/hash_single_text.c | 6 ------ tsl/src/nodes/vector_agg/hash_table_functions_impl.c | 3 --- tsl/src/nodes/vector_agg/single_fixed_key_impl.c | 6 ------ 4 files changed, 21 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hash_serialized.c index 041dce3f85a..9faf6e38663 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hash_serialized.c @@ -289,12 +289,6 @@ serialized_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_ return hash_table_key; } -static pg_attribute_always_inline void -serialized_destroy_key(const text *key) -{ - /* Noop, the memory will be reused by the subsequent key. */ -} - static void serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hash_single_text.c index a3cc478328e..dd98cb9b48f 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hash_single_text.c @@ -106,12 +106,6 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key return hash_table_key; } -static pg_attribute_always_inline void -single_text_destroy_key(BytesView key) -{ - /* Noop. */ -} - /* * We use the standard single-key key output functions. */ diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c index 3d8907c0f4b..0a2b64c5aae 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hash_table_functions_impl.c @@ -104,7 +104,6 @@ FUNCTION_NAME(fill_offsets_impl)( } indexes[row] = policy->null_key_index; DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); - FUNCTION_NAME(destroy_key)(output_key); continue; } @@ -119,7 +118,6 @@ FUNCTION_NAME(fill_offsets_impl)( * for that case. */ indexes[row] = previous_key_index; - FUNCTION_NAME(destroy_key)(output_key); policy->stat_consecutive_keys++; DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; @@ -144,7 +142,6 @@ FUNCTION_NAME(fill_offsets_impl)( else { DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); - FUNCTION_NAME(destroy_key)(output_key); } indexes[row] = entry->key_index; diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c index 23c65e3fe58..1cd2511291c 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/single_fixed_key_impl.c @@ -44,12 +44,6 @@ FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_ return hash_table_key; } -static pg_attribute_always_inline void -FUNCTION_NAME(destroy_key)(OUTPUT_KEY_TYPE key) -{ - /* Noop for fixed-size keys. */ -} - static void FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { From 96b12f30d96c2c59356e0252304d9e6293736f99 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:36:09 +0100 Subject: [PATCH 142/242] move more code around --- tsl/src/nodes/vector_agg/CMakeLists.txt | 6 +- .../nodes/vector_agg/grouping_policy_hash.c | 4 +- .../nodes/vector_agg/grouping_policy_hash.h | 69 ++++------ .../nodes/vector_agg/hashing/CMakeLists.txt | 7 + .../vector_agg/{ => hashing}/bytes_view.h | 0 .../nodes/vector_agg/{ => hashing}/hash64.h | 0 .../hash_strategy_helper_single_fixed_key.c} | 19 ++- .../hash_strategy_helper_single_output_key.c} | 2 +- .../hash_strategy_impl.c} | 125 ++++++++++-------- .../hash_strategy_serialized.c} | 61 ++++++--- .../hash_strategy_single_fixed_2.c} | 10 +- .../hash_strategy_single_fixed_4.c} | 10 +- .../hash_strategy_single_fixed_8.c} | 10 +- .../hash_strategy_single_text.c} | 98 +++++++------- 14 files changed, 221 insertions(+), 200 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hashing/CMakeLists.txt rename tsl/src/nodes/vector_agg/{ => hashing}/bytes_view.h (100%) rename tsl/src/nodes/vector_agg/{ => hashing}/hash64.h (100%) rename tsl/src/nodes/vector_agg/{single_fixed_key_impl.c => hashing/hash_strategy_helper_single_fixed_key.c} (68%) rename tsl/src/nodes/vector_agg/{hash_single_output_key_helper.c => hashing/hash_strategy_helper_single_output_key.c} (95%) rename tsl/src/nodes/vector_agg/{hash_table_functions_impl.c => hashing/hash_strategy_impl.c} (68%) rename tsl/src/nodes/vector_agg/{hash_serialized.c => hashing/hash_strategy_serialized.c} (85%) rename tsl/src/nodes/vector_agg/{hash_single_fixed_2.c => hashing/hash_strategy_single_fixed_2.c} (76%) rename tsl/src/nodes/vector_agg/{hash_single_fixed_4.c => hashing/hash_strategy_single_fixed_4.c} (75%) rename tsl/src/nodes/vector_agg/{hash_single_fixed_8.c => hashing/hash_strategy_single_fixed_8.c} (75%) rename tsl/src/nodes/vector_agg/{hash_single_text.c => hashing/hash_strategy_single_text.c} (79%) diff --git a/tsl/src/nodes/vector_agg/CMakeLists.txt b/tsl/src/nodes/vector_agg/CMakeLists.txt index 934800f64bf..cf69755c077 100644 --- a/tsl/src/nodes/vector_agg/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/CMakeLists.txt @@ -1,11 +1,7 @@ add_subdirectory(function) +add_subdirectory(hashing) set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exec.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_2.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_4.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_fixed_8.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_single_text.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_serialized.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_batch.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_hash.c ${CMAKE_CURRENT_SOURCE_DIR}/plan.c) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 9197a6710ca..6f679e57256 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -110,7 +110,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; - policy->strategy.reset(policy->table); + policy->strategy.reset(&policy->strategy); /* * Have to reset this because it's in the key body context which is also @@ -423,7 +423,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - return policy->strategy.get_size_bytes(policy->table) > 512 * 1024; + return policy->strategy.get_size_bytes(&policy->strategy) > 512 * 1024; } static bool diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 157ad8fee4a..e817e5b95ad 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -23,15 +23,20 @@ typedef struct HashingStrategy { char *explain_name; void (*init)(HashingStrategy *strategy, GroupingPolicyHash *policy); - void (*reset)(void *table); - uint32 (*get_num_keys)(void *table); - uint64 (*get_size_bytes)(void *table); + void (*reset)(HashingStrategy *strategy); + uint64 (*get_size_bytes)(HashingStrategy *strategy); void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row); void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot); + /* + * The hash table we use for grouping. It matches each grouping key to its + * unique integer index. + */ + void *table; + /* * For each unique grouping key, we store the values of the grouping columns. * This is stored separately from hash table keys, because they might not @@ -99,11 +104,6 @@ typedef struct GroupingPolicyHash */ CompressedColumnValues *restrict current_batch_grouping_column_values; - /* - * The hash table we use for grouping. It matches each grouping key to its - * unique integer index. - */ - void *table; HashingStrategy strategy; struct umash_params *umash_params; @@ -188,56 +188,35 @@ typedef struct GroupingPolicyHash uint64 stat_consecutive_keys; } GroupingPolicyHash; -static pg_attribute_always_inline bool -byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) -{ - if (likely(bitmap == NULL)) - { - return true; - } - - const size_t byte_index = row_number / 8; - const size_t bit_index = row_number % 8; - const uint8 mask = ((uint8) 1) << bit_index; - return bitmap[byte_index] & mask; -} - -static pg_attribute_always_inline void -byte_bitmap_set_row_validity(uint8 *bitmap, size_t row_number, bool value) -{ - const size_t byte_index = row_number / 8; - const size_t bit_index = row_number % 8; - const uint8 mask = ((uint8) 1) << bit_index; - const uint8 new_bit = ((uint8) value) << bit_index; - - bitmap[byte_index] = (bitmap[byte_index] & ~mask) | new_bit; - - Assert(byte_bitmap_row_is_valid(bitmap, row_number) == value); -} - //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) #ifndef DEBUG_PRINT #define DEBUG_PRINT(...) #endif -typedef struct HashingConfig +typedef struct BatchHashingParams { const uint64 *batch_filter; CompressedColumnValues single_key; int num_grouping_columns; const CompressedColumnValues *grouping_column_values; - bool have_scalar_columns; + + /* + * Whether we have any scalar or nullable grouping columns in the current + * batch. This is used to select the more efficient implementation when we + * have none. + */ + bool have_scalar_or_nullable_columns; GroupingPolicyHash *restrict policy; uint32 *restrict result_key_indexes; -} HashingConfig; +} BatchHashingParams; -static pg_attribute_always_inline HashingConfig -build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +static pg_attribute_always_inline BatchHashingParams +build_batch_hashing_params(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { - HashingConfig config = { + BatchHashingParams params = { .policy = policy, .batch_filter = batch_state->vector_qual_result, .num_grouping_columns = policy->num_grouping_columns, @@ -248,16 +227,16 @@ build_hashing_config(GroupingPolicyHash *policy, DecompressBatchState *batch_sta Assert(policy->num_grouping_columns > 0); if (policy->num_grouping_columns == 1) { - config.single_key = policy->current_batch_grouping_column_values[0]; + params.single_key = policy->current_batch_grouping_column_values[0]; } for (int i = 0; i < policy->num_grouping_columns; i++) { - config.have_scalar_columns = - config.have_scalar_columns || + params.have_scalar_or_nullable_columns = + params.have_scalar_or_nullable_columns || (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || policy->current_batch_grouping_column_values[i].buffers[0] != NULL); } - return config; + return params; } diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt new file mode 100644 index 00000000000..fab11a7df17 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -0,0 +1,7 @@ +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_2.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_4.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_8.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_serialized.c) +target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/bytes_view.h b/tsl/src/nodes/vector_agg/hashing/bytes_view.h similarity index 100% rename from tsl/src/nodes/vector_agg/bytes_view.h rename to tsl/src/nodes/vector_agg/hashing/bytes_view.h diff --git a/tsl/src/nodes/vector_agg/hash64.h b/tsl/src/nodes/vector_agg/hashing/hash64.h similarity index 100% rename from tsl/src/nodes/vector_agg/hash64.h rename to tsl/src/nodes/vector_agg/hashing/hash64.h diff --git a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c similarity index 68% rename from tsl/src/nodes/vector_agg/single_fixed_key_impl.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c index 1cd2511291c..a23f72f20f2 100644 --- a/tsl/src/nodes/vector_agg/single_fixed_key_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c @@ -4,28 +4,28 @@ * LICENSE-TIMESCALE for a copy of the license. */ -#include "hash_single_output_key_helper.c" +#include "hash_strategy_helper_single_output_key.c" #define FUNCTION_NAME_HELPER2(X, Y) X##_##Y #define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) #define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(HashingConfig config, int row, void *restrict output_key_ptr, +FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output_key_ptr, void *restrict hash_table_key_ptr, bool *restrict valid) { OUTPUT_KEY_TYPE *restrict output_key = (OUTPUT_KEY_TYPE *) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; - if (unlikely(config.single_key.decompression_type == DT_Scalar)) + if (unlikely(params.single_key.decompression_type == DT_Scalar)) { - *output_key = DATUM_TO_output_key(*config.single_key.output_value); - *valid = !*config.single_key.output_isnull; + *output_key = DATUM_TO_OUTPUT_KEY(*params.single_key.output_value); + *valid = !*params.single_key.output_isnull; } - else if (config.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) + else if (params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) { - const OUTPUT_KEY_TYPE *values = config.single_key.buffers[1]; - *valid = arrow_row_is_valid(config.single_key.buffers[0], row); + const OUTPUT_KEY_TYPE *values = params.single_key.buffers[1]; + *valid = arrow_row_is_valid(params.single_key.buffers[0], row); *output_key = values[row]; } else @@ -40,7 +40,7 @@ static pg_attribute_always_inline OUTPUT_KEY_TYPE FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) { - policy->strategy.output_keys[new_key_index] = output_key_TO_DATUM(output_key); + policy->strategy.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); return hash_table_key; } @@ -53,4 +53,3 @@ FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchStat #undef FUNCTION_NAME_HELPER2 #undef FUNCTION_NAME_HELPER #undef FUNCTION_NAME - diff --git a/tsl/src/nodes/vector_agg/hash_single_output_key_helper.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c similarity index 95% rename from tsl/src/nodes/vector_agg/hash_single_output_key_helper.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c index 1db5447abcd..a2bc6306cde 100644 --- a/tsl/src/nodes/vector_agg/hash_single_output_key_helper.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c @@ -14,7 +14,7 @@ FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchStat /* * Allocate enough storage for keys, given that each row of the new * compressed batch might turn out to be a new grouping key. - * We do this here to avoid allocations in the hot loop that fills the hash + * We do this separately to avoid allocations in the hot loop that fills the hash * table. */ HashingStrategy *hashing = &policy->strategy; diff --git a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c similarity index 68% rename from tsl/src/nodes/vector_agg/hash_table_functions_impl.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 0a2b64c5aae..e2ed0c8b8ee 100644 --- a/tsl/src/nodes/vector_agg/hash_table_functions_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -51,39 +51,47 @@ typedef struct struct FUNCTION_NAME(hash); -static uint32 -FUNCTION_NAME(get_num_keys)(void *table) +static uint64 +FUNCTION_NAME(get_size_bytes)(HashingStrategy *strategy) { - struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) table; - return hash->members; + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) strategy->table; + return hash->members * sizeof(FUNCTION_NAME(entry)); } -static uint64 -FUNCTION_NAME(get_size_bytes)(void *table) +static void +FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) { - struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) table; - return hash->members * sizeof(FUNCTION_NAME(entry)); + strategy->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); +#ifdef UMASH + policy->umash_params = palloc0(sizeof(struct umash_params)); + umash_params_derive(policy->umash_params, 0xabcdef1234567890ull, NULL); +#endif +} + +static void +FUNCTION_NAME(reset_strategy)(HashingStrategy *strategy) +{ + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) strategy->table; + FUNCTION_NAME(reset)(hash); } /* * Fill the unique key indexes for all rows using a hash table. */ static pg_attribute_always_inline void -FUNCTION_NAME(fill_offsets_impl)( - - HashingConfig config, int start_row, int end_row) +FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) { - GroupingPolicyHash *policy = config.policy; + GroupingPolicyHash *policy = params.policy; - uint32 *restrict indexes = config.result_key_indexes; + uint32 *restrict indexes = params.result_key_indexes; - struct FUNCTION_NAME(hash) *restrict table = policy->table; + struct FUNCTION_NAME(hash) *restrict table = policy->strategy.table; HASH_TABLE_KEY_TYPE prev_hash_table_key; uint32 previous_key_index = 0; for (int row = start_row; row < end_row; row++) { - if (!arrow_row_is_valid(config.batch_filter, row)) + if (!arrow_row_is_valid(params.batch_filter, row)) { /* The row doesn't pass the filter. */ DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); @@ -93,7 +101,7 @@ FUNCTION_NAME(fill_offsets_impl)( bool key_valid = false; OUTPUT_KEY_TYPE output_key = { 0 }; HASH_TABLE_KEY_TYPE hash_table_key = { 0 }; - FUNCTION_NAME(get_key)(config, row, &output_key, &hash_table_key, &key_valid); + FUNCTION_NAME(get_key)(params, row, &output_key, &hash_table_key, &key_valid); if (unlikely(!key_valid)) { @@ -156,40 +164,46 @@ FUNCTION_NAME(fill_offsets_impl)( * when all the batch and key rows are valid. */ #define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME##_nofilter, (COND) && (config.batch_filter == NULL)) \ - X(NAME##_filter, (COND) && (config.batch_filter != NULL)) + X(NAME##_nofilter, (COND) && (params.batch_filter == NULL)) \ + X(NAME##_filter, (COND) && (params.batch_filter != NULL)) -#define APPLY_FOR_VALIDITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && config.single_key.buffers[0] == NULL) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && config.single_key.buffers[0] != NULL) +#define APPLY_FOR_NULLABILITY(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && params.single_key.buffers[0] == NULL) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && params.single_key.buffers[0] != NULL) #define APPLY_FOR_SCALARS(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_noscalar, (COND) && !config.have_scalar_columns) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_scalar, (COND) && config.have_scalar_columns) + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_noscalar_notnull, \ + (COND) && !params.have_scalar_or_nullable_columns) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_scalar_or_nullable, \ + (COND) && params.have_scalar_or_nullable_columns) #define APPLY_FOR_TYPE(X, NAME, COND) \ - APPLY_FOR_VALIDITY(X, \ - NAME##_byval, \ - (COND) && config.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) \ - APPLY_FOR_VALIDITY(X, \ - NAME##_text, \ - (COND) && config.single_key.decompression_type == DT_ArrowText) \ - APPLY_FOR_VALIDITY(X, \ - NAME##_dict, \ - (COND) && config.single_key.decompression_type == DT_ArrowTextDict) \ - APPLY_FOR_SCALARS(X, NAME##_multi, (COND) && config.single_key.decompression_type == DT_Invalid) + APPLY_FOR_NULLABILITY(X, \ + NAME##_byval, \ + (COND) && \ + params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) \ + APPLY_FOR_NULLABILITY(X, \ + NAME##_text, \ + (COND) && params.single_key.decompression_type == DT_ArrowText) \ + APPLY_FOR_NULLABILITY(X, \ + NAME##_dict, \ + (COND) && params.single_key.decompression_type == DT_ArrowTextDict) \ + APPLY_FOR_SCALARS(X, NAME##_multi, (COND) && params.single_key.decompression_type == DT_Invalid) #define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, index, true) #define DEFINE(NAME, CONDITION) \ - static pg_noinline void FUNCTION_NAME(NAME)(HashingConfig config, int start_row, int end_row) \ + static pg_noinline void FUNCTION_NAME( \ + NAME)(BatchHashingParams params, int start_row, int end_row) \ { \ if (!(CONDITION)) \ { \ pg_unreachable(); \ } \ \ - FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); \ + FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); \ } APPLY_FOR_SPECIALIZATIONS(DEFINE) @@ -197,19 +211,29 @@ APPLY_FOR_SPECIALIZATIONS(DEFINE) #undef DEFINE static void -FUNCTION_NAME(dispatch_for_config)(HashingConfig config, int start_row, int end_row) +FUNCTION_NAME(dispatch_for_params)(BatchHashingParams params, int start_row, int end_row) { + if (params.num_grouping_columns == 0) + { + pg_unreachable(); + } + + if ((params.num_grouping_columns == 1) != (params.single_key.decompression_type != DT_Invalid)) + { + pg_unreachable(); + } + #define DISPATCH(NAME, CONDITION) \ if (CONDITION) \ { \ - FUNCTION_NAME(NAME)(config, start_row, end_row); \ + FUNCTION_NAME(NAME)(params, start_row, end_row); \ } \ else APPLY_FOR_SPECIALIZATIONS(DISPATCH) { /* Use a generic implementation if no specializations matched. */ - FUNCTION_NAME(fill_offsets_impl)(config, start_row, end_row); + FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); } #undef DISPATCH } @@ -226,34 +250,23 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba { Assert((size_t) end_row <= policy->num_key_index_for_row); - HashingConfig config = build_hashing_config(policy, batch_state); + BatchHashingParams params = build_batch_hashing_params(policy, batch_state); #ifdef USE_DICT_HASHING if (policy->use_key_index_for_dict) { - Assert(config.single_key.decompression_type == DT_ArrowTextDict); - single_text_offsets_translate(config, start_row, end_row); + Assert(params.single_key.decompression_type == DT_ArrowTextDict); + single_text_offsets_translate(params, start_row, end_row); return; } #endif - FUNCTION_NAME(dispatch_for_config)(config, start_row, end_row); -} - -static void -FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) -{ - policy->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); -#ifdef UMASH - policy->umash_params = palloc0(sizeof(struct umash_params)); - umash_params_derive(policy->umash_params, 0xabcdef1234567890ull, NULL); -#endif + FUNCTION_NAME(dispatch_for_params)(params, start_row, end_row); } HashingStrategy FUNCTION_NAME(strategy) = { .init = FUNCTION_NAME(init), - .reset = (void (*)(void *)) FUNCTION_NAME(reset), - .get_num_keys = FUNCTION_NAME(get_num_keys), + .reset = FUNCTION_NAME(reset_strategy), .get_size_bytes = FUNCTION_NAME(get_size_bytes), .fill_offsets = FUNCTION_NAME(fill_offsets), .emit_key = FUNCTION_NAME(emit_key), @@ -270,8 +283,8 @@ HashingStrategy FUNCTION_NAME(strategy) = { #undef CHECK_PREVIOUS_KEY #undef OUTPUT_KEY_TYPE #undef HASH_TABLE_KEY_TYPE -#undef DATUM_TO_output_key -#undef output_key_TO_DATUM +#undef DATUM_TO_OUTPUT_KEY +#undef OUTPUT_KEY_TO_DATUM #undef UMASH #undef USE_DICT_HASHING diff --git a/tsl/src/nodes/vector_agg/hash_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c similarity index 85% rename from tsl/src/nodes/vector_agg/hash_serialized.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index 9faf6e38663..cb03c9e5039 100644 --- a/tsl/src/nodes/vector_agg/hash_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -14,9 +14,9 @@ #include "bytes_view.h" #include "compression/arrow_c_data_interface.h" -#include "grouping_policy_hash.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" #include "import/umash.h" @@ -31,16 +31,43 @@ struct hash_table_key #define KEY_HASH(X) (X.hash) #define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) +static pg_attribute_always_inline bool +byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) +{ + if (likely(bitmap == NULL)) + { + return true; + } + + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + return bitmap[byte_index] & mask; +} + +static pg_attribute_always_inline void +byte_bitmap_set_row_validity(uint8 *bitmap, size_t row_number, bool value) +{ + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + const uint8 new_bit = ((uint8) value) << bit_index; + + bitmap[byte_index] = (bitmap[byte_index] & ~mask) | new_bit; + + Assert(byte_bitmap_row_is_valid(bitmap, row_number) == value); +} + static pg_attribute_always_inline void -serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, +serialized_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, void *restrict hash_table_key_ptr, bool *restrict valid) { - GroupingPolicyHash *policy = config.policy; + GroupingPolicyHash *policy = params.policy; text **restrict output_key = (text **) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; - const int num_columns = config.num_grouping_columns; + const int num_columns = params.num_grouping_columns; size_t bitmap_bytes = (num_columns + 7) / 8; uint8 *restrict serialized_key_validity_bitmap; @@ -53,13 +80,14 @@ serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, num_bytes += VARHDRSZ; for (int column_index = 0; column_index < num_columns; column_index++) { - const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; + const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; - if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) + if (params.have_scalar_or_nullable_columns && + column_values->decompression_type == DT_Scalar) { if (!*column_values->output_isnull) { - const GroupingColumn *def = &config.policy->grouping_columns[column_index]; + const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { num_bytes += def->value_bytes; @@ -73,8 +101,8 @@ serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, continue; } - const bool is_valid = - !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); + const bool is_valid = !params.have_scalar_or_nullable_columns || + arrow_row_is_valid(column_values->buffers[0], row); if (!is_valid) { continue; @@ -148,15 +176,16 @@ serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, offset += VARHDRSZ; for (int column_index = 0; column_index < num_columns; column_index++) { - const CompressedColumnValues *column_values = &config.grouping_column_values[column_index]; + const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; - if (config.have_scalar_columns && column_values->decompression_type == DT_Scalar) + if (params.have_scalar_or_nullable_columns && + column_values->decompression_type == DT_Scalar) { const bool is_valid = !*column_values->output_isnull; byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); if (is_valid) { - const GroupingColumn *def = &config.policy->grouping_columns[column_index]; + const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { memcpy(&serialized_key_storage[offset], @@ -184,8 +213,8 @@ serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, continue; } - const bool is_valid = - !config.have_scalar_columns || arrow_row_is_valid(column_values->buffers[0], row); + const bool is_valid = !params.have_scalar_or_nullable_columns || + arrow_row_is_valid(column_values->buffers[0], row); byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); if (!is_valid) @@ -264,7 +293,7 @@ serialized_get_key(HashingConfig config, int row, void *restrict output_key_ptr, */ *valid = true; - struct umash_fp fp = umash_fprint(config.policy->umash_params, + struct umash_fp fp = umash_fprint(params.policy->umash_params, /* seed = */ -1ull, serialized_key_storage, num_bytes); @@ -380,4 +409,4 @@ serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *b #define KEY_VARIANT serialized #define OUTPUT_KEY_TYPE text * -#include "hash_table_functions_impl.c" +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c similarity index 76% rename from tsl/src/nodes/vector_agg/hash_single_fixed_2.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c index 8df1a71bffe..1127b834155 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c @@ -11,23 +11,23 @@ #include #include "compression/arrow_c_data_interface.h" -#include "grouping_policy_hash.h" #include "hash64.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" #define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 #define KEY_BYTES 2 #define OUTPUT_KEY_TYPE int16 #define HASH_TABLE_KEY_TYPE OUTPUT_KEY_TYPE -#define DATUM_TO_output_key DatumGetInt16 -#define output_key_TO_DATUM Int16GetDatum +#define DATUM_TO_OUTPUT_KEY DatumGetInt16 +#define OUTPUT_KEY_TO_DATUM Int16GetDatum #define ABBREVIATE(X) (X) #define KEY_HASH(X) HASH64(X) -#include "single_fixed_key_impl.c" +#include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b -#include "hash_table_functions_impl.c" +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c similarity index 75% rename from tsl/src/nodes/vector_agg/hash_single_fixed_4.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c index 29a7f79cf9f..ab08da7eb43 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c @@ -11,23 +11,23 @@ #include #include "compression/arrow_c_data_interface.h" -#include "grouping_policy_hash.h" #include "hash64.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" #define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 #define KEY_BYTES 4 #define OUTPUT_KEY_TYPE int32 #define HASH_TABLE_KEY_TYPE int32 -#define DATUM_TO_output_key DatumGetInt32 -#define output_key_TO_DATUM Int32GetDatum +#define DATUM_TO_OUTPUT_KEY DatumGetInt32 +#define OUTPUT_KEY_TO_DATUM Int32GetDatum #define KEY_HASH(X) HASH64(X) -#include "single_fixed_key_impl.c" +#include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b -#include "hash_table_functions_impl.c" +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c similarity index 75% rename from tsl/src/nodes/vector_agg/hash_single_fixed_8.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c index 6baedef0ad4..a6f346ced86 100644 --- a/tsl/src/nodes/vector_agg/hash_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c @@ -11,22 +11,22 @@ #include #include "compression/arrow_c_data_interface.h" -#include "grouping_policy_hash.h" #include "hash64.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" #define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 #define KEY_BYTES 8 #define OUTPUT_KEY_TYPE int64 #define HASH_TABLE_KEY_TYPE int64 -#define DATUM_TO_output_key DatumGetInt64 -#define output_key_TO_DATUM Int64GetDatum +#define DATUM_TO_OUTPUT_KEY DatumGetInt64 +#define OUTPUT_KEY_TO_DATUM Int64GetDatum #define KEY_HASH(X) HASH64(X) -#include "single_fixed_key_impl.c" +#include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b -#include "hash_table_functions_impl.c" +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hash_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c similarity index 79% rename from tsl/src/nodes/vector_agg/hash_single_text.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index dd98cb9b48f..859feaa285f 100644 --- a/tsl/src/nodes/vector_agg/hash_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -14,9 +14,9 @@ #include "bytes_view.h" #include "compression/arrow_c_data_interface.h" -#include "grouping_policy_hash.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" #include "import/umash.h" @@ -42,31 +42,31 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(HashingConfig config, int row, void *restrict output_key_ptr, +single_text_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, void *restrict hash_table_key_ptr, bool *restrict valid) { - Assert(config.policy->num_grouping_columns == 1); + Assert(params.policy->num_grouping_columns == 1); BytesView *restrict output_key = (BytesView *) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; - if (unlikely(config.single_key.decompression_type == DT_Scalar)) + if (unlikely(params.single_key.decompression_type == DT_Scalar)) { /* Already stored. */ - output_key->len = VARSIZE_ANY_EXHDR(*config.single_key.output_value); - output_key->data = (const uint8 *) VARDATA_ANY(*config.single_key.output_value); - *valid = !*config.single_key.output_isnull; + output_key->len = VARSIZE_ANY_EXHDR(*params.single_key.output_value); + output_key->data = (const uint8 *) VARDATA_ANY(*params.single_key.output_value); + *valid = !*params.single_key.output_isnull; } - else if (config.single_key.decompression_type == DT_ArrowText) + else if (params.single_key.decompression_type == DT_ArrowText) { - *output_key = get_bytes_view(&config.single_key, row); - *valid = arrow_row_is_valid(config.single_key.buffers[0], row); + *output_key = get_bytes_view(¶ms.single_key, row); + *valid = arrow_row_is_valid(params.single_key.buffers[0], row); } - else if (config.single_key.decompression_type == DT_ArrowTextDict) + else if (params.single_key.decompression_type == DT_ArrowTextDict) { - const int16 index = ((int16 *) config.single_key.buffers[3])[row]; - *output_key = get_bytes_view(&config.single_key, index); - *valid = arrow_row_is_valid(config.single_key.buffers[0], row); + const int16 index = ((int16 *) params.single_key.buffers[3])[row]; + *output_key = get_bytes_view(¶ms.single_key, index); + *valid = arrow_row_is_valid(params.single_key.buffers[0], row); } else { @@ -84,7 +84,7 @@ single_text_get_key(HashingConfig config, int row, void *restrict output_key_ptr } DEBUG_PRINT("\n"); - struct umash_fp fp = umash_fprint(config.policy->umash_params, + struct umash_fp fp = umash_fprint(params.policy->umash_params, /* seed = */ -1ull, output_key->data, output_key->len); @@ -113,7 +113,7 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key #define KEY_VARIANT single_text #define OUTPUT_KEY_TYPE BytesView -#include "hash_single_output_key_helper.c" +#include "hash_strategy_helper_single_output_key.c" /* * We use a special batch preparation function to sometimes hash the dictionary- @@ -122,7 +122,7 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key #define USE_DICT_HASHING -static pg_attribute_always_inline void single_text_dispatch_for_config(HashingConfig config, +static pg_attribute_always_inline void single_text_dispatch_for_params(BatchHashingParams params, int start_row, int end_row); static void @@ -138,16 +138,13 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * */ policy->use_key_index_for_dict = false; - Assert(policy->num_grouping_columns == 1); - - HashingConfig config = build_hashing_config(policy, batch_state); - - if (config.single_key.decompression_type != DT_ArrowTextDict) + BatchHashingParams params = build_batch_hashing_params(policy, batch_state); + if (params.single_key.decompression_type != DT_ArrowTextDict) { return; } - const int dict_rows = config.single_key.arrow->dictionary->length; + const int dict_rows = params.single_key.arrow->dictionary->length; if ((size_t) dict_rows > arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) { @@ -199,7 +196,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * const uint64 word = row_filter[outer]; \ for (int inner = 0; inner < INNER_MAX; inner++) \ { \ - const int16 index = ((int16 *) config.single_key.buffers[3])[outer * 64 + inner]; \ + const int16 index = ((int16 *) params.single_key.buffers[3])[outer * 64 + inner]; \ tmp[index] = tmp[index] || (word & (1ull << inner)); \ } @@ -230,11 +227,11 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * } #undef INNER_LOOP - config.batch_filter = dict_filter; + params.batch_filter = dict_filter; } else { - config.batch_filter = NULL; + params.batch_filter = NULL; } /* @@ -245,23 +242,23 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * bool have_null_key = false; if (batch_state->vector_qual_result != NULL) { - if (config.single_key.arrow->null_count > 0) + if (params.single_key.arrow->null_count > 0) { - Assert(config.single_key.buffers[0] != NULL); + Assert(params.single_key.buffers[0] != NULL); const size_t batch_words = (batch_rows + 63) / 64; for (size_t i = 0; i < batch_words; i++) { have_null_key = have_null_key || - (row_filter[i] & (~((uint64 *) config.single_key.buffers[0])[i])) != 0; + (row_filter[i] & (~((uint64 *) params.single_key.buffers[0])[i])) != 0; } } } else { - if (config.single_key.arrow->null_count > 0) + if (params.single_key.arrow->null_count > 0) { - Assert(config.single_key.buffers[0] != NULL); + Assert(params.single_key.buffers[0] != NULL); have_null_key = true; } } @@ -270,15 +267,16 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * * Build key indexes for the dictionary entries as for normal non-nullable * text values. */ - Assert(config.single_key.decompression_type = DT_ArrowTextDict); - config.single_key.decompression_type = DT_ArrowText; - config.single_key.buffers[0] = NULL; - + Assert(params.single_key.decompression_type = DT_ArrowTextDict); Assert((size_t) dict_rows <= policy->num_key_index_for_dict); - config.result_key_indexes = policy->key_index_for_dict; memset(policy->key_index_for_dict, 0, sizeof(*policy->key_index_for_dict) * dict_rows); - single_text_dispatch_for_config(config, 0, dict_rows); + params.single_key.decompression_type = DT_ArrowText; + params.single_key.buffers[0] = NULL; + params.have_scalar_or_nullable_columns = false; + params.result_key_indexes = policy->key_index_for_dict; + + single_text_dispatch_for_params(params, 0, dict_rows); /* * The dictionary doesn't store nulls, so add the null key separately if we @@ -334,18 +332,18 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * } static pg_attribute_always_inline void -single_text_offsets_translate_impl(HashingConfig config, int start_row, int end_row) +single_text_offsets_translate_impl(BatchHashingParams params, int start_row, int end_row) { - GroupingPolicyHash *policy = config.policy; + GroupingPolicyHash *policy = params.policy; Assert(policy->use_key_index_for_dict); - uint32 *restrict indexes_for_rows = config.result_key_indexes; + uint32 *restrict indexes_for_rows = params.result_key_indexes; uint32 *restrict indexes_for_dict = policy->key_index_for_dict; for (int row = start_row; row < end_row; row++) { - const bool row_valid = arrow_row_is_valid(config.single_key.buffers[0], row); - const int16 dict_index = ((int16 *) config.single_key.buffers[3])[row]; + const bool row_valid = arrow_row_is_valid(params.single_key.buffers[0], row); + const int16 dict_index = ((int16 *) params.single_key.buffers[3])[row]; if (row_valid) { @@ -356,25 +354,25 @@ single_text_offsets_translate_impl(HashingConfig config, int start_row, int end_ indexes_for_rows[row] = policy->null_key_index; } - Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(config.batch_filter, row)); + Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(params.batch_filter, row)); } } #define APPLY_FOR_VALIDITY(X, NAME, COND) \ - X(NAME##_notnull, (COND) && (config.single_key.buffers[0] == NULL)) \ - X(NAME##_nullable, (COND) && (config.single_key.buffers[0] != NULL)) + X(NAME##_notnull, (COND) && (params.single_key.buffers[0] == NULL)) \ + X(NAME##_nullable, (COND) && (params.single_key.buffers[0] != NULL)) #define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, single_text_offsets_translate, true) #define DEFINE(NAME, CONDITION) \ - static pg_noinline void NAME(HashingConfig config, int start_row, int end_row) \ + static pg_noinline void NAME(BatchHashingParams params, int start_row, int end_row) \ { \ if (!(CONDITION)) \ { \ pg_unreachable(); \ } \ \ - single_text_offsets_translate_impl(config, start_row, end_row); \ + single_text_offsets_translate_impl(params, start_row, end_row); \ } APPLY_FOR_SPECIALIZATIONS(DEFINE) @@ -382,12 +380,12 @@ APPLY_FOR_SPECIALIZATIONS(DEFINE) #undef DEFINE static void -single_text_offsets_translate(HashingConfig config, int start_row, int end_row) +single_text_offsets_translate(BatchHashingParams params, int start_row, int end_row) { #define DISPATCH(NAME, CONDITION) \ if (CONDITION) \ { \ - NAME(config, start_row, end_row); \ + NAME(params, start_row, end_row); \ } \ else @@ -399,4 +397,4 @@ single_text_offsets_translate(HashingConfig config, int start_row, int end_row) #undef APPLY_FOR_VALIDITY #undef APPLY_FOR_BATCH_FILTER -#include "hash_table_functions_impl.c" +#include "hash_strategy_impl.c" From d7b331c42f5c3bbca3b46a40f6e2391149019ac5 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:43:44 +0100 Subject: [PATCH 143/242] it is very important to keep moving the code around --- tsl/src/nodes/vector_agg/grouping_policy_hash.c | 1 - tsl/src/nodes/vector_agg/grouping_policy_hash.h | 8 -------- .../hash_strategy_helper_single_output_key.c | 2 +- .../nodes/vector_agg/hashing/hash_strategy_impl.c | 14 ++++++++------ .../vector_agg/hashing/hash_strategy_single_text.c | 8 ++++---- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 6f679e57256..71da09094b1 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -119,7 +119,6 @@ gp_hash_reset(GroupingPolicy *obj) policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; - policy->null_key_index = 0; policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index e817e5b95ad..fb26a61c824 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -119,14 +119,6 @@ typedef struct GroupingPolicyHash */ uint32 last_used_key_index; - /* - * In single-column grouping, we store the null key outside of the hash - * table, and its index is given by this value. Key index 0 is invalid. - * This is done to avoid having an "is null" flag in the hash table entries, - * to reduce the hash table size. - */ - uint32 null_key_index; - /* * Temporary storage of unique key indexes corresponding to a given row of * the compressed batch that is currently being aggregated. We keep it in diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c index a2bc6306cde..1258ec76caa 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c @@ -44,7 +44,7 @@ FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, const GroupingColumn *col = &policy->grouping_columns[0]; aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == policy->null_key_index; + aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; } #undef FUNCTION_NAME_HELPER2 diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index e2ed0c8b8ee..9a4f476d2b2 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -71,8 +71,9 @@ FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) static void FUNCTION_NAME(reset_strategy)(HashingStrategy *strategy) { - struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) strategy->table; - FUNCTION_NAME(reset)(hash); + struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) strategy->table; + FUNCTION_NAME(reset)(table); + strategy->null_key_index = 0; } /* @@ -82,6 +83,7 @@ static pg_attribute_always_inline void FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) { GroupingPolicyHash *policy = params.policy; + HashingStrategy *hashing = &policy->strategy; uint32 *restrict indexes = params.result_key_indexes; @@ -106,12 +108,12 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e if (unlikely(!key_valid)) { /* The key is null. */ - if (policy->null_key_index == 0) + if (hashing->null_key_index == 0) { - policy->null_key_index = ++policy->last_used_key_index; + hashing->null_key_index = ++policy->last_used_key_index; } - indexes[row] = policy->null_key_index; - DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, policy->null_key_index); + indexes[row] = hashing->null_key_index; + DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, hashing->null_key_index); continue; } diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 859feaa285f..fc07a17cfe1 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -284,10 +284,10 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * * * FIXME doesn't respect nulls last/first in GroupAggregate. Add a test. */ - if (have_null_key && policy->null_key_index == 0) + if (have_null_key && policy->strategy.null_key_index == 0) { - policy->null_key_index = ++policy->last_used_key_index; - policy->strategy.output_keys[policy->null_key_index] = PointerGetDatum(NULL); + policy->strategy.null_key_index = ++policy->last_used_key_index; + policy->strategy.output_keys[policy->strategy.null_key_index] = PointerGetDatum(NULL); } policy->use_key_index_for_dict = true; @@ -351,7 +351,7 @@ single_text_offsets_translate_impl(BatchHashingParams params, int start_row, int } else { - indexes_for_rows[row] = policy->null_key_index; + indexes_for_rows[row] = policy->strategy.null_key_index; } Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(params.batch_filter, row)); From 7b191cca934270b8283075c146f53b75c4389197 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 18:39:08 +0100 Subject: [PATCH 144/242] add more files --- .../nodes/vector_agg/grouping_policy_hash.c | 45 +++--- .../nodes/vector_agg/grouping_policy_hash.h | 148 +++++------------- .../vector_agg/hashing/batch_hashing_params.h | 55 +++++++ .../hash_strategy_helper_single_fixed_key.c | 14 +- .../vector_agg/hashing/hash_strategy_impl.c | 28 ++-- .../hashing/hash_strategy_serialized.c | 42 ++--- .../hashing/hash_strategy_single_fixed_2.c | 6 +- .../hashing/hash_strategy_single_fixed_4.c | 4 +- .../hashing/hash_strategy_single_fixed_8.c | 5 +- .../hashing/hash_strategy_single_text.c | 34 ++-- .../vector_agg/hashing/hashing_strategy.h | 49 ++++++ ...output_key.c => output_key_helper_alloc.c} | 22 +-- .../hashing/output_key_helper_emit_single.c | 17 ++ .../vector_agg/hashing/template_helper.h | 10 ++ 14 files changed, 248 insertions(+), 231 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h create mode 100644 tsl/src/nodes/vector_agg/hashing/hashing_strategy.h rename tsl/src/nodes/vector_agg/hashing/{hash_strategy_helper_single_output_key.c => output_key_helper_alloc.c} (57%) create mode 100644 tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c create mode 100644 tsl/src/nodes/vector_agg/hashing/template_helper.h diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 71da09094b1..779a658e097 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -72,17 +72,17 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr switch (g->value_bytes) { case 8: - policy->strategy = single_fixed_8_strategy; + policy->hashing = single_fixed_8_strategy; break; case 4: - policy->strategy = single_fixed_4_strategy; + policy->hashing = single_fixed_4_strategy; break; case 2: - policy->strategy = single_fixed_2_strategy; + policy->hashing = single_fixed_2_strategy; break; case -1: Assert(g->typid == TEXTOID); - policy->strategy = single_text_strategy; + policy->hashing = single_text_strategy; break; default: Assert(false); @@ -91,12 +91,12 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr } else { - policy->strategy = serialized_strategy; + policy->hashing = serialized_strategy; } - policy->strategy.key_body_mctx = policy->agg_extra_mctx; + policy->hashing.key_body_mctx = policy->agg_extra_mctx; - policy->strategy.init(&policy->strategy, policy); + policy->hashing.init(&policy->hashing, policy); return &policy->funcs; } @@ -110,7 +110,7 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; - policy->strategy.reset(&policy->strategy); + policy->hashing.reset(&policy->hashing); /* * Have to reset this because it's in the key body context which is also @@ -129,14 +129,16 @@ gp_hash_reset(GroupingPolicy *obj) static void compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState *batch_state, - int start_row, int end_row, const VectorAggDef *agg_def, void *agg_states, - const uint32 *offsets, MemoryContext agg_extra_mctx) + int start_row, int end_row, const VectorAggDef *agg_def, void *agg_states) { const ArrowArray *arg_arrow = NULL; const uint64 *arg_validity_bitmap = NULL; Datum arg_datum = 0; bool arg_isnull = true; + const uint32 *offsets = policy->key_index_for_row; + MemoryContext agg_extra_mctx = policy->agg_extra_mctx; + /* * We have functions with one argument, and one function with no arguments * (count(*)). Collect the arguments. @@ -231,13 +233,14 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * Remember which aggregation states have already existed, and which we * have to initialize. State index zero is invalid. */ - const uint32 first_initialized_key_index = policy->last_used_key_index; + const uint32 last_initialized_key_index = policy->last_used_key_index; + Assert(last_initialized_key_index <= policy->num_agg_state_rows); /* * Match rows to aggregation states using a hash table. */ Assert((size_t) end_row <= policy->num_key_index_for_row); - policy->strategy.fill_offsets(policy, batch_state, start_row, end_row); + policy->hashing.fill_offsets(policy, batch_state, start_row, end_row); /* * Process the aggregate function states. @@ -246,7 +249,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con for (int i = 0; i < num_fns; i++) { const VectorAggDef *agg_def = &policy->agg_defs[i]; - if (policy->last_used_key_index > first_initialized_key_index) + if (policy->last_used_key_index > last_initialized_key_index) { if (policy->last_used_key_index >= policy->num_agg_state_rows) { @@ -258,10 +261,10 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * Initialize the aggregate function states for the newly added keys. */ void *first_uninitialized_state = - agg_def->func.state_bytes * (first_initialized_key_index + 1) + + agg_def->func.state_bytes * (last_initialized_key_index + 1) + (char *) policy->per_agg_states[i]; agg_def->func.agg_init(first_uninitialized_state, - policy->last_used_key_index - first_initialized_key_index); + policy->last_used_key_index - last_initialized_key_index); } /* @@ -272,9 +275,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con start_row, end_row, agg_def, - policy->per_agg_states[i], - policy->key_index_for_row, - policy->agg_extra_mctx); + policy->per_agg_states[i]); } /* @@ -338,7 +339,7 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * Call the per-batch initialization function of the hashing strategy. */ - policy->strategy.prepare_for_batch(policy, batch_state); + policy->hashing.prepare_for_batch(policy, batch_state); /* * Add the batch rows to aggregate function states. @@ -422,7 +423,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - return policy->strategy.get_size_bytes(&policy->strategy) > 512 * 1024; + return policy->hashing.get_size_bytes(&policy->hashing) > 512 * 1024; } static bool @@ -474,7 +475,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) &aggregated_slot->tts_isnull[agg_def->output_offset]); } - policy->strategy.emit_key(policy, current_key, aggregated_slot); + policy->hashing.emit_key(policy, current_key, aggregated_slot); DEBUG_PRINT("%p: output key index %d\n", policy, current_key); @@ -485,7 +486,7 @@ static char * gp_hash_explain(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - return psprintf("hashed with %s key", policy->strategy.explain_name); + return psprintf("hashed with %s key", policy->hashing.explain_name); } static const GroupingPolicy grouping_policy_hash_functions = { diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index fb26a61c824..92eb51ccfa2 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -13,51 +13,12 @@ #include "nodes/decompress_chunk/compressed_batch.h" -typedef struct GroupingPolicyHash GroupingPolicyHash; +#include "hashing/hashing_strategy.h" -typedef struct HashingStrategy HashingStrategy; +typedef struct GroupingPolicyHash GroupingPolicyHash; struct umash_params; -typedef struct HashingStrategy -{ - char *explain_name; - void (*init)(HashingStrategy *strategy, GroupingPolicyHash *policy); - void (*reset)(HashingStrategy *strategy); - uint64 (*get_size_bytes)(HashingStrategy *strategy); - void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); - void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int start_row, int end_row); - void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, - TupleTableSlot *aggregated_slot); - - /* - * The hash table we use for grouping. It matches each grouping key to its - * unique integer index. - */ - void *table; - - /* - * For each unique grouping key, we store the values of the grouping columns. - * This is stored separately from hash table keys, because they might not - * have the full column values, and also storing them contiguously here - * leads to better memory access patterns when emitting the results. - * The details of the key storage are managed by the hashing strategy. - */ - Datum *restrict output_keys; - uint64 num_output_keys; - MemoryContext key_body_mctx; - - /* - * In single-column grouping, we store the null key outside of the hash - * table, and its index is given by this value. Key index 0 is invalid. - * This is done to avoid having an "is null" flag in the hash table entries, - * to reduce the hash table size. - */ - uint32 null_key_index; - -} HashingStrategy; - /* * Hash grouping policy. * @@ -68,11 +29,12 @@ typedef struct HashingStrategy * spans multiple input compressed batches, and is reset after the partial * aggregation results are emitted. * - * 1) For each row of the new compressed batch, we obtain an integer index that + * 1) For each row of the new compressed batch, we obtain an index that * uniquely identifies its grouping key. This is done by matching the row's * grouping columns to the hash table recording the unique grouping keys and * their respective indexes. It is performed in bulk for all rows of the batch, - * to improve memory locality. + * to improve memory locality. The details of this are managed by the hashing + * strategy. * * 2) The key indexes are used to locate the aggregate function states * corresponding to a given row, and update it. This is done in bulk for all @@ -92,9 +54,15 @@ typedef struct GroupingPolicyHash */ GroupingPolicy funcs; + /* + * Aggregate function definitions. + */ int num_agg_defs; const VectorAggDef *restrict agg_defs; + /* + * Grouping column definitions. + */ int num_grouping_columns; const GroupingColumn *restrict grouping_columns; @@ -104,15 +72,11 @@ typedef struct GroupingPolicyHash */ CompressedColumnValues *restrict current_batch_grouping_column_values; - HashingStrategy strategy; - struct umash_params *umash_params; - /* - * Temporary key storages. Some hashing strategies need to put the key in a - * separate memory area, we don't want to alloc/free it on each row. + * Hashing strategy that is responsible for mapping the rows to the unique + * indexes of their grouping keys. */ - uint8 *tmp_key_storage; - uint64 num_tmp_key_storage_bytes; + HashingStrategy hashing; /* * The last used index of an unique grouping key. Key index 0 is invalid. @@ -120,23 +84,14 @@ typedef struct GroupingPolicyHash uint32 last_used_key_index; /* - * Temporary storage of unique key indexes corresponding to a given row of - * the compressed batch that is currently being aggregated. We keep it in + * Temporary storage of unique indexes of keys corresponding to a given row + * of the compressed batch that is currently being aggregated. We keep it in * the policy because it is potentially too big to keep on stack, and we - * don't want to reallocate it each batch. + * don't want to reallocate it for each batch. */ uint32 *restrict key_index_for_row; uint64 num_key_index_for_row; - /* - * For single text key that uses dictionary encoding, in some cases we first - * calculate the key indexes for the dictionary entries, and then translate - * it to the actual rows. - */ - uint32 *restrict key_index_for_dict; - uint64 num_key_index_for_dict; - bool use_key_index_for_dict; - /* * The temporary filter bitmap we use to combine the results of the * vectorized filters in WHERE, validity of the aggregate function argument, @@ -178,57 +133,30 @@ typedef struct GroupingPolicyHash uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; uint64 stat_consecutive_keys; -} GroupingPolicyHash; - -//#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) -#ifndef DEBUG_PRINT -#define DEBUG_PRINT(...) -#endif - -typedef struct BatchHashingParams -{ - const uint64 *batch_filter; - CompressedColumnValues single_key; - - int num_grouping_columns; - const CompressedColumnValues *grouping_column_values; /* - * Whether we have any scalar or nullable grouping columns in the current - * batch. This is used to select the more efficient implementation when we - * have none. + * FIXME all the stuff below should be moved out. */ - bool have_scalar_or_nullable_columns; + struct umash_params *umash_params; - GroupingPolicyHash *restrict policy; + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; - uint32 *restrict result_key_indexes; -} BatchHashingParams; + /* + * For single text key that uses dictionary encoding, in some cases we first + * calculate the key indexes for the dictionary entries, and then translate + * it to the actual rows. + */ + uint32 *restrict key_index_for_dict; + uint64 num_key_index_for_dict; + bool use_key_index_for_dict; +} GroupingPolicyHash; -static pg_attribute_always_inline BatchHashingParams -build_batch_hashing_params(GroupingPolicyHash *policy, DecompressBatchState *batch_state) -{ - BatchHashingParams params = { - .policy = policy, - .batch_filter = batch_state->vector_qual_result, - .num_grouping_columns = policy->num_grouping_columns, - .grouping_column_values = policy->current_batch_grouping_column_values, - .result_key_indexes = policy->key_index_for_row, - }; - - Assert(policy->num_grouping_columns > 0); - if (policy->num_grouping_columns == 1) - { - params.single_key = policy->current_batch_grouping_column_values[0]; - } - - for (int i = 0; i < policy->num_grouping_columns; i++) - { - params.have_scalar_or_nullable_columns = - params.have_scalar_or_nullable_columns || - (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || - policy->current_batch_grouping_column_values[i].buffers[0] != NULL); - } - - return params; -} +//#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(...) +#endif diff --git a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h new file mode 100644 index 00000000000..a4db2a19b1c --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h @@ -0,0 +1,55 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#pragma once + +typedef struct BatchHashingParams +{ + const uint64 *batch_filter; + CompressedColumnValues single_key; + + int num_grouping_columns; + const CompressedColumnValues *grouping_column_values; + + /* + * Whether we have any scalar or nullable grouping columns in the current + * batch. This is used to select the more efficient implementation when we + * have none. + */ + bool have_scalar_or_nullable_columns; + + GroupingPolicyHash *restrict policy; + + uint32 *restrict result_key_indexes; +} BatchHashingParams; + +static pg_attribute_always_inline BatchHashingParams +build_batch_hashing_params(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + BatchHashingParams params = { + .policy = policy, + .batch_filter = batch_state->vector_qual_result, + .num_grouping_columns = policy->num_grouping_columns, + .grouping_column_values = policy->current_batch_grouping_column_values, + .result_key_indexes = policy->key_index_for_row, + }; + + Assert(policy->num_grouping_columns > 0); + if (policy->num_grouping_columns == 1) + { + params.single_key = policy->current_batch_grouping_column_values[0]; + } + + for (int i = 0; i < policy->num_grouping_columns; i++) + { + params.have_scalar_or_nullable_columns = + params.have_scalar_or_nullable_columns || + (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || + policy->current_batch_grouping_column_values[i].buffers[0] != NULL); + } + + return params; +} diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c index a23f72f20f2..abb7ffc40de 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c @@ -3,12 +3,10 @@ * Please see the included NOTICE for copyright information and * LICENSE-TIMESCALE for a copy of the license. */ +#include "batch_hashing_params.h" -#include "hash_strategy_helper_single_output_key.c" - -#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y -#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) -#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) +#include "output_key_helper_alloc.c" +#include "output_key_helper_emit_single.c" static pg_attribute_always_inline void FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output_key_ptr, @@ -40,7 +38,7 @@ static pg_attribute_always_inline OUTPUT_KEY_TYPE FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) { - policy->strategy.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); + policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); return hash_table_key; } @@ -49,7 +47,3 @@ FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchStat { FUNCTION_NAME(alloc_output_keys)(policy, batch_state); } - -#undef FUNCTION_NAME_HELPER2 -#undef FUNCTION_NAME_HELPER -#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 9a4f476d2b2..6d661f66b6d 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -4,11 +4,9 @@ * LICENSE-TIMESCALE for a copy of the license. */ -#include "import/umash.h" +#include "batch_hashing_params.h" -#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y -#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) -#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) +#include "import/umash.h" /* * The hash table maps the value of the grouping key to its unique index. @@ -52,16 +50,16 @@ typedef struct struct FUNCTION_NAME(hash); static uint64 -FUNCTION_NAME(get_size_bytes)(HashingStrategy *strategy) +FUNCTION_NAME(get_size_bytes)(HashingStrategy *hashing) { - struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) strategy->table; + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) hashing->table; return hash->members * sizeof(FUNCTION_NAME(entry)); } static void -FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) +FUNCTION_NAME(init)(HashingStrategy *hashing, GroupingPolicyHash *policy) { - strategy->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); + hashing->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); #ifdef UMASH policy->umash_params = palloc0(sizeof(struct umash_params)); umash_params_derive(policy->umash_params, 0xabcdef1234567890ull, NULL); @@ -69,11 +67,11 @@ FUNCTION_NAME(init)(HashingStrategy *strategy, GroupingPolicyHash *policy) } static void -FUNCTION_NAME(reset_strategy)(HashingStrategy *strategy) +FUNCTION_NAME(reset_strategy)(HashingStrategy *hashing) { - struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) strategy->table; + struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) hashing->table; FUNCTION_NAME(reset)(table); - strategy->null_key_index = 0; + hashing->null_key_index = 0; } /* @@ -83,11 +81,11 @@ static pg_attribute_always_inline void FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) { GroupingPolicyHash *policy = params.policy; - HashingStrategy *hashing = &policy->strategy; + HashingStrategy *hashing = &policy->hashing; uint32 *restrict indexes = params.result_key_indexes; - struct FUNCTION_NAME(hash) *restrict table = policy->strategy.table; + struct FUNCTION_NAME(hash) *restrict table = hashing->table; HASH_TABLE_KEY_TYPE prev_hash_table_key; uint32 previous_key_index = 0; @@ -289,7 +287,3 @@ HashingStrategy FUNCTION_NAME(strategy) = { #undef OUTPUT_KEY_TO_DATUM #undef UMASH #undef USE_DICT_HASHING - -#undef FUNCTION_NAME_HELPER2 -#undef FUNCTION_NAME_HELPER -#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index cb03c9e5039..b4de4c258df 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -17,9 +17,16 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" #include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#include "batch_hashing_params.h" #include "import/umash.h" +#define EXPLAIN_NAME "serialized" +#define KEY_VARIANT serialized +#define OUTPUT_KEY_TYPE text * + struct hash_table_key { uint32 hash; @@ -156,7 +163,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key { pfree(policy->tmp_key_storage); } - policy->tmp_key_storage = MemoryContextAlloc(policy->strategy.key_body_mctx, num_bytes); + policy->tmp_key_storage = MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes); policy->num_tmp_key_storage_bytes = num_bytes; } uint8 *restrict serialized_key_storage = policy->tmp_key_storage; @@ -313,7 +320,7 @@ serialized_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_ policy->tmp_key_storage = NULL; policy->num_tmp_key_storage_bytes = 0; - policy->strategy.output_keys[new_key_index] = PointerGetDatum(output_key); + policy->hashing.output_keys[new_key_index] = PointerGetDatum(output_key); return hash_table_key; } @@ -322,7 +329,7 @@ static void serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { const int num_key_columns = policy->num_grouping_columns; - const Datum serialized_key_datum = policy->strategy.output_keys[current_key]; + const Datum serialized_key_datum = policy->hashing.output_keys[current_key]; const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); const uint8 *restrict ptr = serialized_key; @@ -378,35 +385,12 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Assert(ptr == key_validity_bitmap); } +#include "output_key_helper_alloc.c" + static void serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { - /* - * Allocate enough storage for keys, given that each row of the new - * compressed batch might turn out to be a new grouping key. - * We do this here to avoid allocations in the hot loop that fills the hash - * table. - */ - HashingStrategy *hashing = &policy->strategy; - const int n = batch_state->total_batch_rows; - const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; - if (num_possible_keys > hashing->num_output_keys) - { - hashing->num_output_keys = num_possible_keys * 2 + 1; - const size_t new_bytes = sizeof(Datum) * hashing->num_output_keys; - if (hashing->output_keys == NULL) - { - hashing->output_keys = palloc(new_bytes); - } - else - { - hashing->output_keys = repalloc(hashing->output_keys, new_bytes); - } - } + serialized_alloc_output_keys(policy, batch_state); } -#define EXPLAIN_NAME "serialized" -#define KEY_VARIANT serialized -#define OUTPUT_KEY_TYPE text * - #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c index 1127b834155..fb687963c89 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c @@ -15,6 +15,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" #include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" #define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 @@ -24,10 +25,9 @@ #define DATUM_TO_OUTPUT_KEY DatumGetInt16 #define OUTPUT_KEY_TO_DATUM Int16GetDatum -#define ABBREVIATE(X) (X) -#define KEY_HASH(X) HASH64(X) - #include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) + #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c index ab08da7eb43..c4a5a984666 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c @@ -15,6 +15,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" #include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" #define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 @@ -24,10 +25,9 @@ #define DATUM_TO_OUTPUT_KEY DatumGetInt32 #define OUTPUT_KEY_TO_DATUM Int32GetDatum -#define KEY_HASH(X) HASH64(X) - #include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c index a6f346ced86..7c1e107e896 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c @@ -15,6 +15,7 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" #include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" #define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 @@ -24,9 +25,9 @@ #define DATUM_TO_OUTPUT_KEY DatumGetInt64 #define OUTPUT_KEY_TO_DATUM Int64GetDatum -#define KEY_HASH(X) HASH64(X) - #include "hash_strategy_helper_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) + #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index fc07a17cfe1..5723ad2695d 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -17,6 +17,9 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" #include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#include "batch_hashing_params.h" #include "import/umash.h" @@ -97,12 +100,11 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key BytesView output_key, HASH_TABLE_KEY_TYPE hash_table_key) { const int total_bytes = output_key.len + VARHDRSZ; - text *restrict stored = - (text *) MemoryContextAlloc(policy->strategy.key_body_mctx, total_bytes); + text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), output_key.data, output_key.len); output_key.data = (uint8 *) VARDATA(stored); - policy->strategy.output_keys[new_key_index] = PointerGetDatum(stored); + policy->hashing.output_keys[new_key_index] = PointerGetDatum(stored); return hash_table_key; } @@ -113,7 +115,8 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key #define KEY_VARIANT single_text #define OUTPUT_KEY_TYPE BytesView -#include "hash_strategy_helper_single_output_key.c" +#include "output_key_helper_alloc.c" +#include "output_key_helper_emit_single.c" /* * We use a special batch preparation function to sometimes hash the dictionary- @@ -150,12 +153,13 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * { return; } + /* - * Remember which - * aggregation states have already existed, and which we have to - * initialize. State index zero is invalid. + * Remember which aggregation states have already existed, and which we have + * to initialize. State index zero is invalid. */ - const uint32 first_initialized_key_index = policy->last_used_key_index; + const uint32 last_initialized_key_index = policy->last_used_key_index; + Assert(last_initialized_key_index <= policy->num_agg_state_rows); /* * Initialize the array for storing the aggregate state offsets corresponding @@ -284,10 +288,10 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * * * FIXME doesn't respect nulls last/first in GroupAggregate. Add a test. */ - if (have_null_key && policy->strategy.null_key_index == 0) + if (have_null_key && policy->hashing.null_key_index == 0) { - policy->strategy.null_key_index = ++policy->last_used_key_index; - policy->strategy.output_keys[policy->strategy.null_key_index] = PointerGetDatum(NULL); + policy->hashing.null_key_index = ++policy->last_used_key_index; + policy->hashing.output_keys[policy->hashing.null_key_index] = PointerGetDatum(NULL); } policy->use_key_index_for_dict = true; @@ -295,7 +299,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * /* * Initialize the new keys if we added any. */ - if (policy->last_used_key_index > first_initialized_key_index) + if (policy->last_used_key_index > last_initialized_key_index) { const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; const int num_fns = policy->num_agg_defs; @@ -312,10 +316,10 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * * Initialize the aggregate function states for the newly added keys. */ void *first_uninitialized_state = - agg_def->func.state_bytes * (first_initialized_key_index + 1) + + agg_def->func.state_bytes * (last_initialized_key_index + 1) + (char *) policy->per_agg_states[i]; agg_def->func.agg_init(first_uninitialized_state, - policy->last_used_key_index - first_initialized_key_index); + policy->last_used_key_index - last_initialized_key_index); } /* @@ -351,7 +355,7 @@ single_text_offsets_translate_impl(BatchHashingParams params, int start_row, int } else { - indexes_for_rows[row] = policy->strategy.null_key_index; + indexes_for_rows[row] = policy->hashing.null_key_index; } Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(params.batch_filter, row)); diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h new file mode 100644 index 00000000000..b4032e930a0 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -0,0 +1,49 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +typedef struct GroupingPolicyHash GroupingPolicyHash; + +typedef struct HashingStrategy HashingStrategy; + +typedef struct HashingStrategy +{ + char *explain_name; + void (*init)(HashingStrategy *hashing, GroupingPolicyHash *policy); + void (*reset)(HashingStrategy *hashing); + uint64 (*get_size_bytes)(HashingStrategy *hashing); + void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); + void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int start_row, int end_row); + void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot); + + /* + * The hash table we use for grouping. It matches each grouping key to its + * unique integer index. + */ + void *table; + + /* + * For each unique grouping key, we store the values of the grouping columns. + * This is stored separately from hash table keys, because they might not + * have the full column values, and also storing them contiguously here + * leads to better memory access patterns when emitting the results. + * The details of the key storage are managed by the hashing strategy. + */ + Datum *restrict output_keys; + uint64 num_output_keys; + MemoryContext key_body_mctx; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and its index is given by this value. Key index 0 is invalid. + * This is done to avoid having an "is null" flag in the hash table entries, + * to reduce the hash table size. + */ + uint32 null_key_index; + +} HashingStrategy; diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c b/tsl/src/nodes/vector_agg/hashing/output_key_helper_alloc.c similarity index 57% rename from tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c rename to tsl/src/nodes/vector_agg/hashing/output_key_helper_alloc.c index 1258ec76caa..7cda7f340f0 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_output_key.c +++ b/tsl/src/nodes/vector_agg/hashing/output_key_helper_alloc.c @@ -4,10 +4,6 @@ * LICENSE-TIMESCALE for a copy of the license. */ -#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y -#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) -#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) - static void FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { @@ -17,7 +13,7 @@ FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchStat * We do this separately to avoid allocations in the hot loop that fills the hash * table. */ - HashingStrategy *hashing = &policy->strategy; + HashingStrategy *hashing = &policy->hashing; const int n = batch_state->total_batch_rows; const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; if (num_possible_keys > hashing->num_output_keys) @@ -34,19 +30,3 @@ FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchStat } } } - -static void -FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, - TupleTableSlot *aggregated_slot) -{ - HashingStrategy *hashing = &policy->strategy; - Assert(policy->num_grouping_columns == 1); - - const GroupingColumn *col = &policy->grouping_columns[0]; - aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; -} - -#undef FUNCTION_NAME_HELPER2 -#undef FUNCTION_NAME_HELPER -#undef FUNCTION_NAME diff --git a/tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c b/tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c new file mode 100644 index 00000000000..ce8764b4f8e --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c @@ -0,0 +1,17 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +static void +FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + HashingStrategy *hashing = &policy->hashing; + Assert(policy->num_grouping_columns == 1); + + const GroupingColumn *col = &policy->grouping_columns[0]; + aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; +} diff --git a/tsl/src/nodes/vector_agg/hashing/template_helper.h b/tsl/src/nodes/vector_agg/hashing/template_helper.h new file mode 100644 index 00000000000..684186ab27e --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/template_helper.h @@ -0,0 +1,10 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) From c2b5e18b31277e01bcdfbe0e7ddc3b3d70665f17 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:01:50 +0100 Subject: [PATCH 145/242] cleanup --- tsl/src/import/umash.c | 14 +++++++ tsl/src/import/umash.h | 38 +++++++++++++++++++ .../hashing/hash_strategy_single_text.c | 2 +- tsl/test/sql/vector_agg_filter.sql | 1 - tsl/test/sql/vector_agg_grouping.sql | 1 - 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/tsl/src/import/umash.c b/tsl/src/import/umash.c index 685bc659c98..eebcf8e2ced 100644 --- a/tsl/src/import/umash.c +++ b/tsl/src/import/umash.c @@ -1,3 +1,17 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This file contains source code that was copied and/or modified from + * the UMASH hash implementation at https://github.com/backtrace-labs/umash. + * + * This is a copy of umash.c, git commit sha + * fc4c5b6ca1f06c308e96c43aa080bd766238e092. + */ + #include "umash.h" /* diff --git a/tsl/src/import/umash.h b/tsl/src/import/umash.h index fcb742cd2d5..f85bd54a49c 100644 --- a/tsl/src/import/umash.h +++ b/tsl/src/import/umash.h @@ -1,3 +1,41 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This file contains source code that was copied and/or modified from + * the UMASH hash implementation at https://github.com/backtrace-labs/umash, + * which is licensed under the MIT License: + * + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * Copyright 2022 Dougall Johnson + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * This is a copy of umash.h, git commit sha + * fc4c5b6ca1f06c308e96c43aa080bd766238e092. + */ + #ifndef UMASH_H #define UMASH_H #include diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 5723ad2695d..8aa40243638 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -178,7 +178,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * } /* - * We shouldn't add the dictionary entries that are not used by any mathching + * We shouldn't add the dictionary entries that are not used by any matching * rows. Translate the batch filter bitmap to dictionary rows. */ const int batch_rows = batch_state->total_batch_rows; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index 1b82ace15f6..cafe5db5578 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -1,4 +1,3 @@ - -- This file and its contents are licensed under the Timescale License. -- Please see the included NOTICE for copyright information and -- LICENSE-TIMESCALE for a copy of the license. diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index 68ac5a5aa91..25253921c47 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -1,4 +1,3 @@ - -- This file and its contents are licensed under the Timescale License. -- Please see the included NOTICE for copyright information and -- LICENSE-TIMESCALE for a copy of the license. From d420e8b0a05bf1ee3ffea665380523874557908e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 18 Nov 2024 23:16:43 +0100 Subject: [PATCH 146/242] continue moving the code around --- .../hashing/hash_strategy_serialized.c | 24 +++--------- .../hashing/hash_strategy_single_text.c | 24 +++--------- .../hashing/umash_fingerprint_key.h | 38 +++++++++++++++++++ 3 files changed, 50 insertions(+), 36 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index b4de4c258df..fcb15b200f6 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -21,23 +21,12 @@ #include "batch_hashing_params.h" -#include "import/umash.h" +#include "umash_fingerprint_key.h" #define EXPLAIN_NAME "serialized" #define KEY_VARIANT serialized #define OUTPUT_KEY_TYPE text * -struct hash_table_key -{ - uint32 hash; - uint64 rest; -} pg_attribute_packed; - -#define UMASH -#define HASH_TABLE_KEY_TYPE struct hash_table_key -#define KEY_HASH(X) (X.hash) -#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) - static pg_attribute_always_inline bool byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) { @@ -300,12 +289,11 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key */ *valid = true; - struct umash_fp fp = umash_fprint(params.policy->umash_params, - /* seed = */ -1ull, - serialized_key_storage, - num_bytes); - hash_table_key->hash = fp.hash[0] & (~(uint32) 0); - hash_table_key->rest = fp.hash[1]; + const struct umash_fp fp = umash_fprint(params.policy->umash_params, + /* seed = */ -1ull, + serialized_key_storage, + num_bytes); + *hash_table_key = umash_fingerprint_get_key(fp); } static pg_attribute_always_inline HASH_TABLE_KEY_TYPE diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 8aa40243638..d79fe39a7eb 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -21,18 +21,7 @@ #include "batch_hashing_params.h" -#include "import/umash.h" - -struct hash_table_key -{ - uint32 hash; - uint64 rest; -} __attribute__((packed)); - -#define UMASH -#define HASH_TABLE_KEY_TYPE struct hash_table_key -#define KEY_HASH(X) (X.hash) -#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) +#include "umash_fingerprint_key.h" static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) @@ -87,12 +76,11 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke } DEBUG_PRINT("\n"); - struct umash_fp fp = umash_fprint(params.policy->umash_params, - /* seed = */ -1ull, - output_key->data, - output_key->len); - hash_table_key->hash = fp.hash[0] & (~(uint32) 0); - hash_table_key->rest = fp.hash[1]; + const struct umash_fp fp = umash_fprint(params.policy->umash_params, + /* seed = */ -1ull, + output_key->data, + output_key->len); + *hash_table_key = umash_fingerprint_get_key(fp); } static pg_attribute_always_inline HASH_TABLE_KEY_TYPE diff --git a/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h new file mode 100644 index 00000000000..0201383aa0d --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h @@ -0,0 +1,38 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +/* + * Helpers to use the umash fingerprint as a hash table key in our hashing + * strategies for vectorized grouping. + */ + +#include "import/umash.h" + +/* + * The struct is packed so that the hash table entry fits into 16 + * bytes with the uint32 key index that goes before. + */ +struct umash_fingerprint_key +{ + uint32 hash; + uint64 rest; +} pg_attribute_packed(); + +#define UMASH +#define HASH_TABLE_KEY_TYPE struct umash_fingerprint_key +#define KEY_HASH(X) (X.hash) +#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) + +static inline struct umash_fingerprint_key +umash_fingerprint_get_key(struct umash_fp fp) +{ + const struct umash_fingerprint_key key = { + .hash = fp.hash[0] & (~(uint32) 0), + .rest = fp.hash[1], + }; + return key; +} From 478c49052f7ae4b9d2fd0070dc67a75b4b65388e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 11:08:07 +0100 Subject: [PATCH 147/242] new day, new code moved around --- .../nodes/vector_agg/grouping_policy_hash.h | 3 --- tsl/src/nodes/vector_agg/hashing/hash64.h | 3 --- .../vector_agg/hashing/hash_strategy_impl.c | 25 ++++++------------- ... => hash_strategy_impl_single_fixed_key.c} | 4 +-- .../hashing/hash_strategy_serialized.c | 4 +-- .../hashing/hash_strategy_single_fixed_2.c | 3 +-- .../hashing/hash_strategy_single_fixed_4.c | 3 +-- .../hashing/hash_strategy_single_fixed_8.c | 3 +-- .../hashing/hash_strategy_single_text.c | 7 +++--- .../vector_agg/hashing/hashing_strategy.h | 4 +++ ..._key_helper_alloc.c => output_key_alloc.c} | 0 ...emit_single.c => output_key_emit_single.c} | 0 12 files changed, 21 insertions(+), 38 deletions(-) rename tsl/src/nodes/vector_agg/hashing/{hash_strategy_helper_single_fixed_key.c => hash_strategy_impl_single_fixed_key.c} (95%) rename tsl/src/nodes/vector_agg/hashing/{output_key_helper_alloc.c => output_key_alloc.c} (100%) rename tsl/src/nodes/vector_agg/hashing/{output_key_helper_emit_single.c => output_key_emit_single.c} (100%) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 92eb51ccfa2..9ae8d2420b9 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -17,8 +17,6 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; -struct umash_params; - /* * Hash grouping policy. * @@ -137,7 +135,6 @@ typedef struct GroupingPolicyHash /* * FIXME all the stuff below should be moved out. */ - struct umash_params *umash_params; /* * Temporary key storages. Some hashing strategies need to put the key in a diff --git a/tsl/src/nodes/vector_agg/hashing/hash64.h b/tsl/src/nodes/vector_agg/hashing/hash64.h index 9f7fdcb1ce8..64877a7936e 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash64.h +++ b/tsl/src/nodes/vector_agg/hashing/hash64.h @@ -9,9 +9,6 @@ * We can use crc32 as a hash function, it has bad properties but takes only one * cycle, which is why it is sometimes used in the existing hash table * implementations. - */ - -/* * When we don't have the crc32 instruction, use the SplitMix64 finalizer. */ static pg_attribute_always_inline uint64 diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 6d661f66b6d..ebeae2830a7 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -14,20 +14,12 @@ * of the hash table randomly, and want it to be as small as possible to fit the * caches. */ -typedef struct +typedef struct FUNCTION_NAME(entry) { /* Key index 0 is invalid. */ uint32 key_index; HASH_TABLE_KEY_TYPE hash_table_key; - -#ifdef STORE_HASH - /* - * We store hash for non-POD types, because it's slow to recalculate it - * on inserts for the existing values. - */ - uint32 hash; -#endif } FUNCTION_NAME(entry); // #define SH_FILLFACTOR (0.5) @@ -61,8 +53,8 @@ FUNCTION_NAME(init)(HashingStrategy *hashing, GroupingPolicyHash *policy) { hashing->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); #ifdef UMASH - policy->umash_params = palloc0(sizeof(struct umash_params)); - umash_params_derive(policy->umash_params, 0xabcdef1234567890ull, NULL); + hashing->umash_params = palloc0(sizeof(struct umash_params)); + umash_params_derive(hashing->umash_params, 0xabcdef1234567890ull, NULL); #endif } @@ -265,22 +257,19 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba } HashingStrategy FUNCTION_NAME(strategy) = { - .init = FUNCTION_NAME(init), - .reset = FUNCTION_NAME(reset_strategy), - .get_size_bytes = FUNCTION_NAME(get_size_bytes), - .fill_offsets = FUNCTION_NAME(fill_offsets), .emit_key = FUNCTION_NAME(emit_key), .explain_name = EXPLAIN_NAME, + .fill_offsets = FUNCTION_NAME(fill_offsets), + .get_size_bytes = FUNCTION_NAME(get_size_bytes), + .init = FUNCTION_NAME(init), .prepare_for_batch = FUNCTION_NAME(prepare_for_batch), + .reset = FUNCTION_NAME(reset_strategy), }; #undef EXPLAIN_NAME #undef KEY_VARIANT -#undef KEY_BYTES -#undef KEY_HASH #undef KEY_EQUAL #undef STORE_HASH -#undef CHECK_PREVIOUS_KEY #undef OUTPUT_KEY_TYPE #undef HASH_TABLE_KEY_TYPE #undef DATUM_TO_OUTPUT_KEY diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c similarity index 95% rename from tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c rename to tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index abb7ffc40de..eca3b21b2ea 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_helper_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -5,8 +5,8 @@ */ #include "batch_hashing_params.h" -#include "output_key_helper_alloc.c" -#include "output_key_helper_emit_single.c" +#include "output_key_alloc.c" +#include "output_key_emit_single.c" static pg_attribute_always_inline void FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output_key_ptr, diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index fcb15b200f6..ab99f3e8382 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -289,7 +289,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key */ *valid = true; - const struct umash_fp fp = umash_fprint(params.policy->umash_params, + const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, /* seed = */ -1ull, serialized_key_storage, num_bytes); @@ -373,7 +373,7 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Assert(ptr == key_validity_bitmap); } -#include "output_key_helper_alloc.c" +#include "output_key_alloc.c" static void serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c index fb687963c89..8e2a9083d06 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c @@ -19,13 +19,12 @@ #define EXPLAIN_NAME "single 2-byte" #define KEY_VARIANT single_fixed_2 -#define KEY_BYTES 2 #define OUTPUT_KEY_TYPE int16 #define HASH_TABLE_KEY_TYPE OUTPUT_KEY_TYPE #define DATUM_TO_OUTPUT_KEY DatumGetInt16 #define OUTPUT_KEY_TO_DATUM Int16GetDatum -#include "hash_strategy_helper_single_fixed_key.c" +#include "hash_strategy_impl_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b #define KEY_HASH(X) HASH64(X) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c index c4a5a984666..96679548d52 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c @@ -19,13 +19,12 @@ #define EXPLAIN_NAME "single 4-byte" #define KEY_VARIANT single_fixed_4 -#define KEY_BYTES 4 #define OUTPUT_KEY_TYPE int32 #define HASH_TABLE_KEY_TYPE int32 #define DATUM_TO_OUTPUT_KEY DatumGetInt32 #define OUTPUT_KEY_TO_DATUM Int32GetDatum -#include "hash_strategy_helper_single_fixed_key.c" +#include "hash_strategy_impl_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b #define KEY_HASH(X) HASH64(X) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c index 7c1e107e896..e0f12adf85b 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c @@ -19,13 +19,12 @@ #define EXPLAIN_NAME "single 8-byte" #define KEY_VARIANT single_fixed_8 -#define KEY_BYTES 8 #define OUTPUT_KEY_TYPE int64 #define HASH_TABLE_KEY_TYPE int64 #define DATUM_TO_OUTPUT_KEY DatumGetInt64 #define OUTPUT_KEY_TO_DATUM Int64GetDatum -#include "hash_strategy_helper_single_fixed_key.c" +#include "hash_strategy_impl_single_fixed_key.c" #define KEY_EQUAL(a, b) a == b #define KEY_HASH(X) HASH64(X) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index d79fe39a7eb..68eb42c55f7 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -44,7 +44,6 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke if (unlikely(params.single_key.decompression_type == DT_Scalar)) { - /* Already stored. */ output_key->len = VARSIZE_ANY_EXHDR(*params.single_key.output_value); output_key->data = (const uint8 *) VARDATA_ANY(*params.single_key.output_value); *valid = !*params.single_key.output_isnull; @@ -76,7 +75,7 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke } DEBUG_PRINT("\n"); - const struct umash_fp fp = umash_fprint(params.policy->umash_params, + const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, /* seed = */ -1ull, output_key->data, output_key->len); @@ -103,8 +102,8 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key #define KEY_VARIANT single_text #define OUTPUT_KEY_TYPE BytesView -#include "output_key_helper_alloc.c" -#include "output_key_helper_emit_single.c" +#include "output_key_alloc.c" +#include "output_key_emit_single.c" /* * We use a special batch preparation function to sometimes hash the dictionary- diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index b4032e930a0..9df36b5a30a 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -46,4 +46,8 @@ typedef struct HashingStrategy */ uint32 null_key_index; + /* + * UMASH fingerprinting parameters. + */ + struct umash_params *umash_params; } HashingStrategy; diff --git a/tsl/src/nodes/vector_agg/hashing/output_key_helper_alloc.c b/tsl/src/nodes/vector_agg/hashing/output_key_alloc.c similarity index 100% rename from tsl/src/nodes/vector_agg/hashing/output_key_helper_alloc.c rename to tsl/src/nodes/vector_agg/hashing/output_key_alloc.c diff --git a/tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c b/tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c similarity index 100% rename from tsl/src/nodes/vector_agg/hashing/output_key_helper_emit_single.c rename to tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c From 9e51c1987e7819be529ce1cf30e4f3fe16de5306 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:00:06 +0100 Subject: [PATCH 148/242] Vectorize aggregate FILTER clause --- tsl/src/compression/arrow_c_data_interface.h | 47 +- .../nodes/decompress_chunk/compressed_batch.c | 16 +- .../nodes/decompress_chunk/compressed_batch.h | 16 + tsl/src/nodes/decompress_chunk/planner.c | 6 - tsl/src/nodes/vector_agg/exec.c | 37 + tsl/src/nodes/vector_agg/exec.h | 2 + .../nodes/vector_agg/grouping_policy_batch.c | 18 +- tsl/src/nodes/vector_agg/plan.c | 305 +- tsl/test/expected/vector_agg_filter.out | 2944 +++++++++++++++++ tsl/test/expected/vector_agg_param.out | 85 +- tsl/test/expected/vectorized_aggregation.out | 59 +- tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vector_agg_filter.sql | 106 + tsl/test/sql/vector_agg_param.sql | 14 +- tsl/test/sql/vectorized_aggregation.sql | 4 + 15 files changed, 3512 insertions(+), 148 deletions(-) create mode 100644 tsl/test/expected/vector_agg_filter.out create mode 100644 tsl/test/sql/vector_agg_filter.sql diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 1473e24945b..077217b14af 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -184,25 +184,62 @@ arrow_set_row_validity(uint64 *bitmap, size_t row_number, bool value) } /* - * AND two optional arrow validity bitmaps into the given storage. + * Combine the validity bitmaps into the given storage. */ static inline const uint64 * arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 *filter1, - const uint64 *filter2) + const uint64 *filter2, const uint64 *filter3) { + /* + * Any and all of the filters can be null. For simplicity, move the non-null + * filters to the front. + */ + const uint64 *tmp; +#define SWAP(X, Y) \ + tmp = (X); \ + (X) = (Y); \ + (Y) = tmp; + + if (filter2 == NULL) + { + SWAP(filter2, filter3); + } + if (filter1 == NULL) { - return filter2; + SWAP(filter1, filter2); + + if (filter2 == NULL) + { + SWAP(filter2, filter3); + } } +#undef SWAP + + Assert(filter2 == NULL || filter1 != NULL); + Assert(filter3 == NULL || filter2 != NULL); if (filter2 == NULL) { + /* Either have one non-null filter, or all of them are null. */ return filter1; } - for (size_t i = 0; i < num_words; i++) + if (filter3 == NULL) + { + /* Have two non-null filters. */ + for (size_t i = 0; i < num_words; i++) + { + storage[i] = filter1[i] & filter2[i]; + } + } + else { - storage[i] = filter1[i] & filter2[i]; + /* Have three non-null filters. */ + for (size_t i = 0; i < num_words; i++) + { + storage[i] = filter1[i] & filter2[i] & filter3[i]; + } } return storage; diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.c b/tsl/src/nodes/decompress_chunk/compressed_batch.c index 81ed77fa8e0..582df8cbc1b 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.c +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.c @@ -20,18 +20,6 @@ #include "nodes/decompress_chunk/vector_predicates.h" #include "nodes/decompress_chunk/vector_quals.h" -/* - * VectorQualState for a compressed batch used to pass - * DecompressChunk-specific data to vector qual functions that are shared - * across scan nodes. - */ -typedef struct CompressedBatchVectorQualState -{ - VectorQualState vqstate; - DecompressBatchState *batch_state; - DecompressContext *dcontext; -} CompressedBatchVectorQualState; - /* * Create a single-value ArrowArray of an arithmetic type. This is a specialized * function because arithmetic types have a particular layout of ArrowArrays. @@ -312,7 +300,7 @@ decompress_column(DecompressContext *dcontext, DecompressBatchState *batch_state * VectorQualState->get_arrow_array() function used to interface with the * vector qual code across different scan nodes. */ -static const ArrowArray * +const ArrowArray * compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_default_value) { CompressedBatchVectorQualState *cbvqstate = (CompressedBatchVectorQualState *) vqstate; @@ -360,8 +348,6 @@ compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, bool *is_ var->varattno); Assert(column_description != NULL); Assert(column_description->typid == var->vartype); - Ensure(column_description->type == COMPRESSED_COLUMN, - "only compressed columns are supported in vectorized quals"); CompressedColumnValues *column_values = &batch_state->compressed_columns[column_index]; diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.h b/tsl/src/nodes/decompress_chunk/compressed_batch.h index 3131c2c7fd2..9871503e37c 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.h +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.h @@ -7,6 +7,7 @@ #include "compression/compression.h" #include "nodes/decompress_chunk/decompress_context.h" +#include "nodes/decompress_chunk/vector_quals.h" #include typedef struct ArrowArray ArrowArray; @@ -172,3 +173,18 @@ compressed_batch_current_tuple(DecompressBatchState *batch_state) Assert(batch_state->per_batch_context != NULL); return &batch_state->decompressed_scan_slot_data.base; } + +/* + * VectorQualState for a compressed batch used to pass + * DecompressChunk-specific data to vector qual functions that are shared + * across scan nodes. + */ +typedef struct CompressedBatchVectorQualState +{ + VectorQualState vqstate; + DecompressBatchState *batch_state; + DecompressContext *dcontext; +} CompressedBatchVectorQualState; + +const ArrowArray *compressed_batch_get_arrow_array(VectorQualState *vqstate, Expr *expr, + bool *is_default_value); diff --git a/tsl/src/nodes/decompress_chunk/planner.c b/tsl/src/nodes/decompress_chunk/planner.c index 8048fc2ceac..785b846e583 100644 --- a/tsl/src/nodes/decompress_chunk/planner.c +++ b/tsl/src/nodes/decompress_chunk/planner.c @@ -148,12 +148,6 @@ typedef struct } DecompressionMapContext; -typedef struct VectorQualInfoDecompressChunk -{ - VectorQualInfo vqinfo; - const UncompressedColumnInfo *colinfo; -} VectorQualInfoDecompressChunk; - static bool * build_vector_attrs_array(const UncompressedColumnInfo *colinfo, const CompressionInfo *info) { diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 1f198d799a9..0bb932bce1a 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -18,6 +18,7 @@ #include "guc.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/decompress_chunk/exec.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" static int @@ -146,6 +147,11 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) { def->input_offset = -1; } + + if (aggref->aggfilter != NULL) + { + def->filter_clauses = list_make1(aggref->aggfilter); + } } else { @@ -282,6 +288,37 @@ vector_agg_exec(CustomScanState *node) dcontext->ps->instrument->tuplecount += not_filtered_rows; } + /* + * Compute the vectorized filters for the aggregate function FILTER + * clauses. + */ + const int naggs = vector_agg_state->num_agg_defs; + for (int i = 0; i < naggs; i++) + { + VectorAggDef *agg_def = &vector_agg_state->agg_defs[i]; + if (agg_def->filter_clauses == NIL) + { + continue; + } + CompressedBatchVectorQualState cbvqstate = { + .vqstate = { + .vectorized_quals_constified = agg_def->filter_clauses, + .num_results = batch_state->total_batch_rows, + .per_vector_mcxt = batch_state->per_batch_context, + .slot = compressed_slot, + .get_arrow_array = compressed_batch_get_arrow_array, + }, + .batch_state = batch_state, + .dcontext = dcontext, + }; + VectorQualState *vqstate = &cbvqstate.vqstate; + vector_qual_compute(vqstate); + agg_def->filter_result = vqstate->vector_qual_result; + } + + /* + * Finally, pass the compressed batch to the grouping policy. + */ grouping->gp_add_batch(grouping, batch_state); } diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 26f832b3548..e5e9775ebb9 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -18,6 +18,8 @@ typedef struct VectorAggDef VectorAggFunctions func; int input_offset; int output_offset; + List *filter_clauses; + uint64 *filter_result; } VectorAggDef; typedef struct GroupingColumn diff --git a/tsl/src/nodes/vector_agg/grouping_policy_batch.c b/tsl/src/nodes/vector_agg/grouping_policy_batch.c index c9fa8f66709..c9b4249c3f4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_batch.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_batch.c @@ -151,6 +151,7 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc const uint64 *filter = arrow_combine_validity(num_words, policy->tmp_filter, batch_state->vector_qual_result, + agg_def->filter_result, arg_validity_bitmap); /* @@ -166,15 +167,16 @@ compute_single_aggregate(GroupingPolicyBatch *policy, DecompressBatchState *batc /* * Scalar argument, or count(*). Have to also count the valid rows in * the batch. - */ - const int n = arrow_num_valid(filter, batch_state->total_batch_rows); - - /* + * * The batches that are fully filtered out by vectorized quals should - * have been skipped by the caller. + * have been skipped by the caller, but we also have to check for the + * case when no rows match the aggregate FILTER clause. */ - Assert(n > 0); - agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + const int n = arrow_num_valid(filter, batch_state->total_batch_rows); + if (n > 0) + { + agg_def->func.agg_scalar(agg_state, arg_datum, arg_isnull, n, agg_extra_mctx); + } } } @@ -185,7 +187,7 @@ gp_batch_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) /* * Allocate the temporary filter array for computing the combined results of - * batch filter and column validity. + * batch filter, aggregate filter and column validity. */ const size_t num_words = (batch_state->total_batch_rows + 63) / 64; if (num_words > policy->num_tmp_filter_words) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index bd0a236de58..5da5b713bac 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -17,6 +17,7 @@ #include "exec.h" #include "nodes/decompress_chunk/planner.h" +#include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" #include "utils.h" @@ -74,29 +75,44 @@ resolve_outer_special_vars_mutator(Node *node, void *context) return expression_tree_mutator(node, resolve_outer_special_vars_mutator, context); } - Var *aggregated_var = castNode(Var, node); - Ensure(aggregated_var->varno == OUTER_VAR, - "encountered unexpected varno %d as an aggregate argument", - aggregated_var->varno); - + Var *var = castNode(Var, node); CustomScan *custom = castNode(CustomScan, context); - TargetEntry *decompress_chunk_tentry = - castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, aggregated_var->varattno - 1)); - Var *decompressed_var = castNode(Var, decompress_chunk_tentry->expr); - if (decompressed_var->varno == INDEX_VAR) + if ((Index) var->varno == (Index) custom->scan.scanrelid) + { + /* + * This is already the uncompressed chunk var. We can see it referenced + * by expressions in the output targetlist of DecompressChunk node. + */ + return (Node *) copyObject(var); + } + + if (var->varno == OUTER_VAR) + { + /* + * Reference into the output targetlist of the DecompressChunk node. + */ + TargetEntry *decompress_chunk_tentry = + castNode(TargetEntry, list_nth(custom->scan.plan.targetlist, var->varattno - 1)); + + return resolve_outer_special_vars_mutator((Node *) decompress_chunk_tentry->expr, context); + } + + if (var->varno == INDEX_VAR) { /* * This is a reference into the custom scan targetlist, we have to resolve * it as well. */ - decompressed_var = - castNode(Var, - castNode(TargetEntry, - list_nth(custom->custom_scan_tlist, decompressed_var->varattno - 1)) - ->expr); - } - Assert(decompressed_var->varno > 0); - return (Node *) copyObject(decompressed_var); + var = castNode(Var, + castNode(TargetEntry, list_nth(custom->custom_scan_tlist, var->varattno - 1)) + ->expr); + Assert(var->varno > 0); + + return (Node *) copyObject(var); + } + + Ensure(false, "encountered unexpected varno %d as an aggregate argument", var->varno); + return node; } /* @@ -115,20 +131,20 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) * node. */ static Plan * -vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) +vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_targetlist) { CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); vector_agg->custom_plans = list_make1(decompress_chunk); vector_agg->methods = &scan_methods; + vector_agg->custom_scan_tlist = resolved_targetlist; + /* * Note that this is being called from the post-planning hook, and therefore * after set_plan_refs(). The meaning of output targetlists is different from * the previous planning stages, and they contain special varnos referencing * the scan targetlists. */ - vector_agg->custom_scan_tlist = - resolve_outer_special_vars(agg->plan.targetlist, decompress_chunk); vector_agg->scan.plan.targetlist = build_trivial_custom_output_targetlist(vector_agg->custom_scan_tlist); @@ -166,6 +182,69 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk) return (Plan *) vector_agg; } +/* + * Map the custom scan attribute number to the uncompressed chunk attribute + * number. + */ +static int +custom_scan_to_uncompressed_chunk_attno(List *custom_scan_tlist, int custom_scan_attno) +{ + if (custom_scan_tlist == NIL) + { + return custom_scan_attno; + } + + Var *var = + castNode(Var, + castNode(TargetEntry, + list_nth(custom_scan_tlist, AttrNumberGetAttrOffset(custom_scan_attno))) + ->expr); + return var->varattno; +} + +/* + * Whether the given compressed column index corresponds to a vector variable. + */ +static bool +is_vector_compressed_column(CustomScan *custom, int compressed_column_index, bool *out_is_segmentby) +{ + List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); + const bool bulk_decompression_enabled_for_column = + list_nth_int(bulk_decompression_column, compressed_column_index); + + /* + * Bulk decompression can be disabled for all columns in the DecompressChunk + * node settings, we can't do vectorized aggregation for compressed columns + * in that case. For segmentby columns it's still possible. + */ + List *settings = linitial(custom->custom_private); + const bool bulk_decompression_enabled_globally = + list_nth_int(settings, DCS_EnableBulkDecompression); + + /* + * Check if this column is a segmentby. + */ + List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); + const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); + if (out_is_segmentby) + { + *out_is_segmentby = is_segmentby; + } + + /* + * We support vectorized aggregation either for segmentby columns or for + * columns with bulk decompression enabled. + */ + if (!is_segmentby && + !(bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)) + { + /* Vectorized aggregation not possible for this particular column. */ + return false; + } + + return true; +} + /* * Whether the expression can be used for vectorized processing: must be a Var * that refers to either a bulk-decompressed or a segmentby column. @@ -179,89 +258,119 @@ is_vector_var(CustomScan *custom, Expr *expr, bool *out_is_segmentby) return false; } - Var *aggregated_var = castNode(Var, expr); + Var *decompressed_var = castNode(Var, expr); /* - * Check if this particular column is a segmentby or has bulk decompression - * enabled. This hook is called after set_plan_refs, and at this stage the - * output targetlist of the aggregation node uses OUTER_VAR references into - * the child scan targetlist, so first we have to translate this. + * This must be called after resolve_outer_special_vars(), so we should only + * see the uncompressed chunk variables here. */ - Assert(aggregated_var->varno == OUTER_VAR); - TargetEntry *decompressed_target_entry = - list_nth(custom->scan.plan.targetlist, AttrNumberGetAttrOffset(aggregated_var->varattno)); + Ensure((Index) decompressed_var->varno == (Index) custom->scan.scanrelid, + "expected scan varno %d got %d", + custom->scan.scanrelid, + decompressed_var->varno); - if (!IsA(decompressed_target_entry->expr, Var)) + if (decompressed_var->varattno <= 0) { - /* - * Can only aggregate the plain Vars. Not sure if this is redundant with - * the similar check above. - */ + /* Can't work with special attributes like tableoid. */ + if (out_is_segmentby) + { + *out_is_segmentby = false; + } return false; } - Var *decompressed_var = castNode(Var, decompressed_target_entry->expr); /* * Now, we have to translate the decompressed varno into the compressed * column index, to check if the column supports bulk decompression. */ List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); - List *is_segmentby_column = list_nth(custom->custom_private, DCP_IsSegmentbyColumn); - List *bulk_decompression_column = list_nth(custom->custom_private, DCP_BulkDecompressionColumn); int compressed_column_index = 0; for (; compressed_column_index < list_length(decompression_map); compressed_column_index++) { - if (list_nth_int(decompression_map, compressed_column_index) == decompressed_var->varattno) + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); + + if (uncompressed_chunk_attno == decompressed_var->varattno) { break; } } Ensure(compressed_column_index < list_length(decompression_map), "compressed column not found"); - Assert(list_length(decompression_map) == list_length(bulk_decompression_column)); - const bool bulk_decompression_enabled_for_column = - list_nth_int(bulk_decompression_column, compressed_column_index); + return is_vector_compressed_column(custom, compressed_column_index, out_is_segmentby); +} + +/* + * Build supplementary info to determine whether we can vectorize the + * aggregate FILTER clauses. + */ +static VectorQualInfo +build_aggfilter_vector_qual_info(CustomScan *custom) +{ + VectorQualInfo vqi = { .rti = custom->scan.scanrelid }; /* - * Bulk decompression can be disabled for all columns in the DecompressChunk - * node settings, we can't do vectorized aggregation for compressed columns - * in that case. For segmentby columns it's still possible. + * Now, we have to translate the decompressed varno into the compressed + * column index, to check if the column supports bulk decompression. */ - List *settings = linitial(custom->custom_private); - const bool bulk_decompression_enabled_globally = - list_nth_int(settings, DCS_EnableBulkDecompression); + List *decompression_map = list_nth(custom->custom_private, DCP_DecompressionMap); /* - * Check if this column is a segmentby. + * There's no easy way to determine maximum attribute number for uncompressed + * chunk at this stage, so we'll have to go through all the compressed columns + * for this. */ - const bool is_segmentby = list_nth_int(is_segmentby_column, compressed_column_index); - if (out_is_segmentby) + int maxattno = 0; + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) { - *out_is_segmentby = is_segmentby; + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); + + if (uncompressed_chunk_attno > maxattno) + { + maxattno = uncompressed_chunk_attno; + } } - /* - * We support vectorized aggregation either for segmentby columns or for - * columns with bulk decompression enabled. - */ - if (!is_segmentby && - !(bulk_decompression_enabled_for_column && bulk_decompression_enabled_globally)) + vqi.vector_attrs = (bool *) palloc0(sizeof(bool) * (maxattno + 1)); + + for (int compressed_column_index = 0; compressed_column_index < list_length(decompression_map); + compressed_column_index++) { - /* Vectorized aggregation not possible for this particular column. */ - return false; + const int custom_scan_attno = list_nth_int(decompression_map, compressed_column_index); + if (custom_scan_attno <= 0) + { + continue; + } + + const int uncompressed_chunk_attno = + custom_scan_to_uncompressed_chunk_attno(custom->custom_scan_tlist, custom_scan_attno); + + vqi.vector_attrs[uncompressed_chunk_attno] = + is_vector_compressed_column(custom, compressed_column_index, NULL); } - return true; + return vqi; } +/* + * Whether we can vectorize this particular aggregate. + */ static bool -can_vectorize_aggref(Aggref *aggref, CustomScan *custom) +can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) { - if (aggref->aggfilter != NULL) - { - /* Filter clause on aggregate is not supported. */ - return false; - } - if (aggref->aggdirectargs != NIL) { /* Can't process ordered-set aggregates with direct arguments. */ @@ -282,8 +391,13 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) if (aggref->aggfilter != NULL) { - /* Can't process aggregates with filter clause. */ - return false; + /* Can process aggregates with filter clause if it's vectorizable. */ + Node *aggfilter_vectorized = vector_qual_make((Node *) aggref->aggfilter, vqi); + if (aggfilter_vectorized == NULL) + { + return false; + } + aggref->aggfilter = (Expr *) aggfilter_vectorized; } if (get_vector_aggregate(aggref->aggfnoid) == NULL) @@ -314,11 +428,13 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) /* * Whether we can perform vectorized aggregation with a given grouping. - * Currently supports either no grouping or grouping by segmentby columns. */ static bool -can_vectorize_grouping(Agg *agg, CustomScan *custom) +can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) { + /* + * We support vectorized aggregation without grouping. + */ if (agg->numCols == 0) { return true; @@ -327,7 +443,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom) for (int i = 0; i < agg->numCols; i++) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + TargetEntry *entry = list_nth_node(TargetEntry, resolved_targetlist, offset); bool is_segmentby = false; if (!is_vector_var(custom, entry->expr, &is_segmentby)) @@ -509,25 +625,54 @@ try_insert_vector_agg_node(Plan *plan) return plan; } - if (!can_vectorize_grouping(agg, custom)) + /* + * To make it easier to examine the variables participating in the aggregation, + * the subsequent checks are performed on the aggregated targetlist with + * all variables resolved to uncompressed chunk variables. + */ + List *resolved_targetlist = resolve_outer_special_vars(agg->plan.targetlist, custom); + + if (!can_vectorize_grouping(agg, custom, resolved_targetlist)) { /* No GROUP BY support for now. */ return plan; } - /* Now check the aggregate functions themselves. */ + /* + * Build supplementary info to determine whether we can vectorize the + * aggregate FILTER clauses. + */ + VectorQualInfo vqi = build_aggfilter_vector_qual_info(custom); + + /* Now check the output targetlist. */ ListCell *lc; - foreach (lc, agg->plan.targetlist) + foreach (lc, resolved_targetlist) { TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); - if (!IsA(target_entry->expr, Aggref)) + if (IsA(target_entry->expr, Aggref)) { - continue; + Aggref *aggref = castNode(Aggref, target_entry->expr); + if (!can_vectorize_aggref(aggref, custom, &vqi)) + { + /* Aggregate function not vectorizable. */ + return plan; + } } - - Aggref *aggref = castNode(Aggref, target_entry->expr); - if (!can_vectorize_aggref(aggref, custom)) + else if (IsA(target_entry->expr, Var)) + { + if (!is_vector_var(custom, target_entry->expr, NULL)) + { + /* Variable not vectorizable. */ + return plan; + } + } + else { + /* + * Sometimes the plan can require this node to perform a projection, + * e.g. we can see a nested loop param in its output targetlist. We + * can't handle this case currently. + */ return plan; } } @@ -536,5 +681,5 @@ try_insert_vector_agg_node(Plan *plan) * Finally, all requirements are satisfied and we can vectorize this partial * aggregation node. */ - return vector_agg_plan_create(agg, custom); + return vector_agg_plan_create(agg, custom, resolved_targetlist); } diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out new file mode 100644 index 00000000000..20d97efd1d4 --- /dev/null +++ b/tsl/test/expected/vector_agg_filter.out @@ -0,0 +1,2944 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +------------------------ + (1,public,aggfilter,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into aggfilter select * from source where s = 1; +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 1 +(1 row) + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze aggfilter; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec +select count(*) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(*) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(*) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select count(cint2) from aggfilter; + count +-------- + 199810 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter; + count +------- + 99946 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter; + count +-------- + 179829 +(1 row) + +select s, count(cint2) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 9993 + 1 | 10034 + 2 | 9876 + 3 | 10052 + 4 | 9990 + 5 | 10095 + 6 | 9968 + 7 | 9976 + 8 | 10010 + 9 | 9952 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 19981 + 1 | 19981 + 2 | 19981 + 3 | 19981 + 4 | 19981 + 5 | 0 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 +(10 rows) + +select min(cint2) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + +select s, min(cint2) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 4 | + 5 | + 6 | + 2 | + 7 | + 8 | + 3 | + 1 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16380 + 4 | -16381 + 5 | -16383 + 6 | -16379 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16380 + 1 | -16378 + 9 | -16375 +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter group by s order by min(cint2), s limit 10; + s | min +---+-------- + 0 | -16383 + 4 | -16383 + 5 | + 6 | -16383 + 2 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 1 | -16378 + 9 | -16375 +(10 rows) + +select count(cint4) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(cint4) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(cint4) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter; + min +----- + 1 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16382 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16381 + 8 | -16382 + 9 | -16381 + 5 | -16380 +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 2 | + 7 | + 1 | + 3 | + 4 | + 6 | + 8 | + 9 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 2 | 2 + 7 | 1 + 1 | 3 + 3 | 2 + 4 | 2 + 6 | 2 + 8 | 2 + 9 | 2 + 5 | 2 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 2 | -16383 + 7 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | +(10 rows) + +select count(s) from aggfilter; + count +-------- + 200000 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter; + count +-------- + 100139 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter; + count +-------- + 100038 +(1 row) + +select count(s) filter (where s != 5) from aggfilter; + count +-------- + 180000 +(1 row) + +select s, count(s) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9968 + 1 | 9885 + 2 | 10113 + 3 | 10088 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 10002 + 1 | 10046 + 2 | 9885 + 3 | 10063 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 20000 + 1 | 20000 + 2 | 20000 + 3 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(s) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter; + count +-------- + 199981 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter; + count +-------- + 100127 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter; + count +-------- + 100027 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter; + count +-------- + 179981 +(1 row) + +select s, count(ss) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10076 + 0 | 9968 + 1 | 9885 + 2 | 10113 + 4 | 10074 + 5 | 9871 + 6 | 10089 + 7 | 10008 + 8 | 10082 + 9 | 9961 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 0 + 0 | 0 + 1 | 0 + 2 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 10052 + 0 | 10002 + 1 | 10046 + 2 | 9885 + 4 | 9995 + 5 | 10106 + 6 | 9977 + 7 | 9983 + 8 | 10020 + 9 | 9961 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter group by s order by count(ss), s limit 10; + s | count +---+------- + 3 | 19981 + 0 | 20000 + 1 | 20000 + 2 | 20000 + 4 | 20000 + 5 | 0 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 +(10 rows) + +select min(ss) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select count(*) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(*) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(*) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(*), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select count(cint2) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(cint2) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint2), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(cint2) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select s, min(cint2) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | + 2 | + 3 | + 5 | + 7 | + 8 | + 9 | + 6 | + 0 | + 4 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 4 + 2 | 4 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 6 + 6 | 3 + 0 | 6 + 4 | 4 +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint2), s limit 10; + s | min +---+----- + 1 | 1 + 2 | 1 + 3 | 1 + 5 | + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 +(10 rows) + +select count(cint4) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(cint4) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(cint4), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(cint4) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 1 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter where cint2 > 0; + min +-------- + -16383 +(1 row) + +select s, min(cint4) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | -16375 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 1 | + 3 | + 4 | + 6 | + 7 | + 9 | + 2 | + 8 | + 5 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | 1 + 1 | 7 + 3 | 2 + 4 | 5 + 6 | 2 + 7 | 1 + 9 | 2 + 2 | 2 + 8 | 5 + 5 | 2 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16383 + 1 | -16382 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 7 | -16382 + 9 | -16382 + 2 | -16377 + 8 | -16377 + 5 | +(10 rows) + +select count(s) from aggfilter where cint2 > 0; + count +------- + 99664 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49817 +(1 row) + +select count(s) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89554 +(1 row) + +select s, count(s) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 0 + 6 | 0 + 3 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 4923 + 6 | 4911 + 3 | 4972 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(s), s limit 10; + s | count +---+------- + 2 | 9868 + 6 | 9890 + 3 | 9893 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(s) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 > 0; + count +------- + 99657 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + count +------- + 49813 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter where cint2 > 0; + count +------- + 89547 +(1 row) + +select s, count(ss) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 10110 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 0 + 3 | 0 + 6 | 0 + 8 | 0 + 4 | 0 + 7 | 0 + 0 | 0 + 9 | 0 + 1 | 0 + 5 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 4923 + 3 | 4968 + 6 | 4911 + 8 | 4929 + 4 | 4944 + 7 | 4990 + 0 | 4963 + 9 | 4951 + 1 | 5067 + 5 | 5167 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by count(ss), s limit 10; + s | count +---+------- + 2 | 9868 + 3 | 9886 + 6 | 9890 + 8 | 9898 + 4 | 9906 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 1 | 10096 + 5 | 0 +(10 rows) + +select min(ss) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter where cint2 > 0; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter where cint2 > 0 group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select count(*) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(*) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(*) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(*) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(*) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(*) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(*) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(*) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(*), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select count(cint2) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint2) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select s, count(cint2) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint2), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select min(cint2) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint2) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select s, min(cint2) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(cint2) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint2), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select count(cint4) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(cint4) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(cint4) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(cint4), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(cint4) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + +select min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 473 +(1 row) + +select min(cint4) filter (where s != 5) from aggfilter where cint2 is null; + min +-------- + -16291 +(1 row) + +select s, min(cint4) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | -15279 + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + +select s, min(cint4) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+----- + 0 | + 7 | + 4 | + 5 | + 2 | + 6 | + 9 | + 8 | + 1 | + 3 | +(10 rows) + +select s, min(cint4) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+------ + 0 | 701 + 7 | 1695 + 4 | 1821 + 5 | 587 + 2 | 2876 + 6 | 1003 + 9 | 2489 + 8 | 1334 + 1 | 2034 + 3 | 473 +(10 rows) + +select s, min(cint4) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(cint4), s limit 10; + s | min +---+-------- + 0 | -16291 + 7 | -16091 + 4 | -15724 + 5 | + 2 | -15063 + 6 | -14998 + 9 | -14699 + 8 | -14214 + 1 | -12217 + 3 | -9908 +(10 rows) + +select count(s) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(s) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(s) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(s), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(s) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(s) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(s) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(s) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(s) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(10 rows) + +select s, min(s) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select s, min(s) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(s), s limit 10; + s | min +---+----- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + +select count(ss) from aggfilter where cint2 is null; + count +------- + 190 +(1 row) + +select count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + count +------- + 0 +(1 row) + +select count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + count +------- + 92 +(1 row) + +select count(ss) filter (where s != 5) from aggfilter where cint2 is null; + count +------- + 171 +(1 row) + +select s, count(ss) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select s, count(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 0 + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(10 rows) + +select s, count(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 9 + 1 | 12 + 2 | 9 + 3 | 11 + 4 | 5 + 5 | 11 + 6 | 9 + 7 | 7 + 8 | 10 + 9 | 9 +(10 rows) + +select s, count(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by count(ss), s limit 10; + s | count +---+------- + 0 | 19 + 1 | 19 + 2 | 19 + 3 | 19 + 4 | 19 + 5 | 0 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 +(10 rows) + +select min(ss) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where ss > 1000) from aggfilter where cint2 is null; + min +----- + +(1 row) + +select min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select min(ss) filter (where s != 5) from aggfilter where cint2 is null; + min +----- + 0 +(1 row) + +select s, min(ss) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where cint2 < 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where ss > 1000) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 1 | + 2 | +(10 rows) + +select s, min(ss) filter (where cint4 > 0) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + +select s, min(ss) filter (where s != 5) from aggfilter where cint2 is null group by s order by min(ss), s limit 10; + s | min +---+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 1 | 11 + 2 | 11 +(10 rows) + diff --git a/tsl/test/expected/vector_agg_param.out b/tsl/test/expected/vector_agg_param.out index b481d9c8a97..c04e7b682b2 100644 --- a/tsl/test/expected/vector_agg_param.out +++ b/tsl/test/expected/vector_agg_param.out @@ -21,23 +21,40 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; (1 row) analyze pvagg; -explain (costs off) +-- Uncomment to generate reference +--set timescaledb.enable_vectorized_aggregation to off; +explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; - QUERY PLAN ---------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Nested Loop - -> Function Scan on unnest x + Output: x.x, (sum(pvagg.a)) + -> Function Scan on pg_catalog.unnest x + Output: x.x + Function Call: unnest('{0,1,2}'::integer[]) -> Finalize Aggregate - -> Custom Scan (ChunkAppend) on pvagg + Output: sum(pvagg.a) + -> Custom Scan (ChunkAppend) on public.pvagg + Output: (PARTIAL sum(pvagg.a)) + Startup Exclusion: false + Runtime Exclusion: true -> Custom Scan (VectorAgg) - -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk - -> Seq Scan on compress_hyper_2_3_chunk - Filter: (s = x.x) + Output: (PARTIAL sum(_hyper_1_1_chunk.a)) + Grouping Policy: all compressed batches + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk + Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a + Filter: (compress_hyper_2_3_chunk.s = x.x) -> Custom Scan (VectorAgg) - -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk - -> Seq Scan on compress_hyper_2_4_chunk - Filter: (s = x.x) -(12 rows) + Output: (PARTIAL sum(_hyper_1_2_chunk.a)) + Grouping Policy: all compressed batches + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk + Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a + Filter: (compress_hyper_2_4_chunk.s = x.x) +(27 rows) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; x | sum @@ -47,4 +64,48 @@ select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg 2 | 1498500 (3 rows) +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Nested Loop + Output: x.x, (sum((_hyper_1_1_chunk.a + x.x))) + -> Function Scan on pg_catalog.unnest x + Output: x.x + Function Call: unnest('{0,1,2}'::integer[]) + -> Finalize Aggregate + Output: sum((_hyper_1_1_chunk.a + x.x)) + -> Append + -> Partial Aggregate + Output: PARTIAL sum((_hyper_1_1_chunk.a + x.x)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_3_chunk + Output: compress_hyper_2_3_chunk._ts_meta_count, compress_hyper_2_3_chunk.s, compress_hyper_2_3_chunk._ts_meta_min_1, compress_hyper_2_3_chunk._ts_meta_max_1, compress_hyper_2_3_chunk.a + -> Partial Aggregate + Output: PARTIAL sum((_hyper_1_2_chunk.a + x.x)) + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.a + -> Seq Scan on _timescaledb_internal.compress_hyper_2_4_chunk + Output: compress_hyper_2_4_chunk._ts_meta_count, compress_hyper_2_4_chunk.s, compress_hyper_2_4_chunk._ts_meta_min_1, compress_hyper_2_4_chunk._ts_meta_max_1, compress_hyper_2_4_chunk.a +(20 rows) + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + x | sum +---+--------- + 0 | 1998000 + 1 | 1999998 + 2 | 2001996 +(3 rows) + +-- The plan for this query differs after PG16, x is not used as grouping key but +-- just added into the output targetlist of partial aggregation nodes. +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + x | sum +---+--------- + 0 | 1998000 + 1 | 1998000 + 2 | 1998000 +(3 rows) + drop table pvagg; diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 54a712d8c12..4baae6e72af 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -2863,67 +2863,77 @@ SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testta Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) Workers Planned: 2 -> Parallel Append - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_81_chunk.segment_by_value) FILTER (WHERE (_hyper_1_81_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_81_chunk Output: _hyper_1_81_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_91_chunk Output: compress_hyper_2_91_chunk._ts_meta_count, compress_hyper_2_91_chunk.segment_by_value, compress_hyper_2_91_chunk._ts_meta_min_1, compress_hyper_2_91_chunk._ts_meta_max_1, compress_hyper_2_91_chunk."time", compress_hyper_2_91_chunk.int_value, compress_hyper_2_91_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_82_chunk.segment_by_value) FILTER (WHERE (_hyper_1_82_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_82_chunk Output: _hyper_1_82_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_92_chunk Output: compress_hyper_2_92_chunk._ts_meta_count, compress_hyper_2_92_chunk.segment_by_value, compress_hyper_2_92_chunk._ts_meta_min_1, compress_hyper_2_92_chunk._ts_meta_max_1, compress_hyper_2_92_chunk."time", compress_hyper_2_92_chunk.int_value, compress_hyper_2_92_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_83_chunk.segment_by_value) FILTER (WHERE (_hyper_1_83_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_83_chunk Output: _hyper_1_83_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_93_chunk Output: compress_hyper_2_93_chunk._ts_meta_count, compress_hyper_2_93_chunk.segment_by_value, compress_hyper_2_93_chunk._ts_meta_min_1, compress_hyper_2_93_chunk._ts_meta_max_1, compress_hyper_2_93_chunk."time", compress_hyper_2_93_chunk.int_value, compress_hyper_2_93_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_84_chunk.segment_by_value) FILTER (WHERE (_hyper_1_84_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_84_chunk Output: _hyper_1_84_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_94_chunk Output: compress_hyper_2_94_chunk._ts_meta_count, compress_hyper_2_94_chunk.segment_by_value, compress_hyper_2_94_chunk._ts_meta_min_1, compress_hyper_2_94_chunk._ts_meta_max_1, compress_hyper_2_94_chunk."time", compress_hyper_2_94_chunk.int_value, compress_hyper_2_94_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_85_chunk.segment_by_value) FILTER (WHERE (_hyper_1_85_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_85_chunk Output: _hyper_1_85_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_95_chunk Output: compress_hyper_2_95_chunk._ts_meta_count, compress_hyper_2_95_chunk.segment_by_value, compress_hyper_2_95_chunk._ts_meta_min_1, compress_hyper_2_95_chunk._ts_meta_max_1, compress_hyper_2_95_chunk."time", compress_hyper_2_95_chunk.int_value, compress_hyper_2_95_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_86_chunk.segment_by_value) FILTER (WHERE (_hyper_1_86_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_86_chunk Output: _hyper_1_86_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_96_chunk Output: compress_hyper_2_96_chunk._ts_meta_count, compress_hyper_2_96_chunk.segment_by_value, compress_hyper_2_96_chunk._ts_meta_min_1, compress_hyper_2_96_chunk._ts_meta_max_1, compress_hyper_2_96_chunk."time", compress_hyper_2_96_chunk.int_value, compress_hyper_2_96_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_87_chunk.segment_by_value) FILTER (WHERE (_hyper_1_87_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_87_chunk Output: _hyper_1_87_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_97_chunk Output: compress_hyper_2_97_chunk._ts_meta_count, compress_hyper_2_97_chunk.segment_by_value, compress_hyper_2_97_chunk._ts_meta_min_1, compress_hyper_2_97_chunk._ts_meta_max_1, compress_hyper_2_97_chunk."time", compress_hyper_2_97_chunk.int_value, compress_hyper_2_97_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_88_chunk.segment_by_value) FILTER (WHERE (_hyper_1_88_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_88_chunk Output: _hyper_1_88_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_98_chunk Output: compress_hyper_2_98_chunk._ts_meta_count, compress_hyper_2_98_chunk.segment_by_value, compress_hyper_2_98_chunk._ts_meta_min_1, compress_hyper_2_98_chunk._ts_meta_max_1, compress_hyper_2_98_chunk."time", compress_hyper_2_98_chunk.int_value, compress_hyper_2_98_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_89_chunk.segment_by_value) FILTER (WHERE (_hyper_1_89_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_89_chunk Output: _hyper_1_89_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_99_chunk Output: compress_hyper_2_99_chunk._ts_meta_count, compress_hyper_2_99_chunk.segment_by_value, compress_hyper_2_99_chunk._ts_meta_min_1, compress_hyper_2_99_chunk._ts_meta_max_1, compress_hyper_2_99_chunk."time", compress_hyper_2_99_chunk.int_value, compress_hyper_2_99_chunk.float_value - -> Partial Aggregate - Output: PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999)) + -> Custom Scan (VectorAgg) + Output: (PARTIAL sum(_hyper_1_90_chunk.segment_by_value) FILTER (WHERE (_hyper_1_90_chunk.segment_by_value > 99999))) + Grouping Policy: all compressed batches -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_90_chunk Output: _hyper_1_90_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_100_chunk Output: compress_hyper_2_100_chunk._ts_meta_count, compress_hyper_2_100_chunk.segment_by_value, compress_hyper_2_100_chunk._ts_meta_min_1, compress_hyper_2_100_chunk._ts_meta_max_1, compress_hyper_2_100_chunk."time", compress_hyper_2_100_chunk.int_value, compress_hyper_2_100_chunk.float_value -(66 rows) +(76 rows) SET timescaledb.enable_vectorized_aggregation = OFF; SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; @@ -3496,3 +3506,10 @@ SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND (84 rows) RESET max_parallel_workers_per_gather; +-- Can't group by a system column +SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; + sum +------- + 82620 +(1 row) + diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 9cc7e62b84a..fae7a0609d2 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -114,6 +114,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) recompress_chunk_segmentwise.sql feature_flags.sql vector_agg_default.sql + vector_agg_filter.sql vector_agg_segmentby.sql) list( diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql new file mode 100644 index 00000000000..316102ee940 --- /dev/null +++ b/tsl/test/sql/vector_agg_filter.sql @@ -0,0 +1,106 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table aggfilter(t int, s int, + cint2 int2, dropped int4, cint4 int4); +select create_hypertable('aggfilter', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + 1 as dropped, + (mix(s + t * 1021) * 32767)::int4 as cint4 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into aggfilter select * from source where s = 1; + +alter table aggfilter set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('aggfilter') x; + +alter table aggfilter add column ss int default 11; +alter table aggfilter drop column dropped; + +insert into aggfilter +select t, s, cint2, cint4, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1053 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss +from source where s != 1 +; +select count(compress_chunk(x)) from show_chunks('aggfilter') x; +vacuum freeze analyze aggfilter; + + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' filter (where ' || agg_filter || ')', + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 's', + 'ss', + 'cint2', + 'cint4', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 's']) with ordinality as grouping(grouping, n), + unnest(array[ + null, + 'cint2 < 0', + 'ss > 1000', + 'cint4 > 0', + 's != 5']) with ordinality as agg_filter(agg_filter, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n, agg_filter.n +\gexec diff --git a/tsl/test/sql/vector_agg_param.sql b/tsl/test/sql/vector_agg_param.sql index 491a877556d..244718ef27f 100644 --- a/tsl/test/sql/vector_agg_param.sql +++ b/tsl/test/sql/vector_agg_param.sql @@ -18,11 +18,23 @@ select count(compress_chunk(x)) from show_chunks('pvagg') x; analyze pvagg; +-- Uncomment to generate reference +--set timescaledb.enable_vectorized_aggregation to off; -explain (costs off) + +explain (verbose, costs off) select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg where s = x) xx; +explain (verbose, costs off) +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a + x) from pvagg) xx; + +-- The plan for this query differs after PG16, x is not used as grouping key but +-- just added into the output targetlist of partial aggregation nodes. +select * from unnest(array[0, 1, 2]::int[]) x, lateral (select sum(a) from pvagg group by x) xx; + drop table pvagg; diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index c8844932a93..bafecd6b544 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -403,3 +403,7 @@ SET max_parallel_workers_per_gather = 0; SELECT sum(segment_by_value1) FROM testtable2 WHERE segment_by_value1 > 1000 AND int_value > 1000; RESET max_parallel_workers_per_gather; + + +-- Can't group by a system column +SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; From b43be707d2d8b1aff5671f1449aa119cb186edb4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:10:47 +0100 Subject: [PATCH 149/242] Optimize array creation in vectorized aggregate functions We can inline the few lines of code required to create an array, instead of calling the very generic `construct_array` function which shows up in profiles. --- .../function/float48_accum_single.c | 24 +++++++++---------- .../function/int24_avg_accum_templates.c | 16 ++++++++----- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index fed87b958d4..f616f967074 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -69,9 +69,17 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) { FUNCTION_NAME(state) *state = (FUNCTION_NAME(state) *) agg_state; - Datum transdatums[3] = { - Float8GetDatumFast(state->N), - Float8GetDatumFast(state->Sx), + const size_t nbytes = 3 * sizeof(float8) + ARR_OVERHEAD_NONULLS(/* ndims = */ 1); + ArrayType *result = palloc(nbytes); + SET_VARSIZE(result, nbytes); + result->ndim = 1; + result->dataoffset = 0; + result->elemtype = FLOAT8OID; + ARR_DIMS(result)[0] = 3; + ARR_LBOUND(result)[0] = 1; + ((Datum *) ARR_DATA_PTR(result))[0] = Float8GetDatumFast(state->N); + ((Datum *) ARR_DATA_PTR(result))[1] = Float8GetDatumFast(state->Sx); + ((Datum *) ARR_DATA_PTR(result))[2] = /* * Sxx should be NaN if any of the inputs are infinite or NaN. This is * checked by float8_combine even if it's not used for the actual @@ -81,15 +89,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) #ifdef NEED_SXX + state->Sxx #endif - ), - }; - - ArrayType *result = construct_array(transdatums, - 3, - FLOAT8OID, - sizeof(float8), - FLOAT8PASSBYVAL, - TYPALIGN_DOUBLE); + ); *out_result = PointerGetDatum(result); *out_isnull = false; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c index 518a7491aab..2e6db8952e9 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c @@ -42,13 +42,17 @@ int24_avg_accum_emit(void *agg_state, Datum *out_result, bool *out_isnull) { Int24AvgAccumState *state = (Int24AvgAccumState *) agg_state; - Datum transdatums[2] = { - Int64GetDatumFast(state->count), - Int64GetDatumFast(state->sum), - }; + const size_t nbytes = 2 * sizeof(int64) + ARR_OVERHEAD_NONULLS(/* ndims = */ 1); + ArrayType *result = palloc(nbytes); + SET_VARSIZE(result, nbytes); + result->ndim = 1; + result->dataoffset = 0; + result->elemtype = INT8OID; + ARR_DIMS(result)[0] = 2; + ARR_LBOUND(result)[0] = 1; + ((Datum *) ARR_DATA_PTR(result))[0] = Int64GetDatumFast(state->count); + ((Datum *) ARR_DATA_PTR(result))[1] = Int64GetDatumFast(state->sum); - ArrayType *result = - construct_array(transdatums, 2, INT8OID, sizeof(int64), FLOAT8PASSBYVAL, TYPALIGN_DOUBLE); *out_result = PointerGetDatum(result); *out_isnull = false; } From 3f8a8723b1f2e03cee0cf9e5927851c01f097ced Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:59:30 +0100 Subject: [PATCH 150/242] Put vectorized aggregation results in short-lived memory context It is enough to use the per-tuple context for them, now they end up in the ExecutorState context which is incorrect. --- tsl/src/nodes/vector_agg/exec.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 1f198d799a9..2795c6c5be0 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -194,23 +194,30 @@ static TupleTableSlot * vector_agg_exec(CustomScanState *node) { VectorAggState *vector_agg_state = (VectorAggState *) node; + ExprContext *econtext = node->ss.ps.ps_ExprContext; TupleTableSlot *aggregated_slot = vector_agg_state->custom.ss.ps.ps_ResultTupleSlot; ExecClearTuple(aggregated_slot); + /* + * If we have more partial aggregation results, continue returning them. + */ GroupingPolicy *grouping = vector_agg_state->grouping; - if (grouping->gp_do_emit(grouping, aggregated_slot)) + MemoryContext old_context = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); + bool have_partial = grouping->gp_do_emit(grouping, aggregated_slot); + MemoryContextSwitchTo(old_context); + if (have_partial) { /* The grouping policy produced a partial aggregation result. */ return ExecStoreVirtualTuple(aggregated_slot); } + /* + * If the partial aggregation results have ended, and the input has ended, + * we're done. + */ if (vector_agg_state->input_ended) { - /* - * The partial aggregation results have ended, and the input has ended, - * so we're done. - */ return NULL; } @@ -285,7 +292,13 @@ vector_agg_exec(CustomScanState *node) grouping->gp_add_batch(grouping, batch_state); } - if (grouping->gp_do_emit(grouping, aggregated_slot)) + /* + * If we have partial aggregation results, start returning them. + */ + old_context = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); + have_partial = grouping->gp_do_emit(grouping, aggregated_slot); + MemoryContextSwitchTo(old_context); + if (have_partial) { /* Have partial aggregation results. */ return ExecStoreVirtualTuple(aggregated_slot); From 3070e6a064209ee86643c6cfa14f853a05f326cc Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:24:38 +0100 Subject: [PATCH 151/242] add a test --- tsl/src/nodes/vector_agg/plan.c | 10 +++++ tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vector_agg_memory.sql | 59 ++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tsl/test/sql/vector_agg_memory.sql diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index bd0a236de58..2d24cad5a7f 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -380,6 +380,11 @@ has_vector_agg_node(Plan *plan, bool *has_normal_agg) append_plans = custom->custom_plans; } } + else if (IsA(plan, SubqueryScan)) + { + SubqueryScan *subquery = castNode(SubqueryScan, plan); + append_plans = list_make1(subquery->subplan); + } if (append_plans) { @@ -437,6 +442,11 @@ try_insert_vector_agg_node(Plan *plan) append_plans = custom->custom_plans; } } + else if (IsA(plan, SubqueryScan)) + { + SubqueryScan *subquery = castNode(SubqueryScan, plan); + append_plans = list_make1(subquery->subplan); + } if (append_plans) { diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 9cc7e62b84a..50ab7107326 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -114,6 +114,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) recompress_chunk_segmentwise.sql feature_flags.sql vector_agg_default.sql + vector_agg_memory.sql vector_agg_segmentby.sql) list( diff --git a/tsl/test/sql/vector_agg_memory.sql b/tsl/test/sql/vector_agg_memory.sql new file mode 100644 index 00000000000..421cb8e8d51 --- /dev/null +++ b/tsl/test/sql/vector_agg_memory.sql @@ -0,0 +1,59 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER + +-- Helper function that returns the amount of memory currently allocated in a +-- given memory context. +create or replace function ts_debug_allocated_bytes(text = 'PortalContext') returns bigint + as :MODULE_PATHNAME, 'ts_debug_allocated_bytes' + language c strict volatile; + + +create table mvagg (t int, s int); +select create_hypertable('mvagg', 't', chunk_time_interval => pow(10, 9)::int); +insert into mvagg select -1 t, 1 s; -- need two chunks for chunkwise aggregation +insert into mvagg select generate_series(1, 2 * pow(10, 6)::int) t, 1 s; +alter table mvagg set (timescaledb.compress, timescaledb.compress_segmentby='s'); +select count(compress_chunk(x)) from show_chunks('mvagg') x; + +-- We are going to log memory usage as a function of number of aggregated elements +-- here. +create table log(n int, bytes int, a bigint, b bigint, c bigint, d bigint, e bigint); + + +-- Run the vectorized aggregation with grouping by segmentby with various number +-- of input row. We expect approximately constant memory usage. +set timescaledb.debug_require_vector_agg = 'require'; + +\set ECHO none +select +format('insert into log + select %1$s, + ts_debug_allocated_bytes() bytes, + count(*) a, count(t) b, sum(t) c, avg(t) d, stddev(t) e + from mvagg where t < %1$s group by s', + pow(10, generate_series(1, 7))) +\gexec +\set ECHO all + +reset timescaledb.debug_require_vector_agg; + +select * from log; + +select regr_slope(bytes, n), regr_intercept(bytes, n), + avg(bytes / n), + regr_slope(bytes, n) / avg(bytes / n), + regr_slope(bytes, n) / regr_intercept(bytes, n)::float, + regr_slope(bytes, n) / regr_intercept(bytes, n)::float > 0.05 +from log; + +select * from log where ( + -- For aggregation by segmentby, memory usage should be constant regardless + -- of the number of tuples. Still, we have to allow for small variations + -- that can be caused by other reasons. + select regr_slope(bytes, n) > 1/65536 from log +); + +reset timescaledb.debug_require_vector_agg; From a1c333d0929a7077e6d2d1e01e82a04c22152287 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:20:25 +0100 Subject: [PATCH 152/242] everything is so broken --- tsl/src/nodes/vector_agg/exec.c | 1 + tsl/test/sql/vector_agg_memory.sql | 45 +++++++++++++++++++----------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 2795c6c5be0..2da6e21c063 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -195,6 +195,7 @@ vector_agg_exec(CustomScanState *node) { VectorAggState *vector_agg_state = (VectorAggState *) node; ExprContext *econtext = node->ss.ps.ps_ExprContext; + ResetExprContext(econtext); TupleTableSlot *aggregated_slot = vector_agg_state->custom.ss.ps.ps_ResultTupleSlot; ExecClearTuple(aggregated_slot); diff --git a/tsl/test/sql/vector_agg_memory.sql b/tsl/test/sql/vector_agg_memory.sql index 421cb8e8d51..542fc4a8e86 100644 --- a/tsl/test/sql/vector_agg_memory.sql +++ b/tsl/test/sql/vector_agg_memory.sql @@ -11,11 +11,20 @@ create or replace function ts_debug_allocated_bytes(text = 'PortalContext') retu language c strict volatile; -create table mvagg (t int, s int); +create table mvagg (t int, s0 int, s1 int); select create_hypertable('mvagg', 't', chunk_time_interval => pow(10, 9)::int); -insert into mvagg select -1 t, 1 s; -- need two chunks for chunkwise aggregation -insert into mvagg select generate_series(1, 2 * pow(10, 6)::int) t, 1 s; -alter table mvagg set (timescaledb.compress, timescaledb.compress_segmentby='s'); +insert into mvagg select generate_series(1, 2 * pow(10, 6)::int) t, 1 s0, 1 s1; + +-- Need two segmentbys to prevent compressed index scans to force hash aggregation. +-- Otherwise we might get GroupAggregate with Sort which uses linear memory in +-- the number of compressed batches. +alter table mvagg set (timescaledb.compress, timescaledb.compress_segmentby='s0, s1'); +-- Need to inflate the estimated cardinalities of segmentby columns, again to +-- force the hash aggregation. +insert into mvagg select -1 - x t, -x s0, -x s1 from generate_series(1, 1000) x; +-- Need two chunks for chunkwise aggregation. +insert into mvagg select -1 t, 1 s0, 1 s1; + select count(compress_chunk(x)) from show_chunks('mvagg') x; -- We are going to log memory usage as a function of number of aggregated elements @@ -25,7 +34,16 @@ create table log(n int, bytes int, a bigint, b bigint, c bigint, d bigint, e big -- Run the vectorized aggregation with grouping by segmentby with various number -- of input row. We expect approximately constant memory usage. +set max_parallel_workers_per_gather = 0; set timescaledb.debug_require_vector_agg = 'require'; +-- Despite the tweaks above, we are unable to force the HashAggregation, because +-- the unsorted DecompressChunk paths for aggregation are not created properly +-- (see issue #6836). Limit the memory consumed by tuplesort. +set work_mem = '64kB'; + +explain (costs off) select ts_debug_allocated_bytes() bytes, + count(*) a, count(t) b, sum(t) c, avg(t) d, stddev(t) e + from mvagg where t >= -1 and t < 1000000 group by s1; \set ECHO none select @@ -33,27 +51,22 @@ format('insert into log select %1$s, ts_debug_allocated_bytes() bytes, count(*) a, count(t) b, sum(t) c, avg(t) d, stddev(t) e - from mvagg where t < %1$s group by s', + from mvagg where t >= -1 and t < %1$s group by s1', pow(10, generate_series(1, 7))) \gexec \set ECHO all reset timescaledb.debug_require_vector_agg; - -select * from log; - -select regr_slope(bytes, n), regr_intercept(bytes, n), - avg(bytes / n), - regr_slope(bytes, n) / avg(bytes / n), - regr_slope(bytes, n) / regr_intercept(bytes, n)::float, - regr_slope(bytes, n) / regr_intercept(bytes, n)::float > 0.05 -from log; +reset max_parallel_workers_per_gather; +reset work_mem; select * from log where ( -- For aggregation by segmentby, memory usage should be constant regardless -- of the number of tuples. Still, we have to allow for small variations - -- that can be caused by other reasons. - select regr_slope(bytes, n) > 1/65536 from log + -- that can be caused by other reasons. Currently the major increase is + -- caused by tuplesort, because we are unable to force hash aggregation due + -- to unrelated planning bugs. + select regr_slope(bytes, n) > 0.05 from log ); reset timescaledb.debug_require_vector_agg; From 89e53c9ead06871ff5ea2ef645b84634a8554405 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:26:59 +0100 Subject: [PATCH 153/242] check the decompression memory usage as well --- tsl/test/sql/vector_agg_memory.sql | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tsl/test/sql/vector_agg_memory.sql b/tsl/test/sql/vector_agg_memory.sql index 542fc4a8e86..38207ffd9c9 100644 --- a/tsl/test/sql/vector_agg_memory.sql +++ b/tsl/test/sql/vector_agg_memory.sql @@ -32,8 +32,33 @@ select count(compress_chunk(x)) from show_chunks('mvagg') x; create table log(n int, bytes int, a bigint, b bigint, c bigint, d bigint, e bigint); --- Run the vectorized aggregation with grouping by segmentby with various number +-- First, ensure that the underlying decompression has constant memory usage. +explain (costs off) select distinct on (s0, s1) ts_debug_allocated_bytes() bytes, + s0, s1, t + from mvagg where t >= -1 and t < 1000000 order by s0, s1, t desc; + +truncate log; +\set ECHO none +select +format('insert into log + select distinct on (s0, s1) %1$s, + ts_debug_allocated_bytes() bytes, + 0 a, 0 b, 0 c, 0 d, 0 e + from mvagg where t >= -1 and t < %1$s + order by s0, s1, t desc', + pow(10, generate_series(1, 7))) +\gexec +\set ECHO all + +select * from log where ( + -- Ideally the memory usage should be constant, but we have to allow for + -- small spurious changes to make this test more robust. + select regr_slope(bytes, n) > 1/65536 from log +); + +-- Test the vectorized aggregation with grouping by segmentby with various number -- of input row. We expect approximately constant memory usage. +truncate log; set max_parallel_workers_per_gather = 0; set timescaledb.debug_require_vector_agg = 'require'; -- Despite the tweaks above, we are unable to force the HashAggregation, because @@ -51,7 +76,7 @@ format('insert into log select %1$s, ts_debug_allocated_bytes() bytes, count(*) a, count(t) b, sum(t) c, avg(t) d, stddev(t) e - from mvagg where t >= -1 and t < %1$s group by s1', + from mvagg where t >= -1 and t < %1$s group by s1', pow(10, generate_series(1, 7))) \gexec \set ECHO all From 20b37b0110e0ba73a74ba237949142736558a140 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:40:31 +0100 Subject: [PATCH 154/242] add the ref --- tsl/test/expected/vector_agg_memory.out | 120 ++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tsl/test/expected/vector_agg_memory.out diff --git a/tsl/test/expected/vector_agg_memory.out b/tsl/test/expected/vector_agg_memory.out new file mode 100644 index 00000000000..d928c06c4e9 --- /dev/null +++ b/tsl/test/expected/vector_agg_memory.out @@ -0,0 +1,120 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- Helper function that returns the amount of memory currently allocated in a +-- given memory context. +create or replace function ts_debug_allocated_bytes(text = 'PortalContext') returns bigint + as :MODULE_PATHNAME, 'ts_debug_allocated_bytes' + language c strict volatile; +create table mvagg (t int, s0 int, s1 int); +select create_hypertable('mvagg', 't', chunk_time_interval => pow(10, 9)::int); +NOTICE: adding not-null constraint to column "t" + create_hypertable +-------------------- + (1,public,mvagg,t) +(1 row) + +insert into mvagg select generate_series(1, 2 * pow(10, 6)::int) t, 1 s0, 1 s1; +-- Need two segmentbys to prevent compressed index scans to force hash aggregation. +-- Otherwise we might get GroupAggregate with Sort which uses linear memory in +-- the number of compressed batches. +alter table mvagg set (timescaledb.compress, timescaledb.compress_segmentby='s0, s1'); +NOTICE: default order by for hypertable "mvagg" is set to "t DESC" +-- Need to inflate the estimated cardinalities of segmentby columns, again to +-- force the hash aggregation. +insert into mvagg select -1 - x t, -x s0, -x s1 from generate_series(1, 1000) x; +-- Need two chunks for chunkwise aggregation. +insert into mvagg select -1 t, 1 s0, 1 s1; +select count(compress_chunk(x)) from show_chunks('mvagg') x; + count +------- + 2 +(1 row) + +-- We are going to log memory usage as a function of number of aggregated elements +-- here. +create table log(n int, bytes int, a bigint, b bigint, c bigint, d bigint, e bigint); +-- First, ensure that the underlying decompression has constant memory usage. +explain (costs off) select distinct on (s0, s1) ts_debug_allocated_bytes() bytes, + s0, s1, t + from mvagg where t >= -1 and t < 1000000 order by s0, s1, t desc; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------- + Result + -> Unique + -> Merge Append + Sort Key: _hyper_1_1_chunk.s0, _hyper_1_1_chunk.s1, _hyper_1_1_chunk.t DESC + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk + Vectorized Filter: ((t >= '-1'::integer) AND (t < 1000000)) + -> Index Scan using compress_hyper_2_3_chunk_s0_s1__ts_meta_min_1__ts_meta_max__idx on compress_hyper_2_3_chunk + Index Cond: ((_ts_meta_min_1 < 1000000) AND (_ts_meta_max_1 >= '-1'::integer)) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk + Vectorized Filter: ((t >= '-1'::integer) AND (t < 1000000)) + -> Index Scan using compress_hyper_2_4_chunk_s0_s1__ts_meta_min_1__ts_meta_max__idx on compress_hyper_2_4_chunk + Index Cond: ((_ts_meta_min_1 < 1000000) AND (_ts_meta_max_1 >= '-1'::integer)) +(12 rows) + +truncate log; +\set ECHO none +select * from log where ( + -- Ideally the memory usage should be constant, but we have to allow for + -- small spurious changes to make this test more robust. + select regr_slope(bytes, n) > 1/65536 from log +); + n | bytes | a | b | c | d | e +---+-------+---+---+---+---+--- +(0 rows) + +-- Test the vectorized aggregation with grouping by segmentby with various number +-- of input row. We expect approximately constant memory usage. +truncate log; +set max_parallel_workers_per_gather = 0; +set timescaledb.debug_require_vector_agg = 'require'; +-- Despite the tweaks above, we are unable to force the HashAggregation, because +-- the unsorted DecompressChunk paths for aggregation are not created properly +-- (see issue #6836). Limit the memory consumed by tuplesort. +set work_mem = '64kB'; +explain (costs off) select ts_debug_allocated_bytes() bytes, + count(*) a, count(t) b, sum(t) c, avg(t) d, stddev(t) e + from mvagg where t >= -1 and t < 1000000 group by s1; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------ + Finalize GroupAggregate + Group Key: _hyper_1_1_chunk.s1 + -> Sort + Sort Key: _hyper_1_1_chunk.s1 + -> Append + -> Custom Scan (VectorAgg) + -> Custom Scan (DecompressChunk) on _hyper_1_1_chunk + Vectorized Filter: ((t >= '-1'::integer) AND (t < 1000000)) + -> Sort + Sort Key: compress_hyper_2_3_chunk.s1 + -> Seq Scan on compress_hyper_2_3_chunk + Filter: ((_ts_meta_max_1 >= '-1'::integer) AND (_ts_meta_min_1 < 1000000)) + -> Custom Scan (VectorAgg) + -> Custom Scan (DecompressChunk) on _hyper_1_2_chunk + Vectorized Filter: ((t >= '-1'::integer) AND (t < 1000000)) + -> Sort + Sort Key: compress_hyper_2_4_chunk.s1 + -> Seq Scan on compress_hyper_2_4_chunk + Filter: ((_ts_meta_max_1 >= '-1'::integer) AND (_ts_meta_min_1 < 1000000)) +(19 rows) + +\set ECHO none +reset timescaledb.debug_require_vector_agg; +reset max_parallel_workers_per_gather; +reset work_mem; +select * from log where ( + -- For aggregation by segmentby, memory usage should be constant regardless + -- of the number of tuples. Still, we have to allow for small variations + -- that can be caused by other reasons. Currently the major increase is + -- caused by tuplesort, because we are unable to force hash aggregation due + -- to unrelated planning bugs. + select regr_slope(bytes, n) > 0.05 from log +); + n | bytes | a | b | c | d | e +---+-------+---+---+---+---+--- +(0 rows) + +reset timescaledb.debug_require_vector_agg; From e0f9dbd83d43b598190547072b13e3c313cdf5d4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:49:57 +0100 Subject: [PATCH 155/242] fix for i386 --- .../vector_agg/function/float48_accum_single.c | 17 +++++++++++------ .../function/int24_avg_accum_templates.c | 9 +++++++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index f616f967074..0bdcd928593 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -77,19 +77,24 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull) result->elemtype = FLOAT8OID; ARR_DIMS(result)[0] = 3; ARR_LBOUND(result)[0] = 1; - ((Datum *) ARR_DATA_PTR(result))[0] = Float8GetDatumFast(state->N); - ((Datum *) ARR_DATA_PTR(result))[1] = Float8GetDatumFast(state->Sx); - ((Datum *) ARR_DATA_PTR(result))[2] = + + /* + * The array elements are stored by value, regardless of if the float8 + * itself is by-value on this platform. + */ + ((float8 *) ARR_DATA_PTR(result))[0] = state->N; + ((float8 *) ARR_DATA_PTR(result))[1] = state->Sx; + ((float8 *) ARR_DATA_PTR(result))[2] = /* * Sxx should be NaN if any of the inputs are infinite or NaN. This is * checked by float8_combine even if it's not used for the actual * calculations. */ - Float8GetDatum(0. * state->Sx + 0. * state->Sx #ifdef NEED_SXX - + state->Sxx + + state->Sxx #endif - ); + ; *out_result = PointerGetDatum(result); *out_isnull = false; diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c index 2e6db8952e9..e0851b4f008 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_templates.c @@ -50,8 +50,13 @@ int24_avg_accum_emit(void *agg_state, Datum *out_result, bool *out_isnull) result->elemtype = INT8OID; ARR_DIMS(result)[0] = 2; ARR_LBOUND(result)[0] = 1; - ((Datum *) ARR_DATA_PTR(result))[0] = Int64GetDatumFast(state->count); - ((Datum *) ARR_DATA_PTR(result))[1] = Int64GetDatumFast(state->sum); + + /* + * The array elements are stored by value, regardless of if the int8 itself + * is by-value on this platform. + */ + ((int64 *) ARR_DATA_PTR(result))[0] = state->count; + ((int64 *) ARR_DATA_PTR(result))[1] = state->sum; *out_result = PointerGetDatum(result); *out_isnull = false; From 7151ecc1c64b3b7980ad47ef0a7ac53bd74a9361 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:35:39 +0100 Subject: [PATCH 156/242] experiments with alignment in serialized strategy --- .../hashing/hash_strategy_serialized.c | 53 ++++++++++++++++--- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index ab99f3e8382..0bc5f5431db 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -86,7 +86,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { - num_bytes += def->value_bytes; + num_bytes = TYPEALIGN(def->value_bytes, num_bytes) + def->value_bytes; } else { @@ -106,6 +106,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { + num_bytes = TYPEALIGN(column_values->decompression_type, num_bytes); num_bytes += column_values->decompression_type; } else @@ -184,6 +185,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { + offset = TYPEALIGN(def->value_bytes, offset); memcpy(&serialized_key_storage[offset], column_values->output_value, def->value_bytes); @@ -221,10 +223,28 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { Assert(offset <= UINT_MAX - column_values->decompression_type); + offset = TYPEALIGN(column_values->decompression_type, offset); + Assert(offset <= UINT_MAX - column_values->decompression_type); + + switch ((int) column_values->decompression_type) + { + case 2: + *(int16 *) &serialized_key_storage[offset] = + ((int16 *) column_values->buffers[1])[row]; + break; + case 4: + *(int32 *) &serialized_key_storage[offset] = + ((int32 *) column_values->buffers[1])[row]; + break; + case 8: + *(int64 *) &serialized_key_storage[offset] = + ((int64 *) column_values->buffers[1])[row]; + break; + default: + pg_unreachable(); + break; + } - memcpy(&serialized_key_storage[offset], - ((char *) column_values->buffers[1]) + column_values->decompression_type * row, - column_values->decompression_type); offset += column_values->decompression_type; continue; @@ -345,12 +365,29 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl } Datum *output = &aggregated_slot->tts_values[col->output_offset]; - if (col->by_value) + if (col->value_bytes > 0) { - Assert(col->value_bytes > 0); + Assert(col->by_value); Assert((size_t) col->value_bytes <= sizeof(Datum)); - *output = 0; - memcpy(output, ptr, col->value_bytes); + + ptr = (const uint8 *) TYPEALIGN(col->value_bytes, ptr); + + switch (col->value_bytes) + { + case 2: + *(int16 *) output = *(int16 *) ptr; + break; + case 4: + *(int32 *) output = *(int32 *) ptr; + break; + case 8: + *(int64 *) output = *(int64 *) ptr; + break; + default: + pg_unreachable(); + break; + } + ptr += col->value_bytes; } else From 89e582ea1403dadd0c41aebcb4aee11b81a13659 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:35:51 +0100 Subject: [PATCH 157/242] Revert "experiments with alignment in serialized strategy" This reverts commit 7151ecc1c64b3b7980ad47ef0a7ac53bd74a9361. --- .../hashing/hash_strategy_serialized.c | 53 +++---------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index 0bc5f5431db..ab99f3e8382 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -86,7 +86,7 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { - num_bytes = TYPEALIGN(def->value_bytes, num_bytes) + def->value_bytes; + num_bytes += def->value_bytes; } else { @@ -106,7 +106,6 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { - num_bytes = TYPEALIGN(column_values->decompression_type, num_bytes); num_bytes += column_values->decompression_type; } else @@ -185,7 +184,6 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; if (def->by_value) { - offset = TYPEALIGN(def->value_bytes, offset); memcpy(&serialized_key_storage[offset], column_values->output_value, def->value_bytes); @@ -223,28 +221,10 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { Assert(offset <= UINT_MAX - column_values->decompression_type); - offset = TYPEALIGN(column_values->decompression_type, offset); - Assert(offset <= UINT_MAX - column_values->decompression_type); - - switch ((int) column_values->decompression_type) - { - case 2: - *(int16 *) &serialized_key_storage[offset] = - ((int16 *) column_values->buffers[1])[row]; - break; - case 4: - *(int32 *) &serialized_key_storage[offset] = - ((int32 *) column_values->buffers[1])[row]; - break; - case 8: - *(int64 *) &serialized_key_storage[offset] = - ((int64 *) column_values->buffers[1])[row]; - break; - default: - pg_unreachable(); - break; - } + memcpy(&serialized_key_storage[offset], + ((char *) column_values->buffers[1]) + column_values->decompression_type * row, + column_values->decompression_type); offset += column_values->decompression_type; continue; @@ -365,29 +345,12 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl } Datum *output = &aggregated_slot->tts_values[col->output_offset]; - if (col->value_bytes > 0) + if (col->by_value) { - Assert(col->by_value); + Assert(col->value_bytes > 0); Assert((size_t) col->value_bytes <= sizeof(Datum)); - - ptr = (const uint8 *) TYPEALIGN(col->value_bytes, ptr); - - switch (col->value_bytes) - { - case 2: - *(int16 *) output = *(int16 *) ptr; - break; - case 4: - *(int32 *) output = *(int32 *) ptr; - break; - case 8: - *(int64 *) output = *(int64 *) ptr; - break; - default: - pg_unreachable(); - break; - } - + *output = 0; + memcpy(output, ptr, col->value_bytes); ptr += col->value_bytes; } else From a3b861385083c0f310353d0f1d94820c238e77ef Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:08:46 +0100 Subject: [PATCH 158/242] new bad filtering of all-matching or no-matching bitmap words --- .../nodes/decompress_chunk/compressed_batch.h | 2 +- .../decompress_chunk/vector_predicates.h | 2 +- .../nodes/vector_agg/grouping_policy_hash.c | 104 ++++++++++++------ 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.h b/tsl/src/nodes/decompress_chunk/compressed_batch.h index 9871503e37c..dcacc40a8a0 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.h +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.h @@ -103,7 +103,7 @@ typedef struct DecompressBatchState * row. Indexed same as arrow arrays, w/o accounting for the reverse scan * direction. Initialized to all ones, i.e. all rows pass. */ - uint64 *restrict vector_qual_result; + const uint64 *restrict vector_qual_result; /* * This follows DecompressContext.compressed_chunk_columns, but does not diff --git a/tsl/src/nodes/decompress_chunk/vector_predicates.h b/tsl/src/nodes/decompress_chunk/vector_predicates.h index cace90dbc44..204177c07a7 100644 --- a/tsl/src/nodes/decompress_chunk/vector_predicates.h +++ b/tsl/src/nodes/decompress_chunk/vector_predicates.h @@ -26,7 +26,7 @@ typedef enum VectorQualSummary } VectorQualSummary; static pg_attribute_always_inline VectorQualSummary -get_vector_qual_summary(uint64 *restrict qual_result, size_t n_rows) +get_vector_qual_summary(const uint64 *qual_result, size_t n_rows) { bool any_rows_pass = false; bool all_rows_pass = true; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 779a658e097..0ce056a189a 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -220,6 +220,31 @@ compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState } } +static VectorQualSummary +get_filter_word_summary(const uint64 *filter, int word, int total_rows) +{ + uint64 all_pass = ~((uint64) 0); + if ((word + 1) * 64 > total_rows) + { + Assert((word + 1) * 64 - total_rows < 64); + all_pass >>= 64 - total_rows % 64; + + // fprintf(stderr, "last word! ap %lx bitmap %lx\n", all_pass, filter[word]); + } + + if (filter[word] == 0) + { + return NoRowsPass; + } + + if (filter[word] == all_pass) + { + return AllRowsPass; + } + + return SomeRowsPass; +} + static void add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, const int start_row, const int end_row) @@ -355,47 +380,54 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } else { - /* - * If we have a filter, skip the rows for which the entire words of the - * filter bitmap are zero. This improves performance for highly - * selective filters. - */ - int stat_range_rows = 0; - int start_word = 0; - int end_word = 0; - int past_the_end_word = (n - 1) / 64 + 1; - for (;;) - { - for (start_word = end_word; start_word < past_the_end_word && filter[start_word] == 0; - start_word++) - ; + const int past_the_end_word = (n - 1) / 64 + 1; - if (start_word >= past_the_end_word) + int range_end_word; + for (int range_start_word = 0; range_start_word < past_the_end_word; + range_start_word = range_end_word) + { + VectorQualSummary range_start_summary = + get_filter_word_summary(filter, range_start_word, n); + VectorQualSummary range_end_summary = range_start_summary; + for (range_end_word = range_start_word + 1; range_end_word < past_the_end_word; + range_end_word++) { - break; + range_end_summary = get_filter_word_summary(filter, range_end_word, n); + if (range_end_summary != range_start_summary) + { + /* + * We have different vector qual summary for this word than the + * current range. Add it and start the new one. + */ + break; + } } - for (end_word = start_word + 1; end_word < past_the_end_word && filter[end_word] != 0; - end_word++) - ; - - const int start_row = start_word * 64 + pg_rightmost_one_pos64(filter[start_word]); - Assert(start_row <= n); - - /* - * The bits for past-the-end rows must be set to zero, so this - * calculation should yield no more than n. - */ - Assert(end_word > start_word); - const int end_row = - (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; - Assert(end_row <= n); - - stat_range_rows += end_row - start_row; - - add_one_range(policy, batch_state, start_row, end_row); + Assert(range_end_word > range_start_word); + // fprintf(stderr, "range [%d,%d) summary %d\n", range_start_word, range_end_word, + // range_start_summary); + if (range_start_summary != NoRowsPass) + { + if (range_start_summary == SomeRowsPass) + { + batch_state->vector_qual_result = filter; + } + else + { + Assert(range_start_summary == AllRowsPass); + batch_state->vector_qual_result = NULL; + } + add_one_range(policy, + batch_state, + range_start_word * 64, + MIN(range_end_word * 64, n)); + } + else + { + policy->stat_bulk_filtered_rows += + MIN(range_end_word * 64, n) - range_start_word * 64; + } } - policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - stat_range_rows; } policy->stat_input_total_rows += batch_state->total_batch_rows; From 074195e368ec969dbc1c229cdc58dc45e2af1b5b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:09:30 +0100 Subject: [PATCH 159/242] bitmap at the beginning in the serialized policy --- .../hashing/hash_strategy_serialized.c | 169 +++++++++++++----- .../hashing/hash_strategy_single_text.c | 4 +- tsl/test/expected/vector_agg_grouping.out | 35 ++++ tsl/test/sql/vector_agg_grouping.sql | 15 ++ 4 files changed, 173 insertions(+), 50 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index ab99f3e8382..e73708966aa 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -65,15 +65,15 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const int num_columns = params.num_grouping_columns; - size_t bitmap_bytes = (num_columns + 7) / 8; - uint8 *restrict serialized_key_validity_bitmap; + const size_t bitmap_bytes = (num_columns + 7) / 8; /* * Loop through the grouping columns to determine the length of the key. We * need that to allocate memory to store it. + * + * The key has the null bitmap at the beginning. */ - size_t num_bytes = 0; - num_bytes += VARHDRSZ; + size_t num_bytes = bitmap_bytes; for (int column_index = 0; column_index < num_columns; column_index++) { const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; @@ -90,7 +90,23 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key } else { - num_bytes = TYPEALIGN(4, num_bytes) + VARSIZE_ANY(*column_values->output_value); + /* + * The default value always has a long varlena header, but + * we are going to use short if it fits. + */ + const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, unaligned. */ + const int total_bytes = value_bytes + VARHDRSZ_SHORT; + num_bytes += total_bytes; + } + else + { + /* Long varlena, requires alignment. */ + const int total_bytes = value_bytes + VARHDRSZ; + num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; + } } } @@ -118,30 +134,37 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key const uint32 data_row = (column_values->decompression_type == DT_ArrowTextDict) ? ((int16 *) column_values->buffers[3])[row] : row; - const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; - int32 total_bytes; if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) { /* Short varlena, unaligned. */ - total_bytes = value_bytes + VARHDRSZ_SHORT; + const int total_bytes = value_bytes + VARHDRSZ_SHORT; num_bytes += total_bytes; } else { /* Long varlena, requires alignment. */ - total_bytes = value_bytes + VARHDRSZ; + const int total_bytes = value_bytes + VARHDRSZ; num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; } } } /* - * The key has a null bitmap at the end. + * The key has short or long varlena header. This is a little tricky, we + * decide the header length after we have counted all the columns, but we + * put it at the beginning. Technically it could change the length because + * of the alignment. In practice, we only use alignment by 4 bytes for long + * varlena strings, and if we have at least one long varlena string column, + * the key is also going to use the long varlena header which is 4 bytes, so + * the alignment is not affected. If we use the short varlena header for the + * key, it necessarily means that there were no long varlena columns and + * therefore no alignment is needed. */ - num_bytes += bitmap_bytes; + const bool key_uses_short_header = num_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX; + num_bytes += key_uses_short_header ? VARHDRSZ_SHORT : VARHDRSZ; /* * Use temporary storage for the new key, reallocate if it's too small. @@ -158,18 +181,23 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key uint8 *restrict serialized_key_storage = policy->tmp_key_storage; /* - * Have to memset the key with zeros, so that the alignment bytes are zeroed - * out. + * Build the actual grouping key. */ - memset(serialized_key_storage, 0, num_bytes); + uint32 offset = 0; + offset += key_uses_short_header ? VARHDRSZ_SHORT : VARHDRSZ; - serialized_key_validity_bitmap = &serialized_key_storage[num_bytes - bitmap_bytes]; + /* + * We must always save the validity bitmap, even when there are no + * null words, so that the key is uniquely deserializable. Otherwise a key + * with some nulls might collide with a key with no nulls. + */ + uint8 *restrict serialized_key_validity_bitmap = &serialized_key_storage[offset]; + offset += bitmap_bytes; /* - * Loop through the grouping columns again and build the actual key. + * Loop through the grouping columns again and add their values to the + * grouping key. */ - uint32 offset = 0; - offset += VARHDRSZ; for (int column_index = 0; column_index < num_columns; column_index++) { const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; @@ -193,17 +221,32 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key else { /* - * FIXME this is not consistent with non-scalar values, add - * a test (how??? it differentiates equal keys, not equates - * different ones). + * The default value always has a long varlena header, but + * we are going to use short if it fits. */ - offset = TYPEALIGN(4, offset); + const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, no alignment. */ + const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; + SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ_SHORT; + } + else + { + /* Long varlena, requires alignment. Zero out the alignment bytes. */ + memset(&serialized_key_storage[offset], 0, 4); + offset = TYPEALIGN(4, offset); + const int32 total_bytes = value_bytes + VARHDRSZ; + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ; + } memcpy(&serialized_key_storage[offset], - DatumGetPointer(*column_values->output_value), - VARSIZE_ANY(*column_values->output_value)); + VARDATA_ANY(*column_values->output_value), + value_bytes); - offset += VARSIZE_ANY(*column_values->output_value); + offset += value_bytes; } } continue; @@ -222,9 +265,28 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key { Assert(offset <= UINT_MAX - column_values->decompression_type); - memcpy(&serialized_key_storage[offset], - ((char *) column_values->buffers[1]) + column_values->decompression_type * row, - column_values->decompression_type); + switch ((int) column_values->decompression_type) + { + case 2: + memcpy(&serialized_key_storage[offset], + row + (int16 *) column_values->buffers[1], + 2); + break; + case 4: + memcpy(&serialized_key_storage[offset], + row + (int32 *) column_values->buffers[1], + 4); + break; + case 8: + memcpy(&serialized_key_storage[offset], + row + (int64 *) column_values->buffers[1], + 8); + break; + default: + pg_unreachable(); + break; + } + offset += column_values->decompression_type; continue; @@ -248,7 +310,8 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key } else { - /* Long varlena, requires alignment. */ + /* Long varlena, requires alignment. Zero out the alignment bytes. */ + memset(&serialized_key_storage[offset], 0, 4); offset = TYPEALIGN(4, offset); const int32 total_bytes = value_bytes + VARHDRSZ; SET_VARSIZE(&serialized_key_storage[offset], total_bytes); @@ -261,16 +324,17 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key offset += value_bytes; } - Assert(&serialized_key_storage[offset] == (void *) serialized_key_validity_bitmap); - - /* - * Note that we must always save the validity bitmap, even when there are no - * null words, so that the key is uniquely deserializable. Otherwise a key - * with some nulls might collide with a key with no nulls. - */ - offset += bitmap_bytes; Assert(offset == num_bytes); + if (key_uses_short_header) + { + SET_VARSIZE_SHORT(serialized_key_storage, offset); + } + else + { + SET_VARSIZE(serialized_key_storage, offset); + } + DEBUG_PRINT("key is %d bytes: ", offset); for (size_t i = 0; i < offset; i++) { @@ -278,10 +342,10 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key } DEBUG_PRINT("\n"); - SET_VARSIZE(serialized_key_storage, offset); - *output_key = (text *) serialized_key_storage; + Assert(VARSIZE_ANY(*output_key) == num_bytes); + /* * The multi-column key is always considered non-null, and the null flags * for the individual columns are stored in a bitmap that is part of the @@ -319,16 +383,24 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl const int num_key_columns = policy->num_grouping_columns; const Datum serialized_key_datum = policy->hashing.output_keys[current_key]; const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); - const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); + PG_USED_FOR_ASSERTS_ONLY const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); const uint8 *restrict ptr = serialized_key; + + /* + * We have the column validity bitmap at the beginning of the key. + */ const int bitmap_bytes = (num_key_columns + 7) / 8; Assert(bitmap_bytes <= key_data_bytes); - const uint8 *restrict key_validity_bitmap = &serialized_key[key_data_bytes - bitmap_bytes]; - - DEBUG_PRINT("emit key #%d, without header %d bytes: ", current_key, key_data_bytes); - for (int i = 0; i < key_data_bytes; i++) + const uint8 *restrict key_validity_bitmap = serialized_key; + ptr += bitmap_bytes; + + DEBUG_PRINT("emit key #%d, with header %ld without %d bytes: ", + current_key, + VARSIZE_ANY(serialized_key_datum), + key_data_bytes); + for (size_t i = 0; i < VARSIZE_ANY(serialized_key_datum); i++) { - DEBUG_PRINT("%.2x.", ptr[i]); + DEBUG_PRINT("%.2x.", ((const uint8 *) serialized_key_datum)[i]); } DEBUG_PRINT("\n"); @@ -345,9 +417,9 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl } Datum *output = &aggregated_slot->tts_values[col->output_offset]; - if (col->by_value) + if (col->value_bytes > 0) { - Assert(col->value_bytes > 0); + Assert(col->by_value); Assert((size_t) col->value_bytes <= sizeof(Datum)); *output = 0; memcpy(output, ptr, col->value_bytes); @@ -356,6 +428,7 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl else { Assert(col->value_bytes == -1); + Assert(!col->by_value); if (VARATT_IS_SHORT(ptr)) { *output = PointerGetDatum(ptr); @@ -370,7 +443,7 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl } } - Assert(ptr == key_validity_bitmap); + Assert(ptr == serialized_key + key_data_bytes); } #include "output_key_alloc.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 68eb42c55f7..6963063c054 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -65,9 +65,9 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke } DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", - policy, + params.policy, row, - policy->last_used_key_index + 1, + params.policy->last_used_key_index + 1, output_key->len); for (size_t i = 0; i < output_key->len; i++) { diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index 5601efd9474..a4bdc3bed86 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -1948,3 +1948,38 @@ select x, min(cint2) from agggroup where cint2 is null and x is null group by x (0 rows) reset timescaledb.debug_require_vector_agg; +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +------------------- + (3,public,long,t) +(1 row) + +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes +NOTICE: default segment by for hypertable "long" is set to "" +NOTICE: default order by for hypertable "long" is set to "t DESC" +select count(compress_chunk(x)) from show_chunks('long') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; + count +------- + 1 + 1 + 1 + 1 + 1 +(5 rows) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index 25253921c47..e087e54c48e 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -109,3 +109,18 @@ order by explain, condition.n, variable, function, grouping.n \gexec reset timescaledb.debug_require_vector_agg; + + +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +select count(compress_chunk(x)) from show_chunks('long') x; + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; +reset timescaledb.debug_require_vector_agg; From 5892267bafa30ef80c97c8541fd246995ecb45bb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:11:35 +0100 Subject: [PATCH 160/242] return the old no-match bitmap skipping --- .../nodes/vector_agg/grouping_policy_hash.c | 104 ++++++------------ 1 file changed, 36 insertions(+), 68 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 0ce056a189a..779a658e097 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -220,31 +220,6 @@ compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState } } -static VectorQualSummary -get_filter_word_summary(const uint64 *filter, int word, int total_rows) -{ - uint64 all_pass = ~((uint64) 0); - if ((word + 1) * 64 > total_rows) - { - Assert((word + 1) * 64 - total_rows < 64); - all_pass >>= 64 - total_rows % 64; - - // fprintf(stderr, "last word! ap %lx bitmap %lx\n", all_pass, filter[word]); - } - - if (filter[word] == 0) - { - return NoRowsPass; - } - - if (filter[word] == all_pass) - { - return AllRowsPass; - } - - return SomeRowsPass; -} - static void add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, const int start_row, const int end_row) @@ -380,54 +355,47 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) } else { - const int past_the_end_word = (n - 1) / 64 + 1; - - int range_end_word; - for (int range_start_word = 0; range_start_word < past_the_end_word; - range_start_word = range_end_word) + /* + * If we have a filter, skip the rows for which the entire words of the + * filter bitmap are zero. This improves performance for highly + * selective filters. + */ + int stat_range_rows = 0; + int start_word = 0; + int end_word = 0; + int past_the_end_word = (n - 1) / 64 + 1; + for (;;) { - VectorQualSummary range_start_summary = - get_filter_word_summary(filter, range_start_word, n); - VectorQualSummary range_end_summary = range_start_summary; - for (range_end_word = range_start_word + 1; range_end_word < past_the_end_word; - range_end_word++) - { - range_end_summary = get_filter_word_summary(filter, range_end_word, n); - if (range_end_summary != range_start_summary) - { - /* - * We have different vector qual summary for this word than the - * current range. Add it and start the new one. - */ - break; - } - } + for (start_word = end_word; start_word < past_the_end_word && filter[start_word] == 0; + start_word++) + ; - Assert(range_end_word > range_start_word); - // fprintf(stderr, "range [%d,%d) summary %d\n", range_start_word, range_end_word, - // range_start_summary); - if (range_start_summary != NoRowsPass) - { - if (range_start_summary == SomeRowsPass) - { - batch_state->vector_qual_result = filter; - } - else - { - Assert(range_start_summary == AllRowsPass); - batch_state->vector_qual_result = NULL; - } - add_one_range(policy, - batch_state, - range_start_word * 64, - MIN(range_end_word * 64, n)); - } - else + if (start_word >= past_the_end_word) { - policy->stat_bulk_filtered_rows += - MIN(range_end_word * 64, n) - range_start_word * 64; + break; } + + for (end_word = start_word + 1; end_word < past_the_end_word && filter[end_word] != 0; + end_word++) + ; + + const int start_row = start_word * 64 + pg_rightmost_one_pos64(filter[start_word]); + Assert(start_row <= n); + + /* + * The bits for past-the-end rows must be set to zero, so this + * calculation should yield no more than n. + */ + Assert(end_word > start_word); + const int end_row = + (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; + Assert(end_row <= n); + + stat_range_rows += end_row - start_row; + + add_one_range(policy, batch_state, start_row, end_row); } + policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - stat_range_rows; } policy->stat_input_total_rows += batch_state->total_batch_rows; From 61afdb838a7d9d7b32fe7135e59e0bc8eaf05d44 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:31:55 +0100 Subject: [PATCH 161/242] cleanup --- .../nodes/vector_agg/grouping_policy_hash.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 779a658e097..3b02a795ec6 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -360,12 +360,15 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) * filter bitmap are zero. This improves performance for highly * selective filters. */ - int stat_range_rows = 0; + int statistics_range_row = 0; int start_word = 0; int end_word = 0; int past_the_end_word = (n - 1) / 64 + 1; for (;;) { + /* + * Skip the bitmap words which are zero. + */ for (start_word = end_word; start_word < past_the_end_word && filter[start_word] == 0; start_word++) ; @@ -375,10 +378,20 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) break; } + /* + * Collect the consecutive bitmap words which are nonzero. + */ for (end_word = start_word + 1; end_word < past_the_end_word && filter[end_word] != 0; end_word++) ; + /* + * Now we have the [start, end] range of bitmap words that are + * nonzero. + * + * Determine starting and ending rows, also skipping the starting + * and trailing zero bits at the ends of the range. + */ const int start_row = start_word * 64 + pg_rightmost_one_pos64(filter[start_word]); Assert(start_row <= n); @@ -391,11 +404,11 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) (end_word - 1) * 64 + pg_leftmost_one_pos64(filter[end_word - 1]) + 1; Assert(end_row <= n); - stat_range_rows += end_row - start_row; + statistics_range_row += end_row - start_row; add_one_range(policy, batch_state, start_row, end_row); } - policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - stat_range_rows; + policy->stat_bulk_filtered_rows += batch_state->total_batch_rows - statistics_range_row; } policy->stat_input_total_rows += batch_state->total_batch_rows; From eca6406261d1f10aa5cc822030765402e43dfd77 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:32:04 +0100 Subject: [PATCH 162/242] caching of validity bitmap in bools (no effect) --- .../vector_agg/hashing/hash_strategy_impl.c | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index ebeae2830a7..49bf5dcb540 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -66,6 +66,16 @@ FUNCTION_NAME(reset_strategy)(HashingStrategy *hashing) hashing->null_key_index = 0; } +static void +expand_validity(const uint64 *filter, int start_row, bool *restrict dest) +{ + const int start_word = start_row / 64; + for (int i = 0; i < 64; i++) + { + dest[i] = arrow_row_is_valid(filter, start_word * 64 + i); + } +} + /* * Fill the unique key indexes for all rows using a hash table. */ @@ -81,9 +91,20 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e HASH_TABLE_KEY_TYPE prev_hash_table_key; uint32 previous_key_index = 0; + bool validity_cache[64]; for (int row = start_row; row < end_row; row++) { - if (!arrow_row_is_valid(params.batch_filter, row)) + if (row % 64 == 0 || row == start_row) + { + if (params.batch_filter != NULL && params.batch_filter[row / 64] == 0) + { + row += 64; + continue; + } + expand_validity(params.batch_filter, row, validity_cache); + } + + if (!validity_cache[row % 64]) { /* The row doesn't pass the filter. */ DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); From a890d61c59db907c6765a3c07aeebc198478f84c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:32:18 +0100 Subject: [PATCH 163/242] Revert "caching of validity bitmap in bools (no effect)" This reverts commit eca6406261d1f10aa5cc822030765402e43dfd77. --- .../vector_agg/hashing/hash_strategy_impl.c | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 49bf5dcb540..ebeae2830a7 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -66,16 +66,6 @@ FUNCTION_NAME(reset_strategy)(HashingStrategy *hashing) hashing->null_key_index = 0; } -static void -expand_validity(const uint64 *filter, int start_row, bool *restrict dest) -{ - const int start_word = start_row / 64; - for (int i = 0; i < 64; i++) - { - dest[i] = arrow_row_is_valid(filter, start_word * 64 + i); - } -} - /* * Fill the unique key indexes for all rows using a hash table. */ @@ -91,20 +81,9 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e HASH_TABLE_KEY_TYPE prev_hash_table_key; uint32 previous_key_index = 0; - bool validity_cache[64]; for (int row = start_row; row < end_row; row++) { - if (row % 64 == 0 || row == start_row) - { - if (params.batch_filter != NULL && params.batch_filter[row / 64] == 0) - { - row += 64; - continue; - } - expand_validity(params.batch_filter, row, validity_cache); - } - - if (!validity_cache[row % 64]) + if (!arrow_row_is_valid(params.batch_filter, row)) { /* The row doesn't pass the filter. */ DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); From aadd86bef904b5c461a9e0e816a0deb6790404cd Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:04:44 +0100 Subject: [PATCH 164/242] allow small overflow in serialized key -- dubious? --- .../hashing/hash_strategy_serialized.c | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index e73708966aa..b672eda47ac 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -168,15 +168,19 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key /* * Use temporary storage for the new key, reallocate if it's too small. + * Allow for overflow of up to 8 bytes, so that we can always use fixed-size + * memcpy. */ + const size_t num_bytes_overflow = num_bytes + 8; if (num_bytes > policy->num_tmp_key_storage_bytes) { if (policy->tmp_key_storage != NULL) { pfree(policy->tmp_key_storage); } - policy->tmp_key_storage = MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes); - policy->num_tmp_key_storage_bytes = num_bytes; + policy->tmp_key_storage = + MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes_overflow); + policy->num_tmp_key_storage_bytes = num_bytes_overflow; } uint8 *restrict serialized_key_storage = policy->tmp_key_storage; @@ -264,31 +268,17 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { Assert(offset <= UINT_MAX - column_values->decompression_type); + Assert(column_values->decompression_type <= 8); - switch ((int) column_values->decompression_type) - { - case 2: - memcpy(&serialized_key_storage[offset], - row + (int16 *) column_values->buffers[1], - 2); - break; - case 4: - memcpy(&serialized_key_storage[offset], - row + (int32 *) column_values->buffers[1], - 4); - break; - case 8: - memcpy(&serialized_key_storage[offset], - row + (int64 *) column_values->buffers[1], - 8); - break; - default: - pg_unreachable(); - break; - } + /* + * We can always use a 8-byte memcpy, because our source and + * destination allow overflows. + */ + memcpy(&serialized_key_storage[offset], + column_values->decompression_type * row + (uint8 *) column_values->buffers[1], + 8); offset += column_values->decompression_type; - continue; } From 3e6e7284a52deadb9c5cfb2dd589a8691da35c7f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 26 Nov 2024 12:16:38 +0100 Subject: [PATCH 165/242] Revert "allow small overflow in serialized key -- dubious?" This reverts commit aadd86bef904b5c461a9e0e816a0deb6790404cd. --- .../hashing/hash_strategy_serialized.c | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index b672eda47ac..e73708966aa 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -168,19 +168,15 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key /* * Use temporary storage for the new key, reallocate if it's too small. - * Allow for overflow of up to 8 bytes, so that we can always use fixed-size - * memcpy. */ - const size_t num_bytes_overflow = num_bytes + 8; if (num_bytes > policy->num_tmp_key_storage_bytes) { if (policy->tmp_key_storage != NULL) { pfree(policy->tmp_key_storage); } - policy->tmp_key_storage = - MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes_overflow); - policy->num_tmp_key_storage_bytes = num_bytes_overflow; + policy->tmp_key_storage = MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes); + policy->num_tmp_key_storage_bytes = num_bytes; } uint8 *restrict serialized_key_storage = policy->tmp_key_storage; @@ -268,17 +264,31 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key if (column_values->decompression_type > 0) { Assert(offset <= UINT_MAX - column_values->decompression_type); - Assert(column_values->decompression_type <= 8); - /* - * We can always use a 8-byte memcpy, because our source and - * destination allow overflows. - */ - memcpy(&serialized_key_storage[offset], - column_values->decompression_type * row + (uint8 *) column_values->buffers[1], - 8); + switch ((int) column_values->decompression_type) + { + case 2: + memcpy(&serialized_key_storage[offset], + row + (int16 *) column_values->buffers[1], + 2); + break; + case 4: + memcpy(&serialized_key_storage[offset], + row + (int32 *) column_values->buffers[1], + 4); + break; + case 8: + memcpy(&serialized_key_storage[offset], + row + (int64 *) column_values->buffers[1], + 8); + break; + default: + pg_unreachable(); + break; + } offset += column_values->decompression_type; + continue; } From 9b0ee388f5c28049a113ff49cc0f3b0d9109eb49 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 28 Nov 2024 21:22:17 +0100 Subject: [PATCH 166/242] cleanups after merge --- tsl/src/nodes/vector_agg/plan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 5da5b713bac..ec95931c733 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -428,6 +428,7 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) /* * Whether we can perform vectorized aggregation with a given grouping. + * Currently supports either no grouping or grouping by segmentby columns. */ static bool can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) @@ -496,6 +497,11 @@ has_vector_agg_node(Plan *plan, bool *has_normal_agg) append_plans = custom->custom_plans; } } + else if (IsA(plan, SubqueryScan)) + { + SubqueryScan *subquery = castNode(SubqueryScan, plan); + append_plans = list_make1(subquery->subplan); + } if (append_plans) { @@ -553,6 +559,11 @@ try_insert_vector_agg_node(Plan *plan) append_plans = custom->custom_plans; } } + else if (IsA(plan, SubqueryScan)) + { + SubqueryScan *subquery = castNode(SubqueryScan, plan); + append_plans = list_make1(subquery->subplan); + } if (append_plans) { From effa7eb81dc9bd419563e5407f43e5eef23c0f0f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:50:32 +0100 Subject: [PATCH 167/242] cleanup --- tsl/src/compression/arrow_c_data_interface.h | 25 ++++++++++++++------ tsl/test/expected/vector_agg_filter.out | 14 +++++++++-- tsl/test/sql/vector_agg_filter.sql | 12 ++++++++-- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/tsl/src/compression/arrow_c_data_interface.h b/tsl/src/compression/arrow_c_data_interface.h index 077217b14af..a1f989c99e2 100644 --- a/tsl/src/compression/arrow_c_data_interface.h +++ b/tsl/src/compression/arrow_c_data_interface.h @@ -192,7 +192,7 @@ arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 { /* * Any and all of the filters can be null. For simplicity, move the non-null - * filters to the front. + * filters to the leading positions. */ const uint64 *tmp; #define SWAP(X, Y) \ @@ -200,17 +200,28 @@ arrow_combine_validity(size_t num_words, uint64 *restrict storage, const uint64 (X) = (Y); \ (Y) = tmp; - if (filter2 == NULL) - { - SWAP(filter2, filter3); - } - if (filter1 == NULL) { - SWAP(filter1, filter2); + /* + * We have at least one NULL that goes to the last position. + */ + SWAP(filter1, filter3); + if (filter1 == NULL) + { + /* + * We have another NULL that goes to the second position. + */ + SWAP(filter1, filter2); + } + } + else + { if (filter2 == NULL) { + /* + * We have at least one NULL that goes to the last position. + */ SWAP(filter2, filter3); } } diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out index 20d97efd1d4..b02db9b96e3 100644 --- a/tsl/test/expected/vector_agg_filter.out +++ b/tsl/test/expected/vector_agg_filter.out @@ -6,6 +6,7 @@ CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ SELECT hashfloat8(x::float8) / pow(2, 32) $$ LANGUAGE SQL; +create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int @@ -62,8 +63,7 @@ select count(compress_chunk(x)) from show_chunks('aggfilter') x; vacuum freeze analyze aggfilter; set timescaledb.debug_require_vector_agg = 'require'; ----- Uncomment to generate reference. Note that there are minor discrepancies ----- on float4 due to different numeric stability in our and PG implementations. +---- Uncomment to generate reference. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', @@ -2942,3 +2942,13 @@ select s, min(ss) filter (where s != 5) from aggfilter where cint2 is null group 2 | 11 (10 rows) +reset timescaledb.debug_require_vector_agg; +-- FILTER that is not vectorizable +set timescaledb.debug_require_vector_agg = 'forbid'; +select count(*) filter (where cint2 === 0) from aggfilter; + count +------- + 7 +(1 row) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index 316102ee940..558b4a54e89 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -8,6 +8,8 @@ CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ SELECT hashfloat8(x::float8) / pow(2, 32) $$ LANGUAGE SQL; +create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); + \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int @@ -58,8 +60,7 @@ vacuum freeze analyze aggfilter; set timescaledb.debug_require_vector_agg = 'require'; ----- Uncomment to generate reference. Note that there are minor discrepancies ----- on float4 due to different numeric stability in our and PG implementations. +---- Uncomment to generate reference. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; select @@ -104,3 +105,10 @@ where and (variable != '*' or function = 'count') order by explain, condition.n, variable, function, grouping.n, agg_filter.n \gexec + +reset timescaledb.debug_require_vector_agg; + +-- FILTER that is not vectorizable +set timescaledb.debug_require_vector_agg = 'forbid'; +select count(*) filter (where cint2 === 0) from aggfilter; +reset timescaledb.debug_require_vector_agg; From 8e6c6d23d3f60867ef08a349c464ea90ce07cb5d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:52:39 +0100 Subject: [PATCH 168/242] changelog --- .unreleased/vectorized-agg-filter | 1 + 1 file changed, 1 insertion(+) create mode 100644 .unreleased/vectorized-agg-filter diff --git a/.unreleased/vectorized-agg-filter b/.unreleased/vectorized-agg-filter new file mode 100644 index 00000000000..79b88afb3db --- /dev/null +++ b/.unreleased/vectorized-agg-filter @@ -0,0 +1 @@ +Implements: #7458 Support vecorized aggregation with aggregate FILTER clauses that are also vectorizable From b717f74c6b27e0e1e45c44ef971dcb04ef6b5b84 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:04:59 +0100 Subject: [PATCH 169/242] constify stable expressions --- tsl/src/nodes/vector_agg/exec.c | 15 ++++++++++++++- tsl/test/expected/vector_agg_filter.out | 11 +++++++++++ tsl/test/sql/vector_agg_filter.sql | 9 ++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 5870723d397..68b6c244a05 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "nodes/vector_agg/exec.h" @@ -68,6 +69,17 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) DecompressChunkState *decompress_state = (DecompressChunkState *) linitial(vector_agg_state->custom.custom_ps); + /* + * Set up the helper structures used to evaluate stable expressions in + * vectorized FILTER clauses. + */ + PlannerGlobal glob = { + .boundParams = node->ss.ps.state->es_param_list_info, + }; + PlannerInfo root = { + .glob = &glob, + }; + /* * The aggregated targetlist with Aggrefs is in the custom scan targetlist * of the custom scan node that is performing the vectorized aggregation. @@ -153,7 +165,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) if (aggref->aggfilter != NULL) { - def->filter_clauses = list_make1(aggref->aggfilter); + Node *constified = estimate_expression_value(&root, (Node *) aggref->aggfilter); + def->filter_clauses = list_make1(constified); } } else diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out index b02db9b96e3..13629d3e4b3 100644 --- a/tsl/test/expected/vector_agg_filter.out +++ b/tsl/test/expected/vector_agg_filter.out @@ -6,7 +6,10 @@ CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ SELECT hashfloat8(x::float8) / pow(2, 32) $$ LANGUAGE SQL; +-- non-vectorizable equality operator create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); +-- an abs() function that is stable not immutable +create function stable_abs(x int4) returns int4 as 'int4abs' language internal stable; \set CHUNKS 2::int \set CHUNK_ROWS 100000::int \set GROUPING_CARDINALITY 10::int @@ -2951,4 +2954,12 @@ select count(*) filter (where cint2 === 0) from aggfilter; 7 (1 row) +-- FILTER with stable function +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; + count +------- + 7 +(1 row) + reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index 558b4a54e89..d3423d84eac 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -7,8 +7,10 @@ CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ SELECT hashfloat8(x::float8) / pow(2, 32) $$ LANGUAGE SQL; - +-- non-vectorizable equality operator create operator === (function = 'int4eq', rightarg = int4, leftarg = int4); +-- an abs() function that is stable not immutable +create function stable_abs(x int4) returns int4 as 'int4abs' language internal stable; \set CHUNKS 2::int \set CHUNK_ROWS 100000::int @@ -111,4 +113,9 @@ reset timescaledb.debug_require_vector_agg; -- FILTER that is not vectorizable set timescaledb.debug_require_vector_agg = 'forbid'; select count(*) filter (where cint2 === 0) from aggfilter; +-- FILTER with stable function +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; + reset timescaledb.debug_require_vector_agg; + From df7007f29734cd7533b149d66e57cb640169797e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:47:42 +0100 Subject: [PATCH 170/242] cleanup --- .../nodes/vector_agg/hashing/CMakeLists.txt | 1 + .../vector_agg/hashing/hash_strategy_common.c | 52 +++++++++++++++++++ .../vector_agg/hashing/hash_strategy_impl.c | 2 +- .../hash_strategy_impl_single_fixed_key.c | 16 +++--- .../hashing/hash_strategy_serialized.c | 8 ++- .../hashing/hash_strategy_single_text.c | 22 ++++---- .../vector_agg/hashing/hashing_strategy.h | 15 +++++- .../vector_agg/hashing/output_key_alloc.c | 32 ------------ .../hashing/output_key_emit_single.c | 17 ------ 9 files changed, 93 insertions(+), 72 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c delete mode 100644 tsl/src/nodes/vector_agg/hashing/output_key_alloc.c delete mode 100644 tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt index fab11a7df17..ce45c457b5c 100644 --- a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -3,5 +3,6 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_4.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_8.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_serialized.c) target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c new file mode 100644 index 00000000000..ead986dc600 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c @@ -0,0 +1,52 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#include "hashing_strategy.h" + +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" + +/* + * Allocate enough storage for keys, given that each row of the new compressed + * batch might turn out to be a new grouping key. We do this separately to avoid + * allocations in the hot loop that fills the hash table. + */ +void +hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + HashingStrategy *hashing = &policy->hashing; + const int n = batch_state->total_batch_rows; + const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; + if (num_possible_keys > hashing->num_allocated_output_keys) + { + hashing->num_allocated_output_keys = num_possible_keys * 2 + 1; + const size_t new_bytes = sizeof(Datum) * hashing->num_allocated_output_keys; + if (hashing->output_keys == NULL) + { + hashing->output_keys = palloc(new_bytes); + } + else + { + hashing->output_keys = repalloc(hashing->output_keys, new_bytes); + } + } +} + +/* + * Emit a single-column grouping key with the given index into the aggregated + * slot. + */ +void +hash_strategy_output_key_single_emit(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + HashingStrategy *hashing = &policy->hashing; + Assert(policy->num_grouping_columns == 1); + + const GroupingColumn *col = &policy->grouping_columns[0]; + aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; +} diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index ebeae2830a7..c94f510604d 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -135,7 +135,7 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e */ const uint32 index = ++policy->last_used_key_index; entry->hash_table_key = - FUNCTION_NAME(store_output_key)(policy, index, output_key, hash_table_key); + FUNCTION_NAME(store_new_output_key)(policy, index, output_key, hash_table_key); entry->key_index = index; DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index eca3b21b2ea..aa51e716cdc 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -5,9 +5,6 @@ */ #include "batch_hashing_params.h" -#include "output_key_alloc.c" -#include "output_key_emit_single.c" - static pg_attribute_always_inline void FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output_key_ptr, void *restrict hash_table_key_ptr, bool *restrict valid) @@ -35,8 +32,8 @@ FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output } static pg_attribute_always_inline OUTPUT_KEY_TYPE -FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, - OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) +FUNCTION_NAME(store_new_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, + OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) { policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); return hash_table_key; @@ -45,5 +42,12 @@ FUNCTION_NAME(store_output_key)(GroupingPolicyHash *restrict policy, uint32 new_ static void FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { - FUNCTION_NAME(alloc_output_keys)(policy, batch_state); + hash_strategy_output_key_alloc(policy, batch_state); +} + +static void +FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + return hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); } diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index e73708966aa..d1b1636b15b 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -361,8 +361,8 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key } static pg_attribute_always_inline HASH_TABLE_KEY_TYPE -serialized_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - text *output_key, HASH_TABLE_KEY_TYPE hash_table_key) +serialized_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, + text *output_key, HASH_TABLE_KEY_TYPE hash_table_key) { /* * We will store this key so we have to consume the temporary storage that @@ -446,12 +446,10 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Assert(ptr == serialized_key + key_data_bytes); } -#include "output_key_alloc.c" - static void serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { - serialized_alloc_output_keys(policy, batch_state); + hash_strategy_output_key_alloc(policy, batch_state); } #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 6963063c054..4309292ae9c 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -23,6 +23,10 @@ #include "umash_fingerprint_key.h" +#define EXPLAIN_NAME "single text" +#define KEY_VARIANT single_text +#define OUTPUT_KEY_TYPE BytesView + static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) { @@ -83,8 +87,8 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke } static pg_attribute_always_inline HASH_TABLE_KEY_TYPE -single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - BytesView output_key, HASH_TABLE_KEY_TYPE hash_table_key) +single_text_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, + BytesView output_key, HASH_TABLE_KEY_TYPE hash_table_key) { const int total_bytes = output_key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); @@ -98,12 +102,12 @@ single_text_store_output_key(GroupingPolicyHash *restrict policy, uint32 new_key /* * We use the standard single-key key output functions. */ -#define EXPLAIN_NAME "single text" -#define KEY_VARIANT single_text -#define OUTPUT_KEY_TYPE BytesView - -#include "output_key_alloc.c" -#include "output_key_emit_single.c" +static void +single_text_emit_key(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + return hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); +} /* * We use a special batch preparation function to sometimes hash the dictionary- @@ -121,7 +125,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * /* * Allocate the key storage. */ - single_text_alloc_output_keys(policy, batch_state); + hash_strategy_output_key_alloc(policy, batch_state); /* * Determine whether we're going to use the dictionary for hashing. diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index 9df36b5a30a..e2bfda3b180 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -5,10 +5,16 @@ */ #pragma once +#include + typedef struct GroupingPolicyHash GroupingPolicyHash; typedef struct HashingStrategy HashingStrategy; +typedef struct DecompressBatchState DecompressBatchState; + +typedef struct TupleTableSlot TupleTableSlot; + typedef struct HashingStrategy { char *explain_name; @@ -32,10 +38,11 @@ typedef struct HashingStrategy * This is stored separately from hash table keys, because they might not * have the full column values, and also storing them contiguously here * leads to better memory access patterns when emitting the results. - * The details of the key storage are managed by the hashing strategy. + * The details of the key storage are managed by the hashing strategy. The + * by-reference keys can use a separate memory context for dense storage. */ Datum *restrict output_keys; - uint64 num_output_keys; + uint64 num_allocated_output_keys; MemoryContext key_body_mctx; /* @@ -51,3 +58,7 @@ typedef struct HashingStrategy */ struct umash_params *umash_params; } HashingStrategy; + +void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state); +void hash_strategy_output_key_single_emit(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot); diff --git a/tsl/src/nodes/vector_agg/hashing/output_key_alloc.c b/tsl/src/nodes/vector_agg/hashing/output_key_alloc.c deleted file mode 100644 index 7cda7f340f0..00000000000 --- a/tsl/src/nodes/vector_agg/hashing/output_key_alloc.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file and its contents are licensed under the Timescale License. - * Please see the included NOTICE for copyright information and - * LICENSE-TIMESCALE for a copy of the license. - */ - -static void -FUNCTION_NAME(alloc_output_keys)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) -{ - /* - * Allocate enough storage for keys, given that each row of the new - * compressed batch might turn out to be a new grouping key. - * We do this separately to avoid allocations in the hot loop that fills the hash - * table. - */ - HashingStrategy *hashing = &policy->hashing; - const int n = batch_state->total_batch_rows; - const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; - if (num_possible_keys > hashing->num_output_keys) - { - hashing->num_output_keys = num_possible_keys * 2 + 1; - const size_t new_bytes = sizeof(Datum) * hashing->num_output_keys; - if (hashing->output_keys == NULL) - { - hashing->output_keys = palloc(new_bytes); - } - else - { - hashing->output_keys = repalloc(hashing->output_keys, new_bytes); - } - } -} diff --git a/tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c b/tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c deleted file mode 100644 index ce8764b4f8e..00000000000 --- a/tsl/src/nodes/vector_agg/hashing/output_key_emit_single.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This file and its contents are licensed under the Timescale License. - * Please see the included NOTICE for copyright information and - * LICENSE-TIMESCALE for a copy of the license. - */ - -static void -FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, - TupleTableSlot *aggregated_slot) -{ - HashingStrategy *hashing = &policy->hashing; - Assert(policy->num_grouping_columns == 1); - - const GroupingColumn *col = &policy->grouping_columns[0]; - aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; - aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; -} From 4511233afafbdc18ffd93fb57c2a2bfa3d9a40c4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 12:58:55 +0100 Subject: [PATCH 171/242] hash table key not updated when storing a new key --- tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c | 3 +-- .../hashing/hash_strategy_impl_single_fixed_key.c | 5 ++--- tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c | 6 ++---- .../nodes/vector_agg/hashing/hash_strategy_single_text.c | 5 ++--- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index c94f510604d..46b66c685fe 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -134,9 +134,8 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e * New key, have to store it persistently. */ const uint32 index = ++policy->last_used_key_index; - entry->hash_table_key = - FUNCTION_NAME(store_new_output_key)(policy, index, output_key, hash_table_key); entry->key_index = index; + FUNCTION_NAME(store_new_output_key)(policy, index, output_key); DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } else diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index aa51e716cdc..2ce0cbd3362 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -31,12 +31,11 @@ FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output *hash_table_key = *output_key; } -static pg_attribute_always_inline OUTPUT_KEY_TYPE +static pg_attribute_always_inline void FUNCTION_NAME(store_new_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, - OUTPUT_KEY_TYPE output_key, HASH_TABLE_KEY_TYPE hash_table_key) + OUTPUT_KEY_TYPE output_key) { policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); - return hash_table_key; } static void diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index d1b1636b15b..daa7a9f041a 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -360,9 +360,9 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key *hash_table_key = umash_fingerprint_get_key(fp); } -static pg_attribute_always_inline HASH_TABLE_KEY_TYPE +static pg_attribute_always_inline void serialized_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - text *output_key, HASH_TABLE_KEY_TYPE hash_table_key) + text *output_key) { /* * We will store this key so we have to consume the temporary storage that @@ -373,8 +373,6 @@ serialized_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_ policy->num_tmp_key_storage_bytes = 0; policy->hashing.output_keys[new_key_index] = PointerGetDatum(output_key); - - return hash_table_key; } static void diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 4309292ae9c..8171ae7643b 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -86,9 +86,9 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke *hash_table_key = umash_fingerprint_get_key(fp); } -static pg_attribute_always_inline HASH_TABLE_KEY_TYPE +static pg_attribute_always_inline void single_text_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - BytesView output_key, HASH_TABLE_KEY_TYPE hash_table_key) + BytesView output_key) { const int total_bytes = output_key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); @@ -96,7 +96,6 @@ single_text_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new memcpy(VARDATA(stored), output_key.data, output_key.len); output_key.data = (uint8 *) VARDATA(stored); policy->hashing.output_keys[new_key_index] = PointerGetDatum(stored); - return hash_table_key; } /* From afd58380072ac142ae062f94dcecfa49047a8352 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:02:34 +0100 Subject: [PATCH 172/242] comments --- .../hashing/hash_strategy_impl_single_fixed_key.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index 2ce0cbd3362..d4448ebd5ba 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -3,6 +3,11 @@ * Please see the included NOTICE for copyright information and * LICENSE-TIMESCALE for a copy of the license. */ + +/* + * Key handling function for a single fixed-size grouping key. + */ + #include "batch_hashing_params.h" static pg_attribute_always_inline void @@ -28,6 +33,10 @@ FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output pg_unreachable(); } + /* + * For the fixed-size hash grouping, we use the output key as the hash table + * key as well. + */ *hash_table_key = *output_key; } @@ -48,5 +57,5 @@ static void FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { - return hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); + hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); } From c0f6d67b03854900d5b6dc914996d3d35b5c6e39 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:03:38 +0100 Subject: [PATCH 173/242] remove extra hashes --- tsl/src/nodes/vector_agg/hashing/hash64.h | 26 ++--------------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash64.h b/tsl/src/nodes/vector_agg/hashing/hash64.h index 64877a7936e..97b0ec17987 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash64.h +++ b/tsl/src/nodes/vector_agg/hashing/hash64.h @@ -8,8 +8,8 @@ /* * We can use crc32 as a hash function, it has bad properties but takes only one * cycle, which is why it is sometimes used in the existing hash table - * implementations. - * When we don't have the crc32 instruction, use the SplitMix64 finalizer. + * implementations. When we don't have the crc32 instruction, use the SplitMix64 + * finalizer. */ static pg_attribute_always_inline uint64 hash64_splitmix(uint64 x) @@ -34,25 +34,3 @@ hash64_crc(uint64 x) #else #define HASH64 hash64_splitmix #endif - -static pg_attribute_always_inline uint32 -hash32(uint32 x) -{ - x ^= x >> 16; - x *= 0x7feb352d; - x ^= x >> 15; - x *= 0x846ca68b; - x ^= x >> 16; - return x; -} - -static pg_attribute_always_inline uint16 -hash16(uint16 x) -{ - x ^= x >> 8; - x *= 0x88b5U; - x ^= x >> 7; - x *= 0xdb2dU; - x ^= x >> 9; - return x; -} From c14a0f710ca372e3c7b19bf1587d65d6f05e1051 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:51:36 +0100 Subject: [PATCH 174/242] cleanup --- tsl/src/nodes/vector_agg/grouping_policy.h | 3 ++ .../nodes/vector_agg/grouping_policy_hash.c | 54 +++++++++++-------- .../nodes/vector_agg/grouping_policy_hash.h | 6 +-- .../vector_agg/hashing/hash_strategy_impl.c | 51 +++++++++--------- .../hash_strategy_impl_single_fixed_key.c | 29 ++++++---- .../hashing/hash_strategy_serialized.c | 26 +++++---- .../hashing/hash_strategy_single_text.c | 41 +++++++------- .../hashing/umash_fingerprint_key.h | 9 +++- 8 files changed, 130 insertions(+), 89 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index e7c77073502..e7c5af909d2 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -28,6 +28,9 @@ typedef struct GroupingPolicy */ void (*gp_reset)(GroupingPolicy *gp); + /* + * Aggregate a single compressed batch. + */ void (*gp_add_batch)(GroupingPolicy *gp, DecompressBatchState *batch_state); /* diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 3b02a795ec6..56ee69e85a1 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -51,16 +51,18 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - policy->num_agg_state_rows = TARGET_COMPRESSED_BATCH_SIZE; + policy->num_allocated_per_key_agg_states = TARGET_COMPRESSED_BATCH_SIZE; policy->num_agg_defs = num_agg_defs; policy->agg_defs = agg_defs; - policy->per_agg_states = palloc(sizeof(*policy->per_agg_states) * policy->num_agg_defs); + policy->per_agg_per_key_states = + palloc(sizeof(*policy->per_agg_per_key_states) * policy->num_agg_defs); for (int i = 0; i < policy->num_agg_defs; i++) { const VectorAggDef *agg_def = &policy->agg_defs[i]; - policy->per_agg_states[i] = palloc(agg_def->func.state_bytes * policy->num_agg_state_rows); + policy->per_agg_per_key_states[i] = + palloc(agg_def->func.state_bytes * policy->num_allocated_per_key_agg_states); } policy->current_batch_grouping_column_values = @@ -234,7 +236,7 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con * have to initialize. State index zero is invalid. */ const uint32 last_initialized_key_index = policy->last_used_key_index; - Assert(last_initialized_key_index <= policy->num_agg_state_rows); + Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); /* * Match rows to aggregation states using a hash table. @@ -243,48 +245,56 @@ add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, con policy->hashing.fill_offsets(policy, batch_state, start_row, end_row); /* - * Process the aggregate function states. + * Process the aggregate function states. We are processing single aggregate + * function for the entire batch to improve the memory locality. */ - const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; - for (int i = 0; i < num_fns; i++) + const uint64 new_aggstate_rows = policy->num_allocated_per_key_agg_states * 2 + 1; + for (int agg_index = 0; agg_index < num_fns; agg_index++) { - const VectorAggDef *agg_def = &policy->agg_defs[i]; + const VectorAggDef *agg_def = &policy->agg_defs[agg_index]; + /* + * If we added new keys, initialize the aggregate function states for + * them. + */ if (policy->last_used_key_index > last_initialized_key_index) { - if (policy->last_used_key_index >= policy->num_agg_state_rows) + /* + * If the aggregate function states don't fit into the existing + * storage, reallocate it. + */ + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) { - policy->per_agg_states[i] = repalloc(policy->per_agg_states[i], - new_aggstate_rows * agg_def->func.state_bytes); + policy->per_agg_per_key_states[agg_index] = + repalloc(policy->per_agg_per_key_states[agg_index], + new_aggstate_rows * agg_def->func.state_bytes); } - /* - * Initialize the aggregate function states for the newly added keys. - */ void *first_uninitialized_state = agg_def->func.state_bytes * (last_initialized_key_index + 1) + - (char *) policy->per_agg_states[i]; + (char *) policy->per_agg_per_key_states[agg_index]; agg_def->func.agg_init(first_uninitialized_state, policy->last_used_key_index - last_initialized_key_index); } /* - * Update the aggregate function states. + * Add this batch to the states of this aggregate function. */ compute_single_aggregate(policy, batch_state, start_row, end_row, agg_def, - policy->per_agg_states[i]); + policy->per_agg_per_key_states[agg_index]); } /* - * Record the newly allocated number of rows in case we had to reallocate. + * Record the newly allocated number of aggregate function states in case we + * had to reallocate. */ - if (policy->last_used_key_index >= policy->num_agg_state_rows) + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) { - Assert(new_aggstate_rows > policy->num_agg_state_rows); - policy->num_agg_state_rows = new_aggstate_rows; + Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); + policy->num_allocated_per_key_agg_states = new_aggstate_rows; } } @@ -481,7 +491,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) for (int i = 0; i < naggs; i++) { const VectorAggDef *agg_def = &policy->agg_defs[i]; - void *agg_states = policy->per_agg_states[i]; + void *agg_states = policy->per_agg_per_key_states[i]; void *agg_state = current_key * agg_def->func.state_bytes + (char *) agg_states; agg_def->func.agg_emit(agg_state, &aggregated_slot->tts_values[agg_def->output_offset], diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 9ae8d2420b9..1c3492ef359 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -102,13 +102,13 @@ typedef struct GroupingPolicyHash /* * Aggregate function states. Each element is an array of states for the * respective function from agg_defs. These arrays are indexed by the unique - * grouping key indexes. The state index 0 is invalid, so the corresponding + * grouping key indexes. The key index 0 is invalid, so the corresponding * states are unused. * The states of each aggregate function are stored separately and * contiguously, to achieve better memory locality when updating them. */ - void **per_agg_states; - uint64 num_agg_state_rows; + void **per_agg_per_key_states; + uint64 num_allocated_per_key_agg_states; /* * A memory context for aggregate functions to allocate additional data, diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 46b66c685fe..206f888bfe3 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -6,8 +6,6 @@ #include "batch_hashing_params.h" -#include "import/umash.h" - /* * The hash table maps the value of the grouping key to its unique index. * We don't store any extra information here, because we're accessing the memory @@ -22,7 +20,6 @@ typedef struct FUNCTION_NAME(entry) HASH_TABLE_KEY_TYPE hash_table_key; } FUNCTION_NAME(entry); -// #define SH_FILLFACTOR (0.5) #define SH_PREFIX KEY_VARIANT #define SH_ELEMENT_TYPE FUNCTION_NAME(entry) #define SH_KEY_TYPE HASH_TABLE_KEY_TYPE @@ -33,10 +30,6 @@ typedef struct FUNCTION_NAME(entry) #define SH_DECLARE #define SH_DEFINE #define SH_ENTRY_EMPTY(entry) ((entry)->key_index == 0) -#ifdef STORE_HASH -#define SH_GET_HASH(tb, entry) entry->hash -#define SH_STORE_HASH -#endif #include "import/ts_simplehash.h" struct FUNCTION_NAME(hash); @@ -49,25 +42,32 @@ FUNCTION_NAME(get_size_bytes)(HashingStrategy *hashing) } static void -FUNCTION_NAME(init)(HashingStrategy *hashing, GroupingPolicyHash *policy) +FUNCTION_NAME(hash_strategy_init)(HashingStrategy *hashing, GroupingPolicyHash *policy) { - hashing->table = FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_agg_state_rows, NULL); -#ifdef UMASH - hashing->umash_params = palloc0(sizeof(struct umash_params)); - umash_params_derive(hashing->umash_params, 0xabcdef1234567890ull, NULL); -#endif + hashing->table = + FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_allocated_per_key_agg_states, NULL); + + FUNCTION_NAME(key_hashing_init)(hashing); } static void -FUNCTION_NAME(reset_strategy)(HashingStrategy *hashing) +FUNCTION_NAME(hash_strategy_reset)(HashingStrategy *hashing) { struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) hashing->table; FUNCTION_NAME(reset)(table); hashing->null_key_index = 0; } +static void +FUNCTION_NAME(hash_strategy_prepare_for_batch)(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ + hash_strategy_output_key_alloc(policy, batch_state); + FUNCTION_NAME(key_hashing_prepare_for_batch)(policy, batch_state); +} + /* - * Fill the unique key indexes for all rows using a hash table. + * Fill the unique key indexes for all rows of the batch, using a hash table. */ static pg_attribute_always_inline void FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) @@ -90,10 +90,15 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e continue; } + /* + * Get the key for the given row. For some hashing strategies, the key + * that is used for the hash table is different from actual values of + * the grouping columns, termed "output key" here. + */ bool key_valid = false; OUTPUT_KEY_TYPE output_key = { 0 }; HASH_TABLE_KEY_TYPE hash_table_key = { 0 }; - FUNCTION_NAME(get_key)(params, row, &output_key, &hash_table_key, &key_valid); + FUNCTION_NAME(key_hashing_get_key)(params, row, &output_key, &hash_table_key, &key_valid); if (unlikely(!key_valid)) { @@ -118,7 +123,9 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e * for that case. */ indexes[row] = previous_key_index; +#ifndef NDEBUG policy->stat_consecutive_keys++; +#endif DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); continue; } @@ -135,7 +142,7 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e */ const uint32 index = ++policy->last_used_key_index; entry->key_index = index; - FUNCTION_NAME(store_new_output_key)(policy, index, output_key); + FUNCTION_NAME(key_hashing_store_new)(policy, index, output_key); DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); } else @@ -260,18 +267,14 @@ HashingStrategy FUNCTION_NAME(strategy) = { .explain_name = EXPLAIN_NAME, .fill_offsets = FUNCTION_NAME(fill_offsets), .get_size_bytes = FUNCTION_NAME(get_size_bytes), - .init = FUNCTION_NAME(init), - .prepare_for_batch = FUNCTION_NAME(prepare_for_batch), - .reset = FUNCTION_NAME(reset_strategy), + .init = FUNCTION_NAME(hash_strategy_init), + .prepare_for_batch = FUNCTION_NAME(hash_strategy_prepare_for_batch), + .reset = FUNCTION_NAME(hash_strategy_reset), }; #undef EXPLAIN_NAME #undef KEY_VARIANT #undef KEY_EQUAL -#undef STORE_HASH #undef OUTPUT_KEY_TYPE #undef HASH_TABLE_KEY_TYPE -#undef DATUM_TO_OUTPUT_KEY -#undef OUTPUT_KEY_TO_DATUM -#undef UMASH #undef USE_DICT_HASHING diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index d4448ebd5ba..c8a3c2da57f 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -10,9 +10,21 @@ #include "batch_hashing_params.h" +static void +FUNCTION_NAME(key_hashing_init)(HashingStrategy *hashing) +{ +} + +static void +FUNCTION_NAME(key_hashing_prepare_for_batch)(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ +} + static pg_attribute_always_inline void -FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output_key_ptr, - void *restrict hash_table_key_ptr, bool *restrict valid) +FUNCTION_NAME(key_hashing_get_key)(BatchHashingParams params, int row, + void *restrict output_key_ptr, void *restrict hash_table_key_ptr, + bool *restrict valid) { OUTPUT_KEY_TYPE *restrict output_key = (OUTPUT_KEY_TYPE *) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; @@ -41,21 +53,18 @@ FUNCTION_NAME(get_key)(BatchHashingParams params, int row, void *restrict output } static pg_attribute_always_inline void -FUNCTION_NAME(store_new_output_key)(GroupingPolicyHash *restrict policy, uint32 new_key_index, - OUTPUT_KEY_TYPE output_key) +FUNCTION_NAME(key_hashing_store_new)(GroupingPolicyHash *restrict policy, uint32 new_key_index, + OUTPUT_KEY_TYPE output_key) { policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); } -static void -FUNCTION_NAME(prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state) -{ - hash_strategy_output_key_alloc(policy, batch_state); -} - static void FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); } + +#undef DATUM_TO_OUTPUT_KEY +#undef OUTPUT_KEY_TO_DATUM diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index daa7a9f041a..95512ce8057 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -27,6 +27,18 @@ #define KEY_VARIANT serialized #define OUTPUT_KEY_TYPE text * +static void +serialized_key_hashing_init(HashingStrategy *hashing) +{ + hashing->umash_params = umash_key_hashing_init(); +} + +static void +serialized_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ +} + static pg_attribute_always_inline bool byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) { @@ -55,8 +67,8 @@ byte_bitmap_set_row_validity(uint8 *bitmap, size_t row_number, bool value) } static pg_attribute_always_inline void -serialized_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, - void *restrict hash_table_key_ptr, bool *restrict valid) +serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) { GroupingPolicyHash *policy = params.policy; @@ -361,8 +373,8 @@ serialized_get_key(BatchHashingParams params, int row, void *restrict output_key } static pg_attribute_always_inline void -serialized_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - text *output_key) +serialized_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, + text *output_key) { /* * We will store this key so we have to consume the temporary storage that @@ -444,10 +456,4 @@ serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSl Assert(ptr == serialized_key + key_data_bytes); } -static void -serialized_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) -{ - hash_strategy_output_key_alloc(policy, batch_state); -} - #include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 8171ae7643b..6714829b06d 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -27,6 +27,12 @@ #define KEY_VARIANT single_text #define OUTPUT_KEY_TYPE BytesView +static void +single_text_key_hashing_init(HashingStrategy *hashing) +{ + hashing->umash_params = umash_key_hashing_init(); +} + static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) { @@ -38,8 +44,8 @@ get_bytes_view(CompressedColumnValues *column_values, int arrow_row) } static pg_attribute_always_inline void -single_text_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, - void *restrict hash_table_key_ptr, bool *restrict valid) +single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) { Assert(params.policy->num_grouping_columns == 1); @@ -87,8 +93,8 @@ single_text_get_key(BatchHashingParams params, int row, void *restrict output_ke } static pg_attribute_always_inline void -single_text_store_new_output_key(GroupingPolicyHash *restrict policy, uint32 new_key_index, - BytesView output_key) +single_text_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, + BytesView output_key) { const int total_bytes = output_key.len + VARHDRSZ; text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); @@ -119,13 +125,9 @@ static pg_attribute_always_inline void single_text_dispatch_for_params(BatchHash int start_row, int end_row); static void -single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) { - /* - * Allocate the key storage. - */ - hash_strategy_output_key_alloc(policy, batch_state); - /* * Determine whether we're going to use the dictionary for hashing. */ @@ -149,7 +151,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * * to initialize. State index zero is invalid. */ const uint32 last_initialized_key_index = policy->last_used_key_index; - Assert(last_initialized_key_index <= policy->num_agg_state_rows); + Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); /* * Initialize the array for storing the aggregate state offsets corresponding @@ -291,15 +293,16 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * */ if (policy->last_used_key_index > last_initialized_key_index) { - const uint64 new_aggstate_rows = policy->num_agg_state_rows * 2 + 1; + const uint64 new_aggstate_rows = policy->num_allocated_per_key_agg_states * 2 + 1; const int num_fns = policy->num_agg_defs; for (int i = 0; i < num_fns; i++) { const VectorAggDef *agg_def = &policy->agg_defs[i]; - if (policy->last_used_key_index >= policy->num_agg_state_rows) + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) { - policy->per_agg_states[i] = repalloc(policy->per_agg_states[i], - new_aggstate_rows * agg_def->func.state_bytes); + policy->per_agg_per_key_states[i] = + repalloc(policy->per_agg_per_key_states[i], + new_aggstate_rows * agg_def->func.state_bytes); } /* @@ -307,7 +310,7 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * */ void *first_uninitialized_state = agg_def->func.state_bytes * (last_initialized_key_index + 1) + - (char *) policy->per_agg_states[i]; + (char *) policy->per_agg_per_key_states[i]; agg_def->func.agg_init(first_uninitialized_state, policy->last_used_key_index - last_initialized_key_index); } @@ -315,10 +318,10 @@ single_text_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState * /* * Record the newly allocated number of rows in case we had to reallocate. */ - if (policy->last_used_key_index >= policy->num_agg_state_rows) + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) { - Assert(new_aggstate_rows > policy->num_agg_state_rows); - policy->num_agg_state_rows = new_aggstate_rows; + Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); + policy->num_allocated_per_key_agg_states = new_aggstate_rows; } } diff --git a/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h index 0201383aa0d..ed6a9b8ce03 100644 --- a/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h +++ b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h @@ -22,7 +22,6 @@ struct umash_fingerprint_key uint64 rest; } pg_attribute_packed(); -#define UMASH #define HASH_TABLE_KEY_TYPE struct umash_fingerprint_key #define KEY_HASH(X) (X.hash) #define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) @@ -36,3 +35,11 @@ umash_fingerprint_get_key(struct umash_fp fp) }; return key; } + +static inline struct umash_params * +umash_key_hashing_init() +{ + struct umash_params *params = palloc0(sizeof(struct umash_params)); + umash_params_derive(params, 0xabcdef1234567890ull, NULL); + return params; +} From 47bcaa956558e0ed3540c5946ebf48fb2d8c33b1 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:12:23 +0100 Subject: [PATCH 175/242] updates --- tsl/src/nodes/vector_agg/CMakeLists.txt | 1 + tsl/src/nodes/vector_agg/exec.c | 46 +- tsl/src/nodes/vector_agg/exec.h | 1 + .../function/agg_many_vector_helper.c | 45 +- .../function/float48_accum_single.c | 2 + tsl/src/nodes/vector_agg/function/functions.c | 70 +- tsl/src/nodes/vector_agg/function/functions.h | 16 + .../vector_agg/function/int128_accum_single.c | 1 + .../function/int24_avg_accum_single.c | 1 + .../vector_agg/function/int24_sum_single.c | 1 + .../function/minmax_arithmetic_single.c | 2 + .../vector_agg/function/sum_float_single.c | 1 + tsl/src/nodes/vector_agg/grouping_policy.h | 7 + .../nodes/vector_agg/grouping_policy_hash.c | 734 ++-- .../nodes/vector_agg/grouping_policy_hash.h | 158 + .../nodes/vector_agg/hashing/CMakeLists.txt | 6 + .../vector_agg/hashing/batch_hashing_params.h | 55 + tsl/src/nodes/vector_agg/hashing/hash64.h | 36 + .../vector_agg/hashing/hash_strategy_common.c | 52 + .../vector_agg/hashing/hash_strategy_impl.c | 281 ++ .../hash_strategy_impl_single_fixed_key.c | 70 + .../hashing/hash_strategy_single_fixed_2.c | 32 + .../hashing/hash_strategy_single_fixed_4.c | 32 + .../hashing/hash_strategy_single_fixed_8.c | 32 + .../vector_agg/hashing/hashing_strategy.h | 64 + .../vector_agg/hashing/template_helper.h | 10 + tsl/src/nodes/vector_agg/plan.c | 6 +- tsl/test/expected/vector_agg_functions.out | 3094 ++++++++++++++++- tsl/test/sql/vector_agg_functions.sql | 14 +- 29 files changed, 4309 insertions(+), 561 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/grouping_policy_hash.h create mode 100644 tsl/src/nodes/vector_agg/hashing/CMakeLists.txt create mode 100644 tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h create mode 100644 tsl/src/nodes/vector_agg/hashing/hash64.h create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c create mode 100644 tsl/src/nodes/vector_agg/hashing/hashing_strategy.h create mode 100644 tsl/src/nodes/vector_agg/hashing/template_helper.h diff --git a/tsl/src/nodes/vector_agg/CMakeLists.txt b/tsl/src/nodes/vector_agg/CMakeLists.txt index c3a85bbd30f..cf69755c077 100644 --- a/tsl/src/nodes/vector_agg/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(function) +add_subdirectory(hashing) set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/exec.c ${CMAKE_CURRENT_SOURCE_DIR}/grouping_policy_batch.c diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 1d773ce1c4e..bfd46aa7863 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -160,17 +160,51 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) Var *var = castNode(Var, tlentry->expr); col->input_offset = get_input_offset(decompress_state, var); + DecompressContext *dcontext = &decompress_state->decompress_context; + CompressionColumnDescription *desc = + &dcontext->compressed_chunk_columns[col->input_offset]; + col->value_bytes = desc->value_bytes; } } /* - * Currently the only grouping policy we use is per-batch grouping. + * Determine which grouping policy we are going to use. */ - vector_agg_state->grouping = - create_grouping_policy_batch(vector_agg_state->num_agg_defs, - vector_agg_state->agg_defs, - vector_agg_state->num_grouping_columns, - vector_agg_state->grouping_columns); + bool all_segmentby = true; + for (int i = 0; i < vector_agg_state->num_grouping_columns; i++) + { + GroupingColumn *col = &vector_agg_state->grouping_columns[i]; + DecompressContext *dcontext = &decompress_state->decompress_context; + CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; + if (desc->type != SEGMENTBY_COLUMN) + { + all_segmentby = false; + break; + } + } + + if (all_segmentby) + { + /* + * Per-batch grouping. + */ + vector_agg_state->grouping = + create_grouping_policy_batch(vector_agg_state->num_agg_defs, + vector_agg_state->agg_defs, + vector_agg_state->num_grouping_columns, + vector_agg_state->grouping_columns); + } + else + { + /* + * Hash grouping. + */ + vector_agg_state->grouping = + create_grouping_policy_hash(vector_agg_state->num_agg_defs, + vector_agg_state->agg_defs, + vector_agg_state->num_grouping_columns, + vector_agg_state->grouping_columns); + } } static void diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index 26f832b3548..e153a287dfd 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -24,6 +24,7 @@ typedef struct GroupingColumn { int input_offset; int output_offset; + int value_bytes; } GroupingColumn; typedef struct diff --git a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c index 47916e29131..192fad35017 100644 --- a/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c +++ b/tsl/src/nodes/vector_agg/function/agg_many_vector_helper.c @@ -10,24 +10,49 @@ * FUNCTION_NAME(one) function, which adds one passing non-null row to the given * aggregate function state. */ -static void -FUNCTION_NAME(many_vector)(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, const ArrowArray *vector, MemoryContext agg_extra_mctx) +static pg_attribute_always_inline void +FUNCTION_NAME(many_vector_impl)(void *restrict agg_states, const uint32 *offsets, + const uint64 *filter, int start_row, int end_row, + const ArrowArray *vector, MemoryContext agg_extra_mctx) { - MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); + FUNCTION_NAME(state) *restrict states = (FUNCTION_NAME(state) *) agg_states; const CTYPE *values = vector->buffers[1]; - const uint64 *valid = vector->buffers[0]; + MemoryContext old = MemoryContextSwitchTo(agg_extra_mctx); for (int row = start_row; row < end_row; row++) { - FUNCTION_NAME(state) *state = (offsets[row] + (FUNCTION_NAME(state) *) agg_states); const CTYPE value = values[row]; - const bool row_passes = (offsets[row] != 0); - const bool value_notnull = arrow_row_is_valid(valid, row); - - if (row_passes && value_notnull) + FUNCTION_NAME(state) *restrict state = &states[offsets[row]]; + if (arrow_row_is_valid(filter, row)) { + Assert(offsets[row] != 0); FUNCTION_NAME(one)(state, value); } } MemoryContextSwitchTo(old); } + +static pg_noinline void +FUNCTION_NAME(many_vector_all_valid)(void *restrict agg_states, const uint32 *offsets, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + FUNCTION_NAME(many_vector_impl) + (agg_states, offsets, NULL, start_row, end_row, vector, agg_extra_mctx); +} + +static void +FUNCTION_NAME(many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) +{ + if (filter == NULL) + { + FUNCTION_NAME(many_vector_all_valid) + (agg_states, offsets, start_row, end_row, vector, agg_extra_mctx); + } + else + { + FUNCTION_NAME(many_vector_impl) + (agg_states, offsets, filter, start_row, end_row, vector, agg_extra_mctx); + } +} diff --git a/tsl/src/nodes/vector_agg/function/float48_accum_single.c b/tsl/src/nodes/vector_agg/function/float48_accum_single.c index 0bdcd928593..eba81ee687b 100644 --- a/tsl/src/nodes/vector_agg/function/float48_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/float48_accum_single.c @@ -316,6 +316,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->Sx = newSx; } +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" @@ -325,6 +326,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = FUNCTION_NAME(emit), .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #undef UPDATE #undef COMBINE diff --git a/tsl/src/nodes/vector_agg/function/functions.c b/tsl/src/nodes/vector_agg/function/functions.c index fad42edc293..bb6ef7cf074 100644 --- a/tsl/src/nodes/vector_agg/function/functions.c +++ b/tsl/src/nodes/vector_agg/function/functions.c @@ -52,20 +52,61 @@ count_star_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, state->count += n; } -static void -count_star_many_scalar(void *restrict agg_states, uint32 *restrict offsets, int start_row, - int end_row, Datum constvalue, bool constisnull, - MemoryContext agg_extra_mctx) +static pg_attribute_always_inline void +count_star_many_scalar_impl(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) { CountState *states = (CountState *) agg_states; for (int row = start_row; row < end_row; row++) { - if (offsets[row] == 0) + if (arrow_row_is_valid(filter, row)) { - continue; + states[offsets[row]].count++; } + } +} - states[offsets[row]].count++; +static pg_noinline void +count_star_many_scalar_nofilter(void *restrict agg_states, const uint32 *offsets, int start_row, + int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) +{ + count_star_many_scalar_impl(agg_states, + offsets, + NULL, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); +} + +static void +count_star_many_scalar(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx) +{ + if (filter == NULL) + { + count_star_many_scalar_nofilter(agg_states, + offsets, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); + } + else + { + count_star_many_scalar_impl(agg_states, + offsets, + filter, + start_row, + end_row, + constvalue, + constisnull, + agg_extra_mctx); } } @@ -94,8 +135,8 @@ count_any_scalar(void *agg_state, Datum constvalue, bool constisnull, int n, } static void -count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, - MemoryContext agg_extra_mctx) +count_any_vector(void *agg_state, const ArrowArray *vector, const uint64 *filter, + MemoryContext agg_extra_mctx) { CountState *state = (CountState *) agg_state; const int n = vector->length; @@ -129,16 +170,14 @@ count_any_many_vector(void *agg_state, const ArrowArray *vector, const uint64 *f } static void -count_any_many(void *restrict agg_states, uint32 *restrict offsets, int start_row, int end_row, - const ArrowArray *vector, MemoryContext agg_extra_mctx) +count_any_many_vector(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx) { - const uint64 *valid = vector->buffers[0]; for (int row = start_row; row < end_row; row++) { CountState *state = (offsets[row] + (CountState *) agg_states); - const bool row_passes = (offsets[row] != 0); - const bool value_notnull = arrow_row_is_valid(valid, row); - if (row_passes && value_notnull) + if (arrow_row_is_valid(filter, row)) { state->count++; } @@ -151,6 +190,7 @@ VectorAggFunctions count_any_agg = { .agg_emit = count_emit, .agg_scalar = count_any_scalar, .agg_vector = count_any_vector, + .agg_many_vector = count_any_many_vector, }; /* diff --git a/tsl/src/nodes/vector_agg/function/functions.h b/tsl/src/nodes/vector_agg/function/functions.h index cd05fe4ea5a..5845333d79d 100644 --- a/tsl/src/nodes/vector_agg/function/functions.h +++ b/tsl/src/nodes/vector_agg/function/functions.h @@ -37,6 +37,22 @@ typedef struct void (*agg_scalar)(void *restrict agg_state, Datum constvalue, bool constisnull, int n, MemoryContext agg_extra_mctx); + /* + * Add the rows of the given arrow array to aggregate function states given + * by the respective offsets. + */ + void (*agg_many_vector)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, const ArrowArray *vector, + MemoryContext agg_extra_mctx); + + /* + * Same as above, but for a scalar argument. This is mostly important for + * count(*) and can be NULL. + */ + void (*agg_many_scalar)(void *restrict agg_states, const uint32 *offsets, const uint64 *filter, + int start_row, int end_row, Datum constvalue, bool constisnull, + MemoryContext agg_extra_mctx); + /* Emit a partial aggregation result. */ void (*agg_emit)(void *restrict agg_state, Datum *out_result, bool *out_isnull); } VectorAggFunctions; diff --git a/tsl/src/nodes/vector_agg/function/int128_accum_single.c b/tsl/src/nodes/vector_agg/function/int128_accum_single.c index 8fdae03917e..2e0b9ca25f2 100644 --- a/tsl/src/nodes/vector_agg/function/int128_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int128_accum_single.c @@ -110,6 +110,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) #endif } +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" diff --git a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c index 7659c74b181..fb90f116255 100644 --- a/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_avg_accum_single.c @@ -38,6 +38,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->sum += value; } +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" diff --git a/tsl/src/nodes/vector_agg/function/int24_sum_single.c b/tsl/src/nodes/vector_agg/function/int24_sum_single.c index 56023517c61..95320240e75 100644 --- a/tsl/src/nodes/vector_agg/function/int24_sum_single.c +++ b/tsl/src/nodes/vector_agg/function/int24_sum_single.c @@ -61,6 +61,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) typedef Int24SumState FUNCTION_NAME(state); +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" diff --git a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c index e21658c4dfe..e64dab8e20c 100644 --- a/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c +++ b/tsl/src/nodes/vector_agg/function/minmax_arithmetic_single.c @@ -58,6 +58,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) } } +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" @@ -67,6 +68,7 @@ VectorAggFunctions FUNCTION_NAME(argdef) = { .agg_emit = minmax_emit, .agg_scalar = FUNCTION_NAME(scalar), .agg_vector = FUNCTION_NAME(vector), + .agg_many_vector = FUNCTION_NAME(many_vector), }; #endif diff --git a/tsl/src/nodes/vector_agg/function/sum_float_single.c b/tsl/src/nodes/vector_agg/function/sum_float_single.c index 88a74a9b122..6f3002fd12f 100644 --- a/tsl/src/nodes/vector_agg/function/sum_float_single.c +++ b/tsl/src/nodes/vector_agg/function/sum_float_single.c @@ -91,6 +91,7 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value) state->result += value; } +#include "agg_many_vector_helper.c" #include "agg_scalar_helper.c" #include "agg_vector_validity_helper.c" diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 98bcbbed315..e7c5af909d2 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -28,6 +28,9 @@ typedef struct GroupingPolicy */ void (*gp_reset)(GroupingPolicy *gp); + /* + * Aggregate a single compressed batch. + */ void (*gp_add_batch)(GroupingPolicy *gp, DecompressBatchState *batch_state); /* @@ -54,3 +57,7 @@ typedef struct GroupingPolicy extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, GroupingColumn *grouping_columns); + +extern GroupingPolicy *create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, + int num_grouping_columns, + GroupingColumn *grouping_columns); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 0a8258efcb2..12e0f09700e 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -19,6 +19,8 @@ #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" +#include "grouping_policy_hash.h" + #ifdef USE_FLOAT8_BYVAL #define DEBUG_LOG(MSG, ...) elog(DEBUG3, MSG, __VA_ARGS__) #else @@ -29,146 +31,64 @@ #define DEBUG_LOG(...) #endif -/* - * We can use crc32 as a hash function, it has bad properties but takes only one - * cycle, which is why it is sometimes used in the existing hash table - * implementations. - */ -#ifdef USE_SSE42_CRC32C -#include -static pg_attribute_always_inline uint64 -hash64(uint64 x) -{ - return _mm_crc32_u64(~0ULL, x); -} - -#else -/* - * When we don't have the crc32 instruction, use the SplitMix64 finalizer. - */ -static pg_attribute_always_inline uint64 -hash64(uint64 x) -{ - x ^= x >> 30; - x *= 0xbf58476d1ce4e5b9U; - x ^= x >> 27; - x *= 0x94d049bb133111ebU; - x ^= x >> 31; - return x; -} -#endif - -/* - * For the hash table, use the generic Datum key that is mapped to the aggregate - * state index. - */ -typedef struct -{ - Datum key; - uint32 status; - uint32 agg_state_index; -} HashEntry; - -#define SH_PREFIX h -#define SH_ELEMENT_TYPE HashEntry -#define SH_KEY_TYPE Datum -#define SH_KEY key -#define SH_HASH_KEY(tb, key) hash64(key) -#define SH_EQUAL(tb, a, b) a == b -#define SH_SCOPE static inline -#define SH_DECLARE -#define SH_DEFINE -#include - -/* - * Hash grouping policy. - */ -typedef struct -{ - /* - * We're using data inheritance from the GroupingPolicy. - */ - GroupingPolicy funcs; - - List *agg_defs; - List *output_grouping_columns; - - /* - * The hash table we use for grouping. - */ - struct h_hash *table; - - /* - * We have to track whether we are in the mode of returning the partial - * aggregation results, and also use a hash table iterator to track our - * progress between emit() calls. - */ - bool returning_results; - struct h_iterator iter; - - /* - * In single-column grouping, we store the null key outside of the hash - * table, and it has a reserved aggregate state index 1. We also reset this - * flag after we output the null key during iteration. - */ - bool have_null_key; - - /* - * A memory context for aggregate functions to allocate additional data, - * i.e. if they store strings or float8 datum on 32-bit systems. Valid until - * the grouping policy is reset. - */ - MemoryContext agg_extra_mctx; - - /* - * Temporary storage of aggregate state offsets for a given batch. We keep - * it in the policy because it is potentially too big to keep on stack, and - * we don't want to reallocate it each batch. - */ - uint32 *offsets; - uint64 num_allocated_offsets; - - /* - * Storage of aggregate function states, each List entry is the array of - * states for the respective function from agg_defs. The state index 0 is - * invalid, and the state index 1 is reserved for a null key. - */ - List *per_agg_states; - uint64 allocated_aggstate_rows; - - /* - * Some statistics for debugging. - */ - uint64 stat_input_total_rows; - uint64 stat_input_valid_rows; - uint64 stat_bulk_filtered_rows; -} GroupingPolicyHash; +extern HashingStrategy single_fixed_2_strategy; +extern HashingStrategy single_fixed_4_strategy; +extern HashingStrategy single_fixed_8_strategy; +extern HashingStrategy single_text_strategy; +extern HashingStrategy serialized_strategy; static const GroupingPolicy grouping_policy_hash_functions; GroupingPolicy * -create_grouping_policy_hash(List *agg_defs, List *output_grouping_columns) +create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, + GroupingColumn *grouping_columns) { GroupingPolicyHash *policy = palloc0(sizeof(GroupingPolicyHash)); policy->funcs = grouping_policy_hash_functions; - policy->output_grouping_columns = output_grouping_columns; - policy->agg_defs = agg_defs; + + policy->num_grouping_columns = num_grouping_columns; + policy->grouping_columns = grouping_columns; + policy->agg_extra_mctx = AllocSetContextCreate(CurrentMemoryContext, "agg extra", ALLOCSET_DEFAULT_SIZES); - policy->allocated_aggstate_rows = TARGET_COMPRESSED_BATCH_SIZE; - ListCell *lc; - foreach (lc, agg_defs) + policy->num_allocated_per_key_agg_states = TARGET_COMPRESSED_BATCH_SIZE; + + policy->num_agg_defs = num_agg_defs; + policy->agg_defs = agg_defs; + + policy->per_agg_per_key_states = + palloc(sizeof(*policy->per_agg_per_key_states) * policy->num_agg_defs); + for (int i = 0; i < policy->num_agg_defs; i++) { - VectorAggDef *agg_def = lfirst(lc); - policy->per_agg_states = - lappend(policy->per_agg_states, - palloc0(agg_def->func.state_bytes * policy->allocated_aggstate_rows)); + const VectorAggDef *agg_def = &policy->agg_defs[i]; + policy->per_agg_per_key_states[i] = + palloc(agg_def->func.state_bytes * policy->num_allocated_per_key_agg_states); } - policy->table = h_create(CurrentMemoryContext, policy->allocated_aggstate_rows, NULL); - policy->have_null_key = false; + policy->current_batch_grouping_column_values = + palloc(sizeof(CompressedColumnValues) * num_grouping_columns); - policy->returning_results = false; + Assert(num_grouping_columns == 1); + const GroupingColumn *g = &policy->grouping_columns[0]; + switch (g->value_bytes) + { + case 8: + policy->hashing = single_fixed_8_strategy; + break; + case 4: + policy->hashing = single_fixed_4_strategy; + break; + case 2: + policy->hashing = single_fixed_2_strategy; + break; + default: + Assert(false); + break; + } + + policy->hashing.key_body_mctx = policy->agg_extra_mctx; + + policy->hashing.init(&policy->hashing, policy); return &policy->funcs; } @@ -182,36 +102,49 @@ gp_hash_reset(GroupingPolicy *obj) policy->returning_results = false; - h_reset(policy->table); - policy->have_null_key = false; + policy->hashing.reset(&policy->hashing); + + /* + * Have to reset this because it's in the key body context which is also + * reset here. + */ + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + + policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; policy->stat_input_total_rows = 0; - policy->stat_bulk_filtered_rows = 0; + policy->stat_consecutive_keys = 0; } static void -compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int end_row, - VectorAggDef *agg_def, void *agg_states, uint32 *offsets, - MemoryContext agg_extra_mctx) +compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState *batch_state, + int start_row, int end_row, const VectorAggDef *agg_def, void *agg_states) { - ArrowArray *arg_arrow = NULL; + const ArrowArray *arg_arrow = NULL; + const uint64 *arg_validity_bitmap = NULL; Datum arg_datum = 0; bool arg_isnull = true; + const uint32 *offsets = policy->key_index_for_row; + MemoryContext agg_extra_mctx = policy->agg_extra_mctx; + /* * We have functions with one argument, and one function with no arguments * (count(*)). Collect the arguments. */ if (agg_def->input_offset >= 0) { - CompressedColumnValues *values = &batch_state->compressed_columns[agg_def->input_offset]; + const CompressedColumnValues *values = + &batch_state->compressed_columns[agg_def->input_offset]; Assert(values->decompression_type != DT_Invalid); Assert(values->decompression_type != DT_Iterator); if (values->arrow != NULL) { arg_arrow = values->arrow; + arg_validity_bitmap = values->buffers[0]; } else { @@ -221,14 +154,28 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } } + /* + * Compute the unified validity bitmap. + */ + const size_t num_words = (batch_state->total_batch_rows + 63) / 64; + const uint64 *filter = arrow_combine_validity(num_words, + policy->tmp_filter, + batch_state->vector_qual_result, + arg_validity_bitmap); + /* * Now call the function. */ if (arg_arrow != NULL) { /* Arrow argument. */ - agg_def->func - .agg_many_vector(agg_states, offsets, start_row, end_row, arg_arrow, agg_extra_mctx); + agg_def->func.agg_many_vector(agg_states, + offsets, + filter, + start_row, + end_row, + arg_arrow, + agg_extra_mctx); } else { @@ -240,6 +187,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e { agg_def->func.agg_many_scalar(agg_states, offsets, + filter, start_row, end_row, arg_datum, @@ -250,7 +198,7 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e { for (int i = start_row; i < end_row; i++) { - if (offsets[i] == 0) + if (!arrow_row_is_valid(filter, i)) { continue; } @@ -262,230 +210,80 @@ compute_single_aggregate(DecompressBatchState *batch_state, int start_row, int e } } -/* - * Fill the aggregation state offsets for all rows using a hash table. - */ -static pg_attribute_always_inline uint32 -fill_offsets_impl(GroupingPolicyHash *policy, CompressedColumnValues column, - const uint64 *restrict filter, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) -{ - struct h_hash *restrict table = policy->table; - for (int row = start_row; row < end_row; row++) - { - bool key_valid = false; - Datum key = { 0 }; - get_key(column, row, &key, &key_valid); - - if (!arrow_row_is_valid(filter, row)) - { - continue; - } - - if (key_valid) - { - bool found = false; - HashEntry *restrict entry = h_insert(table, key, &found); - if (!found) - { - entry->agg_state_index = next_unused_state_index++; - } - offsets[row] = entry->agg_state_index; - } - else - { - policy->have_null_key = true; - offsets[row] = 1; - } - } - - return next_unused_state_index; -} - -/* - * This function exists just to nudge the compiler to generate simplified - * implementation for the important case where the entire batch matches and the - * key has no null values. - */ -static pg_attribute_always_inline uint32 -fill_offsets_dispatch(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets, - void (*get_key)(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid)) -{ - CompressedColumnValues column = batch_state->compressed_columns[key_column_index]; - const uint64 *restrict filter = batch_state->vector_qual_result; - - if (filter == NULL && column.buffers[0] == NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter != NULL && column.buffers[0] == NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter == NULL && column.buffers[0] != NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else if (filter != NULL && column.buffers[0] != NULL) - { - next_unused_state_index = fill_offsets_impl(policy, - column, - filter, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key); - } - else - { - Assert(false); - } - - policy->stat_input_total_rows += batch_state->total_batch_rows; - policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); - return next_unused_state_index; -} - -/* - * Functions to get the key value from the decompressed column, depending on its - * width and whether it's a scalar column. - */ -static pg_attribute_always_inline void -get_key_scalar(CompressedColumnValues column, int row, Datum *restrict key, bool *restrict valid) -{ - Assert(column.decompression_type == DT_Scalar); - *key = *column.output_value; - *valid = !*column.output_isnull; -} - -static pg_attribute_always_inline void -get_key_arrow_fixed(CompressedColumnValues column, int row, int key_bytes, Datum *restrict key, - bool *restrict valid) -{ - Assert(column.decompression_type == key_bytes); - const void *values = column.buffers[1]; - const uint64 *key_validity = column.buffers[0]; - *valid = arrow_row_is_valid(key_validity, row); - memcpy(key, key_bytes * row + (char *) values, key_bytes); -} - -static pg_attribute_always_inline void -get_key_arrow_fixed_2(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) +static void +add_one_range(GroupingPolicyHash *policy, DecompressBatchState *batch_state, const int start_row, + const int end_row) { - get_key_arrow_fixed(column, row, 2, key, valid); -} + const int num_fns = policy->num_agg_defs; -static pg_attribute_always_inline void -get_key_arrow_fixed_4(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) -{ - get_key_arrow_fixed(column, row, 4, key, valid); -} + Assert(start_row < end_row); + Assert(end_row <= batch_state->total_batch_rows); -static pg_attribute_always_inline void -get_key_arrow_fixed_8(CompressedColumnValues column, int row, Datum *restrict key, - bool *restrict valid) -{ -#ifndef USE_FLOAT8_BYVAL /* - * Shouldn't be called for this configuration, because we only use this - * grouping strategy for by-value types. + * Remember which aggregation states have already existed, and which we + * have to initialize. State index zero is invalid. */ - Assert(false); -#endif + const uint32 last_initialized_key_index = policy->last_used_key_index; + Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); - get_key_arrow_fixed(column, row, 8, key, valid); -} + /* + * Match rows to aggregation states using a hash table. + */ + Assert((size_t) end_row <= policy->num_key_index_for_row); + policy->hashing.fill_offsets(policy, batch_state, start_row, end_row); -/* - * Implementation of bulk hashing specialized for a given key width. - */ -static pg_noinline uint32 -fill_offsets_arrow_fixed_8(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_8); -} + /* + * Process the aggregate function states. We are processing single aggregate + * function for the entire batch to improve the memory locality. + */ + const uint64 new_aggstate_rows = policy->num_allocated_per_key_agg_states * 2 + 1; + for (int agg_index = 0; agg_index < num_fns; agg_index++) + { + const VectorAggDef *agg_def = &policy->agg_defs[agg_index]; + /* + * If we added new keys, initialize the aggregate function states for + * them. + */ + if (policy->last_used_key_index > last_initialized_key_index) + { + /* + * If the aggregate function states don't fit into the existing + * storage, reallocate it. + */ + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + { + policy->per_agg_per_key_states[agg_index] = + repalloc(policy->per_agg_per_key_states[agg_index], + new_aggstate_rows * agg_def->func.state_bytes); + } -static pg_noinline uint32 -fill_offsets_arrow_fixed_4(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_arrow_fixed_4); -} + void *first_uninitialized_state = + agg_def->func.state_bytes * (last_initialized_key_index + 1) + + (char *) policy->per_agg_per_key_states[agg_index]; + agg_def->func.agg_init(first_uninitialized_state, + policy->last_used_key_index - last_initialized_key_index); + } -static pg_noinline uint32 -fill_offsets_arrow_fixed_2(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, + /* + * Add this batch to the states of this aggregate function. + */ + compute_single_aggregate(policy, batch_state, - key_column_index, - next_unused_state_index, start_row, end_row, - offsets, - get_key_arrow_fixed_2); -} + agg_def, + policy->per_agg_per_key_states[agg_index]); + } -static pg_noinline uint32 -fill_offsets_scalar(GroupingPolicyHash *policy, DecompressBatchState *batch_state, - int key_column_index, uint32 next_unused_state_index, int start_row, - int end_row, uint32 *restrict offsets) -{ - return fill_offsets_dispatch(policy, - batch_state, - key_column_index, - next_unused_state_index, - start_row, - end_row, - offsets, - get_key_scalar); + /* + * Record the newly allocated number of aggregate function states in case we + * had to reallocate. + */ + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + { + Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); + policy->num_allocated_per_key_agg_states = new_aggstate_rows; + } } static void @@ -495,161 +293,60 @@ gp_hash_add_batch(GroupingPolicy *gp, DecompressBatchState *batch_state) Assert(!policy->returning_results); - const uint64_t *restrict filter = batch_state->vector_qual_result; const int n = batch_state->total_batch_rows; /* * Initialize the array for storing the aggregate state offsets corresponding - * to a given batch row. + * to a given batch row. We don't need the offsets for the previous batch + * that are currently stored there, so we don't need to use repalloc. */ - if ((size_t) n > policy->num_allocated_offsets) + if ((size_t) n > policy->num_key_index_for_row) { - policy->num_allocated_offsets = n; - policy->offsets = palloc(sizeof(policy->offsets[0]) * policy->num_allocated_offsets); + if (policy->key_index_for_row != NULL) + { + pfree(policy->key_index_for_row); + } + policy->num_key_index_for_row = n; + policy->key_index_for_row = + palloc(sizeof(policy->key_index_for_row[0]) * policy->num_key_index_for_row); } - memset(policy->offsets, 0, n * sizeof(policy->offsets[0])); + memset(policy->key_index_for_row, 0, n * sizeof(policy->key_index_for_row[0])); /* - * For the partial aggregation node, the grouping columns are always in the - * output, so we don't have to separately look at the list of the grouping - * columns. + * Allocate the temporary filter array for computing the combined results of + * batch filter, aggregate filter and column validity. */ - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *g = linitial(policy->output_grouping_columns); - CompressedColumnValues *key_column = &batch_state->compressed_columns[g->input_offset]; - int start_row = 0; - int end_row = 0; - for (start_row = 0; start_row < n; start_row = end_row) + const size_t num_words = (n + 63) / 64; + if (num_words > policy->num_tmp_filter_words) { - /* - * If we have a highly selective filter, it's easy to skip the rows for - * which the entire words of the filter bitmap are zero. - */ - if (filter) - { - if (filter[start_row / 64] == 0) - { - end_row = MIN(start_row + 64, n); - policy->stat_bulk_filtered_rows += 64; - continue; - } - - for (end_row = start_row; end_row < n; end_row = MIN(end_row + 64, n)) - { - if (filter[end_row / 64] == 0) - { - break; - } - } - } - else - { - end_row = n; - } - Assert(start_row <= end_row); - Assert(end_row <= n); - - /* - * Remember which aggregation states have already existed, and which we - * have to initialize. State index zero is invalid, and state index one - * is for null key. We have to initialize the null key state at the - * first run. - */ - const uint32 last_initialized_state_index = - policy->table->members ? policy->table->members + 2 : 1; - uint32 next_unused_state_index = policy->table->members + 2; + policy->tmp_filter = palloc(sizeof(*policy->tmp_filter) * (num_words * 2 + 1)); + policy->num_tmp_filter_words = (num_words * 2 + 1); + } - /* - * Match rows to aggregation states using a hash table. - */ - Assert((size_t) end_row <= policy->num_allocated_offsets); - switch ((int) key_column->decompression_type) - { - case DT_Scalar: - next_unused_state_index = fill_offsets_scalar(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 8: - next_unused_state_index = fill_offsets_arrow_fixed_8(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 4: - next_unused_state_index = fill_offsets_arrow_fixed_4(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - case 2: - next_unused_state_index = fill_offsets_arrow_fixed_2(policy, - batch_state, - g->input_offset, - next_unused_state_index, - start_row, - end_row, - policy->offsets); - break; - default: - Assert(false); - break; - } + /* + * Arrange the input compressed columns in the order of grouping columns. + */ + for (int i = 0; i < policy->num_grouping_columns; i++) + { + const GroupingColumn *def = &policy->grouping_columns[i]; + const CompressedColumnValues *values = &batch_state->compressed_columns[def->input_offset]; + policy->current_batch_grouping_column_values[i] = *values; + } - ListCell *aggdeflc; - ListCell *aggstatelc; + /* + * Call the per-batch initialization function of the hashing strategy. + */ - /* - * Initialize the aggregate function states for the newly added keys. - */ - if (next_unused_state_index > last_initialized_state_index) - { - if (next_unused_state_index > policy->allocated_aggstate_rows) - { - policy->allocated_aggstate_rows = policy->allocated_aggstate_rows * 2 + 1; - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { - VectorAggDef *agg_def = lfirst(aggdeflc); - lfirst(aggstatelc) = - repalloc(lfirst(aggstatelc), - policy->allocated_aggstate_rows * agg_def->func.state_bytes); - } - } + policy->hashing.prepare_for_batch(policy, batch_state); - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { - const VectorAggDef *agg_def = lfirst(aggdeflc); - agg_def->func.agg_init(agg_def->func.state_bytes * last_initialized_state_index + - (char *) lfirst(aggstatelc), - next_unused_state_index - last_initialized_state_index); - } - } + /* + * Add the batch rows to aggregate function states. + */ + const uint64_t *restrict filter = batch_state->vector_qual_result; + add_one_range(policy, batch_state, 0, n); - /* - * Update the aggregate function states. - */ - forboth (aggdeflc, policy->agg_defs, aggstatelc, policy->per_agg_states) - { - compute_single_aggregate(batch_state, - start_row, - end_row, - lfirst(aggdeflc), - lfirst(aggstatelc), - policy->offsets, - policy->agg_extra_mctx); - } - } - Assert(end_row == n); + policy->stat_input_total_rows += batch_state->total_batch_rows; + policy->stat_input_valid_rows += arrow_num_valid(filter, batch_state->total_batch_rows); } static bool @@ -657,6 +354,15 @@ gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + if (policy->last_used_key_index > UINT32_MAX - GLOBAL_MAX_ROWS_PER_COMPRESSION) + { + /* + * The max valid key index is UINT32_MAX, so we have to spill if the next + * batch can possibly lead to key index overflow. + */ + return true; + } + /* * Don't grow the hash table cardinality too much, otherwise we become bound * by memory reads. In general, when this first stage of grouping doesn't @@ -664,7 +370,7 @@ gp_hash_should_emit(GroupingPolicy *gp) * work will be done by the final Postgres aggregation, so we should bail * out early here. */ - return policy->table->members * sizeof(HashEntry) > 128 * 1024; + return policy->hashing.get_size_bytes(&policy->hashing) > 512 * 1024; } static bool @@ -675,61 +381,65 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) if (!policy->returning_results) { policy->returning_results = true; - h_start_iterate(policy->table, &policy->iter); + policy->last_returned_key = 1; - const float keys = policy->table->members + policy->have_null_key; + const float keys = policy->last_used_key_index; if (keys > 0) { - DEBUG_LOG("spill after %ld input %ld valid %ld bulk filtered %.0f keys %f ratio %ld " - "aggctx bytes %ld aggstate bytes", + DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " + "%f ratio, %ld curctx bytes, %ld aggstate bytes", policy->stat_input_total_rows, policy->stat_input_valid_rows, - policy->stat_bulk_filtered_rows, + 0UL, + policy->stat_consecutive_keys, keys, policy->stat_input_valid_rows / keys, - MemoryContextMemAllocated(policy->table->ctx, false), + MemoryContextMemAllocated(CurrentMemoryContext, false), MemoryContextMemAllocated(policy->agg_extra_mctx, false)); } } - - HashEntry null_key_entry = { .agg_state_index = 1 }; - HashEntry *entry = h_iterate(policy->table, &policy->iter); - bool key_is_null = false; - if (entry == NULL && policy->have_null_key) + else { - policy->have_null_key = false; - entry = &null_key_entry; - key_is_null = true; + policy->last_returned_key++; } - if (entry == NULL) + const uint32 current_key = policy->last_returned_key; + const uint32 keys_end = policy->last_used_key_index + 1; + if (current_key >= keys_end) { policy->returning_results = false; return false; } - const int naggs = list_length(policy->agg_defs); + const int naggs = policy->num_agg_defs; for (int i = 0; i < naggs; i++) { - VectorAggDef *agg_def = (VectorAggDef *) list_nth(policy->agg_defs, i); - void *agg_states = list_nth(policy->per_agg_states, i); - void *agg_state = entry->agg_state_index * agg_def->func.state_bytes + (char *) agg_states; + const VectorAggDef *agg_def = &policy->agg_defs[i]; + void *agg_states = policy->per_agg_per_key_states[i]; + void *agg_state = current_key * agg_def->func.state_bytes + (char *) agg_states; agg_def->func.agg_emit(agg_state, &aggregated_slot->tts_values[agg_def->output_offset], &aggregated_slot->tts_isnull[agg_def->output_offset]); } - Assert(list_length(policy->output_grouping_columns) == 1); - GroupingColumn *col = linitial(policy->output_grouping_columns); - aggregated_slot->tts_values[col->output_offset] = entry->key; - aggregated_slot->tts_isnull[col->output_offset] = key_is_null; + policy->hashing.emit_key(policy, current_key, aggregated_slot); + + DEBUG_PRINT("%p: output key index %d\n", policy, current_key); return true; } +static char * +gp_hash_explain(GroupingPolicy *gp) +{ + GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; + return psprintf("hashed with %s key", policy->hashing.explain_name); +} + static const GroupingPolicy grouping_policy_hash_functions = { .gp_reset = gp_hash_reset, .gp_add_batch = gp_hash_add_batch, .gp_should_emit = gp_hash_should_emit, .gp_do_emit = gp_hash_do_emit, + .gp_explain = gp_hash_explain, }; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h new file mode 100644 index 00000000000..d7cda9d77c4 --- /dev/null +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -0,0 +1,158 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#include + +#include + +#include "grouping_policy.h" + +#include "nodes/decompress_chunk/compressed_batch.h" + +#include "hashing/hashing_strategy.h" + +typedef struct GroupingPolicyHash GroupingPolicyHash; + +/* + * Hash grouping policy. + * + * The grouping and aggregation is performed as follows: + * + * 0) The grouping policy keeps track of the unique grouping keys seen in + * the input rows, and the states of aggregate functions for each key. This + * spans multiple input compressed batches, and is reset after the partial + * aggregation results are emitted. + * + * 1) For each row of the new compressed batch, we obtain an index that + * uniquely identifies its grouping key. This is done by matching the row's + * grouping columns to the hash table recording the unique grouping keys and + * their respective indexes. It is performed in bulk for all rows of the batch, + * to improve memory locality. The details of this are managed by the hashing + * strategy. + * + * 2) The key indexes are used to locate the aggregate function states + * corresponding to a given row, and update it. This is done in bulk for all + * rows of the batch, and for each aggregate function separately, to generate + * simpler and potentially vectorizable code, and improve memory locality. + * + * 3) After the input have ended, or if the memory limit is reached, the partial + * results are emitted into the output slot. This is done in the order of unique + * grouping key indexes, thereby preserving the incoming key order. This + * guarantees that this policy works correctly even in a Partial GroupAggregate + * node, even though it's not optimal performance-wise. + */ +typedef struct GroupingPolicyHash +{ + /* + * We're using data inheritance from the GroupingPolicy. + */ + GroupingPolicy funcs; + + /* + * Aggregate function definitions. + */ + int num_agg_defs; + const VectorAggDef *restrict agg_defs; + + /* + * Grouping column definitions. + */ + int num_grouping_columns; + const GroupingColumn *restrict grouping_columns; + + /* + * The values of the grouping columns picked from the compressed batch and + * arranged in the order of grouping column definitions. + */ + CompressedColumnValues *restrict current_batch_grouping_column_values; + + /* + * Hashing strategy that is responsible for mapping the rows to the unique + * indexes of their grouping keys. + */ + HashingStrategy hashing; + + /* + * The last used index of an unique grouping key. Key index 0 is invalid. + */ + uint32 last_used_key_index; + + /* + * Temporary storage of unique indexes of keys corresponding to a given row + * of the compressed batch that is currently being aggregated. We keep it in + * the policy because it is potentially too big to keep on stack, and we + * don't want to reallocate it for each batch. + */ + uint32 *restrict key_index_for_row; + uint64 num_key_index_for_row; + + /* + * The temporary filter bitmap we use to combine the results of the + * vectorized filters in WHERE, validity of the aggregate function argument, + * and the aggregate FILTER clause. It is then used by the aggregate + * function implementation to filter out the rows that don't pass. + */ + uint64 *tmp_filter; + uint64 num_tmp_filter_words; + + /* + * Aggregate function states. Each element is an array of states for the + * respective function from agg_defs. These arrays are indexed by the unique + * grouping key indexes. The key index 0 is invalid, so the corresponding + * states are unused. + * The states of each aggregate function are stored separately and + * contiguously, to achieve better memory locality when updating them. + */ + void **per_agg_per_key_states; + uint64 num_allocated_per_key_agg_states; + + /* + * A memory context for aggregate functions to allocate additional data, + * i.e. if they store strings or float8 datum on 32-bit systems. Valid until + * the grouping policy is reset. + */ + MemoryContext agg_extra_mctx; + + /* + * Whether we are in the mode of returning the partial aggregation results. + * If we are, track the index of the last returned grouping key. + */ + bool returning_results; + uint32 last_returned_key; + + /* + * Some statistics for debugging. + */ + uint64 stat_input_total_rows; + uint64 stat_input_valid_rows; + uint64 stat_consecutive_keys; + + /* + * FIXME all the stuff below should be moved out. + */ + + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; + + /* + * For single text key that uses dictionary encoding, in some cases we first + * calculate the key indexes for the dictionary entries, and then translate + * it to the actual rows. + */ + uint32 *restrict key_index_for_dict; + uint64 num_key_index_for_dict; + bool use_key_index_for_dict; +} GroupingPolicyHash; + +//#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(...) +#endif diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt new file mode 100644 index 00000000000..c6ff65f65ca --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -0,0 +1,6 @@ +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_2.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_4.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_8.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c) +target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h new file mode 100644 index 00000000000..a4db2a19b1c --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h @@ -0,0 +1,55 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#pragma once + +typedef struct BatchHashingParams +{ + const uint64 *batch_filter; + CompressedColumnValues single_key; + + int num_grouping_columns; + const CompressedColumnValues *grouping_column_values; + + /* + * Whether we have any scalar or nullable grouping columns in the current + * batch. This is used to select the more efficient implementation when we + * have none. + */ + bool have_scalar_or_nullable_columns; + + GroupingPolicyHash *restrict policy; + + uint32 *restrict result_key_indexes; +} BatchHashingParams; + +static pg_attribute_always_inline BatchHashingParams +build_batch_hashing_params(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + BatchHashingParams params = { + .policy = policy, + .batch_filter = batch_state->vector_qual_result, + .num_grouping_columns = policy->num_grouping_columns, + .grouping_column_values = policy->current_batch_grouping_column_values, + .result_key_indexes = policy->key_index_for_row, + }; + + Assert(policy->num_grouping_columns > 0); + if (policy->num_grouping_columns == 1) + { + params.single_key = policy->current_batch_grouping_column_values[0]; + } + + for (int i = 0; i < policy->num_grouping_columns; i++) + { + params.have_scalar_or_nullable_columns = + params.have_scalar_or_nullable_columns || + (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || + policy->current_batch_grouping_column_values[i].buffers[0] != NULL); + } + + return params; +} diff --git a/tsl/src/nodes/vector_agg/hashing/hash64.h b/tsl/src/nodes/vector_agg/hashing/hash64.h new file mode 100644 index 00000000000..97b0ec17987 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash64.h @@ -0,0 +1,36 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +/* + * We can use crc32 as a hash function, it has bad properties but takes only one + * cycle, which is why it is sometimes used in the existing hash table + * implementations. When we don't have the crc32 instruction, use the SplitMix64 + * finalizer. + */ +static pg_attribute_always_inline uint64 +hash64_splitmix(uint64 x) +{ + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + return x; +} + +#ifdef USE_SSE42_CRC32C +#include +static pg_attribute_always_inline uint64 +hash64_crc(uint64 x) +{ + return _mm_crc32_u64(~0ULL, x); +} + +#define HASH64 hash64_crc +#else +#define HASH64 hash64_splitmix +#endif diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c new file mode 100644 index 00000000000..ead986dc600 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c @@ -0,0 +1,52 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#include "hashing_strategy.h" + +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" + +/* + * Allocate enough storage for keys, given that each row of the new compressed + * batch might turn out to be a new grouping key. We do this separately to avoid + * allocations in the hot loop that fills the hash table. + */ +void +hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state) +{ + HashingStrategy *hashing = &policy->hashing; + const int n = batch_state->total_batch_rows; + const uint32 num_possible_keys = policy->last_used_key_index + 1 + n; + if (num_possible_keys > hashing->num_allocated_output_keys) + { + hashing->num_allocated_output_keys = num_possible_keys * 2 + 1; + const size_t new_bytes = sizeof(Datum) * hashing->num_allocated_output_keys; + if (hashing->output_keys == NULL) + { + hashing->output_keys = palloc(new_bytes); + } + else + { + hashing->output_keys = repalloc(hashing->output_keys, new_bytes); + } + } +} + +/* + * Emit a single-column grouping key with the given index into the aggregated + * slot. + */ +void +hash_strategy_output_key_single_emit(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + HashingStrategy *hashing = &policy->hashing; + Assert(policy->num_grouping_columns == 1); + + const GroupingColumn *col = &policy->grouping_columns[0]; + aggregated_slot->tts_values[col->output_offset] = hashing->output_keys[current_key]; + aggregated_slot->tts_isnull[col->output_offset] = current_key == hashing->null_key_index; +} diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c new file mode 100644 index 00000000000..5656e8d69b4 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -0,0 +1,281 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +#include "batch_hashing_params.h" + +/* + * The hash table maps the value of the grouping key to its unique index. + * We don't store any extra information here, because we're accessing the memory + * of the hash table randomly, and want it to be as small as possible to fit the + * caches. + */ +typedef struct FUNCTION_NAME(entry) +{ + /* Key index 0 is invalid. */ + uint32 key_index; + + uint8 status; + + HASH_TABLE_KEY_TYPE hash_table_key; +} FUNCTION_NAME(entry); + +#define SH_PREFIX KEY_VARIANT +#define SH_ELEMENT_TYPE FUNCTION_NAME(entry) +#define SH_KEY_TYPE HASH_TABLE_KEY_TYPE +#define SH_KEY hash_table_key +#define SH_HASH_KEY(tb, key) KEY_HASH(key) +#define SH_EQUAL(tb, a, b) KEY_EQUAL(a, b) +#define SH_SCOPE static inline +#define SH_DECLARE +#define SH_DEFINE +#include + +struct FUNCTION_NAME(hash); + +static uint64 +FUNCTION_NAME(get_size_bytes)(HashingStrategy *hashing) +{ + struct FUNCTION_NAME(hash) *hash = (struct FUNCTION_NAME(hash) *) hashing->table; + return hash->members * sizeof(FUNCTION_NAME(entry)); +} + +static void +FUNCTION_NAME(hash_strategy_init)(HashingStrategy *hashing, GroupingPolicyHash *policy) +{ + hashing->table = + FUNCTION_NAME(create)(CurrentMemoryContext, policy->num_allocated_per_key_agg_states, NULL); + + FUNCTION_NAME(key_hashing_init)(hashing); +} + +static void +FUNCTION_NAME(hash_strategy_reset)(HashingStrategy *hashing) +{ + struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) hashing->table; + FUNCTION_NAME(reset)(table); + hashing->null_key_index = 0; +} + +static void +FUNCTION_NAME(hash_strategy_prepare_for_batch)(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ + hash_strategy_output_key_alloc(policy, batch_state); + FUNCTION_NAME(key_hashing_prepare_for_batch)(policy, batch_state); +} + +/* + * Fill the unique key indexes for all rows of the batch, using a hash table. + */ +static pg_attribute_always_inline void +FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) +{ + GroupingPolicyHash *policy = params.policy; + HashingStrategy *hashing = &policy->hashing; + + uint32 *restrict indexes = params.result_key_indexes; + + struct FUNCTION_NAME(hash) *restrict table = hashing->table; + + HASH_TABLE_KEY_TYPE prev_hash_table_key; + uint32 previous_key_index = 0; + for (int row = start_row; row < end_row; row++) + { + if (!arrow_row_is_valid(params.batch_filter, row)) + { + /* The row doesn't pass the filter. */ + DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); + continue; + } + + /* + * Get the key for the given row. For some hashing strategies, the key + * that is used for the hash table is different from actual values of + * the grouping columns, termed "output key" here. + */ + bool key_valid = false; + OUTPUT_KEY_TYPE output_key = { 0 }; + HASH_TABLE_KEY_TYPE hash_table_key = { 0 }; + FUNCTION_NAME(key_hashing_get_key)(params, row, &output_key, &hash_table_key, &key_valid); + + if (unlikely(!key_valid)) + { + /* The key is null. */ + if (hashing->null_key_index == 0) + { + hashing->null_key_index = ++policy->last_used_key_index; + } + indexes[row] = hashing->null_key_index; + DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, hashing->null_key_index); + continue; + } + + if (likely(previous_key_index != 0) && KEY_EQUAL(hash_table_key, prev_hash_table_key)) + { + /* + * In real data sets, we often see consecutive rows with the + * same value of a grouping column, so checking for this case + * improves performance. For multi-column keys, this is unlikely, + * but we currently often have suboptimal plans that use this policy + * as a GroupAggregate, so we still use this as an easy optimization + * for that case. + */ + indexes[row] = previous_key_index; +#ifndef NDEBUG + policy->stat_consecutive_keys++; +#endif + DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); + continue; + } + + /* + * Find the key using the hash table. + */ + bool found = false; + FUNCTION_NAME(entry) *restrict entry = FUNCTION_NAME(insert)(table, hash_table_key, &found); + if (!found) + { + /* + * New key, have to store it persistently. + */ + const uint32 index = ++policy->last_used_key_index; + entry->key_index = index; + FUNCTION_NAME(key_hashing_store_new)(policy, index, output_key); + DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); + } + else + { + DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); + } + indexes[row] = entry->key_index; + + previous_key_index = entry->key_index; + prev_hash_table_key = entry->hash_table_key; + } +} + +/* + * For some configurations of hashing, we want to generate dedicated + * implementations that will be more efficient. For example, for 2-byte keys + * when all the batch and key rows are valid. + */ +#define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ + X(NAME##_nofilter, (COND) && (params.batch_filter == NULL)) \ + X(NAME##_filter, (COND) && (params.batch_filter != NULL)) + +#define APPLY_FOR_NULLABILITY(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && params.single_key.buffers[0] == NULL) \ + APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && params.single_key.buffers[0] != NULL) + +#define APPLY_FOR_SCALARS(X, NAME, COND) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_noscalar_notnull, \ + (COND) && !params.have_scalar_or_nullable_columns) \ + APPLY_FOR_BATCH_FILTER(X, \ + NAME##_scalar_or_nullable, \ + (COND) && params.have_scalar_or_nullable_columns) + +#define APPLY_FOR_TYPE(X, NAME, COND) \ + APPLY_FOR_NULLABILITY(X, \ + NAME##_byval, \ + (COND) && \ + params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) \ + APPLY_FOR_NULLABILITY(X, \ + NAME##_text, \ + (COND) && params.single_key.decompression_type == DT_ArrowText) \ + APPLY_FOR_NULLABILITY(X, \ + NAME##_dict, \ + (COND) && params.single_key.decompression_type == DT_ArrowTextDict) \ + APPLY_FOR_SCALARS(X, NAME##_multi, (COND) && params.single_key.decompression_type == DT_Invalid) + +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, index, true) + +#define DEFINE(NAME, CONDITION) \ + static pg_noinline void FUNCTION_NAME( \ + NAME)(BatchHashingParams params, int start_row, int end_row) \ + { \ + if (!(CONDITION)) \ + { \ + pg_unreachable(); \ + } \ + \ + FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); \ + } + +APPLY_FOR_SPECIALIZATIONS(DEFINE) + +#undef DEFINE + +static void +FUNCTION_NAME(dispatch_for_params)(BatchHashingParams params, int start_row, int end_row) +{ + if (params.num_grouping_columns == 0) + { + pg_unreachable(); + } + + if ((params.num_grouping_columns == 1) != (params.single_key.decompression_type != DT_Invalid)) + { + pg_unreachable(); + } + +#define DISPATCH(NAME, CONDITION) \ + if (CONDITION) \ + { \ + FUNCTION_NAME(NAME)(params, start_row, end_row); \ + } \ + else + + APPLY_FOR_SPECIALIZATIONS(DISPATCH) + { + /* Use a generic implementation if no specializations matched. */ + FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); + } +#undef DISPATCH +} + +#undef APPLY_FOR_SPECIALIZATIONS + +/* + * In some special cases we call a more efficient specialization of the grouping + * function. + */ +static void +FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int start_row, int end_row) +{ + Assert((size_t) end_row <= policy->num_key_index_for_row); + + BatchHashingParams params = build_batch_hashing_params(policy, batch_state); + +#ifdef USE_DICT_HASHING + if (policy->use_key_index_for_dict) + { + Assert(params.single_key.decompression_type == DT_ArrowTextDict); + single_text_offsets_translate(params, start_row, end_row); + return; + } +#endif + + FUNCTION_NAME(dispatch_for_params)(params, start_row, end_row); +} + +HashingStrategy FUNCTION_NAME(strategy) = { + .emit_key = FUNCTION_NAME(emit_key), + .explain_name = EXPLAIN_NAME, + .fill_offsets = FUNCTION_NAME(fill_offsets), + .get_size_bytes = FUNCTION_NAME(get_size_bytes), + .init = FUNCTION_NAME(hash_strategy_init), + .prepare_for_batch = FUNCTION_NAME(hash_strategy_prepare_for_batch), + .reset = FUNCTION_NAME(hash_strategy_reset), +}; + +#undef EXPLAIN_NAME +#undef KEY_VARIANT +#undef KEY_EQUAL +#undef OUTPUT_KEY_TYPE +#undef HASH_TABLE_KEY_TYPE +#undef USE_DICT_HASHING diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c new file mode 100644 index 00000000000..c8a3c2da57f --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -0,0 +1,70 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Key handling function for a single fixed-size grouping key. + */ + +#include "batch_hashing_params.h" + +static void +FUNCTION_NAME(key_hashing_init)(HashingStrategy *hashing) +{ +} + +static void +FUNCTION_NAME(key_hashing_prepare_for_batch)(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ +} + +static pg_attribute_always_inline void +FUNCTION_NAME(key_hashing_get_key)(BatchHashingParams params, int row, + void *restrict output_key_ptr, void *restrict hash_table_key_ptr, + bool *restrict valid) +{ + OUTPUT_KEY_TYPE *restrict output_key = (OUTPUT_KEY_TYPE *) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; + + if (unlikely(params.single_key.decompression_type == DT_Scalar)) + { + *output_key = DATUM_TO_OUTPUT_KEY(*params.single_key.output_value); + *valid = !*params.single_key.output_isnull; + } + else if (params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) + { + const OUTPUT_KEY_TYPE *values = params.single_key.buffers[1]; + *valid = arrow_row_is_valid(params.single_key.buffers[0], row); + *output_key = values[row]; + } + else + { + pg_unreachable(); + } + + /* + * For the fixed-size hash grouping, we use the output key as the hash table + * key as well. + */ + *hash_table_key = *output_key; +} + +static pg_attribute_always_inline void +FUNCTION_NAME(key_hashing_store_new)(GroupingPolicyHash *restrict policy, uint32 new_key_index, + OUTPUT_KEY_TYPE output_key) +{ + policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); +} + +static void +FUNCTION_NAME(emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); +} + +#undef DATUM_TO_OUTPUT_KEY +#undef OUTPUT_KEY_TO_DATUM diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c new file mode 100644 index 00000000000..8e2a9083d06 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_2.c @@ -0,0 +1,32 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 2-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#define EXPLAIN_NAME "single 2-byte" +#define KEY_VARIANT single_fixed_2 +#define OUTPUT_KEY_TYPE int16 +#define HASH_TABLE_KEY_TYPE OUTPUT_KEY_TYPE +#define DATUM_TO_OUTPUT_KEY DatumGetInt16 +#define OUTPUT_KEY_TO_DATUM Int16GetDatum + +#include "hash_strategy_impl_single_fixed_key.c" + +#define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) + +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c new file mode 100644 index 00000000000..96679548d52 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c @@ -0,0 +1,32 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 2-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#define EXPLAIN_NAME "single 4-byte" +#define KEY_VARIANT single_fixed_4 +#define OUTPUT_KEY_TYPE int32 +#define HASH_TABLE_KEY_TYPE int32 +#define DATUM_TO_OUTPUT_KEY DatumGetInt32 +#define OUTPUT_KEY_TO_DATUM Int32GetDatum + +#include "hash_strategy_impl_single_fixed_key.c" + +#define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) + +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c new file mode 100644 index 00000000000..e0f12adf85b --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_8.c @@ -0,0 +1,32 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single fixed size 8-byte column. + */ + +#include + +#include "compression/arrow_c_data_interface.h" +#include "hash64.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#define EXPLAIN_NAME "single 8-byte" +#define KEY_VARIANT single_fixed_8 +#define OUTPUT_KEY_TYPE int64 +#define HASH_TABLE_KEY_TYPE int64 +#define DATUM_TO_OUTPUT_KEY DatumGetInt64 +#define OUTPUT_KEY_TO_DATUM Int64GetDatum + +#include "hash_strategy_impl_single_fixed_key.c" + +#define KEY_EQUAL(a, b) a == b +#define KEY_HASH(X) HASH64(X) + +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h new file mode 100644 index 00000000000..e2bfda3b180 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -0,0 +1,64 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#include + +typedef struct GroupingPolicyHash GroupingPolicyHash; + +typedef struct HashingStrategy HashingStrategy; + +typedef struct DecompressBatchState DecompressBatchState; + +typedef struct TupleTableSlot TupleTableSlot; + +typedef struct HashingStrategy +{ + char *explain_name; + void (*init)(HashingStrategy *hashing, GroupingPolicyHash *policy); + void (*reset)(HashingStrategy *hashing); + uint64 (*get_size_bytes)(HashingStrategy *hashing); + void (*prepare_for_batch)(GroupingPolicyHash *policy, DecompressBatchState *batch_state); + void (*fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, + int start_row, int end_row); + void (*emit_key)(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot); + + /* + * The hash table we use for grouping. It matches each grouping key to its + * unique integer index. + */ + void *table; + + /* + * For each unique grouping key, we store the values of the grouping columns. + * This is stored separately from hash table keys, because they might not + * have the full column values, and also storing them contiguously here + * leads to better memory access patterns when emitting the results. + * The details of the key storage are managed by the hashing strategy. The + * by-reference keys can use a separate memory context for dense storage. + */ + Datum *restrict output_keys; + uint64 num_allocated_output_keys; + MemoryContext key_body_mctx; + + /* + * In single-column grouping, we store the null key outside of the hash + * table, and its index is given by this value. Key index 0 is invalid. + * This is done to avoid having an "is null" flag in the hash table entries, + * to reduce the hash table size. + */ + uint32 null_key_index; + + /* + * UMASH fingerprinting parameters. + */ + struct umash_params *umash_params; +} HashingStrategy; + +void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state); +void hash_strategy_output_key_single_emit(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot); diff --git a/tsl/src/nodes/vector_agg/hashing/template_helper.h b/tsl/src/nodes/vector_agg/hashing/template_helper.h new file mode 100644 index 00000000000..684186ab27e --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/template_helper.h @@ -0,0 +1,10 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#define FUNCTION_NAME_HELPER2(X, Y) X##_##Y +#define FUNCTION_NAME_HELPER(X, Y) FUNCTION_NAME_HELPER2(X, Y) +#define FUNCTION_NAME(Y) FUNCTION_NAME_HELPER(KEY_VARIANT, Y) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 34ab45044fc..669a52ca203 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -366,13 +366,11 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) /* * We support hashed vectorized grouping by one fixed-size by-value * compressed column. - * We cannot use it when the plan has GroupAggregate because the - * latter requires sorted output. */ - if (agg->numCols == 1 && agg->aggstrategy == AGG_HASHED) + if (agg->numCols == 1) { int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); - TargetEntry *entry = list_nth(agg->plan.targetlist, offset); + TargetEntry *entry = list_nth(resolved_targetlist, offset); bool is_segmentby = false; if (is_vector_var(custom, entry->expr, &is_segmentby)) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index e7e970986cb..bffb8d7af7d 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -114,7 +114,7 @@ limit 1 set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. --- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, @@ -157,7 +157,8 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's']) with ordinality as grouping(grouping, n) + 's', + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -190,6 +191,21 @@ select s, count(*) from aggfns group by s order by count(*), s limit 10; 9 | 20000 (10 rows) +select ss, count(*) from aggfns group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select max(cdate) from aggfns; max ------------ @@ -211,6 +227,21 @@ select s, max(cdate) from aggfns group by s order by max(cdate), s limit 10; 9 | 06-01-2267 (10 rows) +select ss, max(cdate) from aggfns group by ss order by max(cdate), ss limit 10; + ss | max +----+------------ + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select min(cdate) from aggfns; min ------------ @@ -232,6 +263,21 @@ select s, min(cdate) from aggfns group by s order by min(cdate), s limit 10; 9 | 06-01-2267 (10 rows) +select ss, min(cdate) from aggfns group by ss order by min(cdate), ss limit 10; + ss | min +----+------------ + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select avg(cfloat4) from aggfns; avg ----- @@ -253,6 +299,21 @@ select s, avg(cfloat4) from aggfns group by s order by avg(cfloat4), s limit 10; 1 | NaN (10 rows) +select ss, avg(cfloat4) from aggfns group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+---------------------- + 3 | -Infinity + | -1.39583652270468 + 9 | -0.292700759558938 + 4 | -0.169252917487522 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 11 | NaN +(10 rows) + select max(cfloat4) from aggfns; max ----- @@ -274,6 +335,21 @@ select s, max(cfloat4) from aggfns group by s order by max(cfloat4), s limit 10; 1 | NaN (10 rows) +select ss, max(cfloat4) from aggfns group by ss order by max(cfloat4), ss limit 10; + ss | max +----+--------- + | 47.2047 + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 + 11 | NaN +(10 rows) + select min(cfloat4) from aggfns; min ----------- @@ -295,6 +371,21 @@ select s, min(cfloat4) from aggfns group by s order by min(cfloat4), s limit 10; 9 | -49.9911 (10 rows) +select ss, min(cfloat4) from aggfns group by ss order by min(cfloat4), ss limit 10; + ss | min +----+----------- + 3 | -Infinity + 4 | -49.9999 + 6 | -49.9995 + 7 | -49.9984 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 + | -45.4083 + 11 | NaN +(10 rows) + select stddev(cfloat4) from aggfns; stddev -------- @@ -316,6 +407,21 @@ select s, stddev(cfloat4) from aggfns group by s order by stddev(cfloat4), s lim 3 | NaN (10 rows) +select ss, stddev(cfloat4) from aggfns group by ss order by stddev(cfloat4), ss limit 10; + ss | stddev +----+------------------ + 0 | 28.7274163912974 + 7 | 28.7892027644318 + 4 | 28.8220943927954 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270614 + | 30.6324072248673 + 3 | NaN + 11 | NaN +(10 rows) + select sum(cfloat4) from aggfns; sum ----- @@ -337,6 +443,21 @@ select s, sum(cfloat4) from aggfns group by s order by sum(cfloat4), s limit 10; 1 | NaN (10 rows) +select ss, sum(cfloat4) from aggfns group by ss order by sum(cfloat4), ss limit 10; + ss | sum +----+----------- + 3 | -Infinity + 9 | -5854.02 + 4 | -3381.84 + 6 | -122.193 + | -26.5209 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 11 | NaN +(10 rows) + select avg(cfloat8) from aggfns; avg ----------------- @@ -358,6 +479,21 @@ select s, avg(cfloat8) from aggfns group by s order by avg(cfloat8), s limit 10; 1 | 13 (10 rows) +select ss, avg(cfloat8) from aggfns group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.224160255000712 + 3 | -0.153492446187821 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + | 5.42090986487701 + 11 | 6.59778165165114 +(10 rows) + select max(cfloat8) from aggfns; max ------------------ @@ -379,6 +515,21 @@ select s, max(cfloat8) from aggfns group by s order by max(cfloat8), s limit 10; 9 | 49.9995574122295 (10 rows) +select ss, max(cfloat8) from aggfns group by ss order by max(cfloat8), ss limit 10; + ss | max +----+------------------ + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + select min(cfloat8) from aggfns; min ------------------- @@ -400,6 +551,21 @@ select s, min(cfloat8) from aggfns group by s order by min(cfloat8), s limit 10; 1 | 13 (10 rows) +select ss, min(cfloat8) from aggfns group by ss order by min(cfloat8), ss limit 10; + ss | min +----+------------------- + 0 | -49.9994775978848 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 +(10 rows) + select stddev(cfloat8) from aggfns; stddev ------------------ @@ -421,6 +587,21 @@ select s, stddev(cfloat8) from aggfns group by s order by stddev(cfloat8), s lim 7 | 28.9656492103737 (10 rows) +select ss, stddev(cfloat8) from aggfns group by ss order by stddev(cfloat8), ss limit 10; + ss | stddev +----+------------------ + 11 | 21.3262797346004 + | 22.894065438835 + 9 | 28.7642081921344 + 4 | 28.7760615445521 + 5 | 28.7843925303698 + 6 | 28.8543767497508 + 3 | 28.926156595386 + 8 | 28.96331707256 + 0 | 28.9653425568561 + 7 | 28.9656492103736 +(10 rows) + select sum(cfloat8) from aggfns; sum ----------------- @@ -442,6 +623,21 @@ select s, sum(cfloat8) from aggfns group by s order by sum(cfloat8), s limit 10; 1 | 260000 (10 rows) +select ss, sum(cfloat8) from aggfns group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4478.94605516922 + 3 | -3066.93256727885 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + | 102.997287432663 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 11 | 264036.623917427 +(10 rows) + select avg(cint2) from aggfns; avg ---------------------- @@ -463,6 +659,21 @@ select s, avg(cint2) from aggfns group by s order by avg(cint2), s limit 10; 5 | 110.0305290025524248 (10 rows) +select ss, avg(cint2) from aggfns group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -1368.1578947368421053 + 8 | -129.4959711726139833 + 3 | -94.5546037471195271 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 11 | -33.7550336409794652 + 4 | -27.5652740206392145 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 5 | 110.0305290025524248 +(10 rows) + select count(cint2) from aggfns; count -------- @@ -484,6 +695,21 @@ select s, count(cint2) from aggfns group by s order by count(cint2), s limit 10; 9 | 19981 (10 rows) +select ss, count(cint2) from aggfns group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + select max(cint2) from aggfns; max ------- @@ -505,6 +731,21 @@ select s, max(cint2) from aggfns group by s order by max(cint2), s limit 10; 9 | 16383 (10 rows) +select ss, max(cint2) from aggfns group by ss order by max(cint2), ss limit 10; + ss | max +----+------- + | 16362 + 3 | 16380 + 5 | 16381 + 7 | 16381 + 8 | 16382 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + select min(cint2) from aggfns; min -------- @@ -526,6 +767,21 @@ select s, min(cint2) from aggfns group by s order by min(cint2), s limit 10; 9 | -16375 (10 rows) +select ss, min(cint2) from aggfns group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + select stddev(cint2) from aggfns; stddev ------------------- @@ -547,6 +803,21 @@ select s, stddev(cint2) from aggfns group by s order by stddev(cint2), s limit 1 1 | 9528.039076724276 (10 rows) +select ss, stddev(cint2) from aggfns group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+------------------- + | 8413.549166956554 + 9 | 9450.322790943425 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9474.482349111595 + 8 | 9477.586839536066 + 4 | 9483.611454519949 + 0 | 9484.907423282680 + 11 | 9494.206429493352 +(10 rows) + select sum(cint2) from aggfns; sum ---------- @@ -568,6 +839,21 @@ select s, sum(cint2) from aggfns group by s order by sum(cint2), s limit 10; 5 | 2198520 (10 rows) +select ss, sum(cint2) from aggfns group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 8 | -2587459 + 3 | -1887499 + 11 | -1349560 + 6 | -1220352 + 7 | -1116329 + 4 | -550258 + 9 | -435575 + | -25995 + 0 | 351569 + 5 | 2198520 +(10 rows) + select avg(cint4) from aggfns; avg --------------------- @@ -589,6 +875,21 @@ select s, avg(cint4) from aggfns group by s order by avg(cint4), s limit 10; 5 | 103.1069000000000000 (10 rows) +select ss, avg(cint4) from aggfns group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 9 | -102.4283000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 11 | -16.4247732327144606 + 4 | 9.6930584054852110 + 0 | 27.7536500000000000 + 3 | 68.3874180471447875 + 5 | 103.1069000000000000 + | 2197.6842105263157895 +(10 rows) + select max(cint4) from aggfns; max ------- @@ -610,6 +911,21 @@ select s, max(cint4) from aggfns group by s order by max(cint4), s limit 10; 9 | 16383 (10 rows) +select ss, max(cint4) from aggfns group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + select min(cint4) from aggfns; min -------- @@ -631,6 +947,21 @@ select s, min(cint4) from aggfns group by s order by min(cint4), s limit 10; 5 | -16380 (10 rows) +select ss, min(cint4) from aggfns group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 + | -15907 +(10 rows) + select stddev(cint4) from aggfns; stddev ------------------- @@ -652,6 +983,21 @@ select s, stddev(cint4) from aggfns group by s order by stddev(cint4), s limit 1 5 | 9504.684751625578 (10 rows) +select ss, stddev(cint4) from aggfns group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + | 9361.317298404296 + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 4 | 9442.480718256247 + 8 | 9450.281544631633 + 11 | 9450.690059613938 + 3 | 9474.873657491443 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + select sum(cint4) from aggfns; sum --------- @@ -673,6 +1019,21 @@ select s, sum(cint4) from aggfns group by s order by sum(cint4), s limit 10; 5 | 2062138 (10 rows) +select ss, sum(cint4) from aggfns group by ss order by sum(cint4), ss limit 10; + ss | sum +----+---------- + 9 | -2048566 + 6 | -1063133 + 7 | -852243 + 11 | -657303 + 8 | -585231 + | 41756 + 4 | 193677 + 0 | 555073 + 3 | 1366449 + 5 | 2062138 +(10 rows) + select avg(cint8) from aggfns; avg ---------------------- @@ -694,6 +1055,21 @@ select s, avg(cint8) from aggfns group by s order by avg(cint8), s limit 10; 9 | 61.7467500000000000 (10 rows) +select ss, avg(cint8) from aggfns group by ss order by avg(cint8), ss limit 10; + ss | avg +----+----------------------- + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 4 | -17.0811771182623492 + 11 | -15.1685449411529523 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 37.6662329212752115 + 9 | 61.7467500000000000 + | 2467.2631578947368421 +(10 rows) + select max(cint8) from aggfns; max ------- @@ -715,6 +1091,21 @@ select s, max(cint8) from aggfns group by s order by max(cint8), s limit 10; 5 | 16383 (10 rows) +select ss, max(cint8) from aggfns group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 4 | 16383 + 5 | 16383 + 11 | 16383 +(10 rows) + select min(cint8) from aggfns; min -------- @@ -736,6 +1127,21 @@ select s, min(cint8) from aggfns group by s order by min(cint8), s limit 10; 3 | -16378 (10 rows) +select ss, min(cint8) from aggfns group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 3 | -16378 + | -14174 +(10 rows) + select sum(cint8) from aggfns; sum ---------- @@ -757,6 +1163,21 @@ select s, sum(cint8) from aggfns group by s order by sum(cint8), s limit 10; 9 | 1234935 (10 rows) +select ss, sum(cint8) from aggfns group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -2369740 + 5 | -1633911 + 11 | -607030 + 4 | -341299 + 7 | -47127 + | 46878 + 6 | 238113 + 0 | 306036 + 3 | 752609 + 9 | 1234935 +(10 rows) + select max(cts) from aggfns; max -------------------------- @@ -778,6 +1199,21 @@ select s, max(cts) from aggfns group by s order by max(cts), s limit 10; 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, max(cts) from aggfns group by ss order by max(cts), ss limit 10; + ss | max +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select min(cts) from aggfns; min -------------------------- @@ -799,6 +1235,21 @@ select s, min(cts) from aggfns group by s order by min(cts), s limit 10; 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, min(cts) from aggfns group by ss order by min(cts), ss limit 10; + ss | min +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select max(ctstz) from aggfns; max ------------------------------ @@ -820,6 +1271,21 @@ select s, max(ctstz) from aggfns group by s order by max(ctstz), s limit 10; 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, max(ctstz) from aggfns group by ss order by max(ctstz), ss limit 10; + ss | max +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select min(ctstz) from aggfns; min ------------------------------ @@ -841,6 +1307,21 @@ select s, min(ctstz) from aggfns group by s order by min(ctstz), s limit 10; 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, min(ctstz) from aggfns group by ss order by min(ctstz), ss limit 10; + ss | min +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select avg(s) from aggfns; avg -------------------- @@ -862,6 +1343,21 @@ select s, avg(s) from aggfns group by s order by avg(s), s limit 10; 9 | 9.0000000000000000 (10 rows) +select ss, avg(s) from aggfns group by ss order by avg(s), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 11 | 1.5011869362053025 + 3 | 3.0000000000000000 + | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 +(10 rows) + select count(s) from aggfns; count -------- @@ -883,6 +1379,21 @@ select s, count(s) from aggfns group by s order by count(s), s limit 10; 9 | 20000 (10 rows) +select ss, count(s) from aggfns group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select max(s) from aggfns; max ----- @@ -904,6 +1415,21 @@ select s, max(s) from aggfns group by s order by max(s), s limit 10; 9 | 9 (10 rows) +select ss, max(s) from aggfns group by ss order by max(s), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + | 3 + 4 | 4 + 11 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select min(s) from aggfns; min ----- @@ -925,6 +1451,21 @@ select s, min(s) from aggfns group by s order by min(s), s limit 10; 9 | 9 (10 rows) +select ss, min(s) from aggfns group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select stddev(s) from aggfns; stddev -------------------- @@ -946,6 +1487,21 @@ select s, stddev(s) from aggfns group by s order by stddev(s), s limit 10; 9 | 0 (10 rows) +select ss, stddev(s) from aggfns group by ss order by stddev(s), ss limit 10; + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + | 0 + 11 | 0.50284545977155885187 +(10 rows) + select sum(s) from aggfns; sum -------- @@ -967,6 +1523,21 @@ select s, sum(s) from aggfns group by s order by sum(s), s limit 10; 9 | 180000 (10 rows) +select ss, sum(s) from aggfns group by ss order by sum(s), ss limit 10; + ss | sum +----+-------- + 0 | 0 + | 57 + 3 | 59943 + 11 | 60076 + 4 | 79924 + 5 | 100000 + 6 | 120000 + 7 | 140000 + 8 | 160000 + 9 | 180000 +(10 rows) + select avg(ss) from aggfns; avg -------------------- @@ -988,6 +1559,21 @@ select s, avg(ss) from aggfns group by s order by avg(ss), s limit 10; 2 | 11.0000000000000000 (10 rows) +select ss, avg(ss) from aggfns group by ss order by avg(ss), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 3 | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + select max(ss) from aggfns; max ----- @@ -1009,6 +1595,21 @@ select s, max(ss) from aggfns group by s order by max(ss), s limit 10; 4 | 11 (10 rows) +select ss, max(ss) from aggfns group by ss order by max(ss), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select min(ss) from aggfns; min ----- @@ -1030,6 +1631,21 @@ select s, min(ss) from aggfns group by s order by min(ss), s limit 10; 2 | 11 (10 rows) +select ss, min(ss) from aggfns group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select stddev(ss) from aggfns; stddev -------------------- @@ -1051,6 +1667,21 @@ select s, stddev(ss) from aggfns group by s order by stddev(ss), s limit 10; 4 | 0.21565737387148452722 (10 rows) +select ss, stddev(ss) from aggfns group by ss order by stddev(ss), ss limit 10; + ss | stddev +----+-------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 + | +(10 rows) + select sum(ss) from aggfns; sum --------- @@ -1072,6 +1703,21 @@ select s, sum(ss) from aggfns group by s order by sum(ss), s limit 10; 2 | 220000 (10 rows) +select ss, sum(ss) from aggfns group by ss order by sum(ss), ss limit 10; + ss | sum +----+-------- + 0 | 0 + 3 | 59943 + 4 | 79924 + 5 | 100000 + 6 | 120000 + 7 | 140000 + 8 | 160000 + 9 | 180000 + 11 | 440209 + | +(10 rows) + select max(t) from aggfns; max -------- @@ -1093,6 +1739,21 @@ select s, max(t) from aggfns group by s order by max(t), s limit 10; 9 | 110000 (10 rows) +select ss, max(t) from aggfns group by ss order by max(t), ss limit 10; + ss | max +----+-------- + 0 | 20000 + | 49491 + 3 | 50000 + 11 | 59192 + 4 | 60000 + 5 | 70000 + 6 | 80000 + 7 | 90000 + 8 | 100000 + 9 | 110000 +(10 rows) + select min(t) from aggfns; min ----- @@ -1114,6 +1775,21 @@ select s, min(t) from aggfns group by s order by min(t), s limit 10; 9 | 90001 (10 rows) +select ss, min(t) from aggfns group by ss order by min(t), ss limit 10; + ss | min +----+------- + 0 | 1 + 11 | 10001 + 3 | 30001 + | 30537 + 4 | 40001 + 5 | 50001 + 6 | 60001 + 7 | 70001 + 8 | 80001 + 9 | 90001 +(10 rows) + select count(*) from aggfns where cfloat8 > 0; count -------- @@ -1135,6 +1811,21 @@ select s, count(*) from aggfns where cfloat8 > 0 group by s order by count(*), s 1 | 20000 (10 rows) +select ss, count(*) from aggfns where cfloat8 > 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 13 + 4 | 9872 + 0 | 9881 + 9 | 9945 + 3 | 9950 + 8 | 9950 + 5 | 9972 + 7 | 10021 + 6 | 10097 + 11 | 30084 +(10 rows) + select max(cdate) from aggfns where cfloat8 > 0; max ------------ @@ -1156,6 +1847,21 @@ select s, max(cdate) from aggfns where cfloat8 > 0 group by s order by max(cdate 9 | 06-01-2267 (10 rows) +select ss, max(cdate) from aggfns where cfloat8 > 0 group by ss order by max(cdate), ss limit 10; + ss | max +----+------------ + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select min(cdate) from aggfns where cfloat8 > 0; min ------------ @@ -1177,6 +1883,21 @@ select s, min(cdate) from aggfns where cfloat8 > 0 group by s order by min(cdate 9 | 06-01-2267 (10 rows) +select ss, min(cdate) from aggfns where cfloat8 > 0 group by ss order by min(cdate), ss limit 10; + ss | min +----+------------ + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select avg(cfloat4) from aggfns where cfloat8 > 0; avg ----- @@ -1198,6 +1919,21 @@ select s, avg(cfloat4) from aggfns where cfloat8 > 0 group by s order by avg(cfl 1 | NaN (10 rows) +select ss, avg(cfloat4) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+-------------------- + 3 | -Infinity + 4 | -0.458554823065329 + 0 | -0.334856044433109 + 9 | -0.208302219537011 + 6 | 0.199537611181853 + 7 | 0.313851696029514 + 5 | 0.374879026647364 + 8 | 0.606801085094336 + | 1.47322510755979 + 11 | NaN +(10 rows) + select max(cfloat4) from aggfns where cfloat8 > 0; max ----- @@ -1219,6 +1955,21 @@ select s, max(cfloat4) from aggfns where cfloat8 > 0 group by s order by max(cfl 1 | NaN (10 rows) +select ss, max(cfloat4) from aggfns where cfloat8 > 0 group by ss order by max(cfloat4), ss limit 10; + ss | max +----+--------- + | 47.2047 + 9 | 49.9744 + 3 | 49.9744 + 0 | 49.9863 + 8 | 49.9923 + 4 | 49.9928 + 6 | 49.9956 + 7 | 49.9969 + 5 | 49.9992 + 11 | NaN +(10 rows) + select min(cfloat4) from aggfns where cfloat8 > 0; min ----------- @@ -1240,6 +1991,21 @@ select s, min(cfloat4) from aggfns where cfloat8 > 0 group by s order by min(cfl 6 | -49.9891 (10 rows) +select ss, min(cfloat4) from aggfns where cfloat8 > 0 group by ss order by min(cfloat4), ss limit 10; + ss | min +----+----------- + 3 | -Infinity + 4 | -49.9993 + 8 | -49.9969 + 7 | -49.9969 + 0 | -49.9915 + 9 | -49.9911 + 5 | -49.9892 + 6 | -49.9891 + | -41.6131 + 11 | NaN +(10 rows) + select stddev(cfloat4) from aggfns where cfloat8 > 0; stddev -------- @@ -1261,6 +2027,21 @@ select s, stddev(cfloat4) from aggfns where cfloat8 > 0 group by s order by stdd 3 | NaN (10 rows) +select ss, stddev(cfloat4) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat4), ss limit 10; + ss | stddev +----+------------------ + 7 | 28.7246858657947 + 0 | 28.7315562731003 + 9 | 28.7729261590403 + 4 | 28.8497176060195 + 5 | 28.9107809470208 + 6 | 28.9388387251543 + 8 | 29.1042713834566 + | 29.539145536489 + 3 | NaN + 11 | NaN +(10 rows) + select sum(cfloat4) from aggfns where cfloat8 > 0; sum ----- @@ -1282,6 +2063,21 @@ select s, sum(cfloat4) from aggfns where cfloat8 > 0 group by s order by sum(cfl 1 | NaN (10 rows) +select ss, sum(cfloat4) from aggfns where cfloat8 > 0 group by ss order by sum(cfloat4), ss limit 10; + ss | sum +----+----------- + 3 | -Infinity + 4 | -4526.85 + 0 | -3308.71 + 9 | -2071.57 + | 19.1519 + 6 | 2014.73 + 7 | 3145.11 + 5 | 3738.29 + 8 | 6037.67 + 11 | NaN +(10 rows) + select avg(cfloat8) from aggfns where cfloat8 > 0; avg ------------------ @@ -1303,6 +2099,21 @@ select s, avg(cfloat8) from aggfns where cfloat8 > 0 group by s order by avg(cfl 0 | 25.0776526587937 (10 rows) +select ss, avg(cfloat8) from aggfns where cfloat8 > 0 group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+------------------ + | 16.6705740293345 + 11 | 16.9860875451313 + 6 | 24.9229571834467 + 9 | 24.933601739557 + 8 | 24.9404756362227 + 4 | 24.9719502302445 + 7 | 24.9965050319499 + 5 | 25.0141908239782 + 3 | 25.0352176289523 + 0 | 25.0776526587937 +(10 rows) + select max(cfloat8) from aggfns where cfloat8 > 0; max ------------------ @@ -1324,6 +2135,21 @@ select s, max(cfloat8) from aggfns where cfloat8 > 0 group by s order by max(cfl 9 | 49.9995574122295 (10 rows) +select ss, max(cfloat8) from aggfns where cfloat8 > 0 group by ss order by max(cfloat8), ss limit 10; + ss | max +----+------------------ + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + select min(cfloat8) from aggfns where cfloat8 > 0; min ---------------------- @@ -1345,6 +2171,21 @@ select s, min(cfloat8) from aggfns where cfloat8 > 0 group by s order by min(cfl 1 | 13 (10 rows) +select ss, min(cfloat8) from aggfns where cfloat8 > 0 group by ss order by min(cfloat8), ss limit 10; + ss | min +----+---------------------- + 4 | 0.000765081495046616 + 7 | 0.000956561416387558 + 6 | 0.00179046764969826 + 0 | 0.00247885473072529 + 11 | 0.00441970769315958 + 3 | 0.00545482616871595 + 5 | 0.00628724228590727 + 9 | 0.0187294092029333 + 8 | 0.0195798231288791 + | 0.312147964723408 +(10 rows) + select stddev(cfloat8) from aggfns where cfloat8 > 0; stddev ------------------ @@ -1366,6 +2207,21 @@ select s, stddev(cfloat8) from aggfns where cfloat8 > 0 group by s order by stdd 8 | 14.507225286092 (10 rows) +select ss, stddev(cfloat8) from aggfns where cfloat8 > 0 group by ss order by stddev(cfloat8), ss limit 10; + ss | stddev +----+------------------ + 11 | 10.0892977778207 + 9 | 14.3145979997847 + 3 | 14.3656116060957 + 4 | 14.4158826742614 + 6 | 14.4175557556357 + 5 | 14.4400766885504 + 0 | 14.4509605112521 + 7 | 14.4643374353136 + 8 | 14.507225286092 + | 15.8897779049656 +(10 rows) + select sum(cfloat8) from aggfns where cfloat8 > 0; sum ------------------ @@ -1387,6 +2243,21 @@ select s, sum(cfloat8) from aggfns where cfloat8 > 0 group by s order by sum(cfl 1 | 260000 (10 rows) +select ss, sum(cfloat8) from aggfns where cfloat8 > 0 group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+------------------ + | 216.717462381348 + 4 | 246523.092672974 + 0 | 247792.285921541 + 9 | 247964.669299894 + 8 | 248157.732580416 + 3 | 249100.415408076 + 5 | 249441.510896711 + 7 | 250489.97692517 + 6 | 251647.098681261 + 11 | 511009.457707731 +(10 rows) + select avg(cint2) from aggfns where cfloat8 > 0; avg ---------------------- @@ -1408,6 +2279,21 @@ select s, avg(cint2) from aggfns where cfloat8 > 0 group by s order by avg(cint2 5 | 153.6364822808954924 (10 rows) +select ss, avg(cint2) from aggfns where cfloat8 > 0 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -2431.3076923076923077 + 9 | -192.8237544036235531 + 3 | -156.9368272809576501 + 7 | -142.7671027664036752 + 4 | -119.1966149792236749 + 6 | -98.2421689135606661 + 8 | -1.6297525648762824 + 11 | 7.3528100356037667 + 0 | 28.7771364925070879 + 5 | 153.6364822808954924 +(10 rows) + select count(cint2) from aggfns where cfloat8 > 0; count -------- @@ -1429,6 +2315,21 @@ select s, count(cint2) from aggfns where cfloat8 > 0 group by s order by count(c 1 | 19981 (10 rows) +select ss, count(cint2) from aggfns where cfloat8 > 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 13 + 4 | 9867 + 0 | 9876 + 9 | 9935 + 3 | 9941 + 8 | 9942 + 5 | 9961 + 7 | 10013 + 6 | 10088 + 11 | 30053 +(10 rows) + select max(cint2) from aggfns where cfloat8 > 0; max ------- @@ -1450,6 +2351,21 @@ select s, max(cint2) from aggfns where cfloat8 > 0 group by s order by max(cint2 9 | 16383 (10 rows) +select ss, max(cint2) from aggfns where cfloat8 > 0 group by ss order by max(cint2), ss limit 10; + ss | max +----+------- + | 7971 + 3 | 16380 + 8 | 16380 + 5 | 16381 + 6 | 16381 + 7 | 16381 + 0 | 16383 + 4 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + select min(cint2) from aggfns where cfloat8 > 0; min -------- @@ -1471,6 +2387,21 @@ select s, min(cint2) from aggfns where cfloat8 > 0 group by s order by min(cint2 9 | -16375 (10 rows) +select ss, min(cint2) from aggfns where cfloat8 > 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 6 | -16383 + 8 | -16382 + 5 | -16381 + 7 | -16380 + 3 | -16378 + 11 | -16378 + 9 | -16375 + | -16100 +(10 rows) + select stddev(cint2) from aggfns where cfloat8 > 0; stddev ------------------- @@ -1492,6 +2423,21 @@ select s, stddev(cint2) from aggfns where cfloat8 > 0 group by s order by stddev 1 | 9528.039076724276 (10 rows) +select ss, stddev(cint2) from aggfns where cfloat8 > 0 group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+------------------- + | 7759.524506314969 + 5 | 9422.095841513016 + 6 | 9433.502305093184 + 9 | 9441.945023643920 + 4 | 9447.849754018911 + 7 | 9460.956887483220 + 3 | 9463.490872675688 + 8 | 9466.374225763893 + 11 | 9488.645998388904 + 0 | 9519.824544774386 +(10 rows) + select sum(cint2) from aggfns where cfloat8 > 0; sum ---------- @@ -1513,6 +2459,21 @@ select s, sum(cint2) from aggfns where cfloat8 > 0 group by s order by sum(cint2 1 | 1837240 (10 rows) +select ss, sum(cint2) from aggfns where cfloat8 > 0 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 9 | -1915704 + 3 | -1560109 + 7 | -1429527 + 4 | -1176113 + 6 | -991067 + | -31607 + 8 | -16203 + 11 | 220974 + 0 | 284203 + 5 | 1530373 +(10 rows) + select avg(cint4) from aggfns where cfloat8 > 0; avg --------------------- @@ -1534,6 +2495,21 @@ select s, avg(cint4) from aggfns where cfloat8 > 0 group by s order by avg(cint4 3 | 170.6088527551942186 (10 rows) +select ss, avg(cint4) from aggfns where cfloat8 > 0 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 9 | -227.0452488687782805 + 6 | -94.7697335842329405 + 4 | -40.9285858995137763 + 7 | -7.9618800518910288 + 11 | -4.2226765057838053 + 8 | 30.7776884422110553 + 5 | 70.0002005615724027 + 0 | 78.5152312518975812 + 3 | 169.6967839195979899 + | 868.6923076923076923 +(10 rows) + select max(cint4) from aggfns where cfloat8 > 0; max ------- @@ -1555,6 +2531,21 @@ select s, max(cint4) from aggfns where cfloat8 > 0 group by s order by max(cint4 1 | 16383 (10 rows) +select ss, max(cint4) from aggfns where cfloat8 > 0 group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16380 + 6 | 16380 + 9 | 16381 + 4 | 16382 + 8 | 16382 + 11 | 16383 +(10 rows) + select min(cint4) from aggfns where cfloat8 > 0; min -------- @@ -1576,6 +2567,21 @@ select s, min(cint4) from aggfns where cfloat8 > 0 group by s order by min(cint4 8 | -16377 (10 rows) +select ss, min(cint4) from aggfns where cfloat8 > 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 7 | -16383 + 11 | -16383 + 0 | -16382 + 9 | -16382 + 5 | -16380 + 3 | -16379 + 4 | -16378 + 6 | -16378 + 8 | -16377 + | -15907 +(10 rows) + select stddev(cint4) from aggfns where cfloat8 > 0; stddev ------------------- @@ -1597,6 +2603,21 @@ select s, stddev(cint4) from aggfns where cfloat8 > 0 group by s order by stddev 3 | 9509.065450373130 (10 rows) +select ss, stddev(cint4) from aggfns where cfloat8 > 0 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + | 8985.945186647640 + 0 | 9368.404782340758 + 6 | 9385.470128440942 + 8 | 9411.536015886790 + 4 | 9416.391322858156 + 11 | 9460.260597896060 + 9 | 9474.284943213442 + 5 | 9475.929892556881 + 7 | 9500.872262505529 + 3 | 9510.123363067463 +(10 rows) + select sum(cint4) from aggfns where cfloat8 > 0; sum --------- @@ -1618,6 +2639,21 @@ select s, sum(cint4) from aggfns where cfloat8 > 0 group by s order by sum(cint4 3 | 1699776 (10 rows) +select ss, sum(cint4) from aggfns where cfloat8 > 0 group by ss order by sum(cint4), ss limit 10; + ss | sum +----+---------- + 9 | -2257965 + 6 | -956890 + 4 | -404047 + 11 | -127035 + 7 | -79786 + | 11293 + 8 | 306238 + 5 | 698042 + 0 | 775809 + 3 | 1688483 +(10 rows) + select avg(cint8) from aggfns where cfloat8 > 0; avg --------------------- @@ -1639,6 +2675,21 @@ select s, avg(cint8) from aggfns where cfloat8 > 0 group by s order by avg(cint8 2 | 148.9026206075044669 (10 rows) +select ss, avg(cint8) from aggfns where cfloat8 > 0 group by ss order by avg(cint8), ss limit 10; + ss | avg +----+------------------------ + 8 | -166.4501507537688442 + 5 | -78.9197753710389089 + 4 | -61.5197528363047002 + 6 | -32.8705556105773992 + 7 | 1.15707015267937331604 + 11 | 33.0028919026725170 + 0 | 42.9815808116587390 + 9 | 44.5682252388134741 + 3 | 106.1022110552763819 + | 2876.8461538461538462 +(10 rows) + select max(cint8) from aggfns where cfloat8 > 0; max ------- @@ -1660,6 +2711,21 @@ select s, max(cint8) from aggfns where cfloat8 > 0 group by s order by max(cint8 5 | 16383 (10 rows) +select ss, max(cint8) from aggfns where cfloat8 > 0 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 7 | 16378 + 6 | 16379 + 0 | 16380 + 8 | 16380 + 3 | 16381 + 4 | 16382 + 9 | 16382 + 5 | 16383 + 11 | 16383 +(10 rows) + select min(cint8) from aggfns where cfloat8 > 0; min -------- @@ -1681,6 +2747,21 @@ select s, min(cint8) from aggfns where cfloat8 > 0 group by s order by min(cint8 3 | -16378 (10 rows) +select ss, min(cint8) from aggfns where cfloat8 > 0 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 7 | -16383 + 8 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 6 | -16381 + 9 | -16380 + 0 | -16379 + 3 | -16378 + | -11918 +(10 rows) + select sum(cint8) from aggfns where cfloat8 > 0; sum --------- @@ -1702,6 +2783,21 @@ select s, sum(cint8) from aggfns where cfloat8 > 0 group by s order by sum(cint8 2 | 1500045 (10 rows) +select ss, sum(cint8) from aggfns where cfloat8 > 0 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -1656179 + 5 | -786988 + 4 | -607323 + 6 | -331894 + 7 | 11595 + | 37399 + 0 | 424701 + 9 | 443231 + 11 | 992859 + 3 | 1055717 +(10 rows) + select max(cts) from aggfns where cfloat8 > 0; max -------------------------- @@ -1723,6 +2819,21 @@ select s, max(cts) from aggfns where cfloat8 > 0 group by s order by max(cts), s 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, max(cts) from aggfns where cfloat8 > 0 group by ss order by max(cts), ss limit 10; + ss | max +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select min(cts) from aggfns where cfloat8 > 0; min -------------------------- @@ -1744,6 +2855,21 @@ select s, min(cts) from aggfns where cfloat8 > 0 group by s order by min(cts), s 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, min(cts) from aggfns where cfloat8 > 0 group by ss order by min(cts), ss limit 10; + ss | min +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select max(ctstz) from aggfns where cfloat8 > 0; max ------------------------------ @@ -1765,6 +2891,21 @@ select s, max(ctstz) from aggfns where cfloat8 > 0 group by s order by max(ctstz 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, max(ctstz) from aggfns where cfloat8 > 0 group by ss order by max(ctstz), ss limit 10; + ss | max +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select min(ctstz) from aggfns where cfloat8 > 0; min ------------------------------ @@ -1786,6 +2927,21 @@ select s, min(ctstz) from aggfns where cfloat8 > 0 group by s order by min(ctstz 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, min(ctstz) from aggfns where cfloat8 > 0 group by ss order by min(ctstz), ss limit 10; + ss | min +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select avg(s) from aggfns where cfloat8 > 0; avg -------------------- @@ -1796,10 +2952,10 @@ select s, avg(s) from aggfns where cfloat8 > 0 group by s order by avg(s), s lim s | avg ---+------------------------ 0 | 0.00000000000000000000 - 1 | 11.0000000000000000 - 2 | 11.0000000000000000 + 1 | 1.00000000000000000000 + 2 | 2.0000000000000000 3 | 3.0000000000000000 - 4 | 4.0077441416071608 + 4 | 4.0000000000000000 5 | 5.0000000000000000 6 | 6.0000000000000000 7 | 7.0000000000000000 @@ -1807,6 +2963,21 @@ select s, avg(s) from aggfns where cfloat8 > 0 group by s order by avg(s), s lim 9 | 9.0000000000000000 (10 rows) +select ss, avg(s) from aggfns where cfloat8 > 0 group by ss order by avg(s), ss limit 10; + ss | avg +----+------------------------ + 0 | 0.00000000000000000000 + 11 | 1.3358595931392102 + 3 | 3.0000000000000000 + | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 +(10 rows) + select count(s) from aggfns where cfloat8 > 0; count -------- @@ -1828,20 +2999,35 @@ select s, count(s) from aggfns where cfloat8 > 0 group by s order by count(s), s 1 | 20000 (10 rows) +select ss, count(s) from aggfns where cfloat8 > 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 13 + 4 | 9872 + 0 | 9881 + 9 | 9945 + 3 | 9950 + 8 | 9950 + 5 | 9972 + 7 | 10021 + 6 | 10097 + 11 | 30084 +(10 rows) + select max(s) from aggfns where cfloat8 > 0; max ----- - 11 + 9 (1 row) select s, max(s) from aggfns where cfloat8 > 0 group by s order by max(s), s limit 10; s | max ---+----- 0 | 0 - 1 | 11 - 2 | 11 + 1 | 1 + 2 | 2 3 | 3 - 4 | 11 + 4 | 4 5 | 5 6 | 6 7 | 7 @@ -1849,6 +3035,21 @@ select s, max(s) from aggfns where cfloat8 > 0 group by s order by max(s), s lim 9 | 9 (10 rows) +select ss, max(s) from aggfns where cfloat8 > 0 group by ss order by max(s), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + | 3 + 4 | 4 + 11 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select min(s) from aggfns where cfloat8 > 0; min ----- @@ -1859,8 +3060,8 @@ select s, min(s) from aggfns where cfloat8 > 0 group by s order by min(s), s lim s | min ---+----- 0 | 0 - 1 | 11 - 2 | 11 + 1 | 1 + 2 | 2 3 | 3 4 | 4 5 | 5 @@ -1870,6 +3071,21 @@ select s, min(s) from aggfns where cfloat8 > 0 group by s order by min(s), s lim 9 | 9 (10 rows) +select ss, min(s) from aggfns where cfloat8 > 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select stddev(s) from aggfns where cfloat8 > 0; stddev -------------------- @@ -1891,6 +3107,21 @@ select s, stddev(s) from aggfns where cfloat8 > 0 group by s order by stddev(s), 9 | 0 (10 rows) +select ss, stddev(s) from aggfns where cfloat8 > 0 group by ss order by stddev(s), ss limit 10; + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + | 0 + 11 | 0.47440470436008342899 +(10 rows) + select sum(s) from aggfns where cfloat8 > 0; sum -------- @@ -1912,6 +3143,21 @@ select s, sum(s) from aggfns where cfloat8 > 0 group by s order by sum(s), s lim 9 | 89505 (10 rows) +select ss, sum(s) from aggfns where cfloat8 > 0 group by ss order by sum(s), ss limit 10; + ss | sum +----+------- + 0 | 0 + | 39 + 3 | 29850 + 4 | 39488 + 11 | 40188 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 +(10 rows) + select avg(ss) from aggfns where cfloat8 > 0; avg -------------------- @@ -1933,6 +3179,21 @@ select s, avg(ss) from aggfns where cfloat8 > 0 group by s order by avg(ss), s l 2 | 11.0000000000000000 (10 rows) +select ss, avg(ss) from aggfns where cfloat8 > 0 group by ss order by avg(ss), ss limit 10; + ss | avg +----+------------------------ + 0 | 0.00000000000000000000 + 3 | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + select max(ss) from aggfns where cfloat8 > 0; max ----- @@ -1954,6 +3215,21 @@ select s, max(ss) from aggfns where cfloat8 > 0 group by s order by max(ss), s l 4 | 11 (10 rows) +select ss, max(ss) from aggfns where cfloat8 > 0 group by ss order by max(ss), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select min(ss) from aggfns where cfloat8 > 0; min ----- @@ -1975,6 +3251,21 @@ select s, min(ss) from aggfns where cfloat8 > 0 group by s order by min(ss), s l 2 | 11 (10 rows) +select ss, min(ss) from aggfns where cfloat8 > 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select stddev(ss) from aggfns where cfloat8 > 0; stddev -------------------- @@ -1996,6 +3287,21 @@ select s, stddev(ss) from aggfns where cfloat8 > 0 group by s order by stddev(ss 4 | 0.22257569540261848080 (10 rows) +select ss, stddev(ss) from aggfns where cfloat8 > 0 group by ss order by stddev(ss), ss limit 10; + ss | stddev +----+-------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 + | +(10 rows) + select sum(ss) from aggfns where cfloat8 > 0; sum -------- @@ -2017,6 +3323,21 @@ select s, sum(ss) from aggfns where cfloat8 > 0 group by s order by sum(ss), s l 1 | 220000 (10 rows) +select ss, sum(ss) from aggfns where cfloat8 > 0 group by ss order by sum(ss), ss limit 10; + ss | sum +----+-------- + 0 | 0 + 3 | 29850 + 4 | 39488 + 5 | 49860 + 6 | 60582 + 7 | 70147 + 8 | 79600 + 9 | 89505 + 11 | 330924 + | +(10 rows) + select max(t) from aggfns where cfloat8 > 0; max -------- @@ -2038,6 +3359,21 @@ select s, max(t) from aggfns where cfloat8 > 0 group by s order by max(t), s lim 9 | 110000 (10 rows) +select ss, max(t) from aggfns where cfloat8 > 0 group by ss order by max(t), ss limit 10; + ss | max +----+-------- + 0 | 19999 + | 49491 + 3 | 49999 + 11 | 59192 + 4 | 60000 + 5 | 70000 + 6 | 79998 + 7 | 89995 + 8 | 99997 + 9 | 110000 +(10 rows) + select min(t) from aggfns where cfloat8 > 0; min ----- @@ -2059,6 +3395,21 @@ select s, min(t) from aggfns where cfloat8 > 0 group by s order by min(t), s lim 9 | 90002 (10 rows) +select ss, min(t) from aggfns where cfloat8 > 0 group by ss order by min(t), ss limit 10; + ss | min +----+------- + 0 | 1 + 11 | 10001 + 3 | 30001 + | 30537 + 4 | 40003 + 5 | 50001 + 6 | 60002 + 7 | 70001 + 8 | 80003 + 9 | 90002 +(10 rows) + select count(*) from aggfns where cfloat8 <= 0; count ------- @@ -2079,6 +3430,21 @@ select s, count(*) from aggfns where cfloat8 <= 0 group by s order by count(*), 0 | 10119 (9 rows) +select ss, count(*) from aggfns where cfloat8 <= 0 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 6 + 6 | 9903 + 11 | 9935 + 7 | 9979 + 5 | 10028 + 3 | 10031 + 8 | 10050 + 9 | 10055 + 4 | 10109 + 0 | 10119 +(10 rows) + select max(cdate) from aggfns where cfloat8 <= 0; max ------------ @@ -2099,6 +3465,21 @@ select s, max(cdate) from aggfns where cfloat8 <= 0 group by s order by max(cdat 9 | 06-01-2267 (9 rows) +select ss, max(cdate) from aggfns where cfloat8 <= 0 group by ss order by max(cdate), ss limit 10; + ss | max +----+------------ + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select min(cdate) from aggfns where cfloat8 <= 0; min ------------ @@ -2119,6 +3500,21 @@ select s, min(cdate) from aggfns where cfloat8 <= 0 group by s order by min(cdat 9 | 06-01-2267 (9 rows) +select ss, min(cdate) from aggfns where cfloat8 <= 0 group by ss order by min(cdate), ss limit 10; + ss | min +----+------------ + 0 | 01-01-2021 + 11 | 10-05-2075 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select avg(cfloat4) from aggfns where cfloat8 <= 0; avg ---------- @@ -2139,6 +3535,21 @@ select s, avg(cfloat4) from aggfns where cfloat8 <= 0 group by s order by avg(cf 2 | Infinity (9 rows) +select ss, avg(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+-------------------- + | -7.61213672161102 + 9 | -0.376175993822296 + 5 | -0.351281471733702 + 3 | -0.323676224863234 + 6 | -0.215785538185229 + 7 | 0.0690012062121504 + 4 | 0.113266462457489 + 8 | 0.308099926433512 + 0 | 0.497406092427368 + 11 | Infinity +(10 rows) + select max(cfloat4) from aggfns where cfloat8 <= 0; max ---------- @@ -2159,6 +3570,21 @@ select s, max(cfloat4) from aggfns where cfloat8 <= 0 group by s order by max(cf 2 | Infinity (9 rows) +select ss, max(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat4), ss limit 10; + ss | max +----+---------- + | 43.8334 + 5 | 49.9753 + 9 | 49.9899 + 7 | 49.992 + 6 | 49.9938 + 4 | 49.9946 + 3 | 49.9979 + 0 | 49.9995 + 8 | 49.9997 + 11 | Infinity +(10 rows) + select min(cfloat4) from aggfns where cfloat8 <= 0; min ---------- @@ -2179,6 +3605,21 @@ select s, min(cfloat4) from aggfns where cfloat8 <= 0 group by s order by min(cf 3 | -49.974 (9 rows) +select ss, min(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat4), ss limit 10; + ss | min +----+---------- + 4 | -49.9999 + 6 | -49.9995 + 11 | -49.9991 + 7 | -49.9984 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9874 + 8 | -49.9853 + 3 | -49.974 + | -45.4083 +(10 rows) + select stddev(cfloat4) from aggfns where cfloat8 <= 0; stddev -------- @@ -2199,6 +3640,21 @@ select s, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by s order by std 2 | NaN (9 rows) +select ss, stddev(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat4), ss limit 10; + ss | stddev +----+------------------ + 0 | 28.7188352112159 + 3 | 28.7564997868619 + 4 | 28.7937148382071 + 7 | 28.8547648614793 + 6 | 28.89882973622 + 8 | 28.9050890855561 + 9 | 28.9126192916064 + 5 | 29.1278202173095 + | 34.8729157239149 + 11 | NaN +(10 rows) + select sum(cfloat4) from aggfns where cfloat8 <= 0; sum ---------- @@ -2219,6 +3675,21 @@ select s, sum(cfloat4) from aggfns where cfloat8 <= 0 group by s order by sum(cf 2 | Infinity (9 rows) +select ss, sum(cfloat4) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat4), ss limit 10; + ss | sum +----+---------- + 9 | -3782.45 + 5 | -3522.65 + 3 | -3246.8 + 6 | -2136.92 + | -45.6728 + 7 | 688.563 + 4 | 1145.01 + 8 | 3096.4 + 0 | 5033.25 + 11 | Infinity +(10 rows) + select avg(cfloat8) from aggfns where cfloat8 <= 0; avg ------------------- @@ -2239,6 +3710,21 @@ select s, avg(cfloat8) from aggfns where cfloat8 <= 0 group by s order by avg(cf 5 | -24.7870942066272 (9 rows) +select ss, avg(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+------------------- + 7 | -25.229255062715 + 8 | -25.2270239386592 + 3 | -25.1388045035744 + 0 | -25.0944548448943 + 6 | -25.0686778438405 + 9 | -24.8892608135943 + 11 | -24.858866008083 + 4 | -24.8295616508204 + 5 | -24.7870942066272 + | -18.9533624914475 +(10 rows) + select max(cfloat8) from aggfns where cfloat8 <= 0; max ---------------------- @@ -2259,6 +3745,21 @@ select s, max(cfloat8) from aggfns where cfloat8 <= 0 group by s order by max(cf 2 | -0.00172397121787071 (9 rows) +select ss, max(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by max(cfloat8), ss limit 10; + ss | max +----+---------------------- + | -5.18986904062331 + 0 | -0.00547224190086126 + 9 | -0.00466627534478903 + 4 | -0.0041270861402154 + 6 | -0.00408347696065903 + 7 | -0.00273226760327816 + 3 | -0.00268903095275164 + 5 | -0.00228420831263065 + 8 | -0.00182925723493099 + 11 | -0.00172397121787071 +(10 rows) + select min(cfloat8) from aggfns where cfloat8 <= 0; min ------------------- @@ -2279,6 +3780,21 @@ select s, min(cfloat8) from aggfns where cfloat8 <= 0 group by s order by min(cf 8 | -49.9897602945566 (9 rows) +select ss, min(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by min(cfloat8), ss limit 10; + ss | min +----+------------------- + 0 | -49.9994775978848 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 +(10 rows) + select stddev(cfloat8) from aggfns where cfloat8 <= 0; stddev ------------------ @@ -2299,6 +3815,21 @@ select s, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by s order by std 0 | 14.5136612753879 (9 rows) +select ss, stddev(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by stddev(cfloat8), ss limit 10; + ss | stddev +----+------------------ + 7 | 14.4030112329563 + 11 | 14.4033336871388 + 6 | 14.4144870413512 + 3 | 14.4335904065982 + 4 | 14.4339025361113 + 5 | 14.4378475427373 + 9 | 14.445355480345 + 8 | 14.4532419971748 + 0 | 14.5136612753879 + | 15.4584765893444 +(10 rows) + select sum(cfloat8) from aggfns where cfloat8 <= 0; sum ------------------- @@ -2319,6 +3850,21 @@ select s, sum(cfloat8) from aggfns where cfloat8 <= 0 group by s order by sum(cf 2 | -246743.521314557 (9 rows) +select ss, sum(cfloat8) from aggfns where cfloat8 <= 0 group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+------------------- + 0 | -253930.788575485 + 8 | -253531.590583525 + 3 | -252167.347975355 + 7 | -251762.736270833 + 4 | -251002.038728143 + 9 | -250261.517480691 + 5 | -248564.980704058 + 6 | -248255.116687552 + 11 | -246972.833790304 + | -113.720174948685 +(10 rows) + select avg(cint2) from aggfns where cfloat8 <= 0; avg ---------------------- @@ -2339,6 +3885,21 @@ select s, avg(cint2) from aggfns where cfloat8 <= 0 group by s order by avg(cint 9 | 147.3351582719490344 (9 rows) +select ss, avg(cint2) from aggfns where cfloat8 <= 0 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+----------------------- + 8 | -256.1267058471959359 + 11 | -158.1923851732473811 + 3 | -32.6703921764294981 + 6 | -23.1764884261599110 + 0 | 6.6666006927263731 + 7 | 31.4203451043338684 + 4 | 61.9965329370975731 + 5 | 66.6813373253493014 + 9 | 147.3351582719490344 + | 935.3333333333333333 +(10 rows) + select count(cint2) from aggfns where cfloat8 <= 0; count ------- @@ -2359,6 +3920,21 @@ select s, count(cint2) from aggfns where cfloat8 <= 0 group by s order by count( 0 | 10105 (9 rows) +select ss, count(cint2) from aggfns where cfloat8 <= 0 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 6 + 6 | 9893 + 11 | 9928 + 7 | 9968 + 5 | 10020 + 3 | 10021 + 8 | 10039 + 9 | 10046 + 4 | 10095 + 0 | 10105 +(10 rows) + select max(cint2) from aggfns where cfloat8 <= 0; max ------- @@ -2379,6 +3955,21 @@ select s, max(cint2) from aggfns where cfloat8 <= 0 group by s order by max(cint 6 | 16383 (9 rows) +select ss, max(cint2) from aggfns where cfloat8 <= 0 group by ss order by max(cint2), ss limit 10; + ss | max +----+------- + | 16362 + 7 | 16376 + 9 | 16376 + 3 | 16378 + 0 | 16381 + 5 | 16381 + 11 | 16381 + 8 | 16382 + 4 | 16383 + 6 | 16383 +(10 rows) + select min(cint2) from aggfns where cfloat8 <= 0; min -------- @@ -2399,6 +3990,21 @@ select s, min(cint2) from aggfns where cfloat8 <= 0 group by s order by min(cint 9 | -16374 (9 rows) +select ss, min(cint2) from aggfns where cfloat8 <= 0 group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 4 | -16379 + 9 | -16374 + | -7696 +(10 rows) + select stddev(cint2) from aggfns where cfloat8 <= 0; stddev ------------------- @@ -2419,6 +4025,21 @@ select s, stddev(cint2) from aggfns where cfloat8 <= 0 group by s order by stdde 4 | 9517.027301293118 (9 rows) +select ss, stddev(cint2) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+-------------------- + 0 | 9451.115288155243 + 9 | 9456.028731464701 + 7 | 9463.041992703462 + 3 | 9485.440311868001 + 8 | 9487.451140540082 + 6 | 9502.509922580216 + 11 | 9510.413974851870 + 5 | 9513.243501566793 + 4 | 9518.051043653511 + | 10051.146773710285 +(10 rows) + select sum(cint2) from aggfns where cfloat8 <= 0; sum ---------- @@ -2439,6 +4060,21 @@ select s, sum(cint2) from aggfns where cfloat8 <= 0 group by s order by sum(cint 9 | 1480129 (9 rows) +select ss, sum(cint2) from aggfns where cfloat8 <= 0 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 8 | -2571256 + 11 | -1570534 + 3 | -327390 + 6 | -229285 + | 5612 + 0 | 67366 + 7 | 313198 + 4 | 625855 + 5 | 668147 + 9 | 1480129 +(10 rows) + select avg(cint4) from aggfns where cfloat8 <= 0; avg --------------------- @@ -2459,6 +4095,21 @@ select s, avg(cint4) from aggfns where cfloat8 <= 0 group by s order by avg(cint 5 | 136.0287195851615477 (9 rows) +select ss, avg(cint4) from aggfns where cfloat8 <= 0 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 8 | -88.7033830845771144 + 7 | -77.4082573404148712 + 11 | -53.3737292400603926 + 3 | -32.1038779782673711 + 0 | -21.8140132424152584 + 6 | -10.7283651418761991 + 9 | 20.8253605171556440 + 4 | 59.1279058264912454 + 5 | 136.0287195851615477 + | 5077.1666666666666667 +(10 rows) + select max(cint4) from aggfns where cfloat8 <= 0; max ------- @@ -2479,6 +4130,21 @@ select s, max(cint4) from aggfns where cfloat8 <= 0 group by s order by max(cint 9 | 16383 (9 rows) +select ss, max(cint4) from aggfns where cfloat8 <= 0 group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 13078 + 5 | 16364 + 7 | 16378 + 3 | 16379 + 11 | 16381 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 +(10 rows) + select min(cint4) from aggfns where cfloat8 <= 0; min -------- @@ -2499,6 +4165,21 @@ select s, min(cint4) from aggfns where cfloat8 <= 0 group by s order by min(cint 5 | -16374 (9 rows) +select ss, min(cint4) from aggfns where cfloat8 <= 0 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16381 + 7 | -16379 + 11 | -16377 + 5 | -16374 + | -8992 +(10 rows) + select stddev(cint4) from aggfns where cfloat8 <= 0; stddev ------------------- @@ -2519,6 +4200,21 @@ select s, stddev(cint4) from aggfns where cfloat8 <= 0 group by s order by stdde 5 | 9533.551517829360 (9 rows) +select ss, stddev(cint4) from aggfns where cfloat8 <= 0 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + 9 | 9377.745829196558 + 11 | 9422.029173765748 + 6 | 9436.031206307503 + 3 | 9439.178404000439 + 0 | 9444.372352979574 + 4 | 9468.093604068949 + 7 | 9470.920199125109 + 8 | 9488.579674823607 + 5 | 9533.551517829360 + | 10351.23962464 +(10 rows) + select sum(cint4) from aggfns where cfloat8 <= 0; sum --------- @@ -2539,6 +4235,21 @@ select s, sum(cint4) from aggfns where cfloat8 <= 0 group by s order by sum(cint 5 | 1364096 (9 rows) +select ss, sum(cint4) from aggfns where cfloat8 <= 0 group by ss order by sum(cint4), ss limit 10; + ss | sum +----+--------- + 8 | -891469 + 7 | -772457 + 11 | -530268 + 3 | -322034 + 0 | -220736 + 6 | -106243 + | 30463 + 9 | 209399 + 4 | 597724 + 5 | 1364096 +(10 rows) + select avg(cint8) from aggfns where cfloat8 <= 0; avg ---------------------- @@ -2559,6 +4270,21 @@ select s, avg(cint8) from aggfns where cfloat8 <= 0 group by s order by avg(cint 9 | 78.7373446046742914 (9 rows) +select ss, avg(cint8) from aggfns where cfloat8 <= 0 group by ss order by avg(cint8), ss limit 10; + ss | avg +----+----------------------- + 11 | -161.0356316054353296 + 5 | -84.4558236936577583 + 8 | -71.0010945273631841 + 3 | -30.2171269065895723 + 0 | -11.7269493032908390 + 7 | -5.8845575708988877 + 4 | 26.3155603917301415 + 6 | 57.5590225184287590 + 9 | 78.7373446046742914 + | 1579.8333333333333333 +(10 rows) + select max(cint8) from aggfns where cfloat8 <= 0; max ------- @@ -2579,6 +4305,21 @@ select s, max(cint8) from aggfns where cfloat8 <= 0 group by s order by max(cint 4 | 16383 (9 rows) +select ss, max(cint8) from aggfns where cfloat8 <= 0 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 12678 + 8 | 16379 + 11 | 16379 + 6 | 16380 + 7 | 16380 + 5 | 16381 + 9 | 16381 + 3 | 16382 + 0 | 16383 + 4 | 16383 +(10 rows) + select min(cint8) from aggfns where cfloat8 <= 0; min -------- @@ -2599,6 +4340,21 @@ select s, min(cint8) from aggfns where cfloat8 <= 0 group by s order by min(cint 9 | -16372 (9 rows) +select ss, min(cint8) from aggfns where cfloat8 <= 0 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 8 | -16383 + 5 | -16382 + 4 | -16381 + 7 | -16381 + 3 | -16375 + 11 | -16375 + 9 | -16372 + | -14174 +(10 rows) + select sum(cint8) from aggfns where cfloat8 <= 0; sum ---------- @@ -2619,6 +4375,21 @@ select s, sum(cint8) from aggfns where cfloat8 <= 0 group by s order by sum(cint 9 | 791704 (9 rows) +select ss, sum(cint8) from aggfns where cfloat8 <= 0 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 11 | -1599889 + 5 | -846923 + 8 | -713561 + 3 | -303108 + 0 | -118665 + 7 | -58722 + | 9479 + 4 | 266024 + 6 | 570007 + 9 | 791704 +(10 rows) + select max(cts) from aggfns where cfloat8 <= 0; max -------------------------- @@ -2639,6 +4410,21 @@ select s, max(cts) from aggfns where cfloat8 <= 0 group by s order by max(cts), 9 | Sat Jan 02 02:01:01 2021 (9 rows) +select ss, max(cts) from aggfns where cfloat8 <= 0 group by ss order by max(cts), ss limit 10; + ss | max +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select min(cts) from aggfns where cfloat8 <= 0; min -------------------------- @@ -2659,6 +4445,21 @@ select s, min(cts) from aggfns where cfloat8 <= 0 group by s order by min(cts), 9 | Sat Jan 02 02:01:01 2021 (9 rows) +select ss, min(cts) from aggfns where cfloat8 <= 0 group by ss order by min(cts), ss limit 10; + ss | min +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 06:34:21 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select max(ctstz) from aggfns where cfloat8 <= 0; max ------------------------------ @@ -2679,7 +4480,22 @@ select s, max(ctstz) from aggfns where cfloat8 <= 0 group by s order by max(ctst 9 | Sat Jan 02 02:01:01 2021 PST (9 rows) -select min(ctstz) from aggfns where cfloat8 <= 0; +select ss, max(ctstz) from aggfns where cfloat8 <= 0 group by ss order by max(ctstz), ss limit 10; + ss | max +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + +select min(ctstz) from aggfns where cfloat8 <= 0; min ------------------------------ Fri Jan 01 01:01:01 2021 PST @@ -2699,6 +4515,21 @@ select s, min(ctstz) from aggfns where cfloat8 <= 0 group by s order by min(ctst 9 | Sat Jan 02 02:01:01 2021 PST (9 rows) +select ss, min(ctstz) from aggfns where cfloat8 <= 0 group by ss order by min(ctstz), ss limit 10; + ss | min +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 06:34:21 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select avg(s) from aggfns where cfloat8 <= 0; avg -------------------- @@ -2719,6 +4550,21 @@ select s, avg(s) from aggfns where cfloat8 <= 0 group by s order by avg(s), s li 9 | 9.0000000000000000 (9 rows) +select ss, avg(s) from aggfns where cfloat8 <= 0 group by ss order by avg(s), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 11 | 2.0018117765475591 + 3 | 3.0000000000000000 + | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 +(10 rows) + select count(s) from aggfns where cfloat8 <= 0; count ------- @@ -2739,6 +4585,21 @@ select s, count(s) from aggfns where cfloat8 <= 0 group by s order by count(s), 0 | 10119 (9 rows) +select ss, count(s) from aggfns where cfloat8 <= 0 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 6 + 6 | 9903 + 11 | 9935 + 7 | 9979 + 5 | 10028 + 3 | 10031 + 8 | 10050 + 9 | 10055 + 4 | 10109 + 0 | 10119 +(10 rows) + select max(s) from aggfns where cfloat8 <= 0; max ----- @@ -2759,6 +4620,21 @@ select s, max(s) from aggfns where cfloat8 <= 0 group by s order by max(s), s li 9 | 9 (9 rows) +select ss, max(s) from aggfns where cfloat8 <= 0 group by ss order by max(s), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + | 3 + 4 | 4 + 11 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select min(s) from aggfns where cfloat8 <= 0; min ----- @@ -2779,6 +4655,21 @@ select s, min(s) from aggfns where cfloat8 <= 0 group by s order by min(s), s li 9 | 9 (9 rows) +select ss, min(s) from aggfns where cfloat8 <= 0 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 2 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select stddev(s) from aggfns where cfloat8 <= 0; stddev -------------------- @@ -2799,6 +4690,21 @@ select s, stddev(s) from aggfns where cfloat8 <= 0 group by s order by stddev(s) 9 | 0 (9 rows) +select ss, stddev(s) from aggfns where cfloat8 <= 0 group by ss order by stddev(s), ss limit 10; + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + | 0 + 11 | 0.06017171256636552646 +(10 rows) + select sum(s) from aggfns where cfloat8 <= 0; sum -------- @@ -2819,6 +4725,21 @@ select s, sum(s) from aggfns where cfloat8 <= 0 group by s order by sum(s), s li 9 | 90495 (9 rows) +select ss, sum(s) from aggfns where cfloat8 <= 0 group by ss order by sum(s), ss limit 10; + ss | sum +----+------- + 0 | 0 + | 18 + 11 | 19888 + 3 | 30093 + 4 | 40436 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 +(10 rows) + select avg(ss) from aggfns where cfloat8 <= 0; avg -------------------- @@ -2839,6 +4760,21 @@ select s, avg(ss) from aggfns where cfloat8 <= 0 group by s order by avg(ss), s 2 | 11.0000000000000000 (9 rows) +select ss, avg(ss) from aggfns where cfloat8 <= 0 group by ss order by avg(ss), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 3 | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + select max(ss) from aggfns where cfloat8 <= 0; max ----- @@ -2859,6 +4795,21 @@ select s, max(ss) from aggfns where cfloat8 <= 0 group by s order by max(ss), s 4 | 11 (9 rows) +select ss, max(ss) from aggfns where cfloat8 <= 0 group by ss order by max(ss), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select min(ss) from aggfns where cfloat8 <= 0; min ----- @@ -2879,6 +4830,21 @@ select s, min(ss) from aggfns where cfloat8 <= 0 group by s order by min(ss), s 2 | 11 (9 rows) +select ss, min(ss) from aggfns where cfloat8 <= 0 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select stddev(ss) from aggfns where cfloat8 <= 0; stddev -------------------- @@ -2899,6 +4865,21 @@ select s, stddev(ss) from aggfns where cfloat8 <= 0 group by s order by stddev(s 4 | 0.20868929911309143893 (9 rows) +select ss, stddev(ss) from aggfns where cfloat8 <= 0 group by ss order by stddev(ss), ss limit 10; + ss | stddev +----+-------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 + | +(10 rows) + select sum(ss) from aggfns where cfloat8 <= 0; sum -------- @@ -2919,6 +4900,21 @@ select s, sum(ss) from aggfns where cfloat8 <= 0 group by s order by sum(ss), s 2 | 109186 (9 rows) +select ss, sum(ss) from aggfns where cfloat8 <= 0 group by ss order by sum(ss), ss limit 10; + ss | sum +----+-------- + 0 | 0 + 3 | 30093 + 4 | 40436 + 5 | 50140 + 6 | 59418 + 7 | 69853 + 8 | 80400 + 9 | 90495 + 11 | 109285 + | +(10 rows) + select max(t) from aggfns where cfloat8 <= 0; max -------- @@ -2939,6 +4935,21 @@ select s, max(t) from aggfns where cfloat8 <= 0 group by s order by max(t), s li 9 | 109998 (9 rows) +select ss, max(t) from aggfns where cfloat8 <= 0 group by ss order by max(t), ss limit 10; + ss | max +----+-------- + 0 | 20000 + | 48438 + 3 | 50000 + 11 | 58135 + 4 | 59998 + 5 | 69999 + 6 | 80000 + 7 | 90000 + 8 | 100000 + 9 | 109998 +(10 rows) + select min(t) from aggfns where cfloat8 <= 0; min ----- @@ -2959,6 +4970,21 @@ select s, min(t) from aggfns where cfloat8 <= 0 group by s order by min(t), s li 9 | 90001 (9 rows) +select ss, min(t) from aggfns where cfloat8 <= 0 group by ss order by min(t), ss limit 10; + ss | min +----+------- + 0 | 8 + 11 | 20003 + 3 | 30002 + | 33696 + 4 | 40001 + 5 | 50004 + 6 | 60001 + 7 | 70002 + 8 | 80001 + 9 | 90001 +(10 rows) + select count(*) from aggfns where cfloat8 < 1000; count -------- @@ -2980,6 +5006,21 @@ select s, count(*) from aggfns where cfloat8 < 1000 group by s order by count(*) 9 | 20000 (10 rows) +select ss, count(*) from aggfns where cfloat8 < 1000 group by ss order by count(*), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select max(cdate) from aggfns where cfloat8 < 1000; max ------------ @@ -3001,6 +5042,21 @@ select s, max(cdate) from aggfns where cfloat8 < 1000 group by s order by max(cd 9 | 06-01-2267 (10 rows) +select ss, max(cdate) from aggfns where cfloat8 < 1000 group by ss order by max(cdate), ss limit 10; + ss | max +----+------------ + 0 | 01-01-2021 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 11 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select min(cdate) from aggfns where cfloat8 < 1000; min ------------ @@ -3022,6 +5078,21 @@ select s, min(cdate) from aggfns where cfloat8 < 1000 group by s order by min(cd 9 | 06-01-2267 (10 rows) +select ss, min(cdate) from aggfns where cfloat8 < 1000 group by ss order by min(cdate), ss limit 10; + ss | min +----+------------ + 0 | 01-01-2021 + 11 | 05-19-2048 + 3 | 02-21-2103 + | 02-21-2103 + 4 | 07-09-2130 + 5 | 11-24-2157 + 6 | 04-11-2185 + 7 | 08-28-2212 + 8 | 01-14-2240 + 9 | 06-01-2267 +(10 rows) + select avg(cfloat4) from aggfns where cfloat8 < 1000; avg ----- @@ -3043,6 +5114,21 @@ select s, avg(cfloat4) from aggfns where cfloat8 < 1000 group by s order by avg( 1 | NaN (10 rows) +select ss, avg(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+---------------------- + 3 | -Infinity + | -1.39583652270468 + 9 | -0.292700759558938 + 4 | -0.169252917487522 + 6 | -0.00610964622725733 + 5 | 0.0107821527590975 + 0 | 0.0862269837114494 + 7 | 0.19168354413514 + 8 | 0.456703752867272 + 11 | NaN +(10 rows) + select max(cfloat4) from aggfns where cfloat8 < 1000; max ----- @@ -3064,6 +5150,21 @@ select s, max(cfloat4) from aggfns where cfloat8 < 1000 group by s order by max( 1 | NaN (10 rows) +select ss, max(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by max(cfloat4), ss limit 10; + ss | max +----+--------- + | 47.2047 + 9 | 49.9899 + 4 | 49.9946 + 6 | 49.9956 + 7 | 49.9969 + 3 | 49.9979 + 5 | 49.9992 + 0 | 49.9995 + 8 | 49.9997 + 11 | NaN +(10 rows) + select min(cfloat4) from aggfns where cfloat8 < 1000; min ----------- @@ -3085,6 +5186,21 @@ select s, min(cfloat4) from aggfns where cfloat8 < 1000 group by s order by min( 9 | -49.9911 (10 rows) +select ss, min(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by min(cfloat4), ss limit 10; + ss | min +----+----------- + 3 | -Infinity + 4 | -49.9999 + 6 | -49.9995 + 7 | -49.9984 + 8 | -49.9969 + 0 | -49.9949 + 5 | -49.9942 + 9 | -49.9911 + | -45.4083 + 11 | NaN +(10 rows) + select stddev(cfloat4) from aggfns where cfloat8 < 1000; stddev -------- @@ -3106,6 +5222,21 @@ select s, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by s order by s 3 | NaN (10 rows) +select ss, stddev(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by stddev(cfloat4), ss limit 10; + ss | stddev +----+------------------ + 0 | 28.7274163912974 + 7 | 28.7892027644318 + 4 | 28.8220943927954 + 9 | 28.8426424990846 + 6 | 28.9190577543738 + 8 | 29.0040125904064 + 5 | 29.0213532270614 + | 30.6324072248673 + 3 | NaN + 11 | NaN +(10 rows) + select sum(cfloat4) from aggfns where cfloat8 < 1000; sum ----- @@ -3127,6 +5258,21 @@ select s, sum(cfloat4) from aggfns where cfloat8 < 1000 group by s order by sum( 1 | NaN (10 rows) +select ss, sum(cfloat4) from aggfns where cfloat8 < 1000 group by ss order by sum(cfloat4), ss limit 10; + ss | sum +----+----------- + 3 | -Infinity + 9 | -5854.02 + 4 | -3381.84 + 6 | -122.193 + | -26.5209 + 5 | 215.643 + 0 | 1724.54 + 7 | 3833.67 + 8 | 9134.08 + 11 | NaN +(10 rows) + select avg(cfloat8) from aggfns where cfloat8 < 1000; avg ----------------- @@ -3148,6 +5294,21 @@ select s, avg(cfloat8) from aggfns where cfloat8 < 1000 group by s order by avg( 1 | 13 (10 rows) +select ss, avg(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+-------------------- + 0 | -0.306925132697215 + 8 | -0.268692900155438 + 4 | -0.224160255000712 + 3 | -0.153492446187821 + 9 | -0.114842409039848 + 7 | -0.063637967283139 + 5 | 0.0438265096326359 + 6 | 0.169599099685438 + | 5.42090986487701 + 11 | 6.59778165165114 +(10 rows) + select max(cfloat8) from aggfns where cfloat8 < 1000; max ------------------ @@ -3169,6 +5330,21 @@ select s, max(cfloat8) from aggfns where cfloat8 < 1000 group by s order by max( 9 | 49.9995574122295 (10 rows) +select ss, max(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by max(cfloat8), ss limit 10; + ss | max +----+------------------ + | 46.3985309237614 + 5 | 49.9874341068789 + 3 | 49.9890822684392 + 6 | 49.9939429108053 + 8 | 49.9963666079566 + 0 | 49.9965498689562 + 7 | 49.9973275698721 + 11 | 49.9975695507601 + 4 | 49.9978997278959 + 9 | 49.9995574122295 +(10 rows) + select min(cfloat8) from aggfns where cfloat8 < 1000; min ------------------- @@ -3190,6 +5366,21 @@ select s, min(cfloat8) from aggfns where cfloat8 < 1000 group by s order by min( 1 | 13 (10 rows) +select ss, min(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by min(cfloat8), ss limit 10; + ss | min +----+------------------- + 0 | -49.9994775978848 + 11 | -49.9985320260748 + 4 | -49.9983572866768 + 3 | -49.9977725092322 + 6 | -49.9967515002936 + 9 | -49.992344272323 + 5 | -49.9921301845461 + 7 | -49.99003498815 + 8 | -49.9897602945566 + | -38.5084833716974 +(10 rows) + select stddev(cfloat8) from aggfns where cfloat8 < 1000; stddev ------------------ @@ -3211,6 +5402,21 @@ select s, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by s order by s 7 | 28.9656492103737 (10 rows) +select ss, stddev(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by stddev(cfloat8), ss limit 10; + ss | stddev +----+------------------ + 11 | 21.3262797346004 + | 22.894065438835 + 9 | 28.7642081921344 + 4 | 28.7760615445521 + 5 | 28.7843925303698 + 6 | 28.8543767497508 + 3 | 28.926156595386 + 8 | 28.96331707256 + 0 | 28.9653425568561 + 7 | 28.9656492103736 +(10 rows) + select sum(cfloat8) from aggfns where cfloat8 < 1000; sum ----------------- @@ -3232,6 +5438,21 @@ select s, sum(cfloat8) from aggfns where cfloat8 < 1000 group by s order by sum( 1 | 260000 (10 rows) +select ss, sum(cfloat8) from aggfns where cfloat8 < 1000 group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+------------------- + 0 | -6138.50265394431 + 8 | -5373.85800310876 + 4 | -4478.94605516922 + 3 | -3066.93256727885 + 9 | -2296.84818079695 + 7 | -1272.75934566278 + | 102.997287432663 + 5 | 876.530192652717 + 6 | 3391.98199370876 + 11 | 264036.623917427 +(10 rows) + select avg(cint2) from aggfns where cfloat8 < 1000; avg ---------------------- @@ -3253,6 +5474,21 @@ select s, avg(cint2) from aggfns where cfloat8 < 1000 group by s order by avg(ci 5 | 110.0305290025524248 (10 rows) +select ss, avg(cint2) from aggfns where cfloat8 < 1000 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+------------------------ + | -1368.1578947368421053 + 8 | -129.4959711726139833 + 3 | -94.5546037471195271 + 6 | -61.0756218407487113 + 7 | -55.8695260497472599 + 11 | -33.7550336409794652 + 4 | -27.5652740206392145 + 9 | -21.7994594865121866 + 0 | 17.5951654071367799 + 5 | 110.0305290025524248 +(10 rows) + select count(cint2) from aggfns where cfloat8 < 1000; count -------- @@ -3274,6 +5510,21 @@ select s, count(cint2) from aggfns where cfloat8 < 1000 group by s order by coun 9 | 19981 (10 rows) +select ss, count(cint2) from aggfns where cfloat8 < 1000 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + select max(cint2) from aggfns where cfloat8 < 1000; max ------- @@ -3295,6 +5546,21 @@ select s, max(cint2) from aggfns where cfloat8 < 1000 group by s order by max(ci 9 | 16383 (10 rows) +select ss, max(cint2) from aggfns where cfloat8 < 1000 group by ss order by max(cint2), ss limit 10; + ss | max +----+------- + | 16362 + 3 | 16380 + 5 | 16381 + 7 | 16381 + 8 | 16382 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + select min(cint2) from aggfns where cfloat8 < 1000; min -------- @@ -3316,6 +5582,21 @@ select s, min(cint2) from aggfns where cfloat8 < 1000 group by s order by min(ci 9 | -16375 (10 rows) +select ss, min(cint2) from aggfns where cfloat8 < 1000 group by ss order by min(cint2), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 7 | -16382 + 8 | -16382 + 11 | -16382 + 3 | -16381 + 9 | -16375 + | -16100 +(10 rows) + select stddev(cint2) from aggfns where cfloat8 < 1000; stddev ------------------- @@ -3337,6 +5618,21 @@ select s, stddev(cint2) from aggfns where cfloat8 < 1000 group by s order by std 1 | 9528.039076724276 (10 rows) +select ss, stddev(cint2) from aggfns where cfloat8 < 1000 group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+------------------- + | 8413.549166956554 + 9 | 9450.322790943425 + 7 | 9462.161209850735 + 6 | 9467.569674984571 + 5 | 9467.776835158782 + 3 | 9474.482349111595 + 8 | 9477.586839536066 + 4 | 9483.611454519949 + 0 | 9484.907423282680 + 11 | 9494.206429493352 +(10 rows) + select sum(cint2) from aggfns where cfloat8 < 1000; sum ---------- @@ -3358,6 +5654,21 @@ select s, sum(cint2) from aggfns where cfloat8 < 1000 group by s order by sum(ci 5 | 2198520 (10 rows) +select ss, sum(cint2) from aggfns where cfloat8 < 1000 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+---------- + 8 | -2587459 + 3 | -1887499 + 11 | -1349560 + 6 | -1220352 + 7 | -1116329 + 4 | -550258 + 9 | -435575 + | -25995 + 0 | 351569 + 5 | 2198520 +(10 rows) + select avg(cint4) from aggfns where cfloat8 < 1000; avg --------------------- @@ -3379,6 +5690,21 @@ select s, avg(cint4) from aggfns where cfloat8 < 1000 group by s order by avg(ci 5 | 103.1069000000000000 (10 rows) +select ss, avg(cint4) from aggfns where cfloat8 < 1000 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----------------------- + 9 | -102.4283000000000000 + 6 | -53.1566500000000000 + 7 | -42.6121500000000000 + 8 | -29.2615500000000000 + 11 | -16.4247732327144606 + 4 | 9.6930584054852110 + 0 | 27.7536500000000000 + 3 | 68.3874180471447875 + 5 | 103.1069000000000000 + | 2197.6842105263157895 +(10 rows) + select max(cint4) from aggfns where cfloat8 < 1000; max ------- @@ -3400,6 +5726,21 @@ select s, max(cint4) from aggfns where cfloat8 < 1000 group by s order by max(ci 9 | 16383 (10 rows) +select ss, max(cint4) from aggfns where cfloat8 < 1000 group by ss order by max(cint4), ss limit 10; + ss | max +----+------- + | 14812 + 3 | 16379 + 5 | 16379 + 7 | 16379 + 0 | 16383 + 4 | 16383 + 6 | 16383 + 8 | 16383 + 9 | 16383 + 11 | 16383 +(10 rows) + select min(cint4) from aggfns where cfloat8 < 1000; min -------- @@ -3421,6 +5762,21 @@ select s, min(cint4) from aggfns where cfloat8 < 1000 group by s order by min(ci 5 | -16380 (10 rows) +select ss, min(cint4) from aggfns where cfloat8 < 1000 group by ss order by min(cint4), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 7 | -16383 + 11 | -16383 + 3 | -16382 + 4 | -16382 + 6 | -16382 + 8 | -16382 + 9 | -16382 + 5 | -16380 + | -15907 +(10 rows) + select stddev(cint4) from aggfns where cfloat8 < 1000; stddev ------------------- @@ -3442,6 +5798,21 @@ select s, stddev(cint4) from aggfns where cfloat8 < 1000 group by s order by std 5 | 9504.684751625578 (10 rows) +select ss, stddev(cint4) from aggfns where cfloat8 < 1000 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+------------------- + | 9361.317298404296 + 0 | 9406.815855797801 + 6 | 9410.397911988306 + 9 | 9426.452583637956 + 4 | 9442.480718256247 + 8 | 9450.281544631633 + 11 | 9450.690059613938 + 3 | 9474.873657491443 + 7 | 9485.765898279180 + 5 | 9504.684751625578 +(10 rows) + select sum(cint4) from aggfns where cfloat8 < 1000; sum --------- @@ -3463,6 +5834,21 @@ select s, sum(cint4) from aggfns where cfloat8 < 1000 group by s order by sum(ci 5 | 2062138 (10 rows) +select ss, sum(cint4) from aggfns where cfloat8 < 1000 group by ss order by sum(cint4), ss limit 10; + ss | sum +----+---------- + 9 | -2048566 + 6 | -1063133 + 7 | -852243 + 11 | -657303 + 8 | -585231 + | 41756 + 4 | 193677 + 0 | 555073 + 3 | 1366449 + 5 | 2062138 +(10 rows) + select avg(cint8) from aggfns where cfloat8 < 1000; avg ---------------------- @@ -3484,6 +5870,21 @@ select s, avg(cint8) from aggfns where cfloat8 < 1000 group by s order by avg(ci 9 | 61.7467500000000000 (10 rows) +select ss, avg(cint8) from aggfns where cfloat8 < 1000 group by ss order by avg(cint8), ss limit 10; + ss | avg +----+----------------------- + 8 | -118.4870000000000000 + 5 | -81.6955500000000000 + 4 | -17.0811771182623492 + 11 | -15.1685449411529523 + 7 | -2.3563500000000000 + 6 | 11.9056500000000000 + 0 | 15.3018000000000000 + 3 | 37.6662329212752115 + 9 | 61.7467500000000000 + | 2467.2631578947368421 +(10 rows) + select max(cint8) from aggfns where cfloat8 < 1000; max ------- @@ -3505,6 +5906,21 @@ select s, max(cint8) from aggfns where cfloat8 < 1000 group by s order by max(ci 5 | 16383 (10 rows) +select ss, max(cint8) from aggfns where cfloat8 < 1000 group by ss order by max(cint8), ss limit 10; + ss | max +----+------- + | 13750 + 6 | 16380 + 7 | 16380 + 8 | 16380 + 3 | 16382 + 9 | 16382 + 0 | 16383 + 4 | 16383 + 5 | 16383 + 11 | 16383 +(10 rows) + select min(cint8) from aggfns where cfloat8 < 1000; min -------- @@ -3526,6 +5942,21 @@ select s, min(cint8) from aggfns where cfloat8 < 1000 group by s order by min(ci 3 | -16378 (10 rows) +select ss, min(cint8) from aggfns where cfloat8 < 1000 group by ss order by min(cint8), ss limit 10; + ss | min +----+-------- + 0 | -16383 + 6 | -16383 + 7 | -16383 + 8 | -16383 + 11 | -16383 + 5 | -16382 + 4 | -16381 + 9 | -16380 + 3 | -16378 + | -14174 +(10 rows) + select sum(cint8) from aggfns where cfloat8 < 1000; sum ---------- @@ -3547,6 +5978,21 @@ select s, sum(cint8) from aggfns where cfloat8 < 1000 group by s order by sum(ci 9 | 1234935 (10 rows) +select ss, sum(cint8) from aggfns where cfloat8 < 1000 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+---------- + 8 | -2369740 + 5 | -1633911 + 11 | -607030 + 4 | -341299 + 7 | -47127 + | 46878 + 6 | 238113 + 0 | 306036 + 3 | 752609 + 9 | 1234935 +(10 rows) + select max(cts) from aggfns where cfloat8 < 1000; max -------------------------- @@ -3568,6 +6014,21 @@ select s, max(cts) from aggfns where cfloat8 < 1000 group by s order by max(cts) 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, max(cts) from aggfns where cfloat8 < 1000 group by ss order by max(cts), ss limit 10; + ss | max +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 11 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select min(cts) from aggfns where cfloat8 < 1000; min -------------------------- @@ -3589,6 +6050,21 @@ select s, min(cts) from aggfns where cfloat8 < 1000 group by s order by min(cts) 9 | Sat Jan 02 02:01:01 2021 (10 rows) +select ss, min(cts) from aggfns where cfloat8 < 1000 group by ss order by min(cts), ss limit 10; + ss | min +----+-------------------------- + 0 | Fri Jan 01 01:01:01 2021 + 11 | Fri Jan 01 03:47:41 2021 + 3 | Fri Jan 01 09:21:01 2021 + | Fri Jan 01 09:21:01 2021 + 4 | Fri Jan 01 12:07:41 2021 + 5 | Fri Jan 01 14:54:21 2021 + 6 | Fri Jan 01 17:41:01 2021 + 7 | Fri Jan 01 20:27:41 2021 + 8 | Fri Jan 01 23:14:21 2021 + 9 | Sat Jan 02 02:01:01 2021 +(10 rows) + select max(ctstz) from aggfns where cfloat8 < 1000; max ------------------------------ @@ -3610,6 +6086,21 @@ select s, max(ctstz) from aggfns where cfloat8 < 1000 group by s order by max(ct 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, max(ctstz) from aggfns where cfloat8 < 1000 group by ss order by max(ctstz), ss limit 10; + ss | max +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 11 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select min(ctstz) from aggfns where cfloat8 < 1000; min ------------------------------ @@ -3631,6 +6122,21 @@ select s, min(ctstz) from aggfns where cfloat8 < 1000 group by s order by min(ct 9 | Sat Jan 02 02:01:01 2021 PST (10 rows) +select ss, min(ctstz) from aggfns where cfloat8 < 1000 group by ss order by min(ctstz), ss limit 10; + ss | min +----+------------------------------ + 0 | Fri Jan 01 01:01:01 2021 PST + 11 | Fri Jan 01 03:47:41 2021 PST + 3 | Fri Jan 01 09:21:01 2021 PST + | Fri Jan 01 09:21:01 2021 PST + 4 | Fri Jan 01 12:07:41 2021 PST + 5 | Fri Jan 01 14:54:21 2021 PST + 6 | Fri Jan 01 17:41:01 2021 PST + 7 | Fri Jan 01 20:27:41 2021 PST + 8 | Fri Jan 01 23:14:21 2021 PST + 9 | Sat Jan 02 02:01:01 2021 PST +(10 rows) + select avg(s) from aggfns where cfloat8 < 1000; avg -------------------- @@ -3652,6 +6158,21 @@ select s, avg(s) from aggfns where cfloat8 < 1000 group by s order by avg(s), s 9 | 9.0000000000000000 (10 rows) +select ss, avg(s) from aggfns where cfloat8 < 1000 group by ss order by avg(s), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 11 | 1.5011869362053025 + 3 | 3.0000000000000000 + | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 +(10 rows) + select count(s) from aggfns where cfloat8 < 1000; count -------- @@ -3673,6 +6194,21 @@ select s, count(s) from aggfns where cfloat8 < 1000 group by s order by count(s) 9 | 20000 (10 rows) +select ss, count(s) from aggfns where cfloat8 < 1000 group by ss order by count(s), ss limit 10; + ss | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + select max(s) from aggfns where cfloat8 < 1000; max ----- @@ -3694,6 +6230,21 @@ select s, max(s) from aggfns where cfloat8 < 1000 group by s order by max(s), s 9 | 9 (10 rows) +select ss, max(s) from aggfns where cfloat8 < 1000 group by ss order by max(s), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + | 3 + 4 | 4 + 11 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select min(s) from aggfns where cfloat8 < 1000; min ----- @@ -3715,6 +6266,21 @@ select s, min(s) from aggfns where cfloat8 < 1000 group by s order by min(s), s 9 | 9 (10 rows) +select ss, min(s) from aggfns where cfloat8 < 1000 group by ss order by min(s), ss limit 10; + ss | min +----+----- + 0 | 0 + 11 | 1 + 3 | 3 + | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 +(10 rows) + select stddev(s) from aggfns where cfloat8 < 1000; stddev -------------------- @@ -3736,6 +6302,21 @@ select s, stddev(s) from aggfns where cfloat8 < 1000 group by s order by stddev( 9 | 0 (10 rows) +select ss, stddev(s) from aggfns where cfloat8 < 1000 group by ss order by stddev(s), ss limit 10; + ss | stddev +----+------------------------ + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + | 0 + 11 | 0.50284545977155885187 +(10 rows) + select sum(s) from aggfns where cfloat8 < 1000; sum -------- @@ -3757,6 +6338,21 @@ select s, sum(s) from aggfns where cfloat8 < 1000 group by s order by sum(s), s 9 | 180000 (10 rows) +select ss, sum(s) from aggfns where cfloat8 < 1000 group by ss order by sum(s), ss limit 10; + ss | sum +----+-------- + 0 | 0 + | 57 + 3 | 59943 + 11 | 60076 + 4 | 79924 + 5 | 100000 + 6 | 120000 + 7 | 140000 + 8 | 160000 + 9 | 180000 +(10 rows) + select avg(ss) from aggfns where cfloat8 < 1000; avg -------------------- @@ -3778,6 +6374,21 @@ select s, avg(ss) from aggfns where cfloat8 < 1000 group by s order by avg(ss), 2 | 11.0000000000000000 (10 rows) +select ss, avg(ss) from aggfns where cfloat8 < 1000 group by ss order by avg(ss), ss limit 10; + ss | avg +----+---------------------------- + 0 | 0.000000000000000000000000 + 3 | 3.0000000000000000 + 4 | 4.0000000000000000 + 5 | 5.0000000000000000 + 6 | 6.0000000000000000 + 7 | 7.0000000000000000 + 8 | 8.0000000000000000 + 9 | 9.0000000000000000 + 11 | 11.0000000000000000 + | +(10 rows) + select max(ss) from aggfns where cfloat8 < 1000; max ----- @@ -3799,6 +6410,21 @@ select s, max(ss) from aggfns where cfloat8 < 1000 group by s order by max(ss), 4 | 11 (10 rows) +select ss, max(ss) from aggfns where cfloat8 < 1000 group by ss order by max(ss), ss limit 10; + ss | max +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select min(ss) from aggfns where cfloat8 < 1000; min ----- @@ -3820,6 +6446,21 @@ select s, min(ss) from aggfns where cfloat8 < 1000 group by s order by min(ss), 2 | 11 (10 rows) +select ss, min(ss) from aggfns where cfloat8 < 1000 group by ss order by min(ss), ss limit 10; + ss | min +----+----- + 0 | 0 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + | +(10 rows) + select stddev(ss) from aggfns where cfloat8 < 1000; stddev -------------------- @@ -3841,6 +6482,21 @@ select s, stddev(ss) from aggfns where cfloat8 < 1000 group by s order by stddev 4 | 0.21565737387148452722 (10 rows) +select ss, stddev(ss) from aggfns where cfloat8 < 1000 group by ss order by stddev(ss), ss limit 10; + ss | stddev +----+-------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 + | +(10 rows) + select sum(ss) from aggfns where cfloat8 < 1000; sum --------- @@ -3862,6 +6518,21 @@ select s, sum(ss) from aggfns where cfloat8 < 1000 group by s order by sum(ss), 2 | 220000 (10 rows) +select ss, sum(ss) from aggfns where cfloat8 < 1000 group by ss order by sum(ss), ss limit 10; + ss | sum +----+-------- + 0 | 0 + 3 | 59943 + 4 | 79924 + 5 | 100000 + 6 | 120000 + 7 | 140000 + 8 | 160000 + 9 | 180000 + 11 | 440209 + | +(10 rows) + select max(t) from aggfns where cfloat8 < 1000; max -------- @@ -3883,6 +6554,21 @@ select s, max(t) from aggfns where cfloat8 < 1000 group by s order by max(t), s 9 | 110000 (10 rows) +select ss, max(t) from aggfns where cfloat8 < 1000 group by ss order by max(t), ss limit 10; + ss | max +----+-------- + 0 | 20000 + | 49491 + 3 | 50000 + 11 | 59192 + 4 | 60000 + 5 | 70000 + 6 | 80000 + 7 | 90000 + 8 | 100000 + 9 | 110000 +(10 rows) + select min(t) from aggfns where cfloat8 < 1000; min ----- @@ -3904,6 +6590,21 @@ select s, min(t) from aggfns where cfloat8 < 1000 group by s order by min(t), s 9 | 90001 (10 rows) +select ss, min(t) from aggfns where cfloat8 < 1000 group by ss order by min(t), ss limit 10; + ss | min +----+------- + 0 | 1 + 11 | 10001 + 3 | 30001 + | 30537 + 4 | 40001 + 5 | 50001 + 6 | 60001 + 7 | 70001 + 8 | 80001 + 9 | 90001 +(10 rows) + select count(*) from aggfns where cfloat8 > 1000; count ------- @@ -3915,6 +6616,11 @@ select s, count(*) from aggfns where cfloat8 > 1000 group by s order by count(*) ---+------- (0 rows) +select ss, count(*) from aggfns where cfloat8 > 1000 group by ss order by count(*), ss limit 10; + ss | count +----+------- +(0 rows) + select max(cdate) from aggfns where cfloat8 > 1000; max ----- @@ -3926,6 +6632,11 @@ select s, max(cdate) from aggfns where cfloat8 > 1000 group by s order by max(cd ---+----- (0 rows) +select ss, max(cdate) from aggfns where cfloat8 > 1000 group by ss order by max(cdate), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cdate) from aggfns where cfloat8 > 1000; min ----- @@ -3937,6 +6648,11 @@ select s, min(cdate) from aggfns where cfloat8 > 1000 group by s order by min(cd ---+----- (0 rows) +select ss, min(cdate) from aggfns where cfloat8 > 1000 group by ss order by min(cdate), ss limit 10; + ss | min +----+----- +(0 rows) + select avg(cfloat4) from aggfns where cfloat8 > 1000; avg ----- @@ -3948,6 +6664,11 @@ select s, avg(cfloat4) from aggfns where cfloat8 > 1000 group by s order by avg( ---+----- (0 rows) +select ss, avg(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by avg(cfloat4), ss limit 10; + ss | avg +----+----- +(0 rows) + select max(cfloat4) from aggfns where cfloat8 > 1000; max ----- @@ -3959,6 +6680,11 @@ select s, max(cfloat4) from aggfns where cfloat8 > 1000 group by s order by max( ---+----- (0 rows) +select ss, max(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by max(cfloat4), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cfloat4) from aggfns where cfloat8 > 1000; min ----- @@ -3970,6 +6696,11 @@ select s, min(cfloat4) from aggfns where cfloat8 > 1000 group by s order by min( ---+----- (0 rows) +select ss, min(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by min(cfloat4), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(cfloat4) from aggfns where cfloat8 > 1000; stddev -------- @@ -3981,6 +6712,11 @@ select s, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by s order by s ---+-------- (0 rows) +select ss, stddev(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by stddev(cfloat4), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(cfloat4) from aggfns where cfloat8 > 1000; sum ----- @@ -3992,6 +6728,11 @@ select s, sum(cfloat4) from aggfns where cfloat8 > 1000 group by s order by sum( ---+----- (0 rows) +select ss, sum(cfloat4) from aggfns where cfloat8 > 1000 group by ss order by sum(cfloat4), ss limit 10; + ss | sum +----+----- +(0 rows) + select avg(cfloat8) from aggfns where cfloat8 > 1000; avg ----- @@ -4003,6 +6744,11 @@ select s, avg(cfloat8) from aggfns where cfloat8 > 1000 group by s order by avg( ---+----- (0 rows) +select ss, avg(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by avg(cfloat8), ss limit 10; + ss | avg +----+----- +(0 rows) + select max(cfloat8) from aggfns where cfloat8 > 1000; max ----- @@ -4014,6 +6760,11 @@ select s, max(cfloat8) from aggfns where cfloat8 > 1000 group by s order by max( ---+----- (0 rows) +select ss, max(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by max(cfloat8), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cfloat8) from aggfns where cfloat8 > 1000; min ----- @@ -4025,6 +6776,11 @@ select s, min(cfloat8) from aggfns where cfloat8 > 1000 group by s order by min( ---+----- (0 rows) +select ss, min(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by min(cfloat8), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(cfloat8) from aggfns where cfloat8 > 1000; stddev -------- @@ -4036,6 +6792,11 @@ select s, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by s order by s ---+-------- (0 rows) +select ss, stddev(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by stddev(cfloat8), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(cfloat8) from aggfns where cfloat8 > 1000; sum ----- @@ -4047,6 +6808,11 @@ select s, sum(cfloat8) from aggfns where cfloat8 > 1000 group by s order by sum( ---+----- (0 rows) +select ss, sum(cfloat8) from aggfns where cfloat8 > 1000 group by ss order by sum(cfloat8), ss limit 10; + ss | sum +----+----- +(0 rows) + select avg(cint2) from aggfns where cfloat8 > 1000; avg ----- @@ -4058,6 +6824,11 @@ select s, avg(cint2) from aggfns where cfloat8 > 1000 group by s order by avg(ci ---+----- (0 rows) +select ss, avg(cint2) from aggfns where cfloat8 > 1000 group by ss order by avg(cint2), ss limit 10; + ss | avg +----+----- +(0 rows) + select count(cint2) from aggfns where cfloat8 > 1000; count ------- @@ -4069,6 +6840,11 @@ select s, count(cint2) from aggfns where cfloat8 > 1000 group by s order by coun ---+------- (0 rows) +select ss, count(cint2) from aggfns where cfloat8 > 1000 group by ss order by count(cint2), ss limit 10; + ss | count +----+------- +(0 rows) + select max(cint2) from aggfns where cfloat8 > 1000; max ----- @@ -4080,6 +6856,11 @@ select s, max(cint2) from aggfns where cfloat8 > 1000 group by s order by max(ci ---+----- (0 rows) +select ss, max(cint2) from aggfns where cfloat8 > 1000 group by ss order by max(cint2), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cint2) from aggfns where cfloat8 > 1000; min ----- @@ -4091,6 +6872,11 @@ select s, min(cint2) from aggfns where cfloat8 > 1000 group by s order by min(ci ---+----- (0 rows) +select ss, min(cint2) from aggfns where cfloat8 > 1000 group by ss order by min(cint2), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(cint2) from aggfns where cfloat8 > 1000; stddev -------- @@ -4101,6 +6887,11 @@ select s, stddev(cint2) from aggfns where cfloat8 > 1000 group by s order by std ---+-------- (0 rows) +select ss, stddev(cint2) from aggfns where cfloat8 > 1000 group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(cint2) from aggfns where cfloat8 > 1000; sum ----- @@ -4112,6 +6903,11 @@ select s, sum(cint2) from aggfns where cfloat8 > 1000 group by s order by sum(ci ---+----- (0 rows) +select ss, sum(cint2) from aggfns where cfloat8 > 1000 group by ss order by sum(cint2), ss limit 10; + ss | sum +----+----- +(0 rows) + select avg(cint4) from aggfns where cfloat8 > 1000; avg ----- @@ -4123,6 +6919,11 @@ select s, avg(cint4) from aggfns where cfloat8 > 1000 group by s order by avg(ci ---+----- (0 rows) +select ss, avg(cint4) from aggfns where cfloat8 > 1000 group by ss order by avg(cint4), ss limit 10; + ss | avg +----+----- +(0 rows) + select max(cint4) from aggfns where cfloat8 > 1000; max ----- @@ -4134,6 +6935,11 @@ select s, max(cint4) from aggfns where cfloat8 > 1000 group by s order by max(ci ---+----- (0 rows) +select ss, max(cint4) from aggfns where cfloat8 > 1000 group by ss order by max(cint4), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cint4) from aggfns where cfloat8 > 1000; min ----- @@ -4145,6 +6951,11 @@ select s, min(cint4) from aggfns where cfloat8 > 1000 group by s order by min(ci ---+----- (0 rows) +select ss, min(cint4) from aggfns where cfloat8 > 1000 group by ss order by min(cint4), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(cint4) from aggfns where cfloat8 > 1000; stddev -------- @@ -4155,6 +6966,11 @@ select s, stddev(cint4) from aggfns where cfloat8 > 1000 group by s order by std ---+-------- (0 rows) +select ss, stddev(cint4) from aggfns where cfloat8 > 1000 group by ss order by stddev(cint4), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(cint4) from aggfns where cfloat8 > 1000; sum ----- @@ -4166,6 +6982,11 @@ select s, sum(cint4) from aggfns where cfloat8 > 1000 group by s order by sum(ci ---+----- (0 rows) +select ss, sum(cint4) from aggfns where cfloat8 > 1000 group by ss order by sum(cint4), ss limit 10; + ss | sum +----+----- +(0 rows) + select avg(cint8) from aggfns where cfloat8 > 1000; avg ----- @@ -4176,6 +6997,11 @@ select s, avg(cint8) from aggfns where cfloat8 > 1000 group by s order by avg(ci ---+----- (0 rows) +select ss, avg(cint8) from aggfns where cfloat8 > 1000 group by ss order by avg(cint8), ss limit 10; + ss | avg +----+----- +(0 rows) + select max(cint8) from aggfns where cfloat8 > 1000; max ----- @@ -4187,6 +7013,11 @@ select s, max(cint8) from aggfns where cfloat8 > 1000 group by s order by max(ci ---+----- (0 rows) +select ss, max(cint8) from aggfns where cfloat8 > 1000 group by ss order by max(cint8), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cint8) from aggfns where cfloat8 > 1000; min ----- @@ -4198,6 +7029,11 @@ select s, min(cint8) from aggfns where cfloat8 > 1000 group by s order by min(ci ---+----- (0 rows) +select ss, min(cint8) from aggfns where cfloat8 > 1000 group by ss order by min(cint8), ss limit 10; + ss | min +----+----- +(0 rows) + select sum(cint8) from aggfns where cfloat8 > 1000; sum ----- @@ -4208,6 +7044,11 @@ select s, sum(cint8) from aggfns where cfloat8 > 1000 group by s order by sum(ci ---+----- (0 rows) +select ss, sum(cint8) from aggfns where cfloat8 > 1000 group by ss order by sum(cint8), ss limit 10; + ss | sum +----+----- +(0 rows) + select max(cts) from aggfns where cfloat8 > 1000; max ----- @@ -4219,6 +7060,11 @@ select s, max(cts) from aggfns where cfloat8 > 1000 group by s order by max(cts) ---+----- (0 rows) +select ss, max(cts) from aggfns where cfloat8 > 1000 group by ss order by max(cts), ss limit 10; + ss | max +----+----- +(0 rows) + select min(cts) from aggfns where cfloat8 > 1000; min ----- @@ -4230,6 +7076,11 @@ select s, min(cts) from aggfns where cfloat8 > 1000 group by s order by min(cts) ---+----- (0 rows) +select ss, min(cts) from aggfns where cfloat8 > 1000 group by ss order by min(cts), ss limit 10; + ss | min +----+----- +(0 rows) + select max(ctstz) from aggfns where cfloat8 > 1000; max ----- @@ -4241,6 +7092,11 @@ select s, max(ctstz) from aggfns where cfloat8 > 1000 group by s order by max(ct ---+----- (0 rows) +select ss, max(ctstz) from aggfns where cfloat8 > 1000 group by ss order by max(ctstz), ss limit 10; + ss | max +----+----- +(0 rows) + select min(ctstz) from aggfns where cfloat8 > 1000; min ----- @@ -4252,6 +7108,11 @@ select s, min(ctstz) from aggfns where cfloat8 > 1000 group by s order by min(ct ---+----- (0 rows) +select ss, min(ctstz) from aggfns where cfloat8 > 1000 group by ss order by min(ctstz), ss limit 10; + ss | min +----+----- +(0 rows) + select avg(s) from aggfns where cfloat8 > 1000; avg ----- @@ -4263,6 +7124,11 @@ select s, avg(s) from aggfns where cfloat8 > 1000 group by s order by avg(s), s ---+----- (0 rows) +select ss, avg(s) from aggfns where cfloat8 > 1000 group by ss order by avg(s), ss limit 10; + ss | avg +----+----- +(0 rows) + select count(s) from aggfns where cfloat8 > 1000; count ------- @@ -4274,6 +7140,11 @@ select s, count(s) from aggfns where cfloat8 > 1000 group by s order by count(s) ---+------- (0 rows) +select ss, count(s) from aggfns where cfloat8 > 1000 group by ss order by count(s), ss limit 10; + ss | count +----+------- +(0 rows) + select max(s) from aggfns where cfloat8 > 1000; max ----- @@ -4285,6 +7156,11 @@ select s, max(s) from aggfns where cfloat8 > 1000 group by s order by max(s), s ---+----- (0 rows) +select ss, max(s) from aggfns where cfloat8 > 1000 group by ss order by max(s), ss limit 10; + ss | max +----+----- +(0 rows) + select min(s) from aggfns where cfloat8 > 1000; min ----- @@ -4296,6 +7172,11 @@ select s, min(s) from aggfns where cfloat8 > 1000 group by s order by min(s), s ---+----- (0 rows) +select ss, min(s) from aggfns where cfloat8 > 1000 group by ss order by min(s), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(s) from aggfns where cfloat8 > 1000; stddev -------- @@ -4306,6 +7187,11 @@ select s, stddev(s) from aggfns where cfloat8 > 1000 group by s order by stddev( ---+-------- (0 rows) +select ss, stddev(s) from aggfns where cfloat8 > 1000 group by ss order by stddev(s), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(s) from aggfns where cfloat8 > 1000; sum ----- @@ -4317,6 +7203,11 @@ select s, sum(s) from aggfns where cfloat8 > 1000 group by s order by sum(s), s ---+----- (0 rows) +select ss, sum(s) from aggfns where cfloat8 > 1000 group by ss order by sum(s), ss limit 10; + ss | sum +----+----- +(0 rows) + select avg(ss) from aggfns where cfloat8 > 1000; avg ----- @@ -4328,6 +7219,11 @@ select s, avg(ss) from aggfns where cfloat8 > 1000 group by s order by avg(ss), ---+----- (0 rows) +select ss, avg(ss) from aggfns where cfloat8 > 1000 group by ss order by avg(ss), ss limit 10; + ss | avg +----+----- +(0 rows) + select max(ss) from aggfns where cfloat8 > 1000; max ----- @@ -4339,6 +7235,11 @@ select s, max(ss) from aggfns where cfloat8 > 1000 group by s order by max(ss), ---+----- (0 rows) +select ss, max(ss) from aggfns where cfloat8 > 1000 group by ss order by max(ss), ss limit 10; + ss | max +----+----- +(0 rows) + select min(ss) from aggfns where cfloat8 > 1000; min ----- @@ -4350,6 +7251,11 @@ select s, min(ss) from aggfns where cfloat8 > 1000 group by s order by min(ss), ---+----- (0 rows) +select ss, min(ss) from aggfns where cfloat8 > 1000 group by ss order by min(ss), ss limit 10; + ss | min +----+----- +(0 rows) + select stddev(ss) from aggfns where cfloat8 > 1000; stddev -------- @@ -4360,6 +7266,11 @@ select s, stddev(ss) from aggfns where cfloat8 > 1000 group by s order by stddev ---+-------- (0 rows) +select ss, stddev(ss) from aggfns where cfloat8 > 1000 group by ss order by stddev(ss), ss limit 10; + ss | stddev +----+-------- +(0 rows) + select sum(ss) from aggfns where cfloat8 > 1000; sum ----- @@ -4371,6 +7282,11 @@ select s, sum(ss) from aggfns where cfloat8 > 1000 group by s order by sum(ss), ---+----- (0 rows) +select ss, sum(ss) from aggfns where cfloat8 > 1000 group by ss order by sum(ss), ss limit 10; + ss | sum +----+----- +(0 rows) + select max(t) from aggfns where cfloat8 > 1000; max ----- @@ -4382,6 +7298,11 @@ select s, max(t) from aggfns where cfloat8 > 1000 group by s order by max(t), s ---+----- (0 rows) +select ss, max(t) from aggfns where cfloat8 > 1000 group by ss order by max(t), ss limit 10; + ss | max +----+----- +(0 rows) + select min(t) from aggfns where cfloat8 > 1000; min ----- @@ -4393,6 +7314,11 @@ select s, min(t) from aggfns where cfloat8 > 1000 group by s order by min(t), s ---+----- (0 rows) +select ss, min(t) from aggfns where cfloat8 > 1000 group by ss order by min(t), ss limit 10; + ss | min +----+----- +(0 rows) + select avg(cint2) from aggfns where cint2 is null; avg ----- @@ -4414,6 +7340,20 @@ select s, avg(cint2) from aggfns where cint2 is null group by s order by avg(cin 9 | (10 rows) +select ss, avg(cint2) from aggfns where cint2 is null group by ss order by avg(cint2), ss limit 10; + ss | avg +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + select count(cint2) from aggfns where cint2 is null; count ------- @@ -4435,6 +7375,20 @@ select s, count(cint2) from aggfns where cint2 is null group by s order by count 9 | 0 (10 rows) +select ss, count(cint2) from aggfns where cint2 is null group by ss order by count(cint2), ss limit 10; + ss | count +----+------- + 0 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 + 11 | 0 +(9 rows) + select max(cint2) from aggfns where cint2 is null; max ----- @@ -4456,6 +7410,20 @@ select s, max(cint2) from aggfns where cint2 is null group by s order by max(cin 9 | (10 rows) +select ss, max(cint2) from aggfns where cint2 is null group by ss order by max(cint2), ss limit 10; + ss | max +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + select min(cint2) from aggfns where cint2 is null; min ----- @@ -4477,6 +7445,20 @@ select s, min(cint2) from aggfns where cint2 is null group by s order by min(cin 9 | (10 rows) +select ss, min(cint2) from aggfns where cint2 is null group by ss order by min(cint2), ss limit 10; + ss | min +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + select stddev(cint2) from aggfns where cint2 is null; stddev -------- @@ -4498,6 +7480,20 @@ select s, stddev(cint2) from aggfns where cint2 is null group by s order by stdd 9 | (10 rows) +select ss, stddev(cint2) from aggfns where cint2 is null group by ss order by stddev(cint2), ss limit 10; + ss | stddev +----+-------- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + select sum(cint2) from aggfns where cint2 is null; sum ----- @@ -4519,6 +7515,38 @@ select s, sum(cint2) from aggfns where cint2 is null group by s order by sum(cin 9 | (10 rows) +select ss, sum(cint2) from aggfns where cint2 is null group by ss order by sum(cint2), ss limit 10; + ss | sum +----+----- + 0 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 11 | +(9 rows) + +-- Test multiple aggregate functions as well. +select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 +order by count(*) desc, cint2 limit 10 +; + count | count | min | cint2 +-------+-------+----------+-------- + 190 | 0 | -49.6644 | + 19 | 19 | -49.5299 | -8743 + 17 | 17 | -48.5497 | -12921 + 17 | 17 | -48.5697 | -701 + 17 | 17 | -47.2641 | 525 + 16 | 16 | -42.41 | -10234 + 16 | 16 | -47.2083 | -4609 + 16 | 16 | -49.9555 | -4261 + 16 | 16 | -35.1643 | -296 + 16 | 16 | -45.4426 | 1373 +(10 rows) + -- Test edge cases for various batch sizes and the filter matching around batch -- end. select count(*) from edges; @@ -4588,3 +7616,45 @@ select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; 12 | 1 | 65 (8 rows) +select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; + ss | count | min +----+-------+----- + 3 | 1 | 63 + 4 | 1 | 63 + 5 | 1 | 63 + 6 | 1 | 63 + 7 | 1 | 63 + 8 | 1 | 63 + 9 | 1 | 63 + 10 | 1 | 63 + 11 | 1 | 63 + 12 | 1 | 63 +(10 rows) + +select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; + ss | count | min +----+-------+----- + 4 | 1 | 64 + 5 | 1 | 64 + 6 | 1 | 64 + 7 | 1 | 64 + 8 | 1 | 64 + 9 | 1 | 64 + 10 | 1 | 64 + 11 | 1 | 64 + 12 | 1 | 64 +(9 rows) + +select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + ss | count | min +----+-------+----- + 5 | 1 | 65 + 6 | 1 | 65 + 7 | 1 | 65 + 8 | 1 | 65 + 9 | 1 | 65 + 10 | 1 | 65 + 11 | 1 | 65 + 12 | 1 | 65 +(8 rows) + diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 0e6a0d0860f..2876a303fba 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -98,7 +98,7 @@ limit 1 set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. --- set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; select format('%sselect %s%s(%s) from aggfns%s%s%s;', @@ -142,7 +142,8 @@ from 'cint2 is null']) with ordinality as condition(condition, n), unnest(array[ null, - 's']) with ordinality as grouping(grouping, n) + 's', + 'ss']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -156,6 +157,11 @@ order by explain, condition.n, variable, function, grouping.n \gexec +-- Test multiple aggregate functions as well. +select count(*), count(cint2), min(cfloat4), cint2 from aggfns group by cint2 +order by count(*) desc, cint2 limit 10 +; + -- Test edge cases for various batch sizes and the filter matching around batch -- end. select count(*) from edges; @@ -164,3 +170,7 @@ select s, count(*) from edges group by 1 order by 1; select s, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; select s, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + +select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; +select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; +select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; From b6cee0294be55ba28fa78ecf7d3d52a17c5f4941 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:23:45 +0100 Subject: [PATCH 176/242] remove extras --- .../nodes/vector_agg/grouping_policy_hash.c | 4 - .../vector_agg/hashing/hash_strategy_impl.c | 97 +------------------ .../vector_agg/hashing/hashing_strategy.h | 13 +-- 3 files changed, 6 insertions(+), 108 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 12e0f09700e..a2b388b4b4c 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -34,8 +34,6 @@ extern HashingStrategy single_fixed_2_strategy; extern HashingStrategy single_fixed_4_strategy; extern HashingStrategy single_fixed_8_strategy; -extern HashingStrategy single_text_strategy; -extern HashingStrategy serialized_strategy; static const GroupingPolicy grouping_policy_hash_functions; @@ -86,8 +84,6 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr break; } - policy->hashing.key_body_mctx = policy->agg_extra_mctx; - policy->hashing.init(&policy->hashing, policy); return &policy->funcs; diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 5656e8d69b4..fa5c1f7c7d1 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -157,92 +157,6 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e } } -/* - * For some configurations of hashing, we want to generate dedicated - * implementations that will be more efficient. For example, for 2-byte keys - * when all the batch and key rows are valid. - */ -#define APPLY_FOR_BATCH_FILTER(X, NAME, COND) \ - X(NAME##_nofilter, (COND) && (params.batch_filter == NULL)) \ - X(NAME##_filter, (COND) && (params.batch_filter != NULL)) - -#define APPLY_FOR_NULLABILITY(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_notnull, (COND) && params.single_key.buffers[0] == NULL) \ - APPLY_FOR_BATCH_FILTER(X, NAME##_nullable, (COND) && params.single_key.buffers[0] != NULL) - -#define APPLY_FOR_SCALARS(X, NAME, COND) \ - APPLY_FOR_BATCH_FILTER(X, \ - NAME##_noscalar_notnull, \ - (COND) && !params.have_scalar_or_nullable_columns) \ - APPLY_FOR_BATCH_FILTER(X, \ - NAME##_scalar_or_nullable, \ - (COND) && params.have_scalar_or_nullable_columns) - -#define APPLY_FOR_TYPE(X, NAME, COND) \ - APPLY_FOR_NULLABILITY(X, \ - NAME##_byval, \ - (COND) && \ - params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) \ - APPLY_FOR_NULLABILITY(X, \ - NAME##_text, \ - (COND) && params.single_key.decompression_type == DT_ArrowText) \ - APPLY_FOR_NULLABILITY(X, \ - NAME##_dict, \ - (COND) && params.single_key.decompression_type == DT_ArrowTextDict) \ - APPLY_FOR_SCALARS(X, NAME##_multi, (COND) && params.single_key.decompression_type == DT_Invalid) - -#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_TYPE(X, index, true) - -#define DEFINE(NAME, CONDITION) \ - static pg_noinline void FUNCTION_NAME( \ - NAME)(BatchHashingParams params, int start_row, int end_row) \ - { \ - if (!(CONDITION)) \ - { \ - pg_unreachable(); \ - } \ - \ - FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); \ - } - -APPLY_FOR_SPECIALIZATIONS(DEFINE) - -#undef DEFINE - -static void -FUNCTION_NAME(dispatch_for_params)(BatchHashingParams params, int start_row, int end_row) -{ - if (params.num_grouping_columns == 0) - { - pg_unreachable(); - } - - if ((params.num_grouping_columns == 1) != (params.single_key.decompression_type != DT_Invalid)) - { - pg_unreachable(); - } - -#define DISPATCH(NAME, CONDITION) \ - if (CONDITION) \ - { \ - FUNCTION_NAME(NAME)(params, start_row, end_row); \ - } \ - else - - APPLY_FOR_SPECIALIZATIONS(DISPATCH) - { - /* Use a generic implementation if no specializations matched. */ - FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); - } -#undef DISPATCH -} - -#undef APPLY_FOR_SPECIALIZATIONS - -/* - * In some special cases we call a more efficient specialization of the grouping - * function. - */ static void FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *batch_state, int start_row, int end_row) @@ -251,16 +165,7 @@ FUNCTION_NAME(fill_offsets)(GroupingPolicyHash *policy, DecompressBatchState *ba BatchHashingParams params = build_batch_hashing_params(policy, batch_state); -#ifdef USE_DICT_HASHING - if (policy->use_key_index_for_dict) - { - Assert(params.single_key.decompression_type == DT_ArrowTextDict); - single_text_offsets_translate(params, start_row, end_row); - return; - } -#endif - - FUNCTION_NAME(dispatch_for_params)(params, start_row, end_row); + FUNCTION_NAME(fill_offsets_impl)(params, start_row, end_row); } HashingStrategy FUNCTION_NAME(strategy) = { diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index e2bfda3b180..73c6130ffca 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -15,6 +15,10 @@ typedef struct DecompressBatchState DecompressBatchState; typedef struct TupleTableSlot TupleTableSlot; +/* + * The hashing strategy manages the details of how the grouping keys are stored + * in a hash table. + */ typedef struct HashingStrategy { char *explain_name; @@ -38,12 +42,10 @@ typedef struct HashingStrategy * This is stored separately from hash table keys, because they might not * have the full column values, and also storing them contiguously here * leads to better memory access patterns when emitting the results. - * The details of the key storage are managed by the hashing strategy. The - * by-reference keys can use a separate memory context for dense storage. + * The details of the key storage are managed by the hashing strategy. */ Datum *restrict output_keys; uint64 num_allocated_output_keys; - MemoryContext key_body_mctx; /* * In single-column grouping, we store the null key outside of the hash @@ -52,11 +54,6 @@ typedef struct HashingStrategy * to reduce the hash table size. */ uint32 null_key_index; - - /* - * UMASH fingerprinting parameters. - */ - struct umash_params *umash_params; } HashingStrategy; void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state); From ecb1aec6721f87b92606604d4cedc07df7f52e9e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:25:53 +0100 Subject: [PATCH 177/242] ref --- tsl/test/expected/vectorized_aggregation.out | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 0b0c266a332..a5623050760 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -405,18 +405,21 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with single 8-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -456,7 +459,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; Group Key: _hyper_1_10_chunk.float_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.float_value, _hyper_1_10_chunk.segment_by_value -(60 rows) +(63 rows) :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; @@ -471,18 +474,21 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; -> Parallel Append -> Custom Scan (VectorAgg) Output: _hyper_1_1_chunk.int_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_2_chunk.int_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value -> Custom Scan (VectorAgg) Output: _hyper_1_3_chunk.int_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with single 4-byte key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk @@ -522,7 +528,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Group Key: _hyper_1_10_chunk.int_value -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value -(60 rows) +(63 rows) -- Vectorization possible with grouping by a segmentby column. :EXPLAIN From f64676fd328e9d99ca2d79ca2a0ee6d7bc22ff0e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:27:11 +0100 Subject: [PATCH 178/242] fixes --- tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index fa5c1f7c7d1..319ec06c6fb 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -80,7 +80,7 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e struct FUNCTION_NAME(hash) *restrict table = hashing->table; - HASH_TABLE_KEY_TYPE prev_hash_table_key; + HASH_TABLE_KEY_TYPE prev_hash_table_key = { 0 }; uint32 previous_key_index = 0; for (int row = start_row; row < end_row; row++) { From fab11fbb4fbe68480c191dd61f07e2675cba06b2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:30:30 +0100 Subject: [PATCH 179/242] benchmark single fixed-column hash grouping (2024-12-03 no. 11) From dff6dff7caf1afa691c740db8e1bab4864fffa68 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:34:34 +0100 Subject: [PATCH 180/242] cleanup --- .../nodes/vector_agg/grouping_policy_hash.c | 7 ------- .../nodes/vector_agg/grouping_policy_hash.h | 20 ------------------- 2 files changed, 27 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index a2b388b4b4c..85c81b813ff 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -100,13 +100,6 @@ gp_hash_reset(GroupingPolicy *obj) policy->hashing.reset(&policy->hashing); - /* - * Have to reset this because it's in the key body context which is also - * reset here. - */ - policy->tmp_key_storage = NULL; - policy->num_tmp_key_storage_bytes = 0; - policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index d7cda9d77c4..5e2d5146338 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -130,26 +130,6 @@ typedef struct GroupingPolicyHash uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_consecutive_keys; - - /* - * FIXME all the stuff below should be moved out. - */ - - /* - * Temporary key storages. Some hashing strategies need to put the key in a - * separate memory area, we don't want to alloc/free it on each row. - */ - uint8 *tmp_key_storage; - uint64 num_tmp_key_storage_bytes; - - /* - * For single text key that uses dictionary encoding, in some cases we first - * calculate the key indexes for the dictionary entries, and then translate - * it to the actual rows. - */ - uint32 *restrict key_index_for_dict; - uint64 num_key_index_for_dict; - bool use_key_index_for_dict; } GroupingPolicyHash; //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) From 831cadd80717c531ca8da0aa2d3333e8e029eae2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:26:21 +0100 Subject: [PATCH 181/242] planning fixes for pg 17 --- tsl/src/nodes/vector_agg/plan.c | 103 ++++++++++++------- tsl/test/expected/vectorized_aggregation.out | 8 ++ tsl/test/sql/vectorized_aggregation.sql | 4 + 3 files changed, 80 insertions(+), 35 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 669a52ca203..5b5cc93bb73 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -355,10 +355,68 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom) static bool can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) { + /* + * The Agg->numCols value can be less than the number of the non-aggregated + * vars in the aggregated targetlist, if some of them are equated to a + * constant. This behavior started with PG 16. This case is not very + * important, so we treat all non-aggregated columns as grouping columns to + * keep the vectorized aggregation node simple. + */ + int num_grouping_columns = 0; + bool all_segmentby = true; + Var *single_grouping_var = NULL; + + ListCell *lc; + foreach (lc, resolved_targetlist) + { + TargetEntry *target_entry = lfirst_node(TargetEntry, lc); + if (IsA(target_entry->expr, Aggref)) + { + continue; + } + + if (!IsA(target_entry->expr, Var)) + { + /* + * We shouldn't see anything except Vars or Aggrefs in the + * aggregated targetlists. Just say it's not vectorizable, because + * here we are working with arbitrary plans that we don't control. + */ + return false; + } + + num_grouping_columns++; + + Var *var = castNode(Var, target_entry->expr); + bool is_segmentby; + if (!is_vector_var(custom, (Expr *) var, &is_segmentby)) + { + return false; + } + + all_segmentby &= is_segmentby; + + /* + * If we have a single grouping column, record it for the additional + * checks later. + */ + if (num_grouping_columns == 1) + { + single_grouping_var = var; + } + else + { + single_grouping_var = NULL; + } + } + + Assert(num_grouping_columns == 1 || single_grouping_var == NULL); + Assert(num_grouping_columns >= agg->numCols); + /* * We support vectorized aggregation without grouping. */ - if (agg->numCols == 0) + if (num_grouping_columns == 0) { return true; } @@ -367,46 +425,21 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) * We support hashed vectorized grouping by one fixed-size by-value * compressed column. */ - if (agg->numCols == 1) + if (num_grouping_columns == 1) { - int offset = AttrNumberGetAttrOffset(agg->grpColIdx[0]); - TargetEntry *entry = list_nth(resolved_targetlist, offset); - - bool is_segmentby = false; - if (is_vector_var(custom, entry->expr, &is_segmentby)) + int16 typlen; + bool typbyval; + get_typlenbyval(single_grouping_var->vartype, &typlen, &typbyval); + if (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) { - Var *var = castNode(Var, entry->expr); - int16 typlen; - bool typbyval; - get_typlenbyval(var->vartype, &typlen, &typbyval); - if (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) - { - return true; - } + return true; } } /* * We support grouping by any number of columns if all of them are segmentby. */ - for (int i = 0; i < agg->numCols; i++) - { - int offset = AttrNumberGetAttrOffset(agg->grpColIdx[i]); - TargetEntry *entry = list_nth_node(TargetEntry, resolved_targetlist, offset); - - bool is_segmentby = false; - if (!is_vector_var(custom, entry->expr, &is_segmentby)) - { - return false; - } - - if (!is_segmentby) - { - return false; - } - } - - return true; + return all_segmentby; } /* @@ -593,7 +626,7 @@ try_insert_vector_agg_node(Plan *plan) if (!can_vectorize_grouping(agg, custom, resolved_targetlist)) { - /* No GROUP BY support for now. */ + /* The grouping is not vectorizable. */ return plan; } @@ -601,7 +634,7 @@ try_insert_vector_agg_node(Plan *plan) ListCell *lc; foreach (lc, resolved_targetlist) { - TargetEntry *target_entry = castNode(TargetEntry, lfirst(lc)); + TargetEntry *target_entry = lfirst_node(TargetEntry, lc); if (IsA(target_entry->expr, Aggref)) { Aggref *aggref = castNode(Aggref, target_entry->expr); diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index a5623050760..a218e385880 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -3503,3 +3503,11 @@ SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; 82620 (1 row) +-- Postgres versions starting with 16 remove the grouping columns that are +-- equated to a constant. Check that our planning code handles this well. +SELECT sum(float_value), int_value FROM testtable2 WHERE int_value = 1 GROUP BY int_value; + sum | int_value +------+----------- + 3162 | 1 +(1 row) + diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index bafecd6b544..93866322c9b 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -407,3 +407,7 @@ RESET max_parallel_workers_per_gather; -- Can't group by a system column SELECT sum(float_value) FROM testtable2 GROUP BY tableoid ORDER BY 1 LIMIT 1; + +-- Postgres versions starting with 16 remove the grouping columns that are +-- equated to a constant. Check that our planning code handles this well. +SELECT sum(float_value), int_value FROM testtable2 WHERE int_value = 1 GROUP BY int_value; From 66403f2e2a2ff70767a39fab14bd80dd3caca441 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:26:40 +0100 Subject: [PATCH 182/242] benchmark fixed-size hash grouping (2024-12-04 no. 152) From 99e5b041b4b643395af4246b9fdc8fea293df575 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:46:51 +0100 Subject: [PATCH 183/242] remove some (yet) unused code --- .../vector_agg/hashing/batch_hashing_params.h | 33 ++++--------------- .../hash_strategy_impl_single_fixed_key.c | 12 +++---- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h index a4db2a19b1c..0f18a0f5fe0 100644 --- a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h +++ b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h @@ -6,20 +6,14 @@ #pragma once +/* + * The data required to map the rows of the given compressed batch to the unique + * indexes of grouping keys, using a hash table. + */ typedef struct BatchHashingParams { const uint64 *batch_filter; - CompressedColumnValues single_key; - - int num_grouping_columns; - const CompressedColumnValues *grouping_column_values; - - /* - * Whether we have any scalar or nullable grouping columns in the current - * batch. This is used to select the more efficient implementation when we - * have none. - */ - bool have_scalar_or_nullable_columns; + CompressedColumnValues single_grouping_column; GroupingPolicyHash *restrict policy; @@ -32,24 +26,11 @@ build_batch_hashing_params(GroupingPolicyHash *policy, DecompressBatchState *bat BatchHashingParams params = { .policy = policy, .batch_filter = batch_state->vector_qual_result, - .num_grouping_columns = policy->num_grouping_columns, - .grouping_column_values = policy->current_batch_grouping_column_values, .result_key_indexes = policy->key_index_for_row, }; - Assert(policy->num_grouping_columns > 0); - if (policy->num_grouping_columns == 1) - { - params.single_key = policy->current_batch_grouping_column_values[0]; - } - - for (int i = 0; i < policy->num_grouping_columns; i++) - { - params.have_scalar_or_nullable_columns = - params.have_scalar_or_nullable_columns || - (policy->current_batch_grouping_column_values[i].decompression_type == DT_Scalar || - policy->current_batch_grouping_column_values[i].buffers[0] != NULL); - } + Assert(policy->num_grouping_columns == 1); + params.single_grouping_column = policy->current_batch_grouping_column_values[0]; return params; } diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index c8a3c2da57f..972567dcc10 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -29,15 +29,15 @@ FUNCTION_NAME(key_hashing_get_key)(BatchHashingParams params, int row, OUTPUT_KEY_TYPE *restrict output_key = (OUTPUT_KEY_TYPE *) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; - if (unlikely(params.single_key.decompression_type == DT_Scalar)) + if (unlikely(params.single_grouping_column.decompression_type == DT_Scalar)) { - *output_key = DATUM_TO_OUTPUT_KEY(*params.single_key.output_value); - *valid = !*params.single_key.output_isnull; + *output_key = DATUM_TO_OUTPUT_KEY(*params.single_grouping_column.output_value); + *valid = !*params.single_grouping_column.output_isnull; } - else if (params.single_key.decompression_type == sizeof(OUTPUT_KEY_TYPE)) + else if (params.single_grouping_column.decompression_type == sizeof(OUTPUT_KEY_TYPE)) { - const OUTPUT_KEY_TYPE *values = params.single_key.buffers[1]; - *valid = arrow_row_is_valid(params.single_key.buffers[0], row); + const OUTPUT_KEY_TYPE *values = params.single_grouping_column.buffers[1]; + *valid = arrow_row_is_valid(params.single_grouping_column.buffers[0], row); *output_key = values[row]; } else From 9fccab9896994e6fd9ded0b55560fa6f9336274a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:58:32 +0100 Subject: [PATCH 184/242] ref --- tsl/test/expected/vectorized_aggregation.out | 4 ++-- tsl/test/sql/vectorized_aggregation.sql | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index dfee268fb41..01f690b743a 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -180,7 +180,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; Filter: (_hyper_1_10_chunk.segment_by_value > 0) (65 rows) --- Vectorization not possible due to a used filter +-- Vectorization with filter on compressed columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_value > 0; QUERY PLAN @@ -2858,7 +2858,7 @@ SELECT sum(int_value) FROM testtable; 3538 (1 row) --- Aggregation filters are not supported at the moment +-- Vectorizable aggregation filters are supported :EXPLAIN SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; QUERY PLAN diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index bafecd6b544..324a96716f5 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -42,7 +42,7 @@ SELECT sum(segment_by_value) FROM testtable; :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0; --- Vectorization not possible due to a used filter +-- Vectorization with filter on compressed columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE segment_by_value > 0 AND int_value > 0; @@ -330,7 +330,7 @@ SELECT sum(segment_by_value) FROM testtable; SELECT sum(int_value) FROM testtable; --- Aggregation filters are not supported at the moment +-- Vectorizable aggregation filters are supported :EXPLAIN SELECT sum(segment_by_value) FILTER (WHERE segment_by_value > 99999) FROM testtable; From f5b648ada9b26ffcc9a2d5c2cc8ff0de4349cee7 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:39:27 +0100 Subject: [PATCH 185/242] add test --- .../nodes/vector_agg/grouping_policy_hash.c | 1 + tsl/test/expected/vector_agg_filter.out | 21 +++++++++++++++++++ tsl/test/sql/vector_agg_filter.sql | 9 ++++++++ 3 files changed, 31 insertions(+) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 85c81b813ff..0853d9d47cc 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -149,6 +149,7 @@ compute_single_aggregate(GroupingPolicyHash *policy, const DecompressBatchState const size_t num_words = (batch_state->total_batch_rows + 63) / 64; const uint64 *filter = arrow_combine_validity(num_words, policy->tmp_filter, + agg_def->filter_result, batch_state->vector_qual_result, arg_validity_bitmap); diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out index 13629d3e4b3..81d33e3e7d3 100644 --- a/tsl/test/expected/vector_agg_filter.out +++ b/tsl/test/expected/vector_agg_filter.out @@ -2962,4 +2962,25 @@ select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; 7 (1 row) +-- With hash grouping +select + ss, + count(*) filter (where s != 5), + count(*) filter (where cint2 < 0) +from aggfilter +group by ss; + ss | count | count +----+-------+------- + 3 | 19981 | 10076 + 11 | 40019 | 20008 + 8 | 20000 | 10082 + | 19 | 12 + 9 | 20000 | 9961 + 7 | 20000 | 10008 + 5 | 0 | 9871 + 4 | 19981 | 10064 + 0 | 20000 | 9968 + 6 | 20000 | 10089 +(10 rows) + reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index d3423d84eac..ec861a8f70d 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -113,9 +113,18 @@ reset timescaledb.debug_require_vector_agg; -- FILTER that is not vectorizable set timescaledb.debug_require_vector_agg = 'forbid'; select count(*) filter (where cint2 === 0) from aggfilter; + -- FILTER with stable function set timescaledb.debug_require_vector_agg = 'require'; select count(*) filter (where cint2 = stable_abs(0)) from aggfilter; +-- With hash grouping +select + ss, + count(*) filter (where s != 5), + count(*) filter (where cint2 < 0) +from aggfilter +group by ss; + reset timescaledb.debug_require_vector_agg; From dc6001daef1dccc579fee8701652f3f8d96ed0cb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:45:59 +0100 Subject: [PATCH 186/242] typo --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c index 96679548d52..cdf7a0e84a4 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_fixed_4.c @@ -5,7 +5,7 @@ */ /* - * Implementation of column hashing for a single fixed size 2-byte column. + * Implementation of column hashing for a single fixed size 4-byte column. */ #include From 0ea397a85e956a68e86f20db8c4a643123129a4c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:21:35 +0100 Subject: [PATCH 187/242] disable parallel --- tsl/test/expected/vector_agg_functions.out | 2 ++ tsl/test/sql/vector_agg_functions.sql | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index bffb8d7af7d..2bd56502fb5 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -115,6 +115,7 @@ set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; +set max_parallel_workers_per_gather = 0; select format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, @@ -7658,3 +7659,4 @@ select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; 12 | 1 | 65 (8 rows) +reset max_parallel_workers_per_gather; diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index 2876a303fba..ef5d3c2b8dc 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -100,6 +100,8 @@ set timescaledb.debug_require_vector_agg = :'guc_value'; ---- on float4 due to different numeric stability in our and PG implementations. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; +set max_parallel_workers_per_gather = 0; + select format('%sselect %s%s(%s) from aggfns%s%s%s;', explain, @@ -174,3 +176,5 @@ select s, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; select ss, count(*), min(f1) from edges where f1 = 63 group by 1 order by 1; select ss, count(*), min(f1) from edges where f1 = 64 group by 1 order by 1; select ss, count(*), min(f1) from edges where f1 = 65 group by 1 order by 1; + +reset max_parallel_workers_per_gather; From ea4dab1a2018f3cb9fb319849d51a1d2fa5cec70 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:59:50 +0100 Subject: [PATCH 188/242] add order --- tsl/test/expected/vector_agg_filter.out | 17 ++++++++++------- tsl/test/sql/vector_agg_filter.sql | 7 +++++-- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/tsl/test/expected/vector_agg_filter.out b/tsl/test/expected/vector_agg_filter.out index 81d33e3e7d3..8310a828be5 100644 --- a/tsl/test/expected/vector_agg_filter.out +++ b/tsl/test/expected/vector_agg_filter.out @@ -68,6 +68,7 @@ vacuum freeze analyze aggfilter; set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +set max_parallel_workers_per_gather = 0; select format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', explain, @@ -2968,19 +2969,21 @@ select count(*) filter (where s != 5), count(*) filter (where cint2 < 0) from aggfilter -group by ss; +group by ss +order by 2, 3; ss | count | count ----+-------+------- - 3 | 19981 | 10076 - 11 | 40019 | 20008 - 8 | 20000 | 10082 - | 19 | 12 - 9 | 20000 | 9961 - 7 | 20000 | 10008 5 | 0 | 9871 + | 19 | 12 4 | 19981 | 10064 + 3 | 19981 | 10076 + 9 | 20000 | 9961 0 | 20000 | 9968 + 7 | 20000 | 10008 + 8 | 20000 | 10082 6 | 20000 | 10089 + 11 | 40019 | 20008 (10 rows) reset timescaledb.debug_require_vector_agg; +reset max_parallel_workers_per_gather; diff --git a/tsl/test/sql/vector_agg_filter.sql b/tsl/test/sql/vector_agg_filter.sql index ec861a8f70d..8a5aec27370 100644 --- a/tsl/test/sql/vector_agg_filter.sql +++ b/tsl/test/sql/vector_agg_filter.sql @@ -65,6 +65,8 @@ set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. --set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +set max_parallel_workers_per_gather = 0; + select format('%sselect %s%s(%s)%s from aggfilter%s%s%s;', explain, @@ -124,7 +126,8 @@ select count(*) filter (where s != 5), count(*) filter (where cint2 < 0) from aggfilter -group by ss; +group by ss +order by 2, 3; reset timescaledb.debug_require_vector_agg; - +reset max_parallel_workers_per_gather; From 4b98e4610e350d73ef6dabd0529676d2957bfda3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 18 Dec 2024 17:51:08 +0100 Subject: [PATCH 189/242] Update tsl/src/nodes/vector_agg/grouping_policy_hash.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Nordström <819732+erimatnor@users.noreply.github.com> Signed-off-by: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> --- tsl/src/nodes/vector_agg/grouping_policy_hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 5e2d5146338..27286bb6696 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -39,7 +39,7 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; * rows of the batch, and for each aggregate function separately, to generate * simpler and potentially vectorizable code, and improve memory locality. * - * 3) After the input have ended, or if the memory limit is reached, the partial + * 3) After the input has ended, or if the memory limit is reached, the partial * results are emitted into the output slot. This is done in the order of unique * grouping key indexes, thereby preserving the incoming key order. This * guarantees that this policy works correctly even in a Partial GroupAggregate From b615dbe34f200878b14f7b3ebd6a5140b864b9ca Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 18 Dec 2024 17:51:19 +0100 Subject: [PATCH 190/242] Update tsl/src/nodes/vector_agg/grouping_policy_hash.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Nordström <819732+erimatnor@users.noreply.github.com> Signed-off-by: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> --- tsl/src/nodes/vector_agg/grouping_policy_hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 27286bb6696..3fc0016b444 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -35,7 +35,7 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; * strategy. * * 2) The key indexes are used to locate the aggregate function states - * corresponding to a given row, and update it. This is done in bulk for all + * corresponding to a given row's key, and update it. This is done in bulk for all * rows of the batch, and for each aggregate function separately, to generate * simpler and potentially vectorizable code, and improve memory locality. * From 045f59affc08b76b0f6e197e384c4e1c07435345 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 18 Dec 2024 18:45:33 +0100 Subject: [PATCH 191/242] determine the grouping type at plan time --- tsl/src/nodes/vector_agg/exec.c | 23 +++---- tsl/src/nodes/vector_agg/grouping_policy.h | 16 ++++- .../nodes/vector_agg/grouping_policy_hash.c | 14 ++--- tsl/src/nodes/vector_agg/plan.c | 60 ++++++++++++------- tsl/src/nodes/vector_agg/plan.h | 9 +++ 5 files changed, 75 insertions(+), 47 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 9ada1a62b43..6d9b08fee65 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -21,6 +21,7 @@ #include "nodes/decompress_chunk/exec.h" #include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" +#include "nodes/vector_agg/plan.h" static int get_input_offset(DecompressChunkState *decompress_state, Var *var) @@ -187,22 +188,11 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) } /* - * Determine which grouping policy we are going to use. + * Create the grouping policy chosen at plan time. */ - bool all_segmentby = true; - for (int i = 0; i < vector_agg_state->num_grouping_columns; i++) - { - GroupingColumn *col = &vector_agg_state->grouping_columns[i]; - DecompressContext *dcontext = &decompress_state->decompress_context; - CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[col->input_offset]; - if (desc->type != SEGMENTBY_COLUMN) - { - all_segmentby = false; - break; - } - } - - if (all_segmentby) + const VectorAggGroupingType grouping_type = + intVal(list_nth(cscan->custom_private, VASI_GroupingType)); + if (grouping_type == VAGT_Batch) { /* * Per-batch grouping. @@ -222,7 +212,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) create_grouping_policy_hash(vector_agg_state->num_agg_defs, vector_agg_state->agg_defs, vector_agg_state->num_grouping_columns, - vector_agg_state->grouping_columns); + vector_agg_state->grouping_columns, + grouping_type); } } diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index e7c5af909d2..30a6dfd4690 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -54,10 +54,24 @@ typedef struct GroupingPolicy char *(*gp_explain)(GroupingPolicy *gp); } GroupingPolicy; +/* + * The various types of grouping we might use, as determined at planning time. + * The hashed subtypes are all implemented by hash grouping policy. + */ +typedef enum +{ + VAGT_Invalid, + VAGT_Batch, + VAGT_HashSingleFixed2, + VAGT_HashSingleFixed4, + VAGT_HashSingleFixed8 +} VectorAggGroupingType; + extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, GroupingColumn *grouping_columns); extern GroupingPolicy *create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, - GroupingColumn *grouping_columns); + GroupingColumn *grouping_columns, + VectorAggGroupingType grouping_type); diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 0853d9d47cc..05a8e13d474 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -39,7 +39,7 @@ static const GroupingPolicy grouping_policy_hash_functions; GroupingPolicy * create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_grouping_columns, - GroupingColumn *grouping_columns) + GroupingColumn *grouping_columns, VectorAggGroupingType grouping_type) { GroupingPolicyHash *policy = palloc0(sizeof(GroupingPolicyHash)); policy->funcs = grouping_policy_hash_functions; @@ -66,21 +66,19 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr policy->current_batch_grouping_column_values = palloc(sizeof(CompressedColumnValues) * num_grouping_columns); - Assert(num_grouping_columns == 1); - const GroupingColumn *g = &policy->grouping_columns[0]; - switch (g->value_bytes) + switch (grouping_type) { - case 8: + case VAGT_HashSingleFixed8: policy->hashing = single_fixed_8_strategy; break; - case 4: + case VAGT_HashSingleFixed4: policy->hashing = single_fixed_4_strategy; break; - case 2: + case VAGT_HashSingleFixed2: policy->hashing = single_fixed_2_strategy; break; default: - Assert(false); + Ensure(false, "failed to determine the hashing strategy"); break; } diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 0c9f1cac201..055300e6990 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -16,6 +16,7 @@ #include "plan.h" #include "exec.h" +#include "import/list.h" #include "nodes/decompress_chunk/planner.h" #include "nodes/decompress_chunk/vector_quals.h" #include "nodes/vector_agg.h" @@ -131,7 +132,8 @@ resolve_outer_special_vars(List *agg_tlist, CustomScan *custom) * node. */ static Plan * -vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_targetlist) +vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_targetlist, + VectorAggGroupingType grouping_type) { CustomScan *vector_agg = (CustomScan *) makeNode(CustomScan); vector_agg->custom_plans = list_make1(decompress_chunk); @@ -171,13 +173,9 @@ vector_agg_plan_create(Agg *agg, CustomScan *decompress_chunk, List *resolved_ta vector_agg->scan.plan.extParam = bms_copy(agg->plan.extParam); vector_agg->scan.plan.allParam = bms_copy(agg->plan.allParam); - List *grouping_child_output_offsets = NIL; - for (int i = 0; i < agg->numCols; i++) - { - grouping_child_output_offsets = - lappend_int(grouping_child_output_offsets, AttrNumberGetAttrOffset(agg->grpColIdx[i])); - } - vector_agg->custom_private = list_make1(grouping_child_output_offsets); + vector_agg->custom_private = ts_new_list(T_List, VASI_Count); + lfirst(list_nth_cell(vector_agg->custom_private, VASI_GroupingType)) = + makeInteger(grouping_type); return (Plan *) vector_agg; } @@ -427,10 +425,10 @@ can_vectorize_aggref(Aggref *aggref, CustomScan *custom, VectorQualInfo *vqi) } /* - * Whether we can perform vectorized aggregation with a given grouping. + * What vectorized grouping strategy we can use for the given grouping columns. */ -static bool -can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) +static VectorAggGroupingType +get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_targetlist) { /* * The Agg->numCols value can be less than the number of the non-aggregated @@ -459,7 +457,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) * aggregated targetlists. Just say it's not vectorizable, because * here we are working with arbitrary plans that we don't control. */ - return false; + return VAGT_Invalid; } num_grouping_columns++; @@ -468,7 +466,7 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) bool is_segmentby; if (!is_vector_var(custom, (Expr *) var, &is_segmentby)) { - return false; + return VAGT_Invalid; } all_segmentby &= is_segmentby; @@ -495,7 +493,15 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) */ if (num_grouping_columns == 0) { - return true; + return VAGT_Batch; + } + + /* + * We support grouping by any number of columns if all of them are segmentby. + */ + if (all_segmentby) + { + return VAGT_Batch; } /* @@ -507,16 +513,24 @@ can_vectorize_grouping(Agg *agg, CustomScan *custom, List *resolved_targetlist) int16 typlen; bool typbyval; get_typlenbyval(single_grouping_var->vartype, &typlen, &typbyval); - if (typbyval && typlen > 0 && (size_t) typlen <= sizeof(Datum)) + if (typbyval) { - return true; + switch (typlen) + { + case 2: + return VAGT_HashSingleFixed2; + case 4: + return VAGT_HashSingleFixed4; + case 8: + return VAGT_HashSingleFixed8; + default: + Ensure(false, "invalid fixed size %d of a vector type", typlen); + break; + } } } - /* - * We support grouping by any number of columns if all of them are segmentby. - */ - return all_segmentby; + return VAGT_Invalid; } /* @@ -709,7 +723,9 @@ try_insert_vector_agg_node(Plan *plan) */ List *resolved_targetlist = resolve_outer_special_vars(agg->plan.targetlist, custom); - if (!can_vectorize_grouping(agg, custom, resolved_targetlist)) + const VectorAggGroupingType grouping_type = + get_vectorized_grouping_type(agg, custom, resolved_targetlist); + if (grouping_type == VAGT_Invalid) { /* The grouping is not vectorizable. */ return plan; @@ -758,5 +774,5 @@ try_insert_vector_agg_node(Plan *plan) * Finally, all requirements are satisfied and we can vectorize this partial * aggregation node. */ - return vector_agg_plan_create(agg, custom, resolved_targetlist); + return vector_agg_plan_create(agg, custom, resolved_targetlist, grouping_type); } diff --git a/tsl/src/nodes/vector_agg/plan.h b/tsl/src/nodes/vector_agg/plan.h index 67f0e2957c9..94dabb35d6d 100644 --- a/tsl/src/nodes/vector_agg/plan.h +++ b/tsl/src/nodes/vector_agg/plan.h @@ -13,6 +13,15 @@ typedef struct VectorAggPlan CustomScan custom; } VectorAggPlan; +/* + * The indexes of settings that we have to pass through the custom_private list. + */ +typedef enum +{ + VASI_GroupingType = 0, + VASI_Count +} VectorAggSettingsIndex; + extern void _vector_agg_init(void); Plan *try_insert_vector_agg_node(Plan *plan); From df100f2b042dadf3d6091007b91aa2d707556b06 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 2 Jan 2025 15:28:08 +0100 Subject: [PATCH 192/242] cleanup --- tsl/src/nodes/vector_agg/plan.c | 14 ++-- tsl/test/expected/vectorized_aggregation.out | 72 +++++++++++++++++++- tsl/test/sql/vectorized_aggregation.sql | 6 +- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 055300e6990..e705d23f37a 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -475,14 +475,12 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target * If we have a single grouping column, record it for the additional * checks later. */ - if (num_grouping_columns == 1) - { - single_grouping_var = var; - } - else - { - single_grouping_var = NULL; - } + single_grouping_var = var; + } + + if (num_grouping_columns != 1) + { + single_grouping_var = NULL; } Assert(num_grouping_columns == 1 || single_grouping_var == NULL); diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index 79b6b608d6f..a65b8dd1376 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -397,7 +397,7 @@ SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; Filter: (_hyper_1_10_chunk.float_value > '0'::double precision) (65 rows) --- Vectorization not possible due grouping +-- Vectorization possible with grouping by one fixed-size column :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; QUERY PLAN @@ -536,6 +536,76 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value (63 rows) +-- Vectorization not possible with grouping by multiple columns +:EXPLAIN +SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Finalize HashAggregate + Output: sum(_hyper_1_1_chunk.segment_by_value), _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + -> Gather + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Workers Planned: 2 + -> Parallel Append + -> Partial HashAggregate + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) + Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value + -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk + Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value + -> Partial HashAggregate + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) + Group Key: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value + -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk + Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value + -> Partial HashAggregate + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) + Group Key: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value + -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk + Output: compress_hyper_2_13_chunk._ts_meta_count, compress_hyper_2_13_chunk.segment_by_value, compress_hyper_2_13_chunk._ts_meta_min_1, compress_hyper_2_13_chunk._ts_meta_max_1, compress_hyper_2_13_chunk."time", compress_hyper_2_13_chunk.int_value, compress_hyper_2_13_chunk.float_value + -> Partial HashAggregate + Output: _hyper_1_4_chunk.int_value, _hyper_1_4_chunk.float_value, PARTIAL sum(_hyper_1_4_chunk.segment_by_value) + Group Key: _hyper_1_4_chunk.int_value, _hyper_1_4_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_4_chunk + Output: _hyper_1_4_chunk.int_value, _hyper_1_4_chunk.float_value, _hyper_1_4_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_5_chunk.int_value, _hyper_1_5_chunk.float_value, PARTIAL sum(_hyper_1_5_chunk.segment_by_value) + Group Key: _hyper_1_5_chunk.int_value, _hyper_1_5_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_5_chunk + Output: _hyper_1_5_chunk.int_value, _hyper_1_5_chunk.float_value, _hyper_1_5_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_6_chunk.int_value, _hyper_1_6_chunk.float_value, PARTIAL sum(_hyper_1_6_chunk.segment_by_value) + Group Key: _hyper_1_6_chunk.int_value, _hyper_1_6_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_6_chunk + Output: _hyper_1_6_chunk.int_value, _hyper_1_6_chunk.float_value, _hyper_1_6_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_7_chunk.int_value, _hyper_1_7_chunk.float_value, PARTIAL sum(_hyper_1_7_chunk.segment_by_value) + Group Key: _hyper_1_7_chunk.int_value, _hyper_1_7_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_7_chunk + Output: _hyper_1_7_chunk.int_value, _hyper_1_7_chunk.float_value, _hyper_1_7_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_8_chunk.int_value, _hyper_1_8_chunk.float_value, PARTIAL sum(_hyper_1_8_chunk.segment_by_value) + Group Key: _hyper_1_8_chunk.int_value, _hyper_1_8_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_8_chunk + Output: _hyper_1_8_chunk.int_value, _hyper_1_8_chunk.float_value, _hyper_1_8_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_9_chunk.int_value, _hyper_1_9_chunk.float_value, PARTIAL sum(_hyper_1_9_chunk.segment_by_value) + Group Key: _hyper_1_9_chunk.int_value, _hyper_1_9_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_9_chunk + Output: _hyper_1_9_chunk.int_value, _hyper_1_9_chunk.float_value, _hyper_1_9_chunk.segment_by_value + -> Partial HashAggregate + Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.float_value, PARTIAL sum(_hyper_1_10_chunk.segment_by_value) + Group Key: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.float_value + -> Parallel Seq Scan on _timescaledb_internal._hyper_1_10_chunk + Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.float_value, _hyper_1_10_chunk.segment_by_value +(63 rows) + -- Vectorization possible with grouping by a segmentby column. :EXPLAIN SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index e3deb9bbb16..86a9f5d801c 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -52,13 +52,17 @@ SELECT sum(segment_by_value) FROM testtable WHERE int_value > 0; :EXPLAIN SELECT sum(segment_by_value) FROM testtable WHERE float_value > 0; --- Vectorization not possible due grouping +-- Vectorization possible with grouping by one fixed-size column :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; +-- Vectorization not possible with grouping by multiple columns +:EXPLAIN +SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; + -- Vectorization possible with grouping by a segmentby column. :EXPLAIN SELECT sum(int_value) FROM testtable GROUP BY segment_by_value; From 5569cfb672d620799dc9876170714d8342de8c91 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 6 Jan 2025 14:03:36 +0100 Subject: [PATCH 193/242] fix after merge --- tsl/test/expected/vector_agg_functions.out | 2 +- tsl/test/sql/vector_agg_functions.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tsl/test/expected/vector_agg_functions.out b/tsl/test/expected/vector_agg_functions.out index dbcc819c21f..651fda5ceba 100644 --- a/tsl/test/expected/vector_agg_functions.out +++ b/tsl/test/expected/vector_agg_functions.out @@ -114,7 +114,7 @@ limit 1 set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; +--set timescaledb.enable_chunkwise_aggregation to off; set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; set max_parallel_workers_per_gather = 0; select format('%sselect %s%s(%s) from aggfns%s%s%s;', diff --git a/tsl/test/sql/vector_agg_functions.sql b/tsl/test/sql/vector_agg_functions.sql index ef5d3c2b8dc..b3c65158aa3 100644 --- a/tsl/test/sql/vector_agg_functions.sql +++ b/tsl/test/sql/vector_agg_functions.sql @@ -98,7 +98,7 @@ limit 1 set timescaledb.debug_require_vector_agg = :'guc_value'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; +--set timescaledb.enable_chunkwise_aggregation to off; set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; set max_parallel_workers_per_gather = 0; From 3379669e113840c41b6fd885624333398f92bd3a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 13:47:02 +0100 Subject: [PATCH 194/242] cmake flags for umash support --- tsl/CMakeLists.txt | 27 +++++++++++++++++++ tsl/src/import/CMakeLists.txt | 7 ++++- .../nodes/vector_agg/grouping_policy_hash.c | 4 +++ .../nodes/vector_agg/hashing/CMakeLists.txt | 10 ++++--- tsl/src/nodes/vector_agg/plan.c | 6 +++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 9058a14625a..5184c65a13a 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -4,5 +4,32 @@ if(COMPRESSION_FUZZING) add_compile_definitions(TS_COMPRESSION_FUZZING=1) endif() +# Check whether the UMASH hashing can be supported. We use it for vectorized +# grouping. +check_c_compiler_flag(-mpclmul CC_PCLMUL) +if(CC_PCLMUL) + add_compile_options(-mpclmul) + # For the "C source compiles" check below, it doesn't use the global + # compilation flags. + set(CMAKE_REQUIRED_FLAGS -mpclmul) +endif() + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +check_c_source_compiles( + "#if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) +#error Unsupported platform for UMASH +#endif" UMASH_SUPPORTED) +unset(CMAKE_REQUIRED_FLAGS) +unset(CMAKE_TRY_COMPILE_TARGET_TYPE) + +option(USE_UMASH + "Use the UMASH hash for string and multi-column vectorized grouping" + ${UMASH_SUPPORTED}) + +if(USE_UMASH) + add_compile_definitions(TS_USE_UMASH) +endif() + +# Add the subdirectories add_subdirectory(test) add_subdirectory(src) diff --git a/tsl/src/import/CMakeLists.txt b/tsl/src/import/CMakeLists.txt index 32e5a008652..f0bf598d393 100644 --- a/tsl/src/import/CMakeLists.txt +++ b/tsl/src/import/CMakeLists.txt @@ -1,2 +1,7 @@ -set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) +set(SOURCES) + +if(USE_UMASH) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) +endif() + target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index f2ccca8f879..b28a6c34969 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -34,8 +34,10 @@ extern HashingStrategy single_fixed_2_strategy; extern HashingStrategy single_fixed_4_strategy; extern HashingStrategy single_fixed_8_strategy; +#ifdef TS_USE_UMASH extern HashingStrategy single_text_strategy; extern HashingStrategy serialized_strategy; +#endif static const GroupingPolicy grouping_policy_hash_functions; @@ -70,12 +72,14 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr switch (grouping_type) { +#ifdef TS_USE_UMASH case VAGT_HashSerialized: policy->hashing = serialized_strategy; break; case VAGT_HashSingleText: policy->hashing = single_text_strategy; break; +#endif case VAGT_HashSingleFixed8: policy->hashing = single_fixed_8_strategy; break; diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt index ce45c457b5c..f0e6dfe038b 100644 --- a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -2,7 +2,11 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_2.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_4.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_8.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_serialized.c) + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c) + +if(USE_UMASH) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_serialized.c) +endif() + target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 8ad0d7e0325..0c23b032b81 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -530,6 +530,7 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target break; } } +#ifdef TS_USE_UMASH else { Ensure(single_grouping_var->vartype == TEXTOID, @@ -537,12 +538,17 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target single_grouping_var->vartype); return VAGT_HashSingleText; } +#endif } +#ifdef TS_USE_UMASH /* * Use hashing of serialized keys when we have many grouping columns. */ return VAGT_HashSerialized; +#else + return VAGT_Invalid; +#endif } /* From a4505c97b247eed6e6cf070140426ddec9773f4f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:08:31 +0100 Subject: [PATCH 195/242] disable on 32-bit --- tsl/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 5184c65a13a..a89b47d2453 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -16,9 +16,13 @@ endif() set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) check_c_source_compiles( - "#if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) + " +#if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) \ + && !(defined(__aarch64__) || defined(__x86_64__)) #error Unsupported platform for UMASH -#endif" UMASH_SUPPORTED) +#endif +" + UMASH_SUPPORTED) unset(CMAKE_REQUIRED_FLAGS) unset(CMAKE_TRY_COMPILE_TARGET_TYPE) From 2a1678e6526120928898f38ea5f893e5cca87a25 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:33:29 +0100 Subject: [PATCH 196/242] Fix test sfter merge --- tsl/test/expected/vectorized_aggregation.out | 20 ++++++++++---------- tsl/test/sql/vectorized_aggregation.sql | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index a65b8dd1376..d0df3025f6e 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -536,7 +536,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value (63 rows) --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; QUERY PLAN @@ -548,23 +548,23 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) - Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) - Group Key: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) - Group Key: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index 86a9f5d801c..b54cd74f263 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -59,7 +59,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; From 93906733a278aadabd09dfa883a33ab9aeaebbc9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:39:38 +0100 Subject: [PATCH 197/242] Vectorized hash grouping by a single text column Use the UMASH hashes that have a guaranteed lower bound on collisions as the hash table keys. --- scripts/clang_format_all.sh | 2 +- tsl/CMakeLists.txt | 31 +++++++++++++++++++ tsl/src/import/CMakeLists.txt | 9 ++++-- .../nodes/decompress_chunk/compressed_batch.h | 2 +- .../decompress_chunk/vector_predicates.h | 2 +- tsl/src/nodes/vector_agg/grouping_policy.h | 3 +- .../nodes/vector_agg/grouping_policy_hash.c | 17 ++++++++++ .../nodes/vector_agg/grouping_policy_hash.h | 11 +++++++ .../nodes/vector_agg/hashing/CMakeLists.txt | 5 +++ .../vector_agg/hashing/hashing_strategy.h | 9 +++++- tsl/src/nodes/vector_agg/plan.c | 13 ++++++++ tsl/test/expected/vectorized_aggregation.out | 20 ++++++------ tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vectorized_aggregation.sql | 2 +- 14 files changed, 109 insertions(+), 18 deletions(-) diff --git a/scripts/clang_format_all.sh b/scripts/clang_format_all.sh index ea1bb03e8b8..5828d39b855 100755 --- a/scripts/clang_format_all.sh +++ b/scripts/clang_format_all.sh @@ -5,5 +5,5 @@ SCRIPT_DIR=$(cd "$(dirname $0)" || exit; pwd) BASE_DIR=$(dirname $SCRIPT_DIR) find ${BASE_DIR} \( -path "${BASE_DIR}/src/*" -or -path "${BASE_DIR}/test/*" -or -path "${BASE_DIR}/tsl/*" \) \ - -and -not \( -path "*/.*" -or -path "*CMake*" \) \ + -and -not \( -path "*/.*" -or -path "*CMake*" -or -path "${BASE_DIR}/tsl/src/import/*" \) \ -and \( -name '*.c' -or -name '*.h' \) -print0 | xargs -0 ${SCRIPT_DIR}/clang_format_wrapper.sh -style=file -i diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 9058a14625a..a89b47d2453 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -4,5 +4,36 @@ if(COMPRESSION_FUZZING) add_compile_definitions(TS_COMPRESSION_FUZZING=1) endif() +# Check whether the UMASH hashing can be supported. We use it for vectorized +# grouping. +check_c_compiler_flag(-mpclmul CC_PCLMUL) +if(CC_PCLMUL) + add_compile_options(-mpclmul) + # For the "C source compiles" check below, it doesn't use the global + # compilation flags. + set(CMAKE_REQUIRED_FLAGS -mpclmul) +endif() + +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +check_c_source_compiles( + " +#if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) \ + && !(defined(__aarch64__) || defined(__x86_64__)) +#error Unsupported platform for UMASH +#endif +" + UMASH_SUPPORTED) +unset(CMAKE_REQUIRED_FLAGS) +unset(CMAKE_TRY_COMPILE_TARGET_TYPE) + +option(USE_UMASH + "Use the UMASH hash for string and multi-column vectorized grouping" + ${UMASH_SUPPORTED}) + +if(USE_UMASH) + add_compile_definitions(TS_USE_UMASH) +endif() + +# Add the subdirectories add_subdirectory(test) add_subdirectory(src) diff --git a/tsl/src/import/CMakeLists.txt b/tsl/src/import/CMakeLists.txt index ccac900c3ee..f0bf598d393 100644 --- a/tsl/src/import/CMakeLists.txt +++ b/tsl/src/import/CMakeLists.txt @@ -1,2 +1,7 @@ -set(SOURCES "") -target_sources(${PROJECT_NAME} PRIVATE ${SOURCES}) +set(SOURCES) + +if(USE_UMASH) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) +endif() + +target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/decompress_chunk/compressed_batch.h b/tsl/src/nodes/decompress_chunk/compressed_batch.h index 9871503e37c..dcacc40a8a0 100644 --- a/tsl/src/nodes/decompress_chunk/compressed_batch.h +++ b/tsl/src/nodes/decompress_chunk/compressed_batch.h @@ -103,7 +103,7 @@ typedef struct DecompressBatchState * row. Indexed same as arrow arrays, w/o accounting for the reverse scan * direction. Initialized to all ones, i.e. all rows pass. */ - uint64 *restrict vector_qual_result; + const uint64 *restrict vector_qual_result; /* * This follows DecompressContext.compressed_chunk_columns, but does not diff --git a/tsl/src/nodes/decompress_chunk/vector_predicates.h b/tsl/src/nodes/decompress_chunk/vector_predicates.h index cace90dbc44..204177c07a7 100644 --- a/tsl/src/nodes/decompress_chunk/vector_predicates.h +++ b/tsl/src/nodes/decompress_chunk/vector_predicates.h @@ -26,7 +26,7 @@ typedef enum VectorQualSummary } VectorQualSummary; static pg_attribute_always_inline VectorQualSummary -get_vector_qual_summary(uint64 *restrict qual_result, size_t n_rows) +get_vector_qual_summary(const uint64 *qual_result, size_t n_rows) { bool any_rows_pass = false; bool all_rows_pass = true; diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 30a6dfd4690..0286196e72a 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -64,7 +64,8 @@ typedef enum VAGT_Batch, VAGT_HashSingleFixed2, VAGT_HashSingleFixed4, - VAGT_HashSingleFixed8 + VAGT_HashSingleFixed8, + VAGT_HashSingleText } VectorAggGroupingType; extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 77acbe81ec4..1785af7c4ae 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -34,6 +34,9 @@ extern HashingStrategy single_fixed_2_strategy; extern HashingStrategy single_fixed_4_strategy; extern HashingStrategy single_fixed_8_strategy; +#ifdef TS_USE_UMASH +extern HashingStrategy single_text_strategy; +#endif static const GroupingPolicy grouping_policy_hash_functions; @@ -68,6 +71,11 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr switch (grouping_type) { +#ifdef TS_USE_UMASH + case VAGT_HashSingleText: + policy->hashing = single_text_strategy; + break; +#endif case VAGT_HashSingleFixed8: policy->hashing = single_fixed_8_strategy; break; @@ -82,6 +90,8 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr break; } + policy->hashing.key_body_mctx = policy->agg_extra_mctx; + policy->hashing.init(&policy->hashing, policy); return &policy->funcs; @@ -98,6 +108,13 @@ gp_hash_reset(GroupingPolicy *obj) policy->hashing.reset(&policy->hashing); + /* + * Have to reset this because it's in the key body context which is also + * reset here. + */ + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 3fc0016b444..cf6d7791d21 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -130,6 +130,17 @@ typedef struct GroupingPolicyHash uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_consecutive_keys; + + /* + * FIXME all the stuff below should be moved out. + */ + + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; } GroupingPolicyHash; //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt index c6ff65f65ca..401e5f22025 100644 --- a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -3,4 +3,9 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_4.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_fixed_8.c ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c) + +if(USE_UMASH) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c) +endif() + target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index 73c6130ffca..0d21b851a0a 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -42,10 +42,12 @@ typedef struct HashingStrategy * This is stored separately from hash table keys, because they might not * have the full column values, and also storing them contiguously here * leads to better memory access patterns when emitting the results. - * The details of the key storage are managed by the hashing strategy. + * The details of the key storage are managed by the hashing strategy. The + * by-reference keys can use a separate memory context for dense storage. */ Datum *restrict output_keys; uint64 num_allocated_output_keys; + MemoryContext key_body_mctx; /* * In single-column grouping, we store the null key outside of the hash @@ -54,6 +56,11 @@ typedef struct HashingStrategy * to reduce the hash table size. */ uint32 null_key_index; + + /* + * UMASH fingerprinting parameters. + */ + struct umash_params *umash_params; } HashingStrategy; void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state); diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index e705d23f37a..571804e002e 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -505,6 +505,10 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target /* * We support hashed vectorized grouping by one fixed-size by-value * compressed column. + * We can use our hash table for GroupAggregate as well, because it preserves + * the input order of the keys. + * FIXME write a test for that. + * FIXME rewrite to use num_grouping_columns */ if (num_grouping_columns == 1) { @@ -526,6 +530,15 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target break; } } +#ifdef TS_USE_UMASH + else + { + Ensure(single_grouping_var->vartype == TEXTOID, + "invalid vector type %d for grouping", + single_grouping_var->vartype); + return VAGT_HashSingleText; + } +#endif } return VAGT_Invalid; diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index a65b8dd1376..d0df3025f6e 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -536,7 +536,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value (63 rows) --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; QUERY PLAN @@ -548,23 +548,23 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) - Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) - Group Key: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) - Group Key: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 2b3a007d7a2..b6c89efd677 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -116,6 +116,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) feature_flags.sql vector_agg_default.sql vector_agg_filter.sql + vector_agg_grouping.sql vector_agg_memory.sql vector_agg_segmentby.sql) diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index 86a9f5d801c..b54cd74f263 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -59,7 +59,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; From a68572fc57af23ab6fffe5d50c96b6217630124a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:41:01 +0100 Subject: [PATCH 198/242] forgotten files --- tsl/src/import/umash.c | 1568 +++++++++++++ tsl/src/import/umash.h | 324 +++ .../hashing/hash_strategy_single_text.c | 398 ++++ .../hashing/umash_fingerprint_key.h | 45 + tsl/test/expected/vector_agg_grouping.out | 1985 +++++++++++++++++ tsl/test/sql/vector_agg_grouping.sql | 126 ++ 6 files changed, 4446 insertions(+) create mode 100644 tsl/src/import/umash.c create mode 100644 tsl/src/import/umash.h create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c create mode 100644 tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h create mode 100644 tsl/test/expected/vector_agg_grouping.out create mode 100644 tsl/test/sql/vector_agg_grouping.sql diff --git a/tsl/src/import/umash.c b/tsl/src/import/umash.c new file mode 100644 index 00000000000..eebcf8e2ced --- /dev/null +++ b/tsl/src/import/umash.c @@ -0,0 +1,1568 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This file contains source code that was copied and/or modified from + * the UMASH hash implementation at https://github.com/backtrace-labs/umash. + * + * This is a copy of umash.c, git commit sha + * fc4c5b6ca1f06c308e96c43aa080bd766238e092. + */ + +#include "umash.h" + +/* + * UMASH is distributed under the MIT license. + * + * SPDX-License-Identifier: MIT + * + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * Copyright 2022 Dougall Johnson + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(UMASH_TEST_ONLY) && !defined(NDEBUG) +#define NDEBUG +#endif + +/** + * -DUMASH_LONG_INPUTS=0 to disable the routine specialised for long + * inputs, and -DUMASH_LONG_INPUTS=1 to enable it. If the variable + * isn't defined, we try to probe for `umash_long.inc`: that's where + * the long input routines are defined. + */ +#ifndef UMASH_LONG_INPUTS +#ifdef __has_include +#if __has_include("umash_long.inc") +#define UMASH_LONG_INPUTS 1 +#endif /* __has_include() */ +#endif /* __has_include */ + +#ifndef UMASH_LONG_INPUTS +#define UMASH_LONG_INPUTS 0 +#endif /* !UMASH_LONG_INPUTS */ +#endif /* !UMASH_LONG_INPUTS */ + +/* + * Default to dynamically dispatching implementations on x86-64 + * (there's nothing to dispatch on aarch64). + */ +#ifndef UMASH_DYNAMIC_DISPATCH +#ifdef __x86_64__ +#define UMASH_DYNAMIC_DISPATCH 1 +#else +#define UMASH_DYNAMIC_DISPATCH 0 +#endif +#endif + +/* + * Enable inline assembly by default when building with recent GCC or + * compatible compilers. It should always be safe to disable this + * option, although there may be a performance cost. + */ +#ifndef UMASH_INLINE_ASM + +#if defined(__clang__) +/* + * We need clang 8+ for output flags, and 10+ for relaxed vector + * constraints. + */ +#if __clang_major__ >= 10 +#define UMASH_INLINE_ASM 1 +#else +#define UMASH_INLINE_ASM 0 +#endif /* __clang_major__ */ + +#elif defined(__GNUC__) +#if __GNUC__ >= 6 +#define UMASH_INLINE_ASM 1 +#else +#define UMASH_INLINE_ASM 0 +#endif /* __GNUC__ */ + +#else +#define UMASH_INLINE_ASM 0 +#endif + +#endif + +#include +#include + +#ifdef __PCLMUL__ +/* If we have access to x86 PCLMUL (and some basic SSE). */ +#include + +/* We only use 128-bit vector, as pairs of 64-bit integers. */ +typedef __m128i v128; + +#define V128_ZERO { 0 }; + +static inline v128 +v128_create(uint64_t lo, uint64_t hi) +{ + return _mm_set_epi64x(hi, lo); +} + +/* Shift each 64-bit lane left by one bit. */ +static inline v128 +v128_shift(v128 x) +{ + return _mm_add_epi64(x, x); +} + +/* Computes the 128-bit carryless product of x and y. */ +static inline v128 +v128_clmul(uint64_t x, uint64_t y) +{ + return _mm_clmulepi64_si128(_mm_cvtsi64_si128(x), _mm_cvtsi64_si128(y), 0); +} + +/* Computes the 128-bit carryless product of the high and low halves of x. */ +static inline v128 +v128_clmul_cross(v128 x) +{ + return _mm_clmulepi64_si128(x, x, 1); +} + +#elif defined(__ARM_FEATURE_CRYPTO) + +#include + +typedef uint64x2_t v128; + +#define V128_ZERO { 0 }; + +static inline v128 +v128_create(uint64_t lo, uint64_t hi) +{ + return vcombine_u64(vcreate_u64(lo), vcreate_u64(hi)); +} + +static inline v128 +v128_shift(v128 x) +{ + return vshlq_n_u64(x, 1); +} + +static inline v128 +v128_clmul(uint64_t x, uint64_t y) +{ + return vreinterpretq_u64_p128(vmull_p64(x, y)); +} + +static inline v128 +v128_clmul_cross(v128 x) +{ + v128 swapped = vextq_u64(x, x, 1); +#if UMASH_INLINE_ASM + /* Keep the result out of GPRs. */ + __asm__("" : "+w"(swapped)); +#endif + + return v128_clmul(vgetq_lane_u64(x, 0), vgetq_lane_u64(swapped, 0)); +} + +#else + +#error \ + "Unsupported platform: umash requires CLMUL (-mpclmul) on x86-64, or crypto (-march=...+crypto) extensions on aarch64." +#endif + +/* + * #define UMASH_STAP_PROBE=1 to insert probe points in public UMASH + * functions. + * + * This functionality depends on Systemtap's SDT header file. + */ +#if defined(UMASH_STAP_PROBE) && UMASH_STAP_PROBE +#include +#else +#define DTRACE_PROBE1(lib, name, a0) +#define DTRACE_PROBE2(lib, name, a0, a1) +#define DTRACE_PROBE3(lib, name, a0, a1, a2) +#define DTRACE_PROBE4(lib, name, a0, a1, a2, a3) +#endif + +/* + * #define UMASH_SECTION="special_section" to emit all UMASH symbols + * in the `special_section` ELF section. + */ +#if defined(UMASH_SECTION) && defined(__GNUC__) +#define FN __attribute__((__section__(UMASH_SECTION))) +#else +#define FN +#endif + +/* + * Defining UMASH_TEST_ONLY switches to a debug build with internal + * symbols exposed. + */ +#ifdef UMASH_TEST_ONLY +#define TEST_DEF FN +#include "t/umash_test_only.h" +#else +#define TEST_DEF static FN +#endif + +#ifdef __GNUC__ +#define LIKELY(X) __builtin_expect(!!(X), 1) +#define UNLIKELY(X) __builtin_expect(!!(X), 0) +#define HOT __attribute__((__hot__)) +#define COLD __attribute__((__cold__)) +#else +#define LIKELY(X) X +#define UNLIKELY(X) X +#define HOT +#define COLD +#endif + +#define ARRAY_SIZE(ARR) (sizeof(ARR) / sizeof(ARR[0])) + +#define BLOCK_SIZE (sizeof(uint64_t) * UMASH_OH_PARAM_COUNT) + +/* + * We derive independent short hashes by offsetting the constant array + * by four u64s. In theory, any positive even number works, but this + * is the constant we used in an earlier incarnation, and it works. + */ +#define OH_SHORT_HASH_SHIFT 4 + +/* Incremental UMASH consumes 16 bytes at a time. */ +#define INCREMENTAL_GRANULARITY 16 + +/** + * Modular arithmetic utilities. + * + * The code below uses GCC extensions. It should be possible to add + * support for other compilers. + */ + +#if !defined(__x86_64__) || !UMASH_INLINE_ASM +static inline void +mul128(uint64_t x, uint64_t y, uint64_t *hi, uint64_t *lo) +{ + __uint128_t product = x; + + product *= y; + *hi = product >> 64; + *lo = product; + return; +} +#else +static inline void +mul128(uint64_t x, uint64_t y, uint64_t *hi, uint64_t *lo) +{ + uint64_t mulhi, mullo; + + __asm__("mul %3" : "=a"(mullo), "=d"(mulhi) : "%a"(x), "r"(y) : "cc"); + *hi = mulhi; + *lo = mullo; + return; +} +#endif + +TEST_DEF inline uint64_t +add_mod_fast(uint64_t x, uint64_t y) +{ + unsigned long long sum; + + /* If `sum` overflows, `sum + 8` does not. */ + return (__builtin_uaddll_overflow(x, y, &sum) ? sum + 8 : sum); +} + +static FN COLD uint64_t +add_mod_slow_slow_path(uint64_t sum, uint64_t fixup) +{ + /* Reduce sum, mod 2**64 - 8. */ + sum = (sum >= (uint64_t)-8) ? sum + 8 : sum; + /* sum < 2**64 - 8, so this doesn't overflow. */ + sum += fixup; + /* Reduce again. */ + sum = (sum >= (uint64_t)-8) ? sum + 8 : sum; + return sum; +} + +TEST_DEF inline uint64_t +add_mod_slow(uint64_t x, uint64_t y) +{ + unsigned long long sum; + uint64_t fixup = 0; + + /* x + y \equiv sum + fixup */ + if (__builtin_uaddll_overflow(x, y, &sum)) + fixup = 8; + + /* + * We must ensure `sum + fixup < 2**64 - 8`. + * + * We want a conditional branch here, but not in the + * overflowing add: overflows happen roughly half the time on + * pseudorandom inputs, but `sum < 2**64 - 16` is almost + * always true, for pseudorandom `sum`. + */ + if (LIKELY(sum < (uint64_t)-16)) + return sum + fixup; + +#ifdef UMASH_INLINE_ASM + /* + * Some compilers like to compile the likely branch above with + * conditional moves or predication. Insert a compiler barrier + * in the slow path here to force a branch. + */ + __asm__("" : "+r"(sum)); +#endif + return add_mod_slow_slow_path(sum, fixup); +} + +TEST_DEF inline uint64_t +mul_mod_fast(uint64_t m, uint64_t x) +{ + uint64_t hi, lo; + + mul128(m, x, &hi, &lo); + return add_mod_fast(lo, 8 * hi); +} + +TEST_DEF inline uint64_t +horner_double_update(uint64_t acc, uint64_t m0, uint64_t m1, uint64_t x, uint64_t y) +{ + + acc = add_mod_fast(acc, x); + return add_mod_slow(mul_mod_fast(m0, acc), mul_mod_fast(m1, y)); +} + +/** + * Salsa20 stream generator, used to derive struct umash_param. + * + * Slightly prettified version of D. J. Bernstein's public domain NaCL + * (version 20110121), without paying any attention to constant time + * execution or any other side-channel. + */ +static inline uint32_t +rotate(uint32_t u, int c) +{ + + return (u << c) | (u >> (32 - c)); +} + +static inline uint32_t +load_littleendian(const void *buf) +{ + uint32_t ret = 0; + uint8_t x[4]; + + memcpy(x, buf, sizeof(x)); + for (size_t i = 0; i < 4; i++) + ret |= (uint32_t)x[i] << (8 * i); + + return ret; +} + +static inline void +store_littleendian(void *dst, uint32_t u) +{ + + for (size_t i = 0; i < 4; i++) { + uint8_t lo = u; + + memcpy(dst, &lo, 1); + u >>= 8; + dst = (char *)dst + 1; + } + + return; +} + +static FN void +core_salsa20(char *out, const uint8_t in[static 16], const uint8_t key[static 32], + const uint8_t constant[16]) +{ + enum { ROUNDS = 20 }; + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + + j0 = x0 = load_littleendian(constant + 0); + j1 = x1 = load_littleendian(key + 0); + j2 = x2 = load_littleendian(key + 4); + j3 = x3 = load_littleendian(key + 8); + j4 = x4 = load_littleendian(key + 12); + j5 = x5 = load_littleendian(constant + 4); + j6 = x6 = load_littleendian(in + 0); + j7 = x7 = load_littleendian(in + 4); + j8 = x8 = load_littleendian(in + 8); + j9 = x9 = load_littleendian(in + 12); + j10 = x10 = load_littleendian(constant + 8); + j11 = x11 = load_littleendian(key + 16); + j12 = x12 = load_littleendian(key + 20); + j13 = x13 = load_littleendian(key + 24); + j14 = x14 = load_littleendian(key + 28); + j15 = x15 = load_littleendian(constant + 12); + + for (size_t i = 0; i < ROUNDS; i += 2) { + x4 ^= rotate(x0 + x12, 7); + x8 ^= rotate(x4 + x0, 9); + x12 ^= rotate(x8 + x4, 13); + x0 ^= rotate(x12 + x8, 18); + x9 ^= rotate(x5 + x1, 7); + x13 ^= rotate(x9 + x5, 9); + x1 ^= rotate(x13 + x9, 13); + x5 ^= rotate(x1 + x13, 18); + x14 ^= rotate(x10 + x6, 7); + x2 ^= rotate(x14 + x10, 9); + x6 ^= rotate(x2 + x14, 13); + x10 ^= rotate(x6 + x2, 18); + x3 ^= rotate(x15 + x11, 7); + x7 ^= rotate(x3 + x15, 9); + x11 ^= rotate(x7 + x3, 13); + x15 ^= rotate(x11 + x7, 18); + x1 ^= rotate(x0 + x3, 7); + x2 ^= rotate(x1 + x0, 9); + x3 ^= rotate(x2 + x1, 13); + x0 ^= rotate(x3 + x2, 18); + x6 ^= rotate(x5 + x4, 7); + x7 ^= rotate(x6 + x5, 9); + x4 ^= rotate(x7 + x6, 13); + x5 ^= rotate(x4 + x7, 18); + x11 ^= rotate(x10 + x9, 7); + x8 ^= rotate(x11 + x10, 9); + x9 ^= rotate(x8 + x11, 13); + x10 ^= rotate(x9 + x8, 18); + x12 ^= rotate(x15 + x14, 7); + x13 ^= rotate(x12 + x15, 9); + x14 ^= rotate(x13 + x12, 13); + x15 ^= rotate(x14 + x13, 18); + } + + x0 += j0; + x1 += j1; + x2 += j2; + x3 += j3; + x4 += j4; + x5 += j5; + x6 += j6; + x7 += j7; + x8 += j8; + x9 += j9; + x10 += j10; + x11 += j11; + x12 += j12; + x13 += j13; + x14 += j14; + x15 += j15; + + store_littleendian(out + 0, x0); + store_littleendian(out + 4, x1); + store_littleendian(out + 8, x2); + store_littleendian(out + 12, x3); + store_littleendian(out + 16, x4); + store_littleendian(out + 20, x5); + store_littleendian(out + 24, x6); + store_littleendian(out + 28, x7); + store_littleendian(out + 32, x8); + store_littleendian(out + 36, x9); + store_littleendian(out + 40, x10); + store_littleendian(out + 44, x11); + store_littleendian(out + 48, x12); + store_littleendian(out + 52, x13); + store_littleendian(out + 56, x14); + store_littleendian(out + 60, x15); + return; +} + +TEST_DEF void +salsa20_stream( + void *dst, size_t len, const uint8_t nonce[static 8], const uint8_t key[static 32]) +{ + static const uint8_t sigma[16] = "expand 32-byte k"; + uint8_t in[16]; + + if (len == 0) + return; + + memcpy(in, nonce, 8); + memset(in + 8, 0, 8); + + while (len >= 64) { + unsigned int u; + + core_salsa20(dst, in, key, sigma); + u = 1; + for (size_t i = 8; i < 16; i++) { + u += in[i]; + in[i] = u; + u >>= 8; + } + + dst = (char *)dst + 64; + len -= 64; + } + + if (len > 0) { + char block[64]; + + core_salsa20(block, in, key, sigma); + memcpy(dst, block, len); + } + + return; +} + +#if defined(UMASH_TEST_ONLY) || UMASH_LONG_INPUTS +#include "umash_long.inc" +#endif + +/** + * OH block compression. + */ +TEST_DEF struct umash_oh +oh_varblock(const uint64_t *params, uint64_t tag, const void *block, size_t n_bytes) +{ + struct umash_oh ret; + v128 acc = V128_ZERO; + + /* The final block processes `remaining > 0` bytes. */ + size_t remaining = 1 + ((n_bytes - 1) % sizeof(v128)); + size_t end_full_pairs = (n_bytes - remaining) / sizeof(uint64_t); + const void *last_ptr = (const char *)block + n_bytes - sizeof(v128); + size_t i; + + for (i = 0; i < end_full_pairs; i += 2) { + v128 x, k; + + memcpy(&x, block, sizeof(x)); + block = (const char *)block + sizeof(x); + + memcpy(&k, ¶ms[i], sizeof(k)); + x ^= k; + acc ^= v128_clmul_cross(x); + } + + memcpy(&ret, &acc, sizeof(ret)); + + /* Compress the final (potentially partial) pair. */ + { + uint64_t x, y, enh_hi, enh_lo; + + memcpy(&x, last_ptr, sizeof(x)); + last_ptr = (const char *)last_ptr + sizeof(x); + memcpy(&y, last_ptr, sizeof(y)); + + x += params[i]; + y += params[i + 1]; + mul128(x, y, &enh_hi, &enh_lo); + enh_hi += tag; + + ret.bits[0] ^= enh_lo; + ret.bits[1] ^= enh_hi ^ enh_lo; + } + + return ret; +} + +TEST_DEF void +oh_varblock_fprint(struct umash_oh dst[static restrict 2], + const uint64_t *restrict params, uint64_t tag, const void *restrict block, + size_t n_bytes) +{ + v128 acc = V128_ZERO; /* Base umash */ + v128 acc_shifted = V128_ZERO; /* Accumulates shifted values */ + v128 lrc; + /* The final block processes `remaining > 0` bytes. */ + size_t remaining = 1 + ((n_bytes - 1) % sizeof(v128)); + size_t end_full_pairs = (n_bytes - remaining) / sizeof(uint64_t); + const void *last_ptr = (const char *)block + n_bytes - sizeof(v128); + size_t i; + + lrc = v128_create(params[UMASH_OH_PARAM_COUNT], params[UMASH_OH_PARAM_COUNT + 1]); + for (i = 0; i < end_full_pairs; i += 2) { + v128 x, k; + + memcpy(&x, block, sizeof(x)); + block = (const char *)block + sizeof(x); + + memcpy(&k, ¶ms[i], sizeof(k)); + + x ^= k; + lrc ^= x; + + x = v128_clmul_cross(x); + + acc ^= x; + if (i + 2 >= end_full_pairs) + break; + + acc_shifted ^= x; + acc_shifted = v128_shift(acc_shifted); + } + + /* + * Update the LRC for the last chunk before treating it + * specially. + */ + { + v128 x, k; + + memcpy(&x, last_ptr, sizeof(x)); + memcpy(&k, ¶ms[end_full_pairs], sizeof(k)); + + lrc ^= x ^ k; + } + + acc_shifted ^= acc; + acc_shifted = v128_shift(acc_shifted); + + acc_shifted ^= v128_clmul_cross(lrc); + + memcpy(&dst[0], &acc, sizeof(dst[0])); + memcpy(&dst[1], &acc_shifted, sizeof(dst[1])); + + { + uint64_t x, y, kx, ky, enh_hi, enh_lo; + + memcpy(&x, last_ptr, sizeof(x)); + last_ptr = (const char *)last_ptr + sizeof(x); + memcpy(&y, last_ptr, sizeof(y)); + + kx = x + params[end_full_pairs]; + ky = y + params[end_full_pairs + 1]; + + mul128(kx, ky, &enh_hi, &enh_lo); + enh_hi += tag; + + enh_hi ^= enh_lo; + dst[0].bits[0] ^= enh_lo; + dst[0].bits[1] ^= enh_hi; + + dst[1].bits[0] ^= enh_lo; + dst[1].bits[1] ^= enh_hi; + } + + return; +} + +/** + * Returns `then` if `cond` is true, `otherwise` if false. + * + * This noise helps compiler emit conditional moves. + */ +static inline const void * +select_ptr(bool cond, const void *then, const void *otherwise) +{ + const char *ret; + +#if UMASH_INLINE_ASM + /* Force strict evaluation of both arguments. */ + __asm__("" ::"r"(then), "r"(otherwise)); +#endif + + ret = (cond) ? then : otherwise; + +#if UMASH_INLINE_ASM + /* And also force the result to be materialised with a blackhole. */ + __asm__("" : "+r"(ret)); +#endif + return ret; +} + +/** + * Short UMASH (<= 8 bytes). + */ +TEST_DEF inline uint64_t +vec_to_u64(const void *data, size_t n_bytes) +{ + const char zeros[2] = { 0 }; + uint32_t hi, lo; + + /* + * If there are at least 4 bytes to read, read the first 4 in + * `lo`, and the last 4 in `hi`. This covers the whole range, + * since `n_bytes` is at most 8. + */ + if (LIKELY(n_bytes >= sizeof(lo))) { + memcpy(&lo, data, sizeof(lo)); + memcpy(&hi, (const char *)data + n_bytes - sizeof(hi), sizeof(hi)); + } else { + /* 0 <= n_bytes < 4. Decode the size in binary. */ + uint16_t word; + uint8_t byte; + + /* + * If the size is odd, load the first byte in `byte`; + * otherwise, load in a zero. + */ + memcpy(&byte, select_ptr(n_bytes & 1, data, zeros), 1); + lo = byte; + + /* + * If the size is 2 or 3, load the last two bytes in `word`; + * otherwise, load in a zero. + */ + memcpy(&word, + select_ptr(n_bytes & 2, (const char *)data + n_bytes - 2, zeros), 2); + /* + * We have now read `bytes[0 ... n_bytes - 1]` + * exactly once without overwriting any data. + */ + hi = word; + } + + /* + * Mix `hi` with the `lo` bits: SplitMix64 seems to have + * trouble with the top 4 bits. + */ + return ((uint64_t)hi << 32) | (lo + hi); +} + +TEST_DEF uint64_t +umash_short(const uint64_t *params, uint64_t seed, const void *data, size_t n_bytes) +{ + uint64_t h; + + seed += params[n_bytes]; + h = vec_to_u64(data, n_bytes); + h ^= h >> 30; + h *= 0xbf58476d1ce4e5b9ULL; + h = (h ^ seed) ^ (h >> 27); + h *= 0x94d049bb133111ebULL; + h ^= h >> 31; + return h; +} + +static FN struct umash_fp +umash_fp_short(const uint64_t *params, uint64_t seed, const void *data, size_t n_bytes) +{ + struct umash_fp ret; + uint64_t h; + + ret.hash[0] = seed + params[n_bytes]; + ret.hash[1] = seed + params[n_bytes + OH_SHORT_HASH_SHIFT]; + + h = vec_to_u64(data, n_bytes); + h ^= h >> 30; + h *= 0xbf58476d1ce4e5b9ULL; + h ^= h >> 27; + +#define TAIL(i) \ + do { \ + ret.hash[i] ^= h; \ + ret.hash[i] *= 0x94d049bb133111ebULL; \ + ret.hash[i] ^= ret.hash[i] >> 31; \ + } while (0) + + TAIL(0); + TAIL(1); +#undef TAIL + + return ret; +} + +/** + * Rotates `x` left by `n` bits. + */ +static inline uint64_t +rotl64(uint64_t x, int n) +{ + + return (x << n) | (x >> (64 - n)); +} + +TEST_DEF inline uint64_t +finalize(uint64_t x) +{ + + return (x ^ rotl64(x, 8)) ^ rotl64(x, 33); +} + +TEST_DEF uint64_t +umash_medium(const uint64_t multipliers[static 2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + uint64_t enh_hi, enh_lo; + + { + uint64_t x, y; + + memcpy(&x, data, sizeof(x)); + memcpy(&y, (const char *)data + n_bytes - sizeof(y), sizeof(y)); + x += oh[0]; + y += oh[1]; + + mul128(x, y, &enh_hi, &enh_lo); + enh_hi += seed ^ n_bytes; + } + + enh_hi ^= enh_lo; + return finalize(horner_double_update( + /*acc=*/0, multipliers[0], multipliers[1], enh_lo, enh_hi)); +} + +static FN struct umash_fp +umash_fp_medium(const uint64_t multipliers[static 2][2], const uint64_t *oh, + uint64_t seed, const void *data, size_t n_bytes) +{ + struct umash_fp ret; + const uint64_t offset = seed ^ n_bytes; + uint64_t enh_hi, enh_lo; + union { + v128 v; + uint64_t u64[2]; + } mixed_lrc; + uint64_t lrc[2] = { oh[UMASH_OH_PARAM_COUNT], oh[UMASH_OH_PARAM_COUNT + 1] }; + uint64_t x, y; + uint64_t a, b; + + /* Expand the 9-16 bytes to 16. */ + memcpy(&x, data, sizeof(x)); + memcpy(&y, (const char *)data + n_bytes - sizeof(y), sizeof(y)); + + a = oh[0]; + b = oh[1]; + + lrc[0] ^= x ^ a; + lrc[1] ^= y ^ b; + mixed_lrc.v = v128_clmul(lrc[0], lrc[1]); + + a += x; + b += y; + + mul128(a, b, &enh_hi, &enh_lo); + enh_hi += offset; + enh_hi ^= enh_lo; + + ret.hash[0] = finalize(horner_double_update( + /*acc=*/0, multipliers[0][0], multipliers[0][1], enh_lo, enh_hi)); + + ret.hash[1] = finalize(horner_double_update(/*acc=*/0, multipliers[1][0], + multipliers[1][1], enh_lo ^ mixed_lrc.u64[0], enh_hi ^ mixed_lrc.u64[1])); + + return ret; +} + +TEST_DEF uint64_t +umash_long(const uint64_t multipliers[static 2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + uint64_t acc = 0; + + /* + * umash_long.inc defines this variable when the long input + * routine is enabled. + */ +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes >= UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + size_t n_block = n_bytes / BLOCK_SIZE; + const void *remaining; + + n_bytes %= BLOCK_SIZE; + remaining = (const char *)data + (n_block * BLOCK_SIZE); + acc = umash_multiple_blocks(acc, multipliers, oh, seed, data, n_block); + + data = remaining; + if (n_bytes == 0) + goto finalize; + + goto last_block; + } +#else + /* Avoid warnings about the unused labels. */ + if (0) { + goto last_block; + goto finalize; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + struct umash_oh compressed; + + compressed = oh_varblock(oh, seed, data, BLOCK_SIZE); + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + + acc = horner_double_update(acc, multipliers[0], multipliers[1], + compressed.bits[0], compressed.bits[1]); + } + +last_block: + /* Do the final block. */ + { + struct umash_oh compressed; + + seed ^= (uint8_t)n_bytes; + compressed = oh_varblock(oh, seed, data, n_bytes); + acc = horner_double_update(acc, multipliers[0], multipliers[1], + compressed.bits[0], compressed.bits[1]); + } + +finalize: + return finalize(acc); +} + +TEST_DEF struct umash_fp +umash_fp_long(const uint64_t multipliers[static 2][2], const uint64_t *oh, uint64_t seed, + const void *data, size_t n_bytes) +{ + struct umash_oh compressed[2]; + struct umash_fp ret; + uint64_t acc[2] = { 0, 0 }; + +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes >= UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + struct umash_fp poly = { .hash = { 0, 0 } }; + size_t n_block = n_bytes / BLOCK_SIZE; + const void *remaining; + + n_bytes %= BLOCK_SIZE; + remaining = (const char *)data + (n_block * BLOCK_SIZE); + poly = umash_fprint_multiple_blocks( + poly, multipliers, oh, seed, data, n_block); + + acc[0] = poly.hash[0]; + acc[1] = poly.hash[1]; + + data = remaining; + if (n_bytes == 0) + goto finalize; + + goto last_block; + } +#else + /* Avoid warnings about the unused labels. */ + if (0) { + goto last_block; + goto finalize; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + oh_varblock_fprint(compressed, oh, seed, data, BLOCK_SIZE); + +#define UPDATE(i) \ + acc[i] = horner_double_update(acc[i], multipliers[i][0], multipliers[i][1], \ + compressed[i].bits[0], compressed[i].bits[1]) + + UPDATE(0); + UPDATE(1); +#undef UPDATE + + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + } + +last_block: + oh_varblock_fprint(compressed, oh, seed ^ (uint8_t)n_bytes, data, n_bytes); + +#define FINAL(i) \ + do { \ + acc[i] = horner_double_update(acc[i], multipliers[i][0], \ + multipliers[i][1], compressed[i].bits[0], compressed[i].bits[1]); \ + } while (0) + + FINAL(0); + FINAL(1); +#undef FINAL + +finalize: + ret.hash[0] = finalize(acc[0]); + ret.hash[1] = finalize(acc[1]); + return ret; +} + +static FN bool +value_is_repeated(const uint64_t *values, size_t n, uint64_t needle) +{ + + for (size_t i = 0; i < n; i++) { + if (values[i] == needle) + return true; + } + + return false; +} + +FN bool +umash_params_prepare(struct umash_params *params) +{ + static const uint64_t modulo = (1UL << 61) - 1; + /* + * The polynomial parameters have two redundant fields (for + * the pre-squared multipliers). Use them as our source of + * extra entropy if needed. + */ + uint64_t buf[] = { params->poly[0][0], params->poly[1][0] }; + size_t buf_idx = 0; + +#define GET_RANDOM(DST) \ + do { \ + if (buf_idx >= ARRAY_SIZE(buf)) \ + return false; \ + \ + (DST) = buf[buf_idx++]; \ + } while (0) + + /* Check the polynomial multipliers: we don't want 0s. */ + for (size_t i = 0; i < ARRAY_SIZE(params->poly); i++) { + uint64_t f = params->poly[i][1]; + + while (true) { + /* + * Zero out bits and use rejection sampling to + * guarantee uniformity. + */ + f &= (1UL << 61) - 1; + if (f != 0 && f < modulo) + break; + + GET_RANDOM(f); + } + + /* We can work in 2**64 - 8 and reduce after the fact. */ + params->poly[i][0] = mul_mod_fast(f, f) % modulo; + params->poly[i][1] = f; + } + + /* Avoid repeated OH noise values. */ + for (size_t i = 0; i < ARRAY_SIZE(params->oh); i++) { + while (value_is_repeated(params->oh, i, params->oh[i])) + GET_RANDOM(params->oh[i]); + } + + return true; +} + +FN void +umash_params_derive(struct umash_params *params, uint64_t bits, const void *key) +{ + uint8_t umash_key[32] = "Do not use UMASH VS adversaries."; + + if (key != NULL) + memcpy(umash_key, key, sizeof(umash_key)); + + while (true) { + uint8_t nonce[8]; + + for (size_t i = 0; i < 8; i++) + nonce[i] = bits >> (8 * i); + + salsa20_stream(params, sizeof(*params), nonce, umash_key); + if (umash_params_prepare(params)) + return; + + /* + * This should practically never fail, so really + * shouldn't happen multiple times. If it does, an + * infinite loop is as good as anything else. + */ + bits++; + } +} + +/* + * Updates the polynomial state at the end of a block. + */ +static FN void +sink_update_poly(struct umash_sink *sink) +{ + uint64_t oh0, oh1; + + oh0 = sink->oh_acc.bits[0]; + oh1 = sink->oh_acc.bits[1]; + sink->poly_state[0].acc = horner_double_update(sink->poly_state[0].acc, + sink->poly_state[0].mul[0], sink->poly_state[0].mul[1], oh0, oh1); + + sink->oh_acc = (struct umash_oh) { .bits = { 0 } }; + if (sink->hash_wanted == 0) + return; + + oh0 = sink->oh_twisted.acc.bits[0]; + oh1 = sink->oh_twisted.acc.bits[1]; + sink->poly_state[1].acc = horner_double_update(sink->poly_state[1].acc, + sink->poly_state[1].mul[0], sink->poly_state[1].mul[1], oh0, oh1); + + sink->oh_twisted = + (struct umash_twisted_oh) { .lrc = { sink->oh[UMASH_OH_PARAM_COUNT], + sink->oh[UMASH_OH_PARAM_COUNT + 1] } }; + return; +} + +/* + * Updates the OH state with 16 bytes of data. If `final` is true, we + * are definitely consuming the last chunk in the input. + */ +static FN void +sink_consume_buf( + struct umash_sink *sink, const char buf[static INCREMENTAL_GRANULARITY], bool final) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + const size_t param = sink->oh_iter; + const uint64_t k0 = sink->oh[param]; + const uint64_t k1 = sink->oh[param + 1]; + uint64_t x, y; + + /* Use GPR loads to avoid forwarding stalls. */ + memcpy(&x, buf, sizeof(x)); + memcpy(&y, buf + sizeof(x), sizeof(y)); + + /* All but the last 16-byte chunk of each block goes through PH. */ + if (sink->oh_iter < UMASH_OH_PARAM_COUNT - 2 && !final) { + v128 acc, h, twisted_acc, prev; + uint64_t m0, m1; + + m0 = x ^ k0; + m1 = y ^ k1; + + memcpy(&acc, &sink->oh_acc, sizeof(acc)); + h = v128_clmul(m0, m1); + acc ^= h; + memcpy(&sink->oh_acc, &acc, sizeof(acc)); + + if (sink->hash_wanted == 0) + goto next; + + sink->oh_twisted.lrc[0] ^= m0; + sink->oh_twisted.lrc[1] ^= m1; + + memcpy(&twisted_acc, &sink->oh_twisted.acc, sizeof(twisted_acc)); + memcpy(&prev, sink->oh_twisted.prev, sizeof(prev)); + + twisted_acc ^= prev; + twisted_acc = v128_shift(twisted_acc); + memcpy(&sink->oh_twisted.acc, &twisted_acc, sizeof(twisted_acc)); + memcpy(&sink->oh_twisted.prev, &h, sizeof(h)); + } else { + /* The last chunk is combined with the size tag with ENH. */ + uint64_t tag = sink->seed ^ (uint8_t)(sink->block_size + sink->bufsz); + uint64_t enh_hi, enh_lo; + + mul128(x + k0, y + k1, &enh_hi, &enh_lo); + enh_hi += tag; + enh_hi ^= enh_lo; + + if (sink->hash_wanted != 0) { + union { + v128 vec; + uint64_t h[2]; + } lrc_hash; + uint64_t lrc0, lrc1; + uint64_t oh0, oh1; + uint64_t oh_twisted0, oh_twisted1; + + lrc0 = sink->oh_twisted.lrc[0] ^ x ^ k0; + lrc1 = sink->oh_twisted.lrc[1] ^ y ^ k1; + lrc_hash.vec = v128_clmul(lrc0, lrc1); + + oh_twisted0 = sink->oh_twisted.acc.bits[0]; + oh_twisted1 = sink->oh_twisted.acc.bits[1]; + + oh0 = sink->oh_acc.bits[0]; + oh1 = sink->oh_acc.bits[1]; + oh0 ^= oh_twisted0; + oh0 <<= 1; + oh1 ^= oh_twisted1; + oh1 <<= 1; + + oh0 ^= lrc_hash.h[0]; + oh1 ^= lrc_hash.h[1]; + sink->oh_twisted.acc.bits[0] = oh0 ^ enh_lo; + sink->oh_twisted.acc.bits[1] = oh1 ^ enh_hi; + } + + sink->oh_acc.bits[0] ^= enh_lo; + sink->oh_acc.bits[1] ^= enh_hi; + } + +next: + memmove(&sink->buf, buf, buf_begin); + sink->block_size += sink->bufsz; + sink->bufsz = 0; + sink->oh_iter += 2; + + if (sink->oh_iter == UMASH_OH_PARAM_COUNT || final) { + sink_update_poly(sink); + sink->block_size = 0; + sink->oh_iter = 0; + } + + return; +} + +/** + * Hashes full 256-byte blocks into a sink that just dumped its OH + * state in the toplevel polynomial hash and reset the block state. + */ +static FN size_t +block_sink_update(struct umash_sink *sink, const void *data, size_t n_bytes) +{ + size_t consumed = 0; + + assert(n_bytes >= BLOCK_SIZE); + assert(sink->bufsz == 0); + assert(sink->block_size == 0); + assert(sink->oh_iter == 0); + +#ifdef UMASH_MULTIPLE_BLOCKS_THRESHOLD + if (UNLIKELY(n_bytes > UMASH_MULTIPLE_BLOCKS_THRESHOLD)) { + /* + * We leave the last block (partial or not) for the + * caller: incremental hashing must save some state + * at the end of a block. + */ + size_t n_blocks = (n_bytes - 1) / BLOCK_SIZE; + + if (sink->hash_wanted != 0) { + const uint64_t multipliers[2][2] = { + [0][0] = sink->poly_state[0].mul[0], + [0][1] = sink->poly_state[0].mul[1], + [1][0] = sink->poly_state[1].mul[0], + [1][1] = sink->poly_state[1].mul[1], + }; + struct umash_fp poly = { + .hash[0] = sink->poly_state[0].acc, + .hash[1] = sink->poly_state[1].acc, + }; + + poly = umash_fprint_multiple_blocks( + poly, multipliers, sink->oh, sink->seed, data, n_blocks); + + sink->poly_state[0].acc = poly.hash[0]; + sink->poly_state[1].acc = poly.hash[1]; + } else { + sink->poly_state[0].acc = umash_multiple_blocks( + sink->poly_state[0].acc, sink->poly_state[0].mul, sink->oh, + sink->seed, data, n_blocks); + } + + return n_blocks * BLOCK_SIZE; + } +#endif + + while (n_bytes > BLOCK_SIZE) { + /* + * Is this worth unswitching? Not obviously, given + * the amount of work in one OH block. + */ + if (sink->hash_wanted != 0) { + struct umash_oh hashes[2]; + + oh_varblock_fprint( + hashes, sink->oh, sink->seed, data, BLOCK_SIZE); + sink->oh_acc = hashes[0]; + sink->oh_twisted.acc = hashes[1]; + } else { + sink->oh_acc = + oh_varblock(sink->oh, sink->seed, data, BLOCK_SIZE); + } + + sink_update_poly(sink); + consumed += BLOCK_SIZE; + data = (const char *)data + BLOCK_SIZE; + n_bytes -= BLOCK_SIZE; + } + + return consumed; +} + +FN void +umash_sink_update(struct umash_sink *sink, const void *data, size_t n_bytes) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + size_t remaining = INCREMENTAL_GRANULARITY - sink->bufsz; + + DTRACE_PROBE4(libumash, umash_sink_update, sink, remaining, data, n_bytes); + + if (n_bytes < remaining) { + memcpy(&sink->buf[buf_begin + sink->bufsz], data, n_bytes); + sink->bufsz += n_bytes; + return; + } + + memcpy(&sink->buf[buf_begin + sink->bufsz], data, remaining); + data = (const char *)data + remaining; + n_bytes -= remaining; + /* We know we're hashing at least 16 bytes. */ + sink->large_umash = true; + sink->bufsz = INCREMENTAL_GRANULARITY; + + /* + * We can't compress a 16-byte buffer until we know whether + * data is coming: the last 16-byte chunk goes to `NH` instead + * of `PH`. We could try to detect when the buffer is the + * last chunk in a block and immediately go to `NH`, but it + * seems more robust to always let the stores settle before we + * read them, just in case the combination is bad for forwarding. + */ + if (n_bytes == 0) + return; + + sink_consume_buf(sink, sink->buf + buf_begin, /*final=*/false); + + while (n_bytes > INCREMENTAL_GRANULARITY) { + size_t consumed; + + if (sink->oh_iter == 0 && n_bytes > BLOCK_SIZE) { + consumed = block_sink_update(sink, data, n_bytes); + assert(consumed >= BLOCK_SIZE); + + /* + * Save the tail of the data we just consumed + * in `sink->buf[0 ... buf_begin - 1]`: the + * final digest may need those bytes for its + * redundant read. + */ + memcpy(sink->buf, + (const char *)data + (consumed - INCREMENTAL_GRANULARITY), + buf_begin); + } else { + consumed = INCREMENTAL_GRANULARITY; + sink->bufsz = INCREMENTAL_GRANULARITY; + sink_consume_buf(sink, data, /*final=*/false); + } + + n_bytes -= consumed; + data = (const char *)data + consumed; + } + + memcpy(&sink->buf[buf_begin], data, n_bytes); + sink->bufsz = n_bytes; + return; +} + +FN uint64_t +umash_full(const struct umash_params *params, uint64_t seed, int which, const void *data, + size_t n_bytes) +{ + + DTRACE_PROBE4(libumash, umash_full, params, which, data, n_bytes); + + /* + * We don't (yet) implement code that only evaluates the + * second hash. We don't currently use that logic, and it's + * about to become a bit more complex, so let's just go for a + * full fingerprint and take what we need. + * + * umash_full is also rarely used that way: usually we want + * either the main hash, or the full fingerprint. + */ + if (UNLIKELY(which != 0)) { + struct umash_fp fp; + + fp = umash_fprint(params, seed, data, n_bytes); + return fp.hash[1]; + } + + /* + * It's not that short inputs are necessarily more likely, but + * we want to make sure they fall through correctly to + * minimise latency. + */ + if (LIKELY(n_bytes <= sizeof(v128))) { + if (LIKELY(n_bytes <= sizeof(uint64_t))) + return umash_short(params->oh, seed, data, n_bytes); + + return umash_medium(params->poly[0], params->oh, seed, data, n_bytes); + } + + return umash_long(params->poly[0], params->oh, seed, data, n_bytes); +} + +FN struct umash_fp +umash_fprint( + const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes) +{ + + DTRACE_PROBE3(libumash, umash_fprint, params, data, n_bytes); + if (LIKELY(n_bytes <= sizeof(v128))) { + if (LIKELY(n_bytes <= sizeof(uint64_t))) + return umash_fp_short(params->oh, seed, data, n_bytes); + + return umash_fp_medium(params->poly, params->oh, seed, data, n_bytes); + } + + return umash_fp_long(params->poly, params->oh, seed, data, n_bytes); +} + +FN void +umash_init(struct umash_state *state, const struct umash_params *params, uint64_t seed, + int which) +{ + + which = (which == 0) ? 0 : 1; + DTRACE_PROBE3(libumash, umash_init, state, params, which); + + state->sink = (struct umash_sink) { + .poly_state[0] = { + .mul = { + params->poly[0][0], + params->poly[0][1], + }, + }, + .poly_state[1]= { + .mul = { + params->poly[1][0], + params->poly[1][1], + }, + }, + .oh = params->oh, + .hash_wanted = which, + .oh_twisted.lrc = { params->oh[UMASH_OH_PARAM_COUNT], + params->oh[UMASH_OH_PARAM_COUNT + 1] }, + .seed = seed, + }; + + return; +} + +FN void +umash_fp_init( + struct umash_fp_state *state, const struct umash_params *params, uint64_t seed) +{ + + DTRACE_PROBE2(libumash, umash_fp_init, state, params); + + state->sink = (struct umash_sink) { + .poly_state[0] = { + .mul = { + params->poly[0][0], + params->poly[0][1], + }, + }, + .poly_state[1]= { + .mul = { + params->poly[1][0], + params->poly[1][1], + }, + }, + .oh = params->oh, + .hash_wanted = 2, + .oh_twisted.lrc = { params->oh[UMASH_OH_PARAM_COUNT], + params->oh[UMASH_OH_PARAM_COUNT + 1] }, + .seed = seed, + }; + + return; +} + +/** + * Pumps any last block out of the incremental state. + */ +static FN void +digest_flush(struct umash_sink *sink) +{ + + if (sink->bufsz > 0) + sink_consume_buf(sink, &sink->buf[sink->bufsz], /*final=*/true); + return; +} + +/** + * Finalizes a digest out of `sink`'s current state. + * + * The `sink` must be `digest_flush`ed if it is a `large_umash`. + * + * @param index 0 to return the first (only, if hashing) value, 1 for the + * second independent value for fingerprinting. + */ +static FN uint64_t +digest(const struct umash_sink *sink, int index) +{ + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + const size_t shift = (index == 0) ? 0 : OH_SHORT_HASH_SHIFT; + + if (sink->large_umash) + return finalize(sink->poly_state[index].acc); + + if (sink->bufsz <= sizeof(uint64_t)) + return umash_short( + &sink->oh[shift], sink->seed, &sink->buf[buf_begin], sink->bufsz); + + return umash_medium(sink->poly_state[index].mul, sink->oh, sink->seed, + &sink->buf[buf_begin], sink->bufsz); +} + +static FN struct umash_fp +fp_digest_sink(const struct umash_sink *sink) +{ + struct umash_sink copy; + struct umash_fp ret; + const size_t buf_begin = sizeof(sink->buf) - INCREMENTAL_GRANULARITY; + + if (sink->large_umash) { + copy = *sink; + digest_flush(©); + sink = © + } else if (sink->bufsz <= sizeof(uint64_t)) { + return umash_fp_short( + sink->oh, sink->seed, &sink->buf[buf_begin], sink->bufsz); + } else { + const struct umash_params *params; + + /* + * Back out the params struct from our pointer to its + * `oh` member. + */ + params = (const void *)((const char *)sink->oh - + __builtin_offsetof(struct umash_params, oh)); + return umash_fp_medium(params->poly, sink->oh, sink->seed, + &sink->buf[buf_begin], sink->bufsz); + } + + for (size_t i = 0; i < ARRAY_SIZE(ret.hash); i++) + ret.hash[i] = digest(sink, i); + + return ret; +} + +FN uint64_t +umash_digest(const struct umash_state *state) +{ + struct umash_sink copy; + const struct umash_sink *sink = &state->sink; + + DTRACE_PROBE1(libumash, umash_digest, state); + + if (sink->hash_wanted == 1) { + struct umash_fp fp; + + fp = fp_digest_sink(sink); + return fp.hash[1]; + } + + if (sink->large_umash) { + copy = *sink; + digest_flush(©); + sink = © + } + + return digest(sink, 0); +} + +FN struct umash_fp +umash_fp_digest(const struct umash_fp_state *state) +{ + + DTRACE_PROBE1(libumash, umash_fp_digest, state); + return fp_digest_sink(&state->sink); +} diff --git a/tsl/src/import/umash.h b/tsl/src/import/umash.h new file mode 100644 index 00000000000..f85bd54a49c --- /dev/null +++ b/tsl/src/import/umash.h @@ -0,0 +1,324 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * This file contains source code that was copied and/or modified from + * the UMASH hash implementation at https://github.com/backtrace-labs/umash, + * which is licensed under the MIT License: + * + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * Copyright 2022 Dougall Johnson + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * This is a copy of umash.h, git commit sha + * fc4c5b6ca1f06c308e96c43aa080bd766238e092. + */ + +#ifndef UMASH_H +#define UMASH_H +#include +#include +#include + +/** + * # UMASH: a non-cryptographic hash function with collision bounds + * + * SPDX-License-Identifier: MIT + * Copyright 2020-2022 Backtrace I/O, Inc. + * Copyright 2022 Paul Khuong + * + * UMASH is a fast (9-22 ns latency for inputs of 1-64 bytes and 22 + * GB/s peak throughput, on a 2.5 GHz Intel 8175M) 64-bit hash + * function with mathematically proven collision bounds: it is + * [ceil(s / 4096) * 2^{-55}]-almost-universal for inputs of s or + * fewer bytes. + * + * When that's not enough, UMASH can also generate a pair of 64-bit + * hashes in a single traversal. The resulting fingerprint reduces + * the collision probability to less than [ceil(s / 2^{26})^2 * 2^{-83}]; + * the probability that two distinct inputs receive the same + * fingerprint is less 2^{-83} for inputs up to 64 MB, and less than + * 2^{-70} as long as the inputs are shorter than 5 GB each. This + * expectation is taken over the randomly generated `umash_params`. + * If an attacker can infer the contents of these parameters, the + * bounds do not apply. + * + * ## Initialisation + * + * In order to use `UMASH`, one must first generate a `struct + * umash_params`; each such param defines a distinct `UMASH` function + * (a pair of such functions, in fact). Ideally, one would fill + * a struct with random bytes and call`umash_params_prepare`. + * + * - `umash_params_prepare`: attempts to convert the contents of + * randomly filled `struct umash_params` into a valid UMASH + * parameter struct (key). When the input consists of uniformly + * generated random bytes, the probability of failure is + * astronomically small. + * + * - `umash_params_derive`: deterministically constructs a `struct + * umash_params` from a 64-bit seed and an optional 32-byte secret. + * The seed and secret are expanded into random bytes with Salsa20; + * the resulting `umash_params` should be practically random, as + * long the seed or secret are unknown. + * + * ## Batch hashing and fingerprinting + * + * Once we have a `struct umash_params`, we can use `umash_full` or + * `umash_fprint` like regular hash functions. + * + * - `umash_full` can compute either of the two UMASH functions + * described by a `struct umash_params`. Its `seed` argument will + * change the output, but is not associated with any collision + * bound. + * + * - `umash_fprint` computes both `UMASH` functions described by a + * `struct umash_params`. `umash_fp::hash[0]` corresponds to + * calling `umash_full` with the same arguments and `which = 0`; + * `umash_fp::hash[1]` corresponds to `which = 1`. + * + * ## Incremental hashing and fingerprinting + * + * We can also compute UMASH values by feeding bytes incrementally. + * The result is guaranteed to the same as if we had buffered all the + * bytes and called `umash_full` or `umash_fprint`. + * + * - `umash_init` initialises a `struct umash_state` with the same + * parameters one would pass to `umash_full`. + * + * - `umash_digest` computes the value `umash_full` would return + * were it passed the arguments that were given to `umash_init`, + * and the bytes "fed" into the `umash_state`. + * + * - `umash_fp_init` initialises a `struct umash_fp_state` with the + * same parameters one would pass to `umash_fprint`. + * + * - `umash_fp_digest` computes the value `umash_fprint` would return + * for the bytes "fed" into the `umash_fp_state`. + * + * In both cases, one passes a pointer to `struct umash_state::sink` + * or `struct umash_fp_state::sink` to callees that wish to feed bytes + * into the `umash_state` or `umash_fp_state`. + * + * - `umash_sink_update` feeds a byte range to the `umash_sink` + * initialised by calling `umash_init` or `umash_fp_init`. The sink + * does not take ownership of anything and the input bytes may be + * overwritten or freed as soon as `umash_sink_update` returns. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { UMASH_OH_PARAM_COUNT = 32, UMASH_OH_TWISTING_COUNT = 2 }; + +/** + * A single UMASH params struct stores the parameters for a pair of + * independent `UMASH` functions. + */ +struct umash_params { + /* + * Each uint64_t[2] array consists of {f^2, f}, where f is a + * random multiplier in mod 2**61 - 1. + */ + uint64_t poly[2][2]; + /* + * The second (twisted) OH function uses an additional + * 128-bit constant stored in the last two elements. + */ + uint64_t oh[UMASH_OH_PARAM_COUNT + UMASH_OH_TWISTING_COUNT]; +}; + +/** + * A fingerprint consists of two independent `UMASH` hash values. + */ +struct umash_fp { + uint64_t hash[2]; +}; + +/** + * This struct holds the state for incremental UMASH hashing or + * fingerprinting. + * + * A sink owns no allocation, and simply borrows a pointer to its + * `umash_params`. It can be byte-copied to snapshot its state. + * + * The layout works best with alignment to 64 bytes, but does not + * require it. + */ +struct umash_sink { + /* + * We incrementally maintain two states when fingerprinting. + * When hashing, only the first `poly_state` and `oh_acc` + * entries are active. + */ + struct { + uint64_t mul[2]; /* Multiplier, and multiplier^2. */ + uint64_t acc; /* Current Horner accumulator. */ + } poly_state[2]; + + /* + * We write new bytes to the second half, and keep the previous + * 16 byte chunk in the first half. + * + * We may temporarily have a full 16-byte buffer in the second half: + * we must know if the first 16 byte chunk is the first of many, or + * the whole input. + */ + char buf[2 * 16]; + + /* The next 64 bytes are accessed in the `OH` inner loop. */ + + /* key->oh. */ + const uint64_t *oh; + + /* oh_iter tracks where we are in the inner loop, times 2. */ + uint32_t oh_iter; + uint8_t bufsz; /* Write pointer in `buf + 16`. */ + uint8_t block_size; /* Current OH block size, excluding `bufsz`. */ + bool large_umash; /* True once we definitely have >= 16 bytes. */ + /* + * 0 if we're computing the first umash, 1 for the second, and + * 2 for a fingerprint. + * + * In practice, we treat 1 and 2 the same (always compute a + * full fingerprint), and return only the second half if we + * only want that half. + */ + uint8_t hash_wanted; + + /* Accumulators for the current OH value. */ + struct umash_oh { + uint64_t bits[2]; + } oh_acc; + struct umash_twisted_oh { + uint64_t lrc[2]; + uint64_t prev[2]; + struct umash_oh acc; + } oh_twisted; + + uint64_t seed; +}; + +/** + * The `umash_state` struct wraps a sink in a type-safe interface: we + * don't want to try and extract a fingerprint from a sink configured + * for hashing. + */ +struct umash_state { + struct umash_sink sink; +}; + +/** + * Similarly, the `umash_fp_state` struct wraps a sink from which we + * should extract a fingerprint. + */ +struct umash_fp_state { + struct umash_sink sink; +}; + +/** + * Converts a `umash_params` struct filled with random values into + * something usable by the UMASH functions below. + * + * When it succeeds, this function is idempotent. Failure happens + * with probability < 2**-110 is `params` is filled with uniformly + * distributed random bits. That's an astronomically unlikely event, + * and most likely signals an issue with the caller's (pseudo-)random + * number generator. + * + * @return false on failure, probably because the input was not random. + */ +bool umash_params_prepare(struct umash_params *params); + +/** + * Deterministically derives a `umash_params` struct from `bits` and + * `key`. The `bits` values do not have to be particularly well + * distributed, and can be generated sequentially. + * + * @param key a pointer to exactly 32 secret bytes. NULL will be + * replaced with "Do not use UMASH VS adversaries.", the default + * UMASH secret. + */ +void umash_params_derive(struct umash_params *, uint64_t bits, const void *key); + +/** + * Updates a `umash_sink` to take into account `data[0 ... n_bytes)`. + */ +void umash_sink_update(struct umash_sink *, const void *data, size_t n_bytes); + +/** + * Computes the UMASH hash of `data[0 ... n_bytes)`. + * + * Randomly generated `param` lead to independent UMASH values and + * associated worst-case collision bounds; changing the `seed` comes + * with no guarantee. + * + * @param which 0 to compute the first UMASH defined by `params`, 1 + * for the second. + */ +uint64_t umash_full(const struct umash_params *params, uint64_t seed, int which, + const void *data, size_t n_bytes); + +/** + * Computes the UMASH fingerprint of `data[0 ... n_bytes)`. + * + * Randomly generated `param` lead to independent UMASH values and + * associated worst-case collision bounds; changing the `seed` comes + * with no guarantee. + */ +struct umash_fp umash_fprint( + const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes); + +/** + * Prepares a `umash_state` for computing the `which`th UMASH function in + * `params`. + */ +void umash_init( + struct umash_state *, const struct umash_params *params, uint64_t seed, int which); + +/** + * Returns the UMASH value for the bytes that have been + * `umash_sink_update`d into the state. + */ +uint64_t umash_digest(const struct umash_state *); + +/** + * Prepares a `umash_fp_state` for computing the UMASH fingerprint in + * `params`. + */ +void umash_fp_init( + struct umash_fp_state *, const struct umash_params *params, uint64_t seed); + +/** + * Returns the UMASH fingerprint for the bytes that have been + * `umash_sink_update`d into the state. + */ +struct umash_fp umash_fp_digest(const struct umash_fp_state *); + +#ifdef __cplusplus +} +#endif +#endif /* !UMASH_H */ diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c new file mode 100644 index 00000000000..ece84c6ea76 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -0,0 +1,398 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for a single text column. + */ + +#include + +#include + +#include "bytes_view.h" +#include "compression/arrow_c_data_interface.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#include "batch_hashing_params.h" + +#include "umash_fingerprint_key.h" + +#define EXPLAIN_NAME "single text" +#define KEY_VARIANT single_text +#define OUTPUT_KEY_TYPE BytesView + +static void +single_text_key_hashing_init(HashingStrategy *hashing) +{ + hashing->umash_params = umash_key_hashing_init(); +} + +static BytesView +get_bytes_view(CompressedColumnValues *column_values, int arrow_row) +{ + const uint32 start = ((uint32 *) column_values->buffers[1])[arrow_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[arrow_row + 1] - start; + Assert(value_bytes >= 0); + + return (BytesView){ .len = value_bytes, .data = &((uint8 *) column_values->buffers[2])[start] }; +} + +static pg_attribute_always_inline void +single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) +{ + Assert(params.policy->num_grouping_columns == 1); + + BytesView *restrict output_key = (BytesView *) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; + + if (unlikely(params.single_grouping_column.decompression_type == DT_Scalar)) + { + output_key->len = VARSIZE_ANY_EXHDR(*params.single_grouping_column.output_value); + output_key->data = (const uint8 *) VARDATA_ANY(*params.single_grouping_column.output_value); + *valid = !*params.single_grouping_column.output_isnull; + } + else if (params.single_grouping_column.decompression_type == DT_ArrowText) + { + *output_key = get_bytes_view(¶ms.single_grouping_column, row); + *valid = arrow_row_is_valid(params.single_grouping_column.buffers[0], row); + } + else if (params.single_grouping_column.decompression_type == DT_ArrowTextDict) + { + const int16 index = ((int16 *) params.single_grouping_column.buffers[3])[row]; + *output_key = get_bytes_view(¶ms.single_grouping_column, index); + *valid = arrow_row_is_valid(params.single_grouping_column.buffers[0], row); + } + else + { + pg_unreachable(); + } + + DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", + params.policy, + row, + params.policy->last_used_key_index + 1, + output_key->len); + for (size_t i = 0; i < output_key->len; i++) + { + DEBUG_PRINT("%.2x.", output_key->data[i]); + } + DEBUG_PRINT("\n"); + + const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, + /* seed = */ -1ull, + output_key->data, + output_key->len); + *hash_table_key = umash_fingerprint_get_key(fp); +} + +static pg_attribute_always_inline void +single_text_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, + BytesView output_key) +{ + const int total_bytes = output_key.len + VARHDRSZ; + text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); + SET_VARSIZE(stored, total_bytes); + memcpy(VARDATA(stored), output_key.data, output_key.len); + output_key.data = (uint8 *) VARDATA(stored); + policy->hashing.output_keys[new_key_index] = PointerGetDatum(stored); +} + +/* + * We use the standard single-key key output functions. + */ +static void +single_text_emit_key(GroupingPolicyHash *policy, uint32 current_key, + TupleTableSlot *aggregated_slot) +{ + return hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); +} + +/* + * We use a special batch preparation function to sometimes hash the dictionary- + * encoded column using the dictionary. + */ + +#define USE_DICT_HASHING + +static pg_attribute_always_inline void single_text_dispatch_for_params(BatchHashingParams params, + int start_row, int end_row); + +static void +single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, + DecompressBatchState *batch_state) +{ + /* + * Determine whether we're going to use the dictionary for hashing. + */ + policy->use_key_index_for_dict = false; + + BatchHashingParams params = build_batch_hashing_params(policy, batch_state); + if (params.single_grouping_column.decompression_type != DT_ArrowTextDict) + { + return; + } + + const int dict_rows = params.single_grouping_column.arrow->dictionary->length; + if ((size_t) dict_rows > + arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) + { + return; + } + + /* + * Remember which aggregation states have already existed, and which we have + * to initialize. State index zero is invalid. + */ + const uint32 last_initialized_key_index = policy->last_used_key_index; + Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); + + /* + * Initialize the array for storing the aggregate state offsets corresponding + * to a given batch row. We don't need the offsets for the previous batch + * that are currently stored there, so we don't need to use repalloc. + */ + if ((size_t) dict_rows > policy->num_key_index_for_dict) + { + if (policy->key_index_for_dict != NULL) + { + pfree(policy->key_index_for_dict); + } + policy->num_key_index_for_dict = dict_rows; + policy->key_index_for_dict = + palloc(sizeof(policy->key_index_for_dict[0]) * policy->num_key_index_for_dict); + } + + /* + * We shouldn't add the dictionary entries that are not used by any matching + * rows. Translate the batch filter bitmap to dictionary rows. + */ + const int batch_rows = batch_state->total_batch_rows; + const uint64 *row_filter = batch_state->vector_qual_result; + if (batch_state->vector_qual_result != NULL) + { + uint64 *restrict dict_filter = policy->tmp_filter; + const size_t dict_words = (dict_rows + 63) / 64; + memset(dict_filter, 0, sizeof(*dict_filter) * dict_words); + + bool *restrict tmp = (bool *) policy->key_index_for_dict; + Assert(sizeof(*tmp) <= sizeof(*policy->key_index_for_dict)); + memset(tmp, 0, sizeof(*tmp) * dict_rows); + + int outer; + for (outer = 0; outer < batch_rows / 64; outer++) + { +#define INNER_LOOP(INNER_MAX) \ + const uint64 word = row_filter[outer]; \ + for (int inner = 0; inner < INNER_MAX; inner++) \ + { \ + const int16 index = \ + ((int16 *) params.single_grouping_column.buffers[3])[outer * 64 + inner]; \ + tmp[index] = tmp[index] || (word & (1ull << inner)); \ + } + + INNER_LOOP(64) + } + + if (batch_rows % 64) + { + INNER_LOOP(batch_rows % 64) + } +#undef INNER_LOOP + + for (outer = 0; outer < dict_rows / 64; outer++) + { +#define INNER_LOOP(INNER_MAX) \ + uint64 word = 0; \ + for (int inner = 0; inner < INNER_MAX; inner++) \ + { \ + word |= (tmp[outer * 64 + inner] ? 1ull : 0ull) << inner; \ + } \ + dict_filter[outer] = word; + + INNER_LOOP(64) + } + if (dict_rows % 64) + { + INNER_LOOP(dict_rows % 64) + } +#undef INNER_LOOP + + params.batch_filter = dict_filter; + } + else + { + params.batch_filter = NULL; + } + + /* + * The dictionary contains no null entries, so we will be adding the null + * key separately. Determine if we have any null key that also passes the + * batch filter. + */ + bool have_null_key = false; + if (batch_state->vector_qual_result != NULL) + { + if (params.single_grouping_column.arrow->null_count > 0) + { + Assert(params.single_grouping_column.buffers[0] != NULL); + const size_t batch_words = (batch_rows + 63) / 64; + for (size_t i = 0; i < batch_words; i++) + { + have_null_key = have_null_key || + (row_filter[i] & + (~((uint64 *) params.single_grouping_column.buffers[0])[i])) != 0; + } + } + } + else + { + if (params.single_grouping_column.arrow->null_count > 0) + { + Assert(params.single_grouping_column.buffers[0] != NULL); + have_null_key = true; + } + } + + /* + * Build key indexes for the dictionary entries as for normal non-nullable + * text values. + */ + Assert(params.single_grouping_column.decompression_type = DT_ArrowTextDict); + Assert((size_t) dict_rows <= policy->num_key_index_for_dict); + memset(policy->key_index_for_dict, 0, sizeof(*policy->key_index_for_dict) * dict_rows); + + params.single_grouping_column.decompression_type = DT_ArrowText; + params.single_grouping_column.buffers[0] = NULL; + params.have_scalar_or_nullable_columns = false; + params.result_key_indexes = policy->key_index_for_dict; + + single_text_dispatch_for_params(params, 0, dict_rows); + + /* + * The dictionary doesn't store nulls, so add the null key separately if we + * have one. + * + * FIXME doesn't respect nulls last/first in GroupAggregate. Add a test. + */ + if (have_null_key && policy->hashing.null_key_index == 0) + { + policy->hashing.null_key_index = ++policy->last_used_key_index; + policy->hashing.output_keys[policy->hashing.null_key_index] = PointerGetDatum(NULL); + } + + policy->use_key_index_for_dict = true; + + /* + * Initialize the new keys if we added any. + */ + if (policy->last_used_key_index > last_initialized_key_index) + { + const uint64 new_aggstate_rows = policy->num_allocated_per_key_agg_states * 2 + 1; + const int num_fns = policy->num_agg_defs; + for (int i = 0; i < num_fns; i++) + { + const VectorAggDef *agg_def = &policy->agg_defs[i]; + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + { + policy->per_agg_per_key_states[i] = + repalloc(policy->per_agg_per_key_states[i], + new_aggstate_rows * agg_def->func.state_bytes); + } + + /* + * Initialize the aggregate function states for the newly added keys. + */ + void *first_uninitialized_state = + agg_def->func.state_bytes * (last_initialized_key_index + 1) + + (char *) policy->per_agg_per_key_states[i]; + agg_def->func.agg_init(first_uninitialized_state, + policy->last_used_key_index - last_initialized_key_index); + } + + /* + * Record the newly allocated number of rows in case we had to reallocate. + */ + if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + { + Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); + policy->num_allocated_per_key_agg_states = new_aggstate_rows; + } + } + + DEBUG_PRINT("computed the dict offsets\n"); +} + +static pg_attribute_always_inline void +single_text_offsets_translate_impl(BatchHashingParams params, int start_row, int end_row) +{ + GroupingPolicyHash *policy = params.policy; + Assert(policy->use_key_index_for_dict); + + uint32 *restrict indexes_for_rows = params.result_key_indexes; + uint32 *restrict indexes_for_dict = policy->key_index_for_dict; + + for (int row = start_row; row < end_row; row++) + { + const bool row_valid = arrow_row_is_valid(params.single_grouping_column.buffers[0], row); + const int16 dict_index = ((int16 *) params.single_grouping_column.buffers[3])[row]; + + if (row_valid) + { + indexes_for_rows[row] = indexes_for_dict[dict_index]; + } + else + { + indexes_for_rows[row] = policy->hashing.null_key_index; + } + + Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(params.batch_filter, row)); + } +} + +#define APPLY_FOR_VALIDITY(X, NAME, COND) \ + X(NAME##_notnull, (COND) && (params.single_grouping_column.buffers[0] == NULL)) \ + X(NAME##_nullable, (COND) && (params.single_grouping_column.buffers[0] != NULL)) + +#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, single_text_offsets_translate, true) + +#define DEFINE(NAME, CONDITION) \ + static pg_noinline void NAME(BatchHashingParams params, int start_row, int end_row) \ + { \ + if (!(CONDITION)) \ + { \ + pg_unreachable(); \ + } \ + \ + single_text_offsets_translate_impl(params, start_row, end_row); \ + } + +APPLY_FOR_SPECIALIZATIONS(DEFINE) + +#undef DEFINE + +static void +single_text_offsets_translate(BatchHashingParams params, int start_row, int end_row) +{ +#define DISPATCH(NAME, CONDITION) \ + if (CONDITION) \ + { \ + NAME(params, start_row, end_row); \ + } \ + else + + APPLY_FOR_SPECIALIZATIONS(DISPATCH) { pg_unreachable(); } +#undef DISPATCH +} + +#undef APPLY_FOR_SPECIALIZATIONS +#undef APPLY_FOR_VALIDITY +#undef APPLY_FOR_BATCH_FILTER + +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h new file mode 100644 index 00000000000..ed6a9b8ce03 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/umash_fingerprint_key.h @@ -0,0 +1,45 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +/* + * Helpers to use the umash fingerprint as a hash table key in our hashing + * strategies for vectorized grouping. + */ + +#include "import/umash.h" + +/* + * The struct is packed so that the hash table entry fits into 16 + * bytes with the uint32 key index that goes before. + */ +struct umash_fingerprint_key +{ + uint32 hash; + uint64 rest; +} pg_attribute_packed(); + +#define HASH_TABLE_KEY_TYPE struct umash_fingerprint_key +#define KEY_HASH(X) (X.hash) +#define KEY_EQUAL(a, b) (a.hash == b.hash && a.rest == b.rest) + +static inline struct umash_fingerprint_key +umash_fingerprint_get_key(struct umash_fp fp) +{ + const struct umash_fingerprint_key key = { + .hash = fp.hash[0] & (~(uint32) 0), + .rest = fp.hash[1], + }; + return key; +} + +static inline struct umash_params * +umash_key_hashing_init() +{ + struct umash_params *params = palloc0(sizeof(struct umash_params)); + umash_params_derive(params, 0xabcdef1234567890ull, NULL); + return params; +} diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out new file mode 100644 index 00000000000..a4bdc3bed86 --- /dev/null +++ b/tsl/test/expected/vector_agg_grouping.out @@ -0,0 +1,1985 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +----------------------- + (1,public,agggroup,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into agggroup select * from source where s = 1; +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 1 +(1 row) + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1051 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze agggroup; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 'cint2', + 'cint4', + 'cint4, cint8', + 'cint8', + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint4, cint8, cint2', + 'x']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec +select count(*) from agggroup; + count +-------- + 200000 +(1 row) + +select cint2, count(*) from agggroup group by cint2 order by count(*), cint2 limit 10; + cint2 | count +--------+------- + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 + -15615 | 1 +(10 rows) + +select cint4, count(*) from agggroup group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 + -15760 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16383 | 7417 | 1 + -16383 | 8953 | 1 + -16382 | -8851 | 1 + -16382 | -8612 | 1 + -16382 | -5254 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 899 | 1 +(10 rows) + +select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+--------+------- + 0 | -16377 | 1 + 0 | -16376 | 1 + 0 | -16375 | 1 + 0 | -16373 | 1 + 0 | -16372 | 1 + 0 | -16371 | 1 + 0 | -16370 | 1 + 0 | -16369 | 1 + 0 | -16368 | 1 + 0 | -16367 | 1 +(10 rows) + +select s, ss, count(*) from agggroup group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select s, x, count(*) from agggroup group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select ss, cint2, x, count(*) from agggroup group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+---+------- + 0 | -16377 | 0 | 1 + 0 | -16376 | 0 | 1 + 0 | -16375 | 0 | 1 + 0 | -16373 | 0 | 1 + 0 | -16372 | 0 | 1 + 0 | -16371 | 0 | 1 + 0 | -16370 | 0 | 1 + 0 | -16369 | 0 | 1 + 0 | -16368 | 0 | 1 + 0 | -16367 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 + 8 | 8 | 20000 + 9 | 9 | 20000 +(10 rows) + +select ss, x, cint2, count(*) from agggroup group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+--------+------- + 0 | 0 | -16377 | 1 + 0 | 0 | -16376 | 1 + 0 | 0 | -16375 | 1 + 0 | 0 | -16373 | 1 + 0 | 0 | -16372 | 1 + 0 | 0 | -16371 | 1 + 0 | 0 | -16370 | 1 + 0 | 0 | -16369 | 1 + 0 | 0 | -16368 | 1 + 0 | 0 | -16367 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+--------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 2 | 0 | 0 | 0 | 1096 | -6638 | -5373 | 1 + 3 | 0 | 0 | 0 | -15920 | 13672 | -7109 | 1 + 4 | 0 | 0 | 0 | 14299 | -8187 | -4927 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 8 | 0 | 0 | 0 | -10427 | 876 | -12705 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 +(10 rows) + +select x, count(*) from agggroup group by x order by count(*), x limit 10; + x | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select count(cint2) from agggroup; + count +-------- + 199810 +(1 row) + +select cint2, count(cint2) from agggroup group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +--------+------- + | 0 + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + 8426 | 0 + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + +select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + +select s, cint2, count(cint2) from agggroup group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select s, x, count(cint2) from agggroup group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 + 0 | -16377 | 0 | 1 +(10 rows) + +select ss, s, count(cint2) from agggroup group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 + 8 | 8 | 19981 + 9 | 9 | 19981 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+--------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 + 0 | 0 | -16377 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 +(10 rows) + +select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; + x | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + +select min(cint2) from agggroup; + min +-------- + -16383 +(1 row) + +select cint2, min(cint2) from agggroup group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +--------+-------- + -16383 | -16383 + -16382 | -16382 + -16381 | -16381 + -16380 | -16380 + -16379 | -16379 + -16378 | -16378 + -16377 | -16377 + -16376 | -16376 + -16375 | -16375 + -16374 | -16374 +(10 rows) + +select cint4, min(cint2) from agggroup group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+-------- + -16190 | -16383 + -13372 | -16383 + -10318 | -16383 + -9008 | -16383 + -3043 | -16383 + 6729 | -16383 + -14012 | -16382 + -8606 | -16382 + -3080 | -16382 + 2223 | -16382 +(10 rows) + +select cint4, cint8, min(cint2) from agggroup group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+-------- + -16190 | 13646 | -16383 + -13372 | 11094 | -16383 + -10318 | 6326 | -16383 + -9008 | 4390 | -16383 + -3043 | -1794 | -16383 + 6729 | 6717 | -16383 + -14012 | -9888 | -16382 + -8606 | -10357 | -16382 + -3080 | -15609 | -16382 + 2223 | 9035 | -16382 +(10 rows) + +select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+-------- + -1794 | -16383 + 4390 | -16383 + 6326 | -16383 + 6717 | -16383 + 11094 | -16383 + 13646 | -16383 + -15609 | -16382 + -10357 | -16382 + -9888 | -16382 + 206 | -16382 +(10 rows) + +select s, cint2, min(cint2) from agggroup group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+--------+-------- + 0 | -16383 | -16383 + 4 | -16383 | -16383 + 5 | -16383 | -16383 + 6 | -16383 | -16383 + 2 | -16382 | -16382 + 7 | -16382 | -16382 + 8 | -16382 | -16382 + 2 | -16381 | -16381 + 3 | -16381 | -16381 + 4 | -16381 | -16381 +(10 rows) + +select s, ss, min(cint2) from agggroup group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select s, x, min(cint2) from agggroup group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+--------+----+-------- + 0 | -16383 | 0 | -16383 + 4 | -16383 | 4 | -16383 + 5 | -16383 | 5 | -16383 + 6 | -16383 | 6 | -16383 + 7 | -16382 | 7 | -16382 + 8 | -16382 | 8 | -16382 + 11 | -16382 | 11 | -16382 + 3 | -16381 | 3 | -16381 + 4 | -16381 | 4 | -16381 + 5 | -16381 | 5 | -16381 +(10 rows) + +select ss, s, min(cint2) from agggroup group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 7 | 7 | -16382 + 8 | 8 | -16382 + 11 | 2 | -16382 + 3 | 3 | -16381 + 11 | 1 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+--------+-------- + 0 | 0 | -16383 | -16383 + 4 | 4 | -16383 | -16383 + 5 | 5 | -16383 | -16383 + 6 | 6 | -16383 | -16383 + 7 | 7 | -16382 | -16382 + 8 | 8 | -16382 | -16382 + 11 | 11 | -16382 | -16382 + 3 | 3 | -16381 | -16381 + 4 | 4 | -16381 | -16381 + 5 | 5 | -16381 | -16381 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+----+--------+--------+--------+-------- + 6194 | 0 | 0 | 0 | -13372 | 11094 | -16383 | -16383 + 17044 | 0 | 0 | 0 | -10318 | 6326 | -16383 | -16383 + 53843 | 4 | 4 | 4 | -9008 | 4390 | -16383 | -16383 + 60530 | 5 | 5 | 5 | 6729 | 6717 | -16383 | -16383 + 73208 | 6 | 6 | 6 | -3043 | -1794 | -16383 | -16383 + 74870 | 6 | 6 | 6 | -16190 | 13646 | -16383 | -16383 + 22836 | 2 | 11 | 11 | -3080 | -15609 | -16382 | -16382 + 29858 | 2 | 11 | 11 | -14012 | -9888 | -16382 | -16382 + 31516 | 2 | 11 | 11 | 6193 | 206 | -16382 | -16382 + 76781 | 7 | 7 | 7 | 9938 | 6519 | -16382 | -16382 +(10 rows) + +select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; + x | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 11 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 9 | -16375 + | -16295 +(10 rows) + +select count(*) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select cint2, count(*) from agggroup where cint2 > 0 group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(*) from agggroup where cint2 > 0 group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup where cint2 > 0 group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup where cint2 > 0 group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(*) from agggroup where cint2 > 0 group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 > 0 group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup where cint2 > 0 group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 9 + | 3 | 9 + 11 | 2 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 +(10 rows) + +select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select count(cint2) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 > 0 group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup where cint2 > 0 group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + +select s, cint2, count(cint2) from agggroup where cint2 > 0 group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 > 0 group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 +(10 rows) + +select ss, s, count(cint2) from agggroup where cint2 > 0 group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 9 + | 3 | 9 + 11 | 2 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 +(10 rows) + +select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select min(cint2) from agggroup where cint2 > 0; + min +----- + 1 +(1 row) + +select cint2, min(cint2) from agggroup where cint2 > 0 group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 +(10 rows) + +select cint4, min(cint2) from agggroup where cint2 > 0 group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -12025 | 1 + -10344 | 1 + -4190 | 1 + -1493 | 1 + 1863 | 1 + 9242 | 1 + 11189 | 1 + 14078 | 1 + 15656 | 1 + -11410 | 2 +(10 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -12025 | -2210 | 1 + -10344 | -13684 | 1 + -4190 | -2827 | 1 + -1493 | -1043 | 1 + 1863 | 7650 | 1 + 9242 | -9798 | 1 + 11189 | -5168 | 1 + 14078 | 9929 | 1 + 15656 | 12597 | 1 + -11410 | 6033 | 2 +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -13684 | 1 + -9798 | 1 + -5168 | 1 + -2827 | 1 + -2210 | 1 + -1043 | 1 + 7650 | 1 + 9929 | 1 + 12597 | 1 + -13639 | 2 +(10 rows) + +select s, cint2, min(cint2) from agggroup where cint2 > 0 group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 1 | 1 | 1 + 2 | 1 | 1 + 3 | 1 | 1 + 5 | 1 | 1 + 7 | 1 | 1 + 8 | 1 | 1 + 1 | 2 | 2 + 3 | 2 | 2 + 7 | 2 | 2 + 9 | 2 | 2 +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 > 0 group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select s, x, min(cint2) from agggroup where cint2 > 0 group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 3 | 1 | 3 | 1 + 5 | 1 | 5 | 1 + 7 | 1 | 7 | 1 + 8 | 1 | 8 | 1 + 11 | 1 | 11 | 1 + 3 | 2 | 3 | 2 + 7 | 2 | 7 | 2 + 9 | 2 | 9 | 2 + 11 | 2 | 11 | 2 + 3 | 3 | 3 | 3 +(10 rows) + +select ss, s, min(cint2) from agggroup where cint2 > 0 group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 11 | 1 | 1 + 11 | 2 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 3 | 3 | 1 | 1 + 5 | 5 | 1 | 1 + 7 | 7 | 1 | 1 + 8 | 8 | 1 | 1 + 11 | 11 | 1 | 1 + 3 | 3 | 2 | 2 + 7 | 7 | 2 | 2 + 9 | 9 | 2 | 2 + 11 | 11 | 2 | 2 + 3 | 3 | 3 | 3 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+----+--------+--------+-------+----- + 11611 | 1 | 11 | 11 | -12025 | -2210 | 1 | 1 + 28649 | 2 | 11 | 11 | -1493 | -1043 | 1 | 1 + 28786 | 1 | 11 | 11 | -4190 | -2827 | 1 | 1 + 41774 | 3 | 3 | 3 | 1863 | 7650 | 1 | 1 + 41779 | 3 | 3 | 3 | 14078 | 9929 | 1 | 1 + 51152 | 5 | 5 | 5 | 9242 | -9798 | 1 | 1 + 70932 | 7 | 7 | 7 | -10344 | -13684 | 1 | 1 + 86957 | 7 | 7 | 7 | 15656 | 12597 | 1 | 1 + 89689 | 8 | 8 | 8 | 11189 | -5168 | 1 | 1 + 22147 | 1 | 11 | 11 | -9569 | 9760 | 2 | 2 +(10 rows) + +select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; + x | min +----+------ + 11 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 4895 +(10 rows) + +select count(*) from agggroup where cint2 is null; + count +------- + 190 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + | 190 +(1 row) + +select cint4, count(*) from agggroup where cint2 is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 1 + -16091 | 1 + -15799 | 1 + -15724 | 1 + -15328 | 1 + -15279 | 1 + -15063 | 1 + -14998 | 1 + -14949 | 1 + -14848 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 1 + -16091 | -4084 | 1 + -15799 | 12603 | 1 + -15724 | 15426 | 1 + -15328 | -6092 | 1 + -15279 | -3475 | 1 + -15063 | 3990 | 1 + -14998 | 14464 | 1 + -14949 | -10395 | 1 + -14848 | 3110 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 1 + -15987 | 1 + -15904 | 1 + -15897 | 1 + -15761 | 1 + -15506 | 1 + -15346 | 1 + -14986 | 1 + -14811 | 1 + -14674 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup where cint2 is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 19 + 1 | | 19 + 2 | | 19 + 3 | | 19 + 4 | | 19 + 5 | | 19 + 6 | | 19 + 7 | | 19 + 8 | | 19 + 9 | | 19 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select s, x, count(*) from agggroup where cint2 is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 19 + 3 | | 3 | 19 + 4 | | 4 | 19 + 5 | | 5 | 19 + 6 | | 6 | 19 + 7 | | 7 | 19 + 8 | | 8 | 19 + 9 | | 9 | 19 + 11 | | 11 | 38 +(9 rows) + +select ss, s, count(*) from agggroup where cint2 is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 + 11 | 1 | 19 + 11 | 2 | 19 +(10 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 19 + 3 | 3 | | 19 + 4 | 4 | | 19 + 5 | 5 | | 19 + 6 | 6 | | 19 + 7 | 7 | | 19 + 8 | 8 | | 19 + 9 | 9 | | 19 + 11 | 11 | | 38 +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 1 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 1 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 1 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 1 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 1 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 1 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 1 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 1 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 1 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 1 +(10 rows) + +select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; + x | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select count(cint2) from agggroup where cint2 is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + | 0 +(1 row) + +select cint4, count(cint2) from agggroup where cint2 is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 0 + -16091 | 0 + -15799 | 0 + -15724 | 0 + -15328 | 0 + -15279 | 0 + -15063 | 0 + -14998 | 0 + -14949 | 0 + -14848 | 0 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 0 + -15987 | 0 + -15904 | 0 + -15897 | 0 + -15761 | 0 + -15506 | 0 + -15346 | 0 + -14986 | 0 + -14811 | 0 + -14674 | 0 +(10 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 +(9 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 + 11 | 1 | 0 + 11 | 2 | 0 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 +(10 rows) + +select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; + x | count +----+------- + 0 | 0 + 11 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(9 rows) + +select min(cint2) from agggroup where cint2 is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + | +(1 row) + +select cint4, min(cint2) from agggroup where cint2 is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -16291 | + -16091 | + -15799 | + -15724 | + -15328 | + -15279 | + -15063 | + -14998 | + -14949 | + -14848 | +(10 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -16291 | 113 | + -16091 | -4084 | + -15799 | 12603 | + -15724 | 15426 | + -15328 | -6092 | + -15279 | -3475 | + -15063 | 3990 | + -14998 | 14464 | + -14949 | -10395 | + -14848 | 3110 | +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -16026 | + -15987 | + -15904 | + -15897 | + -15761 | + -15506 | + -15346 | + -14986 | + -14811 | + -14674 | +(10 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 0 | | + 1 | | + 2 | | + 3 | | + 4 | | + 5 | | + 6 | | + 7 | | + 8 | | + 9 | | +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select s, x, min(cint2) from agggroup where cint2 is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 0 | | 0 | + 3 | | 3 | + 4 | | 4 | + 5 | | 5 | + 6 | | 6 | + 7 | | 7 | + 8 | | 8 | + 9 | | 9 | + 11 | | 11 | +(9 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 0 | 0 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 11 | 1 | + 11 | 2 | +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 0 | 0 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | | + 7 | 7 | | + 8 | 8 | | + 9 | 9 | | + 11 | 11 | | +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+---+--------+--------+-------+----- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | + 2102 | 0 | 0 | 0 | 11069 | 16047 | | + 3153 | 0 | 0 | 0 | 6192 | 12700 | | + 4204 | 0 | 0 | 0 | 4165 | -10102 | | + 5255 | 0 | 0 | 0 | 16314 | 13418 | | + 6306 | 0 | 0 | 0 | 701 | -3029 | | + 7357 | 0 | 0 | 0 | 1115 | 4913 | | + 8408 | 0 | 0 | 0 | 15553 | 1743 | | + 9459 | 0 | 0 | 0 | -14640 | 11933 | | + 10510 | 0 | 0 | 0 | -14725 | 6531 | | +(10 rows) + +select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; + x | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select count(*) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null and x is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(*) from agggroup where cint2 is null and x is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(*) from agggroup where cint2 is null and x is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(*) from agggroup where cint2 is null and x is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(*) from agggroup where cint2 is null and x is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(*) from agggroup where cint2 is null and x is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(*) from agggroup where cint2 is null and x is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(*) from agggroup where cint2 is null and x is null group by x order by count(*), x limit 10; + x | count +---+------- +(0 rows) + +select count(cint2) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null and x is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(cint2) from agggroup where cint2 is null and x is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null and x is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(cint2) from agggroup where cint2 is null and x is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null and x is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(cint2) from agggroup where cint2 is null and x is null group by x order by count(cint2), x limit 10; + x | count +---+------- +(0 rows) + +select min(cint2) from agggroup where cint2 is null and x is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null and x is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- +(0 rows) + +select cint4, min(cint2) from agggroup where cint2 is null and x is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +-------+----- +(0 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +-------+-------+----- +(0 rows) + +select cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +-------+----- +(0 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- +(0 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null and x is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- +(0 rows) + +select s, x, min(cint2) from agggroup where cint2 is null and x is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+---+----- +(0 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+---+----- +(0 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null and x is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- +(0 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+---+-------+----- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +---+---+----+---+-------+-------+-------+----- +(0 rows) + +select x, min(cint2) from agggroup where cint2 is null and x is null group by x order by min(cint2), x limit 10; + x | min +---+----- +(0 rows) + +reset timescaledb.debug_require_vector_agg; +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +------------------- + (3,public,long,t) +(1 row) + +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes +NOTICE: default segment by for hypertable "long" is set to "" +NOTICE: default order by for hypertable "long" is set to "t DESC" +select count(compress_chunk(x)) from show_chunks('long') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; + count +------- + 1 + 1 + 1 + 1 + 1 +(5 rows) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql new file mode 100644 index 00000000000..e087e54c48e --- /dev/null +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -0,0 +1,126 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into agggroup select * from source where s = 1; + +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('agggroup') x; + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; + +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1051 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; +vacuum freeze analyze agggroup; + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 'cint2', + 'cint4', + 'cint4, cint8', + 'cint8', + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint4, cint8, cint2', + 'x']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec + +reset timescaledb.debug_require_vector_agg; + + +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +select count(compress_chunk(x)) from show_chunks('long') x; + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; +reset timescaledb.debug_require_vector_agg; From 4aeecac58f6fe9c74f800d0c6803cea2facb08e6 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:52:12 +0100 Subject: [PATCH 199/242] cleanup --- .../nodes/vector_agg/grouping_policy_hash.c | 7 - .../nodes/vector_agg/grouping_policy_hash.h | 11 - .../hashing/hash_strategy_single_text.c | 275 --- tsl/test/expected/vector_agg_grouping.out | 1985 ----------------- tsl/test/expected/vector_agg_text.out | 283 +++ tsl/test/sql/CMakeLists.txt | 2 +- ...r_agg_grouping.sql => vector_agg_text.sql} | 45 +- 7 files changed, 300 insertions(+), 2308 deletions(-) delete mode 100644 tsl/test/expected/vector_agg_grouping.out create mode 100644 tsl/test/expected/vector_agg_text.out rename tsl/test/sql/{vector_agg_grouping.sql => vector_agg_text.sql} (85%) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 1785af7c4ae..a570b766e0c 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -108,13 +108,6 @@ gp_hash_reset(GroupingPolicy *obj) policy->hashing.reset(&policy->hashing); - /* - * Have to reset this because it's in the key body context which is also - * reset here. - */ - policy->tmp_key_storage = NULL; - policy->num_tmp_key_storage_bytes = 0; - policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index cf6d7791d21..3fc0016b444 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -130,17 +130,6 @@ typedef struct GroupingPolicyHash uint64 stat_input_total_rows; uint64 stat_input_valid_rows; uint64 stat_consecutive_keys; - - /* - * FIXME all the stuff below should be moved out. - */ - - /* - * Temporary key storages. Some hashing strategies need to put the key in a - * separate memory area, we don't want to alloc/free it on each row. - */ - uint8 *tmp_key_storage; - uint64 num_tmp_key_storage_bytes; } GroupingPolicyHash; //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index ece84c6ea76..51a8ea29467 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -114,285 +114,10 @@ single_text_emit_key(GroupingPolicyHash *policy, uint32 current_key, return hash_strategy_output_key_single_emit(policy, current_key, aggregated_slot); } -/* - * We use a special batch preparation function to sometimes hash the dictionary- - * encoded column using the dictionary. - */ - -#define USE_DICT_HASHING - -static pg_attribute_always_inline void single_text_dispatch_for_params(BatchHashingParams params, - int start_row, int end_row); - static void single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, DecompressBatchState *batch_state) { - /* - * Determine whether we're going to use the dictionary for hashing. - */ - policy->use_key_index_for_dict = false; - - BatchHashingParams params = build_batch_hashing_params(policy, batch_state); - if (params.single_grouping_column.decompression_type != DT_ArrowTextDict) - { - return; - } - - const int dict_rows = params.single_grouping_column.arrow->dictionary->length; - if ((size_t) dict_rows > - arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) - { - return; - } - - /* - * Remember which aggregation states have already existed, and which we have - * to initialize. State index zero is invalid. - */ - const uint32 last_initialized_key_index = policy->last_used_key_index; - Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); - - /* - * Initialize the array for storing the aggregate state offsets corresponding - * to a given batch row. We don't need the offsets for the previous batch - * that are currently stored there, so we don't need to use repalloc. - */ - if ((size_t) dict_rows > policy->num_key_index_for_dict) - { - if (policy->key_index_for_dict != NULL) - { - pfree(policy->key_index_for_dict); - } - policy->num_key_index_for_dict = dict_rows; - policy->key_index_for_dict = - palloc(sizeof(policy->key_index_for_dict[0]) * policy->num_key_index_for_dict); - } - - /* - * We shouldn't add the dictionary entries that are not used by any matching - * rows. Translate the batch filter bitmap to dictionary rows. - */ - const int batch_rows = batch_state->total_batch_rows; - const uint64 *row_filter = batch_state->vector_qual_result; - if (batch_state->vector_qual_result != NULL) - { - uint64 *restrict dict_filter = policy->tmp_filter; - const size_t dict_words = (dict_rows + 63) / 64; - memset(dict_filter, 0, sizeof(*dict_filter) * dict_words); - - bool *restrict tmp = (bool *) policy->key_index_for_dict; - Assert(sizeof(*tmp) <= sizeof(*policy->key_index_for_dict)); - memset(tmp, 0, sizeof(*tmp) * dict_rows); - - int outer; - for (outer = 0; outer < batch_rows / 64; outer++) - { -#define INNER_LOOP(INNER_MAX) \ - const uint64 word = row_filter[outer]; \ - for (int inner = 0; inner < INNER_MAX; inner++) \ - { \ - const int16 index = \ - ((int16 *) params.single_grouping_column.buffers[3])[outer * 64 + inner]; \ - tmp[index] = tmp[index] || (word & (1ull << inner)); \ - } - - INNER_LOOP(64) - } - - if (batch_rows % 64) - { - INNER_LOOP(batch_rows % 64) - } -#undef INNER_LOOP - - for (outer = 0; outer < dict_rows / 64; outer++) - { -#define INNER_LOOP(INNER_MAX) \ - uint64 word = 0; \ - for (int inner = 0; inner < INNER_MAX; inner++) \ - { \ - word |= (tmp[outer * 64 + inner] ? 1ull : 0ull) << inner; \ - } \ - dict_filter[outer] = word; - - INNER_LOOP(64) - } - if (dict_rows % 64) - { - INNER_LOOP(dict_rows % 64) - } -#undef INNER_LOOP - - params.batch_filter = dict_filter; - } - else - { - params.batch_filter = NULL; - } - - /* - * The dictionary contains no null entries, so we will be adding the null - * key separately. Determine if we have any null key that also passes the - * batch filter. - */ - bool have_null_key = false; - if (batch_state->vector_qual_result != NULL) - { - if (params.single_grouping_column.arrow->null_count > 0) - { - Assert(params.single_grouping_column.buffers[0] != NULL); - const size_t batch_words = (batch_rows + 63) / 64; - for (size_t i = 0; i < batch_words; i++) - { - have_null_key = have_null_key || - (row_filter[i] & - (~((uint64 *) params.single_grouping_column.buffers[0])[i])) != 0; - } - } - } - else - { - if (params.single_grouping_column.arrow->null_count > 0) - { - Assert(params.single_grouping_column.buffers[0] != NULL); - have_null_key = true; - } - } - - /* - * Build key indexes for the dictionary entries as for normal non-nullable - * text values. - */ - Assert(params.single_grouping_column.decompression_type = DT_ArrowTextDict); - Assert((size_t) dict_rows <= policy->num_key_index_for_dict); - memset(policy->key_index_for_dict, 0, sizeof(*policy->key_index_for_dict) * dict_rows); - - params.single_grouping_column.decompression_type = DT_ArrowText; - params.single_grouping_column.buffers[0] = NULL; - params.have_scalar_or_nullable_columns = false; - params.result_key_indexes = policy->key_index_for_dict; - - single_text_dispatch_for_params(params, 0, dict_rows); - - /* - * The dictionary doesn't store nulls, so add the null key separately if we - * have one. - * - * FIXME doesn't respect nulls last/first in GroupAggregate. Add a test. - */ - if (have_null_key && policy->hashing.null_key_index == 0) - { - policy->hashing.null_key_index = ++policy->last_used_key_index; - policy->hashing.output_keys[policy->hashing.null_key_index] = PointerGetDatum(NULL); - } - - policy->use_key_index_for_dict = true; - - /* - * Initialize the new keys if we added any. - */ - if (policy->last_used_key_index > last_initialized_key_index) - { - const uint64 new_aggstate_rows = policy->num_allocated_per_key_agg_states * 2 + 1; - const int num_fns = policy->num_agg_defs; - for (int i = 0; i < num_fns; i++) - { - const VectorAggDef *agg_def = &policy->agg_defs[i]; - if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) - { - policy->per_agg_per_key_states[i] = - repalloc(policy->per_agg_per_key_states[i], - new_aggstate_rows * agg_def->func.state_bytes); - } - - /* - * Initialize the aggregate function states for the newly added keys. - */ - void *first_uninitialized_state = - agg_def->func.state_bytes * (last_initialized_key_index + 1) + - (char *) policy->per_agg_per_key_states[i]; - agg_def->func.agg_init(first_uninitialized_state, - policy->last_used_key_index - last_initialized_key_index); - } - - /* - * Record the newly allocated number of rows in case we had to reallocate. - */ - if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) - { - Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); - policy->num_allocated_per_key_agg_states = new_aggstate_rows; - } - } - - DEBUG_PRINT("computed the dict offsets\n"); } -static pg_attribute_always_inline void -single_text_offsets_translate_impl(BatchHashingParams params, int start_row, int end_row) -{ - GroupingPolicyHash *policy = params.policy; - Assert(policy->use_key_index_for_dict); - - uint32 *restrict indexes_for_rows = params.result_key_indexes; - uint32 *restrict indexes_for_dict = policy->key_index_for_dict; - - for (int row = start_row; row < end_row; row++) - { - const bool row_valid = arrow_row_is_valid(params.single_grouping_column.buffers[0], row); - const int16 dict_index = ((int16 *) params.single_grouping_column.buffers[3])[row]; - - if (row_valid) - { - indexes_for_rows[row] = indexes_for_dict[dict_index]; - } - else - { - indexes_for_rows[row] = policy->hashing.null_key_index; - } - - Assert(indexes_for_rows[row] != 0 || !arrow_row_is_valid(params.batch_filter, row)); - } -} - -#define APPLY_FOR_VALIDITY(X, NAME, COND) \ - X(NAME##_notnull, (COND) && (params.single_grouping_column.buffers[0] == NULL)) \ - X(NAME##_nullable, (COND) && (params.single_grouping_column.buffers[0] != NULL)) - -#define APPLY_FOR_SPECIALIZATIONS(X) APPLY_FOR_VALIDITY(X, single_text_offsets_translate, true) - -#define DEFINE(NAME, CONDITION) \ - static pg_noinline void NAME(BatchHashingParams params, int start_row, int end_row) \ - { \ - if (!(CONDITION)) \ - { \ - pg_unreachable(); \ - } \ - \ - single_text_offsets_translate_impl(params, start_row, end_row); \ - } - -APPLY_FOR_SPECIALIZATIONS(DEFINE) - -#undef DEFINE - -static void -single_text_offsets_translate(BatchHashingParams params, int start_row, int end_row) -{ -#define DISPATCH(NAME, CONDITION) \ - if (CONDITION) \ - { \ - NAME(params, start_row, end_row); \ - } \ - else - - APPLY_FOR_SPECIALIZATIONS(DISPATCH) { pg_unreachable(); } -#undef DISPATCH -} - -#undef APPLY_FOR_SPECIALIZATIONS -#undef APPLY_FOR_VALIDITY -#undef APPLY_FOR_BATCH_FILTER - #include "hash_strategy_impl.c" diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out deleted file mode 100644 index a4bdc3bed86..00000000000 --- a/tsl/test/expected/vector_agg_grouping.out +++ /dev/null @@ -1,1985 +0,0 @@ --- This file and its contents are licensed under the Timescale License. --- Please see the included NOTICE for copyright information and --- LICENSE-TIMESCALE for a copy of the license. -\c :TEST_DBNAME :ROLE_SUPERUSER --- helper function: float -> pseudorandom float [-0.5..0.5] -CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ - SELECT hashfloat8(x::float8) / pow(2, 32) -$$ LANGUAGE SQL; -\set CHUNKS 2::int -\set CHUNK_ROWS 100000::int -\set GROUPING_CARDINALITY 10::int -create table agggroup(t int, s int, - cint2 int2, cint4 int4, cint8 int8); -select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); -NOTICE: adding not-null constraint to column "s" - create_hypertable ------------------------ - (1,public,agggroup,t) -(1 row) - -create view source as -select s * 10000 + t as t, - s, - case when t % 1051 = 0 then null - else (mix(s + t * 1019) * 32767)::int2 end as cint2, - (mix(s + t * 1021) * 32767)::int4 as cint4, - (mix(s + t * 1031) * 32767)::int8 as cint8 -from - generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, - generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) -; -insert into agggroup select * from source where s = 1; -alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', - timescaledb.compress_segmentby = 's'); -select count(compress_chunk(x)) from show_chunks('agggroup') x; - count -------- - 1 -(1 row) - -alter table agggroup add column ss int default 11; -alter table agggroup add column x text default '11'; -insert into agggroup -select *, ss::text as x from ( - select *, - case - -- null in entire batch - when s = 2 then null - -- null for some rows - when s = 3 and t % 1051 = 0 then null - -- for some rows same as default - when s = 4 and t % 1057 = 0 then 11 - -- not null for entire batch - else s - end as ss - from source where s != 1 -) t -; -select count(compress_chunk(x)) from show_chunks('agggroup') x; - count -------- - 2 -(1 row) - -vacuum freeze analyze agggroup; -set timescaledb.debug_require_vector_agg = 'require'; ----- Uncomment to generate reference. Note that there are minor discrepancies ----- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; -select - format('%sselect %s%s(%s) from agggroup%s%s%s;', - explain, - grouping || ', ', - function, variable, - ' where ' || condition, - ' group by ' || grouping, - format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', - function, variable) -from - unnest(array[ - 'explain (costs off) ', - null]) explain, - unnest(array[ - 'cint2', - '*']) variable, - unnest(array[ - 'min', - 'count']) function, - unnest(array[ - null, - 'cint2 > 0', - 'cint2 is null', - 'cint2 is null and x is null']) with ordinality as condition(condition, n), - unnest(array[ - null, - 'cint2', - 'cint4', - 'cint4, cint8', - 'cint8', - 's, cint2', - 's, ss', - 's, x', - 'ss, cint2, x', - 'ss, s', - 'ss, x, cint2', - 't, s, ss, x, cint4, cint8, cint2', - 'x']) with ordinality as grouping(grouping, n) -where - true - and (explain is null /* or condition is null and grouping = 's' */) - and (variable != '*' or function = 'count') -order by explain, condition.n, variable, function, grouping.n -\gexec -select count(*) from agggroup; - count --------- - 200000 -(1 row) - -select cint2, count(*) from agggroup group by cint2 order by count(*), cint2 limit 10; - cint2 | count ---------+------- - -16216 | 1 - -16071 | 1 - -15916 | 1 - -15892 | 1 - -15891 | 1 - -15732 | 1 - -15693 | 1 - -15637 | 1 - -15620 | 1 - -15615 | 1 -(10 rows) - -select cint4, count(*) from agggroup group by cint4 order by count(*), cint4 limit 10; - cint4 | count ---------+------- - -16350 | 1 - -16237 | 1 - -16144 | 1 - -15987 | 1 - -15925 | 1 - -15862 | 1 - -15849 | 1 - -15825 | 1 - -15804 | 1 - -15760 | 1 -(10 rows) - -select cint4, cint8, count(*) from agggroup group by cint4, cint8 order by count(*), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+-------+------- - -16383 | 4889 | 1 - -16383 | 7417 | 1 - -16383 | 8953 | 1 - -16382 | -8851 | 1 - -16382 | -8612 | 1 - -16382 | -5254 | 1 - -16382 | -4489 | 1 - -16382 | -470 | 1 - -16382 | 411 | 1 - -16382 | 899 | 1 -(10 rows) - -select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 limit 10; - cint8 | count ---------+------- - -16342 | 1 - -16246 | 1 - -16197 | 1 - -16152 | 1 - -16064 | 1 - -15932 | 1 - -15908 | 1 - -15869 | 1 - -15819 | 1 - -15753 | 1 -(10 rows) - -select s, cint2, count(*) from agggroup group by s, cint2 order by count(*), s, cint2 limit 10; - s | cint2 | count ----+--------+------- - 0 | -16377 | 1 - 0 | -16376 | 1 - 0 | -16375 | 1 - 0 | -16373 | 1 - 0 | -16372 | 1 - 0 | -16371 | 1 - 0 | -16370 | 1 - 0 | -16369 | 1 - 0 | -16368 | 1 - 0 | -16367 | 1 -(10 rows) - -select s, ss, count(*) from agggroup group by s, ss order by count(*), s, ss limit 10; - s | ss | count ----+----+------- - 3 | | 19 - 4 | 11 | 19 - 3 | 3 | 19981 - 4 | 4 | 19981 - 0 | 0 | 20000 - 1 | 11 | 20000 - 2 | 11 | 20000 - 5 | 5 | 20000 - 6 | 6 | 20000 - 7 | 7 | 20000 -(10 rows) - -select s, x, count(*) from agggroup group by s, x order by count(*), s, x limit 10; - s | x | count ----+----+------- - 3 | | 19 - 4 | 11 | 19 - 3 | 3 | 19981 - 4 | 4 | 19981 - 0 | 0 | 20000 - 1 | 11 | 20000 - 2 | 11 | 20000 - 5 | 5 | 20000 - 6 | 6 | 20000 - 7 | 7 | 20000 -(10 rows) - -select ss, cint2, x, count(*) from agggroup group by ss, cint2, x order by count(*), ss, cint2, x limit 10; - ss | cint2 | x | count -----+--------+---+------- - 0 | -16377 | 0 | 1 - 0 | -16376 | 0 | 1 - 0 | -16375 | 0 | 1 - 0 | -16373 | 0 | 1 - 0 | -16372 | 0 | 1 - 0 | -16371 | 0 | 1 - 0 | -16370 | 0 | 1 - 0 | -16369 | 0 | 1 - 0 | -16368 | 0 | 1 - 0 | -16367 | 0 | 1 -(10 rows) - -select ss, s, count(*) from agggroup group by ss, s order by count(*), ss, s limit 10; - ss | s | count -----+---+------- - 11 | 4 | 19 - | 3 | 19 - 3 | 3 | 19981 - 4 | 4 | 19981 - 0 | 0 | 20000 - 5 | 5 | 20000 - 6 | 6 | 20000 - 7 | 7 | 20000 - 8 | 8 | 20000 - 9 | 9 | 20000 -(10 rows) - -select ss, x, cint2, count(*) from agggroup group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+---+--------+------- - 0 | 0 | -16377 | 1 - 0 | 0 | -16376 | 1 - 0 | 0 | -16375 | 1 - 0 | 0 | -16373 | 1 - 0 | 0 | -16372 | 1 - 0 | 0 | -16371 | 1 - 0 | 0 | -16370 | 1 - 0 | 0 | -16369 | 1 - 0 | 0 | -16368 | 1 - 0 | 0 | -16367 | 1 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count -----+---+----+---+--------+-------+--------+------- - 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 - 2 | 0 | 0 | 0 | 1096 | -6638 | -5373 | 1 - 3 | 0 | 0 | 0 | -15920 | 13672 | -7109 | 1 - 4 | 0 | 0 | 0 | 14299 | -8187 | -4927 | 1 - 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 - 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 - 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 - 8 | 0 | 0 | 0 | -10427 | 876 | -12705 | 1 - 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 - 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 -(10 rows) - -select x, count(*) from agggroup group by x order by count(*), x limit 10; - x | count -----+------- - | 19 - 3 | 19981 - 4 | 19981 - 0 | 20000 - 5 | 20000 - 6 | 20000 - 7 | 20000 - 8 | 20000 - 9 | 20000 - 11 | 40019 -(10 rows) - -select count(cint2) from agggroup; - count --------- - 199810 -(1 row) - -select cint2, count(cint2) from agggroup group by cint2 order by count(cint2), cint2 limit 10; - cint2 | count ---------+------- - | 0 - -16216 | 1 - -16071 | 1 - -15916 | 1 - -15892 | 1 - -15891 | 1 - -15732 | 1 - -15693 | 1 - -15637 | 1 - -15620 | 1 -(10 rows) - -select cint4, count(cint2) from agggroup group by cint4 order by count(cint2), cint4 limit 10; - cint4 | count ---------+------- - 8426 | 0 - -16350 | 1 - -16237 | 1 - -16144 | 1 - -15987 | 1 - -15925 | 1 - -15862 | 1 - -15849 | 1 - -15825 | 1 - -15804 | 1 -(10 rows) - -select cint4, cint8, count(cint2) from agggroup group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+--------+------- - -16291 | 113 | 0 - -16091 | -4084 | 0 - -15799 | 12603 | 0 - -15724 | 15426 | 0 - -15328 | -6092 | 0 - -15279 | -3475 | 0 - -15063 | 3990 | 0 - -14998 | 14464 | 0 - -14949 | -10395 | 0 - -14848 | 3110 | 0 -(10 rows) - -select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), cint8 limit 10; - cint8 | count ---------+------- - -16342 | 1 - -16246 | 1 - -16197 | 1 - -16152 | 1 - -16064 | 1 - -15932 | 1 - -15908 | 1 - -15869 | 1 - -15819 | 1 - -15753 | 1 -(10 rows) - -select s, cint2, count(cint2) from agggroup group by s, cint2 order by count(cint2), s, cint2 limit 10; - s | cint2 | count ----+-------+------- - 0 | | 0 - 1 | | 0 - 2 | | 0 - 3 | | 0 - 4 | | 0 - 5 | | 0 - 6 | | 0 - 7 | | 0 - 8 | | 0 - 9 | | 0 -(10 rows) - -select s, ss, count(cint2) from agggroup group by s, ss order by count(cint2), s, ss limit 10; - s | ss | count ----+----+------- - 3 | | 19 - 4 | 11 | 19 - 3 | 3 | 19962 - 4 | 4 | 19962 - 0 | 0 | 19981 - 1 | 11 | 19981 - 2 | 11 | 19981 - 5 | 5 | 19981 - 6 | 6 | 19981 - 7 | 7 | 19981 -(10 rows) - -select s, x, count(cint2) from agggroup group by s, x order by count(cint2), s, x limit 10; - s | x | count ----+----+------- - 3 | | 19 - 4 | 11 | 19 - 3 | 3 | 19962 - 4 | 4 | 19962 - 0 | 0 | 19981 - 1 | 11 | 19981 - 2 | 11 | 19981 - 5 | 5 | 19981 - 6 | 6 | 19981 - 7 | 7 | 19981 -(10 rows) - -select ss, cint2, x, count(cint2) from agggroup group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; - ss | cint2 | x | count -----+--------+----+------- - 0 | | 0 | 0 - 3 | | 3 | 0 - 4 | | 4 | 0 - 5 | | 5 | 0 - 6 | | 6 | 0 - 7 | | 7 | 0 - 8 | | 8 | 0 - 9 | | 9 | 0 - 11 | | 11 | 0 - 0 | -16377 | 0 | 1 -(10 rows) - -select ss, s, count(cint2) from agggroup group by ss, s order by count(cint2), ss, s limit 10; - ss | s | count -----+---+------- - 11 | 4 | 19 - | 3 | 19 - 3 | 3 | 19962 - 4 | 4 | 19962 - 0 | 0 | 19981 - 5 | 5 | 19981 - 6 | 6 | 19981 - 7 | 7 | 19981 - 8 | 8 | 19981 - 9 | 9 | 19981 -(10 rows) - -select ss, x, cint2, count(cint2) from agggroup group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+----+--------+------- - 0 | 0 | | 0 - 3 | 3 | | 0 - 4 | 4 | | 0 - 5 | 5 | | 0 - 6 | 6 | | 0 - 7 | 7 | | 0 - 8 | 8 | | 0 - 9 | 9 | | 0 - 11 | 11 | | 0 - 0 | 0 | -16377 | 1 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count --------+---+----+---+--------+--------+-------+------- - 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 - 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 - 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 - 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 - 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 - 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 - 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 - 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 - 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 - 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 -(10 rows) - -select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; - x | count -----+------- - | 19 - 3 | 19962 - 4 | 19962 - 0 | 19981 - 5 | 19981 - 6 | 19981 - 7 | 19981 - 8 | 19981 - 9 | 19981 - 11 | 39981 -(10 rows) - -select min(cint2) from agggroup; - min --------- - -16383 -(1 row) - -select cint2, min(cint2) from agggroup group by cint2 order by min(cint2), cint2 limit 10; - cint2 | min ---------+-------- - -16383 | -16383 - -16382 | -16382 - -16381 | -16381 - -16380 | -16380 - -16379 | -16379 - -16378 | -16378 - -16377 | -16377 - -16376 | -16376 - -16375 | -16375 - -16374 | -16374 -(10 rows) - -select cint4, min(cint2) from agggroup group by cint4 order by min(cint2), cint4 limit 10; - cint4 | min ---------+-------- - -16190 | -16383 - -13372 | -16383 - -10318 | -16383 - -9008 | -16383 - -3043 | -16383 - 6729 | -16383 - -14012 | -16382 - -8606 | -16382 - -3080 | -16382 - 2223 | -16382 -(10 rows) - -select cint4, cint8, min(cint2) from agggroup group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; - cint4 | cint8 | min ---------+--------+-------- - -16190 | 13646 | -16383 - -13372 | 11094 | -16383 - -10318 | 6326 | -16383 - -9008 | 4390 | -16383 - -3043 | -1794 | -16383 - 6729 | 6717 | -16383 - -14012 | -9888 | -16382 - -8606 | -10357 | -16382 - -3080 | -15609 | -16382 - 2223 | 9035 | -16382 -(10 rows) - -select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 limit 10; - cint8 | min ---------+-------- - -1794 | -16383 - 4390 | -16383 - 6326 | -16383 - 6717 | -16383 - 11094 | -16383 - 13646 | -16383 - -15609 | -16382 - -10357 | -16382 - -9888 | -16382 - 206 | -16382 -(10 rows) - -select s, cint2, min(cint2) from agggroup group by s, cint2 order by min(cint2), s, cint2 limit 10; - s | cint2 | min ----+--------+-------- - 0 | -16383 | -16383 - 4 | -16383 | -16383 - 5 | -16383 | -16383 - 6 | -16383 | -16383 - 2 | -16382 | -16382 - 7 | -16382 | -16382 - 8 | -16382 | -16382 - 2 | -16381 | -16381 - 3 | -16381 | -16381 - 4 | -16381 | -16381 -(10 rows) - -select s, ss, min(cint2) from agggroup group by s, ss order by min(cint2), s, ss limit 10; - s | ss | min ----+----+-------- - 0 | 0 | -16383 - 4 | 4 | -16383 - 5 | 5 | -16383 - 6 | 6 | -16383 - 2 | 11 | -16382 - 7 | 7 | -16382 - 8 | 8 | -16382 - 3 | 3 | -16381 - 1 | 11 | -16378 - 9 | 9 | -16375 -(10 rows) - -select s, x, min(cint2) from agggroup group by s, x order by min(cint2), s, x limit 10; - s | x | min ----+----+-------- - 0 | 0 | -16383 - 4 | 4 | -16383 - 5 | 5 | -16383 - 6 | 6 | -16383 - 2 | 11 | -16382 - 7 | 7 | -16382 - 8 | 8 | -16382 - 3 | 3 | -16381 - 1 | 11 | -16378 - 9 | 9 | -16375 -(10 rows) - -select ss, cint2, x, min(cint2) from agggroup group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; - ss | cint2 | x | min -----+--------+----+-------- - 0 | -16383 | 0 | -16383 - 4 | -16383 | 4 | -16383 - 5 | -16383 | 5 | -16383 - 6 | -16383 | 6 | -16383 - 7 | -16382 | 7 | -16382 - 8 | -16382 | 8 | -16382 - 11 | -16382 | 11 | -16382 - 3 | -16381 | 3 | -16381 - 4 | -16381 | 4 | -16381 - 5 | -16381 | 5 | -16381 -(10 rows) - -select ss, s, min(cint2) from agggroup group by ss, s order by min(cint2), ss, s limit 10; - ss | s | min -----+---+-------- - 0 | 0 | -16383 - 4 | 4 | -16383 - 5 | 5 | -16383 - 6 | 6 | -16383 - 7 | 7 | -16382 - 8 | 8 | -16382 - 11 | 2 | -16382 - 3 | 3 | -16381 - 11 | 1 | -16378 - 9 | 9 | -16375 -(10 rows) - -select ss, x, cint2, min(cint2) from agggroup group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | min -----+----+--------+-------- - 0 | 0 | -16383 | -16383 - 4 | 4 | -16383 | -16383 - 5 | 5 | -16383 | -16383 - 6 | 6 | -16383 | -16383 - 7 | 7 | -16382 | -16382 - 8 | 8 | -16382 | -16382 - 11 | 11 | -16382 | -16382 - 3 | 3 | -16381 | -16381 - 4 | 4 | -16381 | -16381 - 5 | 5 | -16381 | -16381 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | min --------+---+----+----+--------+--------+--------+-------- - 6194 | 0 | 0 | 0 | -13372 | 11094 | -16383 | -16383 - 17044 | 0 | 0 | 0 | -10318 | 6326 | -16383 | -16383 - 53843 | 4 | 4 | 4 | -9008 | 4390 | -16383 | -16383 - 60530 | 5 | 5 | 5 | 6729 | 6717 | -16383 | -16383 - 73208 | 6 | 6 | 6 | -3043 | -1794 | -16383 | -16383 - 74870 | 6 | 6 | 6 | -16190 | 13646 | -16383 | -16383 - 22836 | 2 | 11 | 11 | -3080 | -15609 | -16382 | -16382 - 29858 | 2 | 11 | 11 | -14012 | -9888 | -16382 | -16382 - 31516 | 2 | 11 | 11 | 6193 | 206 | -16382 | -16382 - 76781 | 7 | 7 | 7 | 9938 | 6519 | -16382 | -16382 -(10 rows) - -select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; - x | min -----+-------- - 0 | -16383 - 4 | -16383 - 5 | -16383 - 6 | -16383 - 11 | -16382 - 7 | -16382 - 8 | -16382 - 3 | -16381 - 9 | -16375 - | -16295 -(10 rows) - -select count(*) from agggroup where cint2 > 0; - count -------- - 99664 -(1 row) - -select cint2, count(*) from agggroup where cint2 > 0 group by cint2 order by count(*), cint2 limit 10; - cint2 | count --------+------- - 153 | 1 - 290 | 1 - 490 | 1 - 605 | 1 - 666 | 1 - 700 | 1 - 780 | 1 - 851 | 1 - 936 | 1 - 1001 | 1 -(10 rows) - -select cint4, count(*) from agggroup where cint2 > 0 group by cint4 order by count(*), cint4 limit 10; - cint4 | count ---------+------- - -16383 | 1 - -16380 | 1 - -16371 | 1 - -16368 | 1 - -16366 | 1 - -16365 | 1 - -16363 | 1 - -16360 | 1 - -16356 | 1 - -16350 | 1 -(10 rows) - -select cint4, cint8, count(*) from agggroup where cint2 > 0 group by cint4, cint8 order by count(*), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+-------+------- - -16383 | 4889 | 1 - -16382 | -8851 | 1 - -16382 | -4489 | 1 - -16382 | -470 | 1 - -16382 | 411 | 1 - -16382 | 8377 | 1 - -16382 | 8832 | 1 - -16382 | 15709 | 1 - -16380 | 1449 | 1 - -16379 | 1234 | 1 -(10 rows) - -select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by count(*), cint8 limit 10; - cint8 | count ---------+------- - -16382 | 1 - -16378 | 1 - -16372 | 1 - -16353 | 1 - -16342 | 1 - -16338 | 1 - -16337 | 1 - -16336 | 1 - -16330 | 1 - -16328 | 1 -(10 rows) - -select s, cint2, count(*) from agggroup where cint2 > 0 group by s, cint2 order by count(*), s, cint2 limit 10; - s | cint2 | count ----+-------+------- - 0 | 4 | 1 - 0 | 7 | 1 - 0 | 8 | 1 - 0 | 9 | 1 - 0 | 10 | 1 - 0 | 11 | 1 - 0 | 18 | 1 - 0 | 24 | 1 - 0 | 28 | 1 - 0 | 31 | 1 -(10 rows) - -select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by count(*), s, ss limit 10; - s | ss | count ----+----+------- - 3 | | 9 - 4 | 11 | 9 - 2 | 11 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select s, x, count(*) from agggroup where cint2 > 0 group by s, x order by count(*), s, x limit 10; - s | x | count ----+----+------- - 3 | | 9 - 4 | 11 | 9 - 2 | 11 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select ss, cint2, x, count(*) from agggroup where cint2 > 0 group by ss, cint2, x order by count(*), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+---+------- - 0 | 4 | 0 | 1 - 0 | 7 | 0 | 1 - 0 | 8 | 0 | 1 - 0 | 9 | 0 | 1 - 0 | 10 | 0 | 1 - 0 | 11 | 0 | 1 - 0 | 18 | 0 | 1 - 0 | 24 | 0 | 1 - 0 | 28 | 0 | 1 - 0 | 31 | 0 | 1 -(10 rows) - -select ss, s, count(*) from agggroup where cint2 > 0 group by ss, s order by count(*), ss, s limit 10; - ss | s | count -----+---+------- - 11 | 4 | 9 - | 3 | 9 - 11 | 2 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select ss, x, cint2, count(*) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+---+-------+------- - 0 | 0 | 4 | 1 - 0 | 0 | 7 | 1 - 0 | 0 | 8 | 1 - 0 | 0 | 9 | 1 - 0 | 0 | 10 | 1 - 0 | 0 | 11 | 1 - 0 | 0 | 18 | 1 - 0 | 0 | 24 | 1 - 0 | 0 | 28 | 1 - 0 | 0 | 31 | 1 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count -----+---+----+---+--------+-------+-------+------- - 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 - 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 - 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 - 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 - 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 - 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 - 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 - 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 - 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 - 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 -(10 rows) - -select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; - x | count -----+------- - | 9 - 3 | 9884 - 6 | 9890 - 4 | 9897 - 8 | 9898 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 5 | 10110 - 11 | 19973 -(10 rows) - -select count(cint2) from agggroup where cint2 > 0; - count -------- - 99664 -(1 row) - -select cint2, count(cint2) from agggroup where cint2 > 0 group by cint2 order by count(cint2), cint2 limit 10; - cint2 | count --------+------- - 153 | 1 - 290 | 1 - 490 | 1 - 605 | 1 - 666 | 1 - 700 | 1 - 780 | 1 - 851 | 1 - 936 | 1 - 1001 | 1 -(10 rows) - -select cint4, count(cint2) from agggroup where cint2 > 0 group by cint4 order by count(cint2), cint4 limit 10; - cint4 | count ---------+------- - -16383 | 1 - -16380 | 1 - -16371 | 1 - -16368 | 1 - -16366 | 1 - -16365 | 1 - -16363 | 1 - -16360 | 1 - -16356 | 1 - -16350 | 1 -(10 rows) - -select cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+-------+------- - -16383 | 4889 | 1 - -16382 | -8851 | 1 - -16382 | -4489 | 1 - -16382 | -470 | 1 - -16382 | 411 | 1 - -16382 | 8377 | 1 - -16382 | 8832 | 1 - -16382 | 15709 | 1 - -16380 | 1449 | 1 - -16379 | 1234 | 1 -(10 rows) - -select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by count(cint2), cint8 limit 10; - cint8 | count ---------+------- - -16382 | 1 - -16378 | 1 - -16372 | 1 - -16353 | 1 - -16342 | 1 - -16338 | 1 - -16337 | 1 - -16336 | 1 - -16330 | 1 - -16328 | 1 -(10 rows) - -select s, cint2, count(cint2) from agggroup where cint2 > 0 group by s, cint2 order by count(cint2), s, cint2 limit 10; - s | cint2 | count ----+-------+------- - 0 | 4 | 1 - 0 | 7 | 1 - 0 | 8 | 1 - 0 | 9 | 1 - 0 | 10 | 1 - 0 | 11 | 1 - 0 | 18 | 1 - 0 | 24 | 1 - 0 | 28 | 1 - 0 | 31 | 1 -(10 rows) - -select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by count(cint2), s, ss limit 10; - s | ss | count ----+----+------- - 3 | | 9 - 4 | 11 | 9 - 2 | 11 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select s, x, count(cint2) from agggroup where cint2 > 0 group by s, x order by count(cint2), s, x limit 10; - s | x | count ----+----+------- - 3 | | 9 - 4 | 11 | 9 - 2 | 11 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select ss, cint2, x, count(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+---+------- - 0 | 4 | 0 | 1 - 0 | 7 | 0 | 1 - 0 | 8 | 0 | 1 - 0 | 9 | 0 | 1 - 0 | 10 | 0 | 1 - 0 | 11 | 0 | 1 - 0 | 18 | 0 | 1 - 0 | 24 | 0 | 1 - 0 | 28 | 0 | 1 - 0 | 31 | 0 | 1 -(10 rows) - -select ss, s, count(cint2) from agggroup where cint2 > 0 group by ss, s order by count(cint2), ss, s limit 10; - ss | s | count -----+---+------- - 11 | 4 | 9 - | 3 | 9 - 11 | 2 | 9868 - 3 | 3 | 9884 - 6 | 6 | 9890 - 4 | 4 | 9897 - 8 | 8 | 9898 - 7 | 7 | 9973 - 0 | 0 | 10012 - 9 | 9 | 10018 -(10 rows) - -select ss, x, cint2, count(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+---+-------+------- - 0 | 0 | 4 | 1 - 0 | 0 | 7 | 1 - 0 | 0 | 8 | 1 - 0 | 0 | 9 | 1 - 0 | 0 | 10 | 1 - 0 | 0 | 11 | 1 - 0 | 0 | 18 | 1 - 0 | 0 | 24 | 1 - 0 | 0 | 28 | 1 - 0 | 0 | 31 | 1 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count -----+---+----+---+--------+-------+-------+------- - 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 - 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 - 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 - 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 - 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 - 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 - 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 - 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 - 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 - 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 -(10 rows) - -select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; - x | count -----+------- - | 9 - 3 | 9884 - 6 | 9890 - 4 | 9897 - 8 | 9898 - 7 | 9973 - 0 | 10012 - 9 | 10018 - 5 | 10110 - 11 | 19973 -(10 rows) - -select min(cint2) from agggroup where cint2 > 0; - min ------ - 1 -(1 row) - -select cint2, min(cint2) from agggroup where cint2 > 0 group by cint2 order by min(cint2), cint2 limit 10; - cint2 | min --------+----- - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 - 6 | 6 - 7 | 7 - 8 | 8 - 9 | 9 - 10 | 10 -(10 rows) - -select cint4, min(cint2) from agggroup where cint2 > 0 group by cint4 order by min(cint2), cint4 limit 10; - cint4 | min ---------+----- - -12025 | 1 - -10344 | 1 - -4190 | 1 - -1493 | 1 - 1863 | 1 - 9242 | 1 - 11189 | 1 - 14078 | 1 - 15656 | 1 - -11410 | 2 -(10 rows) - -select cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; - cint4 | cint8 | min ---------+--------+----- - -12025 | -2210 | 1 - -10344 | -13684 | 1 - -4190 | -2827 | 1 - -1493 | -1043 | 1 - 1863 | 7650 | 1 - 9242 | -9798 | 1 - 11189 | -5168 | 1 - 14078 | 9929 | 1 - 15656 | 12597 | 1 - -11410 | 6033 | 2 -(10 rows) - -select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by min(cint2), cint8 limit 10; - cint8 | min ---------+----- - -13684 | 1 - -9798 | 1 - -5168 | 1 - -2827 | 1 - -2210 | 1 - -1043 | 1 - 7650 | 1 - 9929 | 1 - 12597 | 1 - -13639 | 2 -(10 rows) - -select s, cint2, min(cint2) from agggroup where cint2 > 0 group by s, cint2 order by min(cint2), s, cint2 limit 10; - s | cint2 | min ----+-------+----- - 1 | 1 | 1 - 2 | 1 | 1 - 3 | 1 | 1 - 5 | 1 | 1 - 7 | 1 | 1 - 8 | 1 | 1 - 1 | 2 | 2 - 3 | 2 | 2 - 7 | 2 | 2 - 9 | 2 | 2 -(10 rows) - -select s, ss, min(cint2) from agggroup where cint2 > 0 group by s, ss order by min(cint2), s, ss limit 10; - s | ss | min ----+----+----- - 1 | 11 | 1 - 2 | 11 | 1 - 3 | 3 | 1 - 5 | 5 | 1 - 7 | 7 | 1 - 8 | 8 | 1 - 9 | 9 | 2 - 6 | 6 | 3 - 0 | 0 | 4 - 4 | 4 | 4 -(10 rows) - -select s, x, min(cint2) from agggroup where cint2 > 0 group by s, x order by min(cint2), s, x limit 10; - s | x | min ----+----+----- - 1 | 11 | 1 - 2 | 11 | 1 - 3 | 3 | 1 - 5 | 5 | 1 - 7 | 7 | 1 - 8 | 8 | 1 - 9 | 9 | 2 - 6 | 6 | 3 - 0 | 0 | 4 - 4 | 4 | 4 -(10 rows) - -select ss, cint2, x, min(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; - ss | cint2 | x | min -----+-------+----+----- - 3 | 1 | 3 | 1 - 5 | 1 | 5 | 1 - 7 | 1 | 7 | 1 - 8 | 1 | 8 | 1 - 11 | 1 | 11 | 1 - 3 | 2 | 3 | 2 - 7 | 2 | 7 | 2 - 9 | 2 | 9 | 2 - 11 | 2 | 11 | 2 - 3 | 3 | 3 | 3 -(10 rows) - -select ss, s, min(cint2) from agggroup where cint2 > 0 group by ss, s order by min(cint2), ss, s limit 10; - ss | s | min -----+---+----- - 3 | 3 | 1 - 5 | 5 | 1 - 7 | 7 | 1 - 8 | 8 | 1 - 11 | 1 | 1 - 11 | 2 | 1 - 9 | 9 | 2 - 6 | 6 | 3 - 0 | 0 | 4 - 4 | 4 | 4 -(10 rows) - -select ss, x, cint2, min(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | min -----+----+-------+----- - 3 | 3 | 1 | 1 - 5 | 5 | 1 | 1 - 7 | 7 | 1 | 1 - 8 | 8 | 1 | 1 - 11 | 11 | 1 | 1 - 3 | 3 | 2 | 2 - 7 | 7 | 2 | 2 - 9 | 9 | 2 | 2 - 11 | 11 | 2 | 2 - 3 | 3 | 3 | 3 -(10 rows) - -select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | min --------+---+----+----+--------+--------+-------+----- - 11611 | 1 | 11 | 11 | -12025 | -2210 | 1 | 1 - 28649 | 2 | 11 | 11 | -1493 | -1043 | 1 | 1 - 28786 | 1 | 11 | 11 | -4190 | -2827 | 1 | 1 - 41774 | 3 | 3 | 3 | 1863 | 7650 | 1 | 1 - 41779 | 3 | 3 | 3 | 14078 | 9929 | 1 | 1 - 51152 | 5 | 5 | 5 | 9242 | -9798 | 1 | 1 - 70932 | 7 | 7 | 7 | -10344 | -13684 | 1 | 1 - 86957 | 7 | 7 | 7 | 15656 | 12597 | 1 | 1 - 89689 | 8 | 8 | 8 | 11189 | -5168 | 1 | 1 - 22147 | 1 | 11 | 11 | -9569 | 9760 | 2 | 2 -(10 rows) - -select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; - x | min -----+------ - 11 | 1 - 3 | 1 - 5 | 1 - 7 | 1 - 8 | 1 - 9 | 2 - 6 | 3 - 0 | 4 - 4 | 4 - | 4895 -(10 rows) - -select count(*) from agggroup where cint2 is null; - count -------- - 190 -(1 row) - -select cint2, count(*) from agggroup where cint2 is null group by cint2 order by count(*), cint2 limit 10; - cint2 | count --------+------- - | 190 -(1 row) - -select cint4, count(*) from agggroup where cint2 is null group by cint4 order by count(*), cint4 limit 10; - cint4 | count ---------+------- - -16291 | 1 - -16091 | 1 - -15799 | 1 - -15724 | 1 - -15328 | 1 - -15279 | 1 - -15063 | 1 - -14998 | 1 - -14949 | 1 - -14848 | 1 -(10 rows) - -select cint4, cint8, count(*) from agggroup where cint2 is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+--------+------- - -16291 | 113 | 1 - -16091 | -4084 | 1 - -15799 | 12603 | 1 - -15724 | 15426 | 1 - -15328 | -6092 | 1 - -15279 | -3475 | 1 - -15063 | 3990 | 1 - -14998 | 14464 | 1 - -14949 | -10395 | 1 - -14848 | 3110 | 1 -(10 rows) - -select cint8, count(*) from agggroup where cint2 is null group by cint8 order by count(*), cint8 limit 10; - cint8 | count ---------+------- - -16026 | 1 - -15987 | 1 - -15904 | 1 - -15897 | 1 - -15761 | 1 - -15506 | 1 - -15346 | 1 - -14986 | 1 - -14811 | 1 - -14674 | 1 -(10 rows) - -select s, cint2, count(*) from agggroup where cint2 is null group by s, cint2 order by count(*), s, cint2 limit 10; - s | cint2 | count ----+-------+------- - 0 | | 19 - 1 | | 19 - 2 | | 19 - 3 | | 19 - 4 | | 19 - 5 | | 19 - 6 | | 19 - 7 | | 19 - 8 | | 19 - 9 | | 19 -(10 rows) - -select s, ss, count(*) from agggroup where cint2 is null group by s, ss order by count(*), s, ss limit 10; - s | ss | count ----+----+------- - 0 | 0 | 19 - 1 | 11 | 19 - 2 | 11 | 19 - 3 | 3 | 19 - 4 | 4 | 19 - 5 | 5 | 19 - 6 | 6 | 19 - 7 | 7 | 19 - 8 | 8 | 19 - 9 | 9 | 19 -(10 rows) - -select s, x, count(*) from agggroup where cint2 is null group by s, x order by count(*), s, x limit 10; - s | x | count ----+----+------- - 0 | 0 | 19 - 1 | 11 | 19 - 2 | 11 | 19 - 3 | 3 | 19 - 4 | 4 | 19 - 5 | 5 | 19 - 6 | 6 | 19 - 7 | 7 | 19 - 8 | 8 | 19 - 9 | 9 | 19 -(10 rows) - -select ss, cint2, x, count(*) from agggroup where cint2 is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+----+------- - 0 | | 0 | 19 - 3 | | 3 | 19 - 4 | | 4 | 19 - 5 | | 5 | 19 - 6 | | 6 | 19 - 7 | | 7 | 19 - 8 | | 8 | 19 - 9 | | 9 | 19 - 11 | | 11 | 38 -(9 rows) - -select ss, s, count(*) from agggroup where cint2 is null group by ss, s order by count(*), ss, s limit 10; - ss | s | count -----+---+------- - 0 | 0 | 19 - 3 | 3 | 19 - 4 | 4 | 19 - 5 | 5 | 19 - 6 | 6 | 19 - 7 | 7 | 19 - 8 | 8 | 19 - 9 | 9 | 19 - 11 | 1 | 19 - 11 | 2 | 19 -(10 rows) - -select ss, x, cint2, count(*) from agggroup where cint2 is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+----+-------+------- - 0 | 0 | | 19 - 3 | 3 | | 19 - 4 | 4 | | 19 - 5 | 5 | | 19 - 6 | 6 | | 19 - 7 | 7 | | 19 - 8 | 8 | | 19 - 9 | 9 | | 19 - 11 | 11 | | 38 -(9 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count --------+---+----+---+--------+--------+-------+------- - 1051 | 0 | 0 | 0 | -8612 | 14327 | | 1 - 2102 | 0 | 0 | 0 | 11069 | 16047 | | 1 - 3153 | 0 | 0 | 0 | 6192 | 12700 | | 1 - 4204 | 0 | 0 | 0 | 4165 | -10102 | | 1 - 5255 | 0 | 0 | 0 | 16314 | 13418 | | 1 - 6306 | 0 | 0 | 0 | 701 | -3029 | | 1 - 7357 | 0 | 0 | 0 | 1115 | 4913 | | 1 - 8408 | 0 | 0 | 0 | 15553 | 1743 | | 1 - 9459 | 0 | 0 | 0 | -14640 | 11933 | | 1 - 10510 | 0 | 0 | 0 | -14725 | 6531 | | 1 -(10 rows) - -select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; - x | count -----+------- - 0 | 19 - 3 | 19 - 4 | 19 - 5 | 19 - 6 | 19 - 7 | 19 - 8 | 19 - 9 | 19 - 11 | 38 -(9 rows) - -select count(cint2) from agggroup where cint2 is null; - count -------- - 0 -(1 row) - -select cint2, count(cint2) from agggroup where cint2 is null group by cint2 order by count(cint2), cint2 limit 10; - cint2 | count --------+------- - | 0 -(1 row) - -select cint4, count(cint2) from agggroup where cint2 is null group by cint4 order by count(cint2), cint4 limit 10; - cint4 | count ---------+------- - -16291 | 0 - -16091 | 0 - -15799 | 0 - -15724 | 0 - -15328 | 0 - -15279 | 0 - -15063 | 0 - -14998 | 0 - -14949 | 0 - -14848 | 0 -(10 rows) - -select cint4, cint8, count(cint2) from agggroup where cint2 is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; - cint4 | cint8 | count ---------+--------+------- - -16291 | 113 | 0 - -16091 | -4084 | 0 - -15799 | 12603 | 0 - -15724 | 15426 | 0 - -15328 | -6092 | 0 - -15279 | -3475 | 0 - -15063 | 3990 | 0 - -14998 | 14464 | 0 - -14949 | -10395 | 0 - -14848 | 3110 | 0 -(10 rows) - -select cint8, count(cint2) from agggroup where cint2 is null group by cint8 order by count(cint2), cint8 limit 10; - cint8 | count ---------+------- - -16026 | 0 - -15987 | 0 - -15904 | 0 - -15897 | 0 - -15761 | 0 - -15506 | 0 - -15346 | 0 - -14986 | 0 - -14811 | 0 - -14674 | 0 -(10 rows) - -select s, cint2, count(cint2) from agggroup where cint2 is null group by s, cint2 order by count(cint2), s, cint2 limit 10; - s | cint2 | count ----+-------+------- - 0 | | 0 - 1 | | 0 - 2 | | 0 - 3 | | 0 - 4 | | 0 - 5 | | 0 - 6 | | 0 - 7 | | 0 - 8 | | 0 - 9 | | 0 -(10 rows) - -select s, ss, count(cint2) from agggroup where cint2 is null group by s, ss order by count(cint2), s, ss limit 10; - s | ss | count ----+----+------- - 0 | 0 | 0 - 1 | 11 | 0 - 2 | 11 | 0 - 3 | 3 | 0 - 4 | 4 | 0 - 5 | 5 | 0 - 6 | 6 | 0 - 7 | 7 | 0 - 8 | 8 | 0 - 9 | 9 | 0 -(10 rows) - -select s, x, count(cint2) from agggroup where cint2 is null group by s, x order by count(cint2), s, x limit 10; - s | x | count ----+----+------- - 0 | 0 | 0 - 1 | 11 | 0 - 2 | 11 | 0 - 3 | 3 | 0 - 4 | 4 | 0 - 5 | 5 | 0 - 6 | 6 | 0 - 7 | 7 | 0 - 8 | 8 | 0 - 9 | 9 | 0 -(10 rows) - -select ss, cint2, x, count(cint2) from agggroup where cint2 is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+----+------- - 0 | | 0 | 0 - 3 | | 3 | 0 - 4 | | 4 | 0 - 5 | | 5 | 0 - 6 | | 6 | 0 - 7 | | 7 | 0 - 8 | | 8 | 0 - 9 | | 9 | 0 - 11 | | 11 | 0 -(9 rows) - -select ss, s, count(cint2) from agggroup where cint2 is null group by ss, s order by count(cint2), ss, s limit 10; - ss | s | count -----+---+------- - 0 | 0 | 0 - 3 | 3 | 0 - 4 | 4 | 0 - 5 | 5 | 0 - 6 | 6 | 0 - 7 | 7 | 0 - 8 | 8 | 0 - 9 | 9 | 0 - 11 | 1 | 0 - 11 | 2 | 0 -(10 rows) - -select ss, x, cint2, count(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+----+-------+------- - 0 | 0 | | 0 - 3 | 3 | | 0 - 4 | 4 | | 0 - 5 | 5 | | 0 - 6 | 6 | | 0 - 7 | 7 | | 0 - 8 | 8 | | 0 - 9 | 9 | | 0 - 11 | 11 | | 0 -(9 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count --------+---+----+---+--------+--------+-------+------- - 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 - 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 - 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 - 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 - 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 - 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 - 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 - 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 - 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 - 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 -(10 rows) - -select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; - x | count -----+------- - 0 | 0 - 11 | 0 - 3 | 0 - 4 | 0 - 5 | 0 - 6 | 0 - 7 | 0 - 8 | 0 - 9 | 0 -(9 rows) - -select min(cint2) from agggroup where cint2 is null; - min ------ - -(1 row) - -select cint2, min(cint2) from agggroup where cint2 is null group by cint2 order by min(cint2), cint2 limit 10; - cint2 | min --------+----- - | -(1 row) - -select cint4, min(cint2) from agggroup where cint2 is null group by cint4 order by min(cint2), cint4 limit 10; - cint4 | min ---------+----- - -16291 | - -16091 | - -15799 | - -15724 | - -15328 | - -15279 | - -15063 | - -14998 | - -14949 | - -14848 | -(10 rows) - -select cint4, cint8, min(cint2) from agggroup where cint2 is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; - cint4 | cint8 | min ---------+--------+----- - -16291 | 113 | - -16091 | -4084 | - -15799 | 12603 | - -15724 | 15426 | - -15328 | -6092 | - -15279 | -3475 | - -15063 | 3990 | - -14998 | 14464 | - -14949 | -10395 | - -14848 | 3110 | -(10 rows) - -select cint8, min(cint2) from agggroup where cint2 is null group by cint8 order by min(cint2), cint8 limit 10; - cint8 | min ---------+----- - -16026 | - -15987 | - -15904 | - -15897 | - -15761 | - -15506 | - -15346 | - -14986 | - -14811 | - -14674 | -(10 rows) - -select s, cint2, min(cint2) from agggroup where cint2 is null group by s, cint2 order by min(cint2), s, cint2 limit 10; - s | cint2 | min ----+-------+----- - 0 | | - 1 | | - 2 | | - 3 | | - 4 | | - 5 | | - 6 | | - 7 | | - 8 | | - 9 | | -(10 rows) - -select s, ss, min(cint2) from agggroup where cint2 is null group by s, ss order by min(cint2), s, ss limit 10; - s | ss | min ----+----+----- - 0 | 0 | - 1 | 11 | - 2 | 11 | - 3 | 3 | - 4 | 4 | - 5 | 5 | - 6 | 6 | - 7 | 7 | - 8 | 8 | - 9 | 9 | -(10 rows) - -select s, x, min(cint2) from agggroup where cint2 is null group by s, x order by min(cint2), s, x limit 10; - s | x | min ----+----+----- - 0 | 0 | - 1 | 11 | - 2 | 11 | - 3 | 3 | - 4 | 4 | - 5 | 5 | - 6 | 6 | - 7 | 7 | - 8 | 8 | - 9 | 9 | -(10 rows) - -select ss, cint2, x, min(cint2) from agggroup where cint2 is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; - ss | cint2 | x | min -----+-------+----+----- - 0 | | 0 | - 3 | | 3 | - 4 | | 4 | - 5 | | 5 | - 6 | | 6 | - 7 | | 7 | - 8 | | 8 | - 9 | | 9 | - 11 | | 11 | -(9 rows) - -select ss, s, min(cint2) from agggroup where cint2 is null group by ss, s order by min(cint2), ss, s limit 10; - ss | s | min -----+---+----- - 0 | 0 | - 3 | 3 | - 4 | 4 | - 5 | 5 | - 6 | 6 | - 7 | 7 | - 8 | 8 | - 9 | 9 | - 11 | 1 | - 11 | 2 | -(10 rows) - -select ss, x, cint2, min(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | min -----+----+-------+----- - 0 | 0 | | - 3 | 3 | | - 4 | 4 | | - 5 | 5 | | - 6 | 6 | | - 7 | 7 | | - 8 | 8 | | - 9 | 9 | | - 11 | 11 | | -(9 rows) - -select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | min --------+---+----+---+--------+--------+-------+----- - 1051 | 0 | 0 | 0 | -8612 | 14327 | | - 2102 | 0 | 0 | 0 | 11069 | 16047 | | - 3153 | 0 | 0 | 0 | 6192 | 12700 | | - 4204 | 0 | 0 | 0 | 4165 | -10102 | | - 5255 | 0 | 0 | 0 | 16314 | 13418 | | - 6306 | 0 | 0 | 0 | 701 | -3029 | | - 7357 | 0 | 0 | 0 | 1115 | 4913 | | - 8408 | 0 | 0 | 0 | 15553 | 1743 | | - 9459 | 0 | 0 | 0 | -14640 | 11933 | | - 10510 | 0 | 0 | 0 | -14725 | 6531 | | -(10 rows) - -select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; - x | min -----+----- - 0 | - 11 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(9 rows) - -select count(*) from agggroup where cint2 is null and x is null; - count -------- - 0 -(1 row) - -select cint2, count(*) from agggroup where cint2 is null and x is null group by cint2 order by count(*), cint2 limit 10; - cint2 | count --------+------- -(0 rows) - -select cint4, count(*) from agggroup where cint2 is null and x is null group by cint4 order by count(*), cint4 limit 10; - cint4 | count --------+------- -(0 rows) - -select cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; - cint4 | cint8 | count --------+-------+------- -(0 rows) - -select cint8, count(*) from agggroup where cint2 is null and x is null group by cint8 order by count(*), cint8 limit 10; - cint8 | count --------+------- -(0 rows) - -select s, cint2, count(*) from agggroup where cint2 is null and x is null group by s, cint2 order by count(*), s, cint2 limit 10; - s | cint2 | count ----+-------+------- -(0 rows) - -select s, ss, count(*) from agggroup where cint2 is null and x is null group by s, ss order by count(*), s, ss limit 10; - s | ss | count ----+----+------- -(0 rows) - -select s, x, count(*) from agggroup where cint2 is null and x is null group by s, x order by count(*), s, x limit 10; - s | x | count ----+---+------- -(0 rows) - -select ss, cint2, x, count(*) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+---+------- -(0 rows) - -select ss, s, count(*) from agggroup where cint2 is null and x is null group by ss, s order by count(*), ss, s limit 10; - ss | s | count -----+---+------- -(0 rows) - -select ss, x, cint2, count(*) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+---+-------+------- -(0 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count ----+---+----+---+-------+-------+-------+------- -(0 rows) - -select x, count(*) from agggroup where cint2 is null and x is null group by x order by count(*), x limit 10; - x | count ----+------- -(0 rows) - -select count(cint2) from agggroup where cint2 is null and x is null; - count -------- - 0 -(1 row) - -select cint2, count(cint2) from agggroup where cint2 is null and x is null group by cint2 order by count(cint2), cint2 limit 10; - cint2 | count --------+------- -(0 rows) - -select cint4, count(cint2) from agggroup where cint2 is null and x is null group by cint4 order by count(cint2), cint4 limit 10; - cint4 | count --------+------- -(0 rows) - -select cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; - cint4 | cint8 | count --------+-------+------- -(0 rows) - -select cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint8 order by count(cint2), cint8 limit 10; - cint8 | count --------+------- -(0 rows) - -select s, cint2, count(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by count(cint2), s, cint2 limit 10; - s | cint2 | count ----+-------+------- -(0 rows) - -select s, ss, count(cint2) from agggroup where cint2 is null and x is null group by s, ss order by count(cint2), s, ss limit 10; - s | ss | count ----+----+------- -(0 rows) - -select s, x, count(cint2) from agggroup where cint2 is null and x is null group by s, x order by count(cint2), s, x limit 10; - s | x | count ----+---+------- -(0 rows) - -select ss, cint2, x, count(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; - ss | cint2 | x | count -----+-------+---+------- -(0 rows) - -select ss, s, count(cint2) from agggroup where cint2 is null and x is null group by ss, s order by count(cint2), ss, s limit 10; - ss | s | count -----+---+------- -(0 rows) - -select ss, x, cint2, count(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | count -----+---+-------+------- -(0 rows) - -select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | count ----+---+----+---+-------+-------+-------+------- -(0 rows) - -select x, count(cint2) from agggroup where cint2 is null and x is null group by x order by count(cint2), x limit 10; - x | count ----+------- -(0 rows) - -select min(cint2) from agggroup where cint2 is null and x is null; - min ------ - -(1 row) - -select cint2, min(cint2) from agggroup where cint2 is null and x is null group by cint2 order by min(cint2), cint2 limit 10; - cint2 | min --------+----- -(0 rows) - -select cint4, min(cint2) from agggroup where cint2 is null and x is null group by cint4 order by min(cint2), cint4 limit 10; - cint4 | min --------+----- -(0 rows) - -select cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; - cint4 | cint8 | min --------+-------+----- -(0 rows) - -select cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint8 order by min(cint2), cint8 limit 10; - cint8 | min --------+----- -(0 rows) - -select s, cint2, min(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by min(cint2), s, cint2 limit 10; - s | cint2 | min ----+-------+----- -(0 rows) - -select s, ss, min(cint2) from agggroup where cint2 is null and x is null group by s, ss order by min(cint2), s, ss limit 10; - s | ss | min ----+----+----- -(0 rows) - -select s, x, min(cint2) from agggroup where cint2 is null and x is null group by s, x order by min(cint2), s, x limit 10; - s | x | min ----+---+----- -(0 rows) - -select ss, cint2, x, min(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; - ss | cint2 | x | min -----+-------+---+----- -(0 rows) - -select ss, s, min(cint2) from agggroup where cint2 is null and x is null group by ss, s order by min(cint2), ss, s limit 10; - ss | s | min -----+---+----- -(0 rows) - -select ss, x, cint2, min(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; - ss | x | cint2 | min -----+---+-------+----- -(0 rows) - -select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; - t | s | ss | x | cint4 | cint8 | cint2 | min ----+---+----+---+-------+-------+-------+----- -(0 rows) - -select x, min(cint2) from agggroup where cint2 is null and x is null group by x order by min(cint2), x limit 10; - x | min ----+----- -(0 rows) - -reset timescaledb.debug_require_vector_agg; -create table long(t int, a text, b text, c text, d text); -select create_hypertable('long', 't'); -NOTICE: adding not-null constraint to column "t" - create_hypertable -------------------- - (3,public,long,t) -(1 row) - -insert into long select n, x, x, x, x from ( - select n, repeat('1', 100 * 4 + n) x - from generate_series(1, 4) n) t -; -insert into long values (-1, 'a', 'b', 'c', 'd'); -alter table long set (timescaledb.compress); -WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes -NOTICE: default segment by for hypertable "long" is set to "" -NOTICE: default order by for hypertable "long" is set to "t DESC" -select count(compress_chunk(x)) from show_chunks('long') x; - count -------- - 2 -(1 row) - -set timescaledb.debug_require_vector_agg = 'require'; -select count(*) from long group by a, b, c, d order by 1 limit 10; - count -------- - 1 - 1 - 1 - 1 - 1 -(5 rows) - -reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/expected/vector_agg_text.out b/tsl/test/expected/vector_agg_text.out new file mode 100644 index 00000000000..3e38713f3fe --- /dev/null +++ b/tsl/test/expected/vector_agg_text.out @@ -0,0 +1,283 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +----------------------- + (1,public,agggroup,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into agggroup select * from source where s = 1; +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 1 +(1 row) + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1051 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze agggroup; +-- Long strings +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +------------------- + (3,public,long,t) +(1 row) + +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes +NOTICE: default segment by for hypertable "long" is set to "" +NOTICE: default order by for hypertable "long" is set to "t DESC" +select count(compress_chunk(x)) from show_chunks('long') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_chunkwise_aggregation to off; set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), + unnest(array['x']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec +select x, count(*) from agggroup group by x order by count(*), x limit 10; + x | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; + x | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + +select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; + x | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 11 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 9 | -16375 + | -16295 +(10 rows) + +select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; + x | min +----+------ + 11 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 4895 +(10 rows) + +select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; + x | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; + x | count +----+------- + 0 | 0 + 11 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(9 rows) + +select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; + x | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select x, count(*) from agggroup where cint2 is null and x is null group by x order by count(*), x limit 10; + x | count +---+------- +(0 rows) + +select x, count(cint2) from agggroup where cint2 is null and x is null group by x order by count(cint2), x limit 10; + x | count +---+------- +(0 rows) + +select x, min(cint2) from agggroup where cint2 is null and x is null group by x order by min(cint2), x limit 10; + x | min +---+----- +(0 rows) + +-- Test grouping by long strings +select count(*) from long group by a order by 1 limit 10; + count +------- + 1 + 1 + 1 + 1 + 1 +(5 rows) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index b6c89efd677..c60b30d3c19 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -116,7 +116,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) feature_flags.sql vector_agg_default.sql vector_agg_filter.sql - vector_agg_grouping.sql + vector_agg_text.sql vector_agg_memory.sql vector_agg_segmentby.sql) diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_text.sql similarity index 85% rename from tsl/test/sql/vector_agg_grouping.sql rename to tsl/test/sql/vector_agg_text.sql index e087e54c48e..51542d6306a 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_text.sql @@ -54,14 +54,26 @@ select *, ss::text as x from ( from source where s != 1 ) t ; + select count(compress_chunk(x)) from show_chunks('agggroup') x; vacuum freeze analyze agggroup; +-- Long strings +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +select count(compress_chunk(x)) from show_chunks('long') x; + set timescaledb.debug_require_vector_agg = 'require'; ---- Uncomment to generate reference. Note that there are minor discrepancies ---- on float4 due to different numeric stability in our and PG implementations. ---set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +--set timescaledb.enable_chunkwise_aggregation to off; set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'forbid'; select format('%sselect %s%s(%s) from agggroup%s%s%s;', @@ -87,20 +99,7 @@ from 'cint2 > 0', 'cint2 is null', 'cint2 is null and x is null']) with ordinality as condition(condition, n), - unnest(array[ - null, - 'cint2', - 'cint4', - 'cint4, cint8', - 'cint8', - 's, cint2', - 's, ss', - 's, x', - 'ss, cint2, x', - 'ss, s', - 'ss, x, cint2', - 't, s, ss, x, cint4, cint8, cint2', - 'x']) with ordinality as grouping(grouping, n) + unnest(array['x']) with ordinality as grouping(grouping, n) where true and (explain is null /* or condition is null and grouping = 's' */) @@ -108,19 +107,7 @@ where order by explain, condition.n, variable, function, grouping.n \gexec -reset timescaledb.debug_require_vector_agg; - +-- Test grouping by long strings +select count(*) from long group by a order by 1 limit 10; -create table long(t int, a text, b text, c text, d text); -select create_hypertable('long', 't'); -insert into long select n, x, x, x, x from ( - select n, repeat('1', 100 * 4 + n) x - from generate_series(1, 4) n) t -; -insert into long values (-1, 'a', 'b', 'c', 'd'); -alter table long set (timescaledb.compress); -select count(compress_chunk(x)) from show_chunks('long') x; - -set timescaledb.debug_require_vector_agg = 'require'; -select count(*) from long group by a, b, c, d order by 1 limit 10; reset timescaledb.debug_require_vector_agg; From 979e59b57117d725eaa496c18d69c8fc091d72d2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 14:53:18 +0100 Subject: [PATCH 200/242] cleanup --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 51a8ea29467..2f42e666699 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -12,7 +12,6 @@ #include -#include "bytes_view.h" #include "compression/arrow_c_data_interface.h" #include "nodes/decompress_chunk/compressed_batch.h" #include "nodes/vector_agg/exec.h" From 3311861438e408740cb9616c66adb9a56c20fbf8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 15:01:42 +0100 Subject: [PATCH 201/242] bytes view --- .../nodes/vector_agg/hashing/hash_strategy_single_text.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 2f42e666699..236a0a8c133 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -32,6 +32,12 @@ single_text_key_hashing_init(HashingStrategy *hashing) hashing->umash_params = umash_key_hashing_init(); } +typedef struct BytesView +{ + const uint8 *data; + uint32 len; +} BytesView; + static BytesView get_bytes_view(CompressedColumnValues *column_values, int arrow_row) { From ef106b74999d3f9f6d980097d8b2df8d98472e01 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:09:02 +0100 Subject: [PATCH 202/242] fix the test --- tsl/test/expected/vectorized_aggregation.out | 20 ++++++++++---------- tsl/test/sql/vectorized_aggregation.sql | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index d0df3025f6e..a65b8dd1376 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -536,7 +536,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value (63 rows) --- Vectorization possible with grouping by multiple columns +-- Vectorization not possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; QUERY PLAN @@ -548,23 +548,23 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Custom Scan (VectorAgg) - Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) - Grouping Policy: hashed with serialized key + -> Partial HashAggregate + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) + Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Custom Scan (VectorAgg) - Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) - Grouping Policy: hashed with serialized key + -> Partial HashAggregate + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) + Group Key: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Custom Scan (VectorAgg) - Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) - Grouping Policy: hashed with serialized key + -> Partial HashAggregate + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) + Group Key: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index b54cd74f263..86a9f5d801c 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -59,7 +59,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; --- Vectorization possible with grouping by multiple columns +-- Vectorization not possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; From 89fd4ade4e67800641c216d6d4ebbc20b6515eeb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:50:56 +0100 Subject: [PATCH 203/242] disable clang-tidy for imported code --- tsl/src/import/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tsl/src/import/CMakeLists.txt b/tsl/src/import/CMakeLists.txt index f0bf598d393..d61b88e2506 100644 --- a/tsl/src/import/CMakeLists.txt +++ b/tsl/src/import/CMakeLists.txt @@ -4,4 +4,9 @@ if(USE_UMASH) list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) endif() -target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) +# Disable clang-tidy for imported code +add_library(target_no_static_code_analysis OBJECT ${SOURCES}) +set_target_properties(target_no_static_code_analysis PROPERTIES C_CLANG_TIDY "") + +target_link_libraries(${TSL_LIBRARY_NAME} + $) From 192ec2c1e9fc245519d6c4004fb00ad549d44df7 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:55:23 +0100 Subject: [PATCH 204/242] try to detect i386 differently --- tsl/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index a89b47d2453..a76c015ea50 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -14,11 +14,14 @@ if(CC_PCLMUL) set(CMAKE_REQUIRED_FLAGS -mpclmul) endif() +# Detect if we have the needed instructions. +# Also refer to this link for the proper way of detecting i386: +# https://wiki.debian.org/X32Port set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) check_c_source_compiles( " #if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) \ - && !(defined(__aarch64__) || defined(__x86_64__)) + && !(defined(__aarch64__) || (defined(__x86_64__) && !defined(__ILP32__))) #error Unsupported platform for UMASH #endif " From 37b4ccaa794fa52375522b913467f7e107bdf79d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:48:56 +0100 Subject: [PATCH 205/242] fix cmake --- tsl/CMakeLists.txt | 5 ++--- tsl/src/import/CMakeLists.txt | 13 ++++++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index a76c015ea50..2d812829193 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -14,9 +14,8 @@ if(CC_PCLMUL) set(CMAKE_REQUIRED_FLAGS -mpclmul) endif() -# Detect if we have the needed instructions. -# Also refer to this link for the proper way of detecting i386: -# https://wiki.debian.org/X32Port +# Detect if we have the needed instructions. Also refer to this link for the +# proper way of detecting i386: https://wiki.debian.org/X32Port set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) check_c_source_compiles( " diff --git a/tsl/src/import/CMakeLists.txt b/tsl/src/import/CMakeLists.txt index d61b88e2506..b938decf792 100644 --- a/tsl/src/import/CMakeLists.txt +++ b/tsl/src/import/CMakeLists.txt @@ -4,9 +4,12 @@ if(USE_UMASH) list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/umash.c) endif() -# Disable clang-tidy for imported code -add_library(target_no_static_code_analysis OBJECT ${SOURCES}) -set_target_properties(target_no_static_code_analysis PROPERTIES C_CLANG_TIDY "") +if(SOURCES) + # Disable clang-tidy for imported code + add_library(target_no_static_code_analysis OBJECT ${SOURCES}) + set_target_properties(target_no_static_code_analysis PROPERTIES C_CLANG_TIDY + "") -target_link_libraries(${TSL_LIBRARY_NAME} - $) + target_link_libraries(${TSL_LIBRARY_NAME} + $) +endif() From 16d490824dcdcb8622fa969e828d5cf3e528f057 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:51:08 +0100 Subject: [PATCH 206/242] clang-tidy --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 236a0a8c133..498877a06f8 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -91,7 +91,7 @@ single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restri DEBUG_PRINT("\n"); const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, - /* seed = */ -1ull, + /* seed = */ ~0ULL, output_key->data, output_key->len); *hash_table_key = umash_fingerprint_get_key(fp); From e4b79ef3521d8fad67eeb52330b9ef136de4a493 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:21:15 +0100 Subject: [PATCH 207/242] fix? --- tsl/src/import/umash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/import/umash.c b/tsl/src/import/umash.c index eebcf8e2ced..1c112a02112 100644 --- a/tsl/src/import/umash.c +++ b/tsl/src/import/umash.c @@ -138,7 +138,7 @@ v128_shift(v128 x) static inline v128 v128_clmul(uint64_t x, uint64_t y) { - return _mm_clmulepi64_si128(_mm_cvtsi64_si128(x), _mm_cvtsi64_si128(y), 0); + return _mm_clmulepi64_si128(_mm_cvtsi64x_si128(x), _mm_cvtsi64x_si128(y), 0); } /* Computes the 128-bit carryless product of the high and low halves of x. */ From 5b08c990b25f5ea5a5fbff8a1b40735c9e7d9060 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:40:34 +0100 Subject: [PATCH 208/242] cmake --- tsl/CMakeLists.txt | 36 ++++++++++++++++++++++++------------ tsl/src/import/umash.c | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 2d812829193..b4009840c36 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -4,23 +4,35 @@ if(COMPRESSION_FUZZING) add_compile_definitions(TS_COMPRESSION_FUZZING=1) endif() -# Check whether the UMASH hashing can be supported. We use it for vectorized -# grouping. -check_c_compiler_flag(-mpclmul CC_PCLMUL) -if(CC_PCLMUL) - add_compile_options(-mpclmul) - # For the "C source compiles" check below, it doesn't use the global - # compilation flags. - set(CMAKE_REQUIRED_FLAGS -mpclmul) +# Check whether we can enable the pclmul instruction required for the UMASH +# hashing on amd64. Shouldn't be done if the user has manually specified the +# target architecture, no idea how to detect this, but at least we shouldn't do +# this when cross-compiling. +if(NOT CMAKE_CROSSCOMPILING) + check_c_compiler_flag(-mpclmul CC_PCLMUL) + if(CC_PCLMUL) + add_compile_options(-mpclmul) + # The "C source compiles" check below doesn't use the global compilation + # flags, so we have to modify its flags separately. + set(CMAKE_REQUIRED_FLAGS -mpclmul) + endif() endif() -# Detect if we have the needed instructions. Also refer to this link for the -# proper way of detecting i386: https://wiki.debian.org/X32Port +# Detect if we can compile UMASH on this platform. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) check_c_source_compiles( " -#if !defined(__PCLMUL__) && !defined(__ARM_FEATURE_CRYPTO) \ - && !(defined(__aarch64__) || (defined(__x86_64__) && !defined(__ILP32__))) +#if defined(__PCLMUL__) +#include +#include +/* + * For some reason, this doesn't compile on our i386 CI, but I also can't detect + * it using the standart condition of defined(__x86_64__) && !defined(__ILP32__), + * as described at https://wiki.debian.org/X32Port . + */ +void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } +#elif defined(__ARM_FEATURE_CRYPTO) +#else #error Unsupported platform for UMASH #endif " diff --git a/tsl/src/import/umash.c b/tsl/src/import/umash.c index 1c112a02112..eebcf8e2ced 100644 --- a/tsl/src/import/umash.c +++ b/tsl/src/import/umash.c @@ -138,7 +138,7 @@ v128_shift(v128 x) static inline v128 v128_clmul(uint64_t x, uint64_t y) { - return _mm_clmulepi64_si128(_mm_cvtsi64x_si128(x), _mm_cvtsi64x_si128(y), 0); + return _mm_clmulepi64_si128(_mm_cvtsi64_si128(x), _mm_cvtsi64_si128(y), 0); } /* Computes the 128-bit carryless product of the high and low halves of x. */ From c4fc9395feb0034ef235b9de7e3bb9c18ec16302 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:42:42 +0100 Subject: [PATCH 209/242] changelog --- .unreleased/vectorized-text-grouping | 1 + 1 file changed, 1 insertion(+) create mode 100644 .unreleased/vectorized-text-grouping diff --git a/.unreleased/vectorized-text-grouping b/.unreleased/vectorized-text-grouping new file mode 100644 index 00000000000..5dfbe17b015 --- /dev/null +++ b/.unreleased/vectorized-text-grouping @@ -0,0 +1 @@ +Implements: #7586 Vectorized aggregation with grouping by a single text column. From 8cf8c6923ae6c578c168395e686ea27a0d6a8ed9 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:44:40 +0100 Subject: [PATCH 210/242] license cleanup --- tsl/src/import/umash.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tsl/src/import/umash.h b/tsl/src/import/umash.h index f85bd54a49c..9f055c2ad00 100644 --- a/tsl/src/import/umash.h +++ b/tsl/src/import/umash.h @@ -6,8 +6,16 @@ /* * This file contains source code that was copied and/or modified from - * the UMASH hash implementation at https://github.com/backtrace-labs/umash, - * which is licensed under the MIT License: + * the UMASH hash implementation at https://github.com/backtrace-labs/umash. + * + * This is a copy of umash.h, git commit sha + * fc4c5b6ca1f06c308e96c43aa080bd766238e092. + */ + +/* + * UMASH is distributed under the MIT license. + * + * SPDX-License-Identifier: MIT * * Copyright 2020-2022 Backtrace I/O, Inc. * Copyright 2022 Paul Khuong @@ -31,9 +39,6 @@ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * This is a copy of umash.h, git commit sha - * fc4c5b6ca1f06c308e96c43aa080bd766238e092. */ #ifndef UMASH_H From 8d45d717a7a75f7e5f807a915d69f813096de6ef Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:57:36 +0100 Subject: [PATCH 211/242] disable on windows --- tsl/CMakeLists.txt | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index b4009840c36..40c8d7a7a59 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -18,16 +18,18 @@ if(NOT CMAKE_CROSSCOMPILING) endif() endif() -# Detect if we can compile UMASH on this platform. -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -check_c_source_compiles( - " +# Detect if we can compile UMASH on this platform. It is not tested on Windows +# and leads to a weird CI freeze, so don't even try for now. +if(NOT WIN32) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + check_c_source_compiles( + " #if defined(__PCLMUL__) #include #include /* * For some reason, this doesn't compile on our i386 CI, but I also can't detect - * it using the standart condition of defined(__x86_64__) && !defined(__ILP32__), + * it using the standard condition of defined(__x86_64__) && !defined(__ILP32__), * as described at https://wiki.debian.org/X32Port . */ void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } @@ -36,9 +38,12 @@ void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } #error Unsupported platform for UMASH #endif " - UMASH_SUPPORTED) -unset(CMAKE_REQUIRED_FLAGS) -unset(CMAKE_TRY_COMPILE_TARGET_TYPE) + UMASH_SUPPORTED) + unset(CMAKE_REQUIRED_FLAGS) + unset(CMAKE_TRY_COMPILE_TARGET_TYPE) +else() + set(UMASH_SUPPORTED CACHE OFF) +endif() option(USE_UMASH "Use the UMASH hash for string and multi-column vectorized grouping" From dc188e676ed5cb79a887bba8741adcc7686d00aa Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 23 Jan 2025 10:46:04 +0100 Subject: [PATCH 212/242] fix --- tsl/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 40c8d7a7a59..333a52d2409 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -21,6 +21,8 @@ endif() # Detect if we can compile UMASH on this platform. It is not tested on Windows # and leads to a weird CI freeze, so don't even try for now. if(NOT WIN32) + set(CMAKE_REQUIRED_FLAGS + "${CMAKE_REQUIRED_FLAGS} -Werror=implicit-function-declaration") set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) check_c_source_compiles( " From b63c057459629fbea34eec737e0c9bd6acac811f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 23 Jan 2025 10:47:49 +0100 Subject: [PATCH 213/242] fix --- tsl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 333a52d2409..a500056953d 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -44,7 +44,7 @@ void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } unset(CMAKE_REQUIRED_FLAGS) unset(CMAKE_TRY_COMPILE_TARGET_TYPE) else() - set(UMASH_SUPPORTED CACHE OFF) + set(UMASH_SUPPORTED OFF) endif() option(USE_UMASH From 17d4124d8c274c8722c528b3cbf1c2f1e2b25766 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 23 Jan 2025 12:04:12 +0100 Subject: [PATCH 214/242] fixes --- .../workflows/linux-32bit-build-and-test.yaml | 4 +- .github/workflows/windows-build-and-test.yaml | 2 +- tsl/CMakeLists.txt | 40 +++++++++++-------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index 51fcc458cf5..775e6221a3d 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -48,7 +48,9 @@ jobs: DEBIAN_FRONTEND: noninteractive # vectorized_aggregation has different output on i386 because int8 is by # reference and currently it cannot be used for vectorized hash grouping. - IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* hypercore_vacuum vectorized_aggregation" + # vector_agg_text uses the UMASH hashing library that we can't compile + # on i386. + IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* hypercore_vacuum vectorized_aggregation vector_agg_text" SKIPS: chunk_adaptive histogram_test-* EXTENSIONS: "postgres_fdw test_decoding pageinspect pgstattuple" strategy: diff --git a/.github/workflows/windows-build-and-test.yaml b/.github/workflows/windows-build-and-test.yaml index 85b123c3f09..d556bc16afc 100644 --- a/.github/workflows/windows-build-and-test.yaml +++ b/.github/workflows/windows-build-and-test.yaml @@ -58,7 +58,7 @@ jobs: build_type: ${{ fromJson(needs.config.outputs.build_type) }} ignores: ["chunk_adaptive metadata telemetry"] tsl_ignores: ["compression_algos"] - tsl_skips: ["bgw_db_scheduler bgw_db_scheduler_fixed"] + tsl_skips: ["vector_agg_text bgw_db_scheduler bgw_db_scheduler_fixed"] pg_config: ["-cfsync=off -cstatement_timeout=60s"] include: - pg: 14 diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index a500056953d..9734e5df10b 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -4,23 +4,24 @@ if(COMPRESSION_FUZZING) add_compile_definitions(TS_COMPRESSION_FUZZING=1) endif() -# Check whether we can enable the pclmul instruction required for the UMASH -# hashing on amd64. Shouldn't be done if the user has manually specified the -# target architecture, no idea how to detect this, but at least we shouldn't do -# this when cross-compiling. -if(NOT CMAKE_CROSSCOMPILING) - check_c_compiler_flag(-mpclmul CC_PCLMUL) - if(CC_PCLMUL) - add_compile_options(-mpclmul) - # The "C source compiles" check below doesn't use the global compilation - # flags, so we have to modify its flags separately. - set(CMAKE_REQUIRED_FLAGS -mpclmul) +# We use the UMASH library for hashing in vectorized grouping. Detect if we can +# compile it on this platform. It is not tested on Windows and leads to a weird +# CI freeze, so don't even try for now. +if(NOT WIN32) + # Check whether we can enable the pclmul instruction required for the UMASH + # hashing on amd64. Shouldn't be done if the user has manually specified the + # target architecture, no idea how to detect this, but at least we shouldn't + # do this when cross-compiling. + if(NOT CMAKE_CROSSCOMPILING) + check_c_compiler_flag(-mpclmul CC_PCLMUL) + if(CC_PCLMUL) + add_compile_options(-mpclmul) + # The "C source compiles" check below doesn't use the global compilation + # flags, so we have to modify its flags separately. + set(CMAKE_REQUIRED_FLAGS -mpclmul) + endif() endif() -endif() -# Detect if we can compile UMASH on this platform. It is not tested on Windows -# and leads to a weird CI freeze, so don't even try for now. -if(NOT WIN32) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=implicit-function-declaration") set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) @@ -34,8 +35,9 @@ if(NOT WIN32) * it using the standard condition of defined(__x86_64__) && !defined(__ILP32__), * as described at https://wiki.debian.org/X32Port . */ -void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } +static void test() { (void) _mm_cvtsi64_si128((uint64_t) 0); } #elif defined(__ARM_FEATURE_CRYPTO) +/* OK */ #else #error Unsupported platform for UMASH #endif @@ -52,6 +54,12 @@ option(USE_UMASH ${UMASH_SUPPORTED}) if(USE_UMASH) + if(NOT UMASH_SUPPORTED) + message( + FATAL_ERROR + "UMASH use is requested, but it is not supported in the current configuration" + ) + endif() add_compile_definitions(TS_USE_UMASH) endif() From cfbf9d48edfcf6e008fee858c506225ec264b0c7 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 23 Jan 2025 15:49:49 +0100 Subject: [PATCH 215/242] more fixes --- tsl/CMakeLists.txt | 9 +++++---- tsl/src/import/umash.h | 12 ++++++++---- tsl/src/nodes/vector_agg/hashing/hashing_strategy.h | 2 ++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/tsl/CMakeLists.txt b/tsl/CMakeLists.txt index 9734e5df10b..ffcde553703 100644 --- a/tsl/CMakeLists.txt +++ b/tsl/CMakeLists.txt @@ -4,10 +4,11 @@ if(COMPRESSION_FUZZING) add_compile_definitions(TS_COMPRESSION_FUZZING=1) endif() -# We use the UMASH library for hashing in vectorized grouping. Detect if we can -# compile it on this platform. It is not tested on Windows and leads to a weird -# CI freeze, so don't even try for now. -if(NOT WIN32) +# We use the UMASH library for hashing in vectorized grouping. If it was not +# explicitly disabled already, detect if we can compile it on this platform. It +# is not tested on Windows and leads to a weird CI freeze, so don't even try for +# now. +if((NOT WIN32) AND ((NOT DEFINED USE_UMASH) OR USE_UMASH)) # Check whether we can enable the pclmul instruction required for the UMASH # hashing on amd64. Shouldn't be done if the user has manually specified the # target architecture, no idea how to detect this, but at least we shouldn't diff --git a/tsl/src/import/umash.h b/tsl/src/import/umash.h index 9f055c2ad00..3ad9460b46a 100644 --- a/tsl/src/import/umash.h +++ b/tsl/src/import/umash.h @@ -47,6 +47,10 @@ #include #include +#ifndef TS_USE_UMASH +#error "UMASH usage is disabled, but the header is included" +#endif + /** * # UMASH: a non-cryptographic hash function with collision bounds * @@ -285,7 +289,7 @@ void umash_sink_update(struct umash_sink *, const void *data, size_t n_bytes); * for the second. */ uint64_t umash_full(const struct umash_params *params, uint64_t seed, int which, - const void *data, size_t n_bytes); + const void *data, size_t n_bytes); /** * Computes the UMASH fingerprint of `data[0 ... n_bytes)`. @@ -295,14 +299,14 @@ uint64_t umash_full(const struct umash_params *params, uint64_t seed, int which, * with no guarantee. */ struct umash_fp umash_fprint( - const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes); + const struct umash_params *params, uint64_t seed, const void *data, size_t n_bytes); /** * Prepares a `umash_state` for computing the `which`th UMASH function in * `params`. */ void umash_init( - struct umash_state *, const struct umash_params *params, uint64_t seed, int which); + struct umash_state *, const struct umash_params *params, uint64_t seed, int which); /** * Returns the UMASH value for the bytes that have been @@ -315,7 +319,7 @@ uint64_t umash_digest(const struct umash_state *); * `params`. */ void umash_fp_init( - struct umash_fp_state *, const struct umash_params *params, uint64_t seed); + struct umash_fp_state *, const struct umash_params *params, uint64_t seed); /** * Returns the UMASH fingerprint for the bytes that have been diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index 0d21b851a0a..c6bb512fc14 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -57,10 +57,12 @@ typedef struct HashingStrategy */ uint32 null_key_index; +#ifdef TS_USE_UMASH /* * UMASH fingerprinting parameters. */ struct umash_params *umash_params; +#endif } HashingStrategy; void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, DecompressBatchState *batch_state); From 1919e38b56cddacbf274c3c3acd1fee6dec3161b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 29 Jan 2025 12:59:34 +0100 Subject: [PATCH 216/242] add a test for groupagg mode with nulls --- .../hashing/hash_strategy_single_text.c | 12 ++- tsl/src/nodes/vector_agg/plan.c | 2 - tsl/test/expected/vector_agg_groupagg.out | 77 +++++++++++++++++++ tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vector_agg_groupagg.sql | 37 +++++++++ 5 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 tsl/test/expected/vector_agg_groupagg.out create mode 100644 tsl/test/sql/vector_agg_groupagg.sql diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 498877a06f8..03916c57b3b 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -59,9 +59,17 @@ single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restri if (unlikely(params.single_grouping_column.decompression_type == DT_Scalar)) { - output_key->len = VARSIZE_ANY_EXHDR(*params.single_grouping_column.output_value); - output_key->data = (const uint8 *) VARDATA_ANY(*params.single_grouping_column.output_value); *valid = !*params.single_grouping_column.output_isnull; + if (*valid) + { + output_key->len = VARSIZE_ANY_EXHDR(*params.single_grouping_column.output_value); + output_key->data = (const uint8 *) VARDATA_ANY(*params.single_grouping_column.output_value); + } + else + { + output_key->len = 0; + output_key->data = NULL; + } } else if (params.single_grouping_column.decompression_type == DT_ArrowText) { diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 571804e002e..bb26d319016 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -507,8 +507,6 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target * compressed column. * We can use our hash table for GroupAggregate as well, because it preserves * the input order of the keys. - * FIXME write a test for that. - * FIXME rewrite to use num_grouping_columns */ if (num_grouping_columns == 1) { diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out new file mode 100644 index 00000000000..3310a05ee77 --- /dev/null +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -0,0 +1,77 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +create table groupagg(t int, s text, value int); +select create_hypertable('groupagg', 't', chunk_time_interval => 10000); +NOTICE: adding not-null constraint to column "t" + create_hypertable +----------------------- + (1,public,groupagg,t) +(1 row) + +insert into groupagg +select + xfast * 100 + xslow, + case when xfast = 13 then null else xfast end, + xfast * 7 + xslow * 3 +from generate_series(10, 99) xfast, + generate_series(1, 10000) xslow +; +alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 's'); +select count(compress_chunk(x)) from show_chunks('groupagg') x; + count +------- + 2 +(1 row) + +set enable_hashagg to off; +set timescaledb.debug_require_vector_agg to 'allow'; +select s, sum(value) from groupagg group by s order by s limit 10; + s | sum +----+----------- + 10 | 150715000 + 11 | 150785000 + 12 | 150855000 + 14 | 150995000 + 15 | 151065000 + 16 | 151135000 + 17 | 151205000 + 18 | 151275000 + 19 | 151345000 + 20 | 151415000 +(10 rows) + +reset timescaledb.debug_require_vector_agg; +select count(decompress_chunk(x)) from show_chunks('groupagg') x; + count +------- + 2 +(1 row) + +alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 's nulls first'); +select count(compress_chunk(x)) from show_chunks('groupagg') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg to 'require'; +select s , sum(value) from groupagg group by s order by s nulls first limit 10; + s | sum +----+----------- + | 150925000 + 10 | 150715000 + 11 | 150785000 + 12 | 150855000 + 14 | 150995000 + 15 | 151065000 + 16 | 151135000 + 17 | 151205000 + 18 | 151275000 + 19 | 151345000 +(10 rows) + +reset enable_hashagg; +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index c84a451d890..a12491cb756 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -45,6 +45,7 @@ set(TEST_FILES skip_scan.sql transparent_decompression_join_index.sql vector_agg_functions.sql + vector_agg_groupagg.sql vector_agg_param.sql vectorized_aggregation.sql) diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql new file mode 100644 index 00000000000..29c45b3972d --- /dev/null +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -0,0 +1,37 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +create table groupagg(t int, s text, value int); +select create_hypertable('groupagg', 't', chunk_time_interval => 10000); + +insert into groupagg +select + xfast * 100 + xslow, + case when xfast = 13 then null else xfast end, + xfast * 7 + xslow * 3 +from generate_series(10, 99) xfast, + generate_series(1, 10000) xslow +; + +alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 's'); +select count(compress_chunk(x)) from show_chunks('groupagg') x; + +set enable_hashagg to off; +set timescaledb.debug_require_vector_agg to 'allow'; +select s, sum(value) from groupagg group by s order by s limit 10; + + +reset timescaledb.debug_require_vector_agg; +select count(decompress_chunk(x)) from show_chunks('groupagg') x; +alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 's nulls first'); +select count(compress_chunk(x)) from show_chunks('groupagg') x; + +set timescaledb.debug_require_vector_agg to 'require'; +select s , sum(value) from groupagg group by s order by s nulls first limit 10; + + +reset enable_hashagg; +reset timescaledb.debug_require_vector_agg; From 1529ed9fb6c9214418c0992f16d4537c8dcb068a Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 29 Jan 2025 13:01:05 +0100 Subject: [PATCH 217/242] format --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 03916c57b3b..5ef3f22a3e7 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -63,7 +63,8 @@ single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restri if (*valid) { output_key->len = VARSIZE_ANY_EXHDR(*params.single_grouping_column.output_value); - output_key->data = (const uint8 *) VARDATA_ANY(*params.single_grouping_column.output_value); + output_key->data = + (const uint8 *) VARDATA_ANY(*params.single_grouping_column.output_value); } else { From c7efeb0405b1656229f39f42e56d323352d90937 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 29 Jan 2025 13:53:35 +0100 Subject: [PATCH 218/242] ignore the test --- .github/workflows/linux-32bit-build-and-test.yaml | 9 ++++++--- .github/workflows/windows-build-and-test.yaml | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index 775e6221a3d..e4700fd714e 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -48,9 +48,12 @@ jobs: DEBIAN_FRONTEND: noninteractive # vectorized_aggregation has different output on i386 because int8 is by # reference and currently it cannot be used for vectorized hash grouping. - # vector_agg_text uses the UMASH hashing library that we can't compile - # on i386. - IGNORES: "append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* hypercore_vacuum vectorized_aggregation vector_agg_text" + # vector_agg_text and vector_agg_groupagg use the UMASH hashing library + # that we can't compile on i386. + IGNORES: >- append-* transparent_decompression-* + transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* + hypercore_vacuum vectorized_aggregation vector_agg_text + vector_agg_groupagg SKIPS: chunk_adaptive histogram_test-* EXTENSIONS: "postgres_fdw test_decoding pageinspect pgstattuple" strategy: diff --git a/.github/workflows/windows-build-and-test.yaml b/.github/workflows/windows-build-and-test.yaml index 8d5208b3cd4..fbab17457c1 100644 --- a/.github/workflows/windows-build-and-test.yaml +++ b/.github/workflows/windows-build-and-test.yaml @@ -59,7 +59,7 @@ jobs: build_type: ${{ fromJson(needs.config.outputs.build_type) }} ignores: ["chunk_adaptive metadata telemetry"] tsl_ignores: ["compression_algos"] - tsl_skips: ["vector_agg_text bgw_db_scheduler bgw_db_scheduler_fixed"] + tsl_skips: ["vector_agg_text vector_agg_groupagg bgw_db_scheduler bgw_db_scheduler_fixed"] pg_config: ["-cfsync=off -cstatement_timeout=60s"] include: - pg: 14 From d0e2431c100ab37247ded68762ec94be3611e464 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 29 Jan 2025 14:00:08 +0100 Subject: [PATCH 219/242] yaml --- .github/workflows/linux-32bit-build-and-test.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux-32bit-build-and-test.yaml b/.github/workflows/linux-32bit-build-and-test.yaml index e4700fd714e..0cec2577a08 100644 --- a/.github/workflows/linux-32bit-build-and-test.yaml +++ b/.github/workflows/linux-32bit-build-and-test.yaml @@ -50,7 +50,8 @@ jobs: # reference and currently it cannot be used for vectorized hash grouping. # vector_agg_text and vector_agg_groupagg use the UMASH hashing library # that we can't compile on i386. - IGNORES: >- append-* transparent_decompression-* + IGNORES: >- + append-* transparent_decompression-* transparent_decompress_chunk-* pg_dump telemetry bgw_db_scheduler* hypercore_vacuum vectorized_aggregation vector_agg_text vector_agg_groupagg From 621500d47555c7901cc035549579d75a2808d4d0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:18:44 +0100 Subject: [PATCH 220/242] comment --- tsl/test/expected/vector_agg_groupagg.out | 2 ++ tsl/test/sql/vector_agg_groupagg.sql | 3 +++ 2 files changed, 5 insertions(+) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index 3310a05ee77..93784426438 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -1,6 +1,8 @@ -- This file and its contents are licensed under the Timescale License. -- Please see the included NOTICE for copyright information and -- LICENSE-TIMESCALE for a copy of the license. +-- Check that the vectorized aggregation works properly in the GroupAggregate +-- mode. create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); NOTICE: adding not-null constraint to column "t" diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 29c45b3972d..d27a6b90095 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -2,6 +2,9 @@ -- Please see the included NOTICE for copyright information and -- LICENSE-TIMESCALE for a copy of the license. +-- Check that the vectorized aggregation works properly in the GroupAggregate +-- mode. + create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); From 18f51f54491a2fc5bd8003c5c5995e1920e6cd97 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 3 Feb 2025 15:30:44 +0100 Subject: [PATCH 221/242] fix after merge --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 5ef3f22a3e7..0f5719cc1a2 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -129,8 +129,7 @@ single_text_emit_key(GroupingPolicyHash *policy, uint32 current_key, } static void -single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, - DecompressBatchState *batch_state) +single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTableSlot *vector_slot) { } From 09d1036367d621c7bc7ce3528c39cfc762e82809 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:29:31 +0100 Subject: [PATCH 222/242] Update tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Nordström <819732+erimatnor@users.noreply.github.com> Signed-off-by: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> --- tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 0f5719cc1a2..5b54970b595 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -114,7 +114,6 @@ single_text_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 ne text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), output_key.data, output_key.len); - output_key.data = (uint8 *) VARDATA(stored); policy->hashing.output_keys[new_key_index] = PointerGetDatum(stored); } From 8243f8a82d039bf260f82d65aa4a35e37d41c933 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:35:37 +0100 Subject: [PATCH 223/242] some fixes after merge -- tmp --- tsl/src/nodes/vector_agg/exec.c | 79 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 505806f865f..8d5485ee878 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -76,13 +76,46 @@ grouping_column_comparator(const void *a_ptr, const void *b_ptr) return 1; } -static int -get_value_bytes(const CustomScanState *state, int input_offset) +static void +get_column_storage_properties(const CustomScanState *state, int input_offset, + GroupingColum *result) { const DecompressChunkState *decompress_state = (DecompressChunkState *) state; const DecompressContext *dcontext = &decompress_state->decompress_context; const CompressionColumnDescription *desc = &dcontext->compressed_chunk_columns[input_offset]; - return desc->value_bytes; + result->typid = desc->typid; + result->value_bytes = desc->value_bytes; + result->by_value = desc->by_value; + + if (result->value_bytes == -1) + { + /* + * long varlena requires 4 byte alignment, not sure why text has 'i' + * typalign in pg catalog. + */ + result->alignment_bytes = 4; + } + else + { + switch (desc->typalign) + { + case TYPALIGN_CHAR: + result->alignment_bytes = 1; + break; + case TYPALIGN_SHORT: + result->alignment_bytes = ALIGNOF_SHORT; + break; + case TYPALIGN_INT: + result->alignment_bytes = ALIGNOF_INT; + break; + case TYPALIGN_DOUBLE: + result->alignment_bytes = ALIGNOF_DOUBLE; + break; + default: + Assert(false); + result->alignment_bytes = 1; + } + } } static void @@ -205,44 +238,8 @@ vector_agg_begin(CustomScanState *node, EState *estate, int eflags) col->output_offset = i; Var *var = castNode(Var, tlentry->expr); - col->input_offset = get_input_offset(decompress_state, var); - - DecompressContext *dcontext = &decompress_state->decompress_context; - CompressionColumnDescription *desc = - &dcontext->compressed_chunk_columns[col->input_offset]; - - col->typid = desc->typid; - col->value_bytes = get_value_bytes(childstate, col->input_offset); - col->by_value = desc->by_value; - if (col->value_bytes == -1) - { - /* - * long varlena requires 4 byte alignment, not sure why text has 'i' - * typalign in pg catalog. - */ - col->alignment_bytes = 4; - } - else - { - switch (desc->typalign) - { - case TYPALIGN_CHAR: - col->alignment_bytes = 1; - break; - case TYPALIGN_SHORT: - col->alignment_bytes = ALIGNOF_SHORT; - break; - case TYPALIGN_INT: - col->alignment_bytes = ALIGNOF_INT; - break; - case TYPALIGN_DOUBLE: - col->alignment_bytes = ALIGNOF_DOUBLE; - break; - default: - Assert(false); - col->alignment_bytes = 1; - } - } + col->input_offset = get_input_offset(childstate, var); + get_column_storage_properties(childstate, col->input_offset, col); } } From 880e7f1ddc3d8125547329718ba7cb7390dd943c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:54:52 +0100 Subject: [PATCH 224/242] more fixes --- tsl/src/nodes/vector_agg/exec.c | 2 +- .../vector_agg/hashing/hash_strategy_serialized.c | 3 +-- .../vector_agg/hashing/hash_strategy_single_text.c | 14 +++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 8d5485ee878..7cd3888417f 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -78,7 +78,7 @@ grouping_column_comparator(const void *a_ptr, const void *b_ptr) static void get_column_storage_properties(const CustomScanState *state, int input_offset, - GroupingColum *result) + GroupingColumn *result) { const DecompressChunkState *decompress_state = (DecompressChunkState *) state; const DecompressContext *dcontext = &decompress_state->decompress_context; diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index 95512ce8057..c47df3537de 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -34,8 +34,7 @@ serialized_key_hashing_init(HashingStrategy *hashing) } static void -serialized_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, - DecompressBatchState *batch_state) +serialized_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTableSlot *vector_slot) { } diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index e6dc5e161fd..fe8333fbc38 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -145,15 +145,17 @@ single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTable */ policy->use_key_index_for_dict = false; - BatchHashingParams params = build_batch_hashing_params(policy, batch_state); + BatchHashingParams params = build_batch_hashing_params(policy, vector_slot); if (params.single_grouping_column.decompression_type != DT_ArrowTextDict) { return; } + uint16 batch_rows; + const uint64 *row_filter = vector_slot_get_qual_result(vector_slot, &batch_rows); + const int dict_rows = params.single_grouping_column.arrow->dictionary->length; - if ((size_t) dict_rows > - arrow_num_valid(batch_state->vector_qual_result, batch_state->total_batch_rows)) + if ((size_t) dict_rows > arrow_num_valid(row_filter, batch_rows)) { return; } @@ -185,9 +187,7 @@ single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTable * We shouldn't add the dictionary entries that are not used by any matching * rows. Translate the batch filter bitmap to dictionary rows. */ - const int batch_rows = batch_state->total_batch_rows; - const uint64 *row_filter = batch_state->vector_qual_result; - if (batch_state->vector_qual_result != NULL) + if (row_filter != NULL) { uint64 *restrict dict_filter = policy->tmp_filter; const size_t dict_words = (dict_rows + 63) / 64; @@ -249,7 +249,7 @@ single_text_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTable * batch filter. */ bool have_null_key = false; - if (batch_state->vector_qual_result != NULL) + if (row_filter != NULL) { if (params.single_grouping_column.arrow->null_count > 0) { From 7c03e463af7130fd01ad073b77cd680a76c1dea3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:56:49 +0100 Subject: [PATCH 225/242] alignment not used as of now --- .../decompress_chunk/decompress_context.h | 1 - tsl/src/nodes/decompress_chunk/exec.c | 5 +--- tsl/src/nodes/vector_agg/exec.c | 30 ------------------- tsl/src/nodes/vector_agg/exec.h | 1 - 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/decompress_context.h b/tsl/src/nodes/decompress_chunk/decompress_context.h index 6eae55d5467..bd12927d77e 100644 --- a/tsl/src/nodes/decompress_chunk/decompress_context.h +++ b/tsl/src/nodes/decompress_chunk/decompress_context.h @@ -29,7 +29,6 @@ typedef struct CompressionColumnDescription Oid typid; int16 value_bytes; bool by_value; - char typalign; /* * Attno of the decompressed column in the scan tuple of DecompressChunk node. diff --git a/tsl/src/nodes/decompress_chunk/exec.c b/tsl/src/nodes/decompress_chunk/exec.c index a2e04c6492d..18d1ec1e54b 100644 --- a/tsl/src/nodes/decompress_chunk/exec.c +++ b/tsl/src/nodes/decompress_chunk/exec.c @@ -297,10 +297,7 @@ decompress_chunk_begin(CustomScanState *node, EState *estate, int eflags) TupleDescAttr(desc, AttrNumberGetAttrOffset(column.custom_scan_attno)); column.typid = attribute->atttypid; - get_typlenbyvalalign(column.typid, - &column.value_bytes, - &column.by_value, - &column.typalign); + get_typlenbyval(column.typid, &column.value_bytes, &column.by_value); if (list_nth_int(chunk_state->is_segmentby_column, compressed_index)) column.type = SEGMENTBY_COLUMN; diff --git a/tsl/src/nodes/vector_agg/exec.c b/tsl/src/nodes/vector_agg/exec.c index 7cd3888417f..ab70d07c245 100644 --- a/tsl/src/nodes/vector_agg/exec.c +++ b/tsl/src/nodes/vector_agg/exec.c @@ -86,36 +86,6 @@ get_column_storage_properties(const CustomScanState *state, int input_offset, result->typid = desc->typid; result->value_bytes = desc->value_bytes; result->by_value = desc->by_value; - - if (result->value_bytes == -1) - { - /* - * long varlena requires 4 byte alignment, not sure why text has 'i' - * typalign in pg catalog. - */ - result->alignment_bytes = 4; - } - else - { - switch (desc->typalign) - { - case TYPALIGN_CHAR: - result->alignment_bytes = 1; - break; - case TYPALIGN_SHORT: - result->alignment_bytes = ALIGNOF_SHORT; - break; - case TYPALIGN_INT: - result->alignment_bytes = ALIGNOF_INT; - break; - case TYPALIGN_DOUBLE: - result->alignment_bytes = ALIGNOF_DOUBLE; - break; - default: - Assert(false); - result->alignment_bytes = 1; - } - } } static void diff --git a/tsl/src/nodes/vector_agg/exec.h b/tsl/src/nodes/vector_agg/exec.h index aaca098f891..639295e3b65 100644 --- a/tsl/src/nodes/vector_agg/exec.h +++ b/tsl/src/nodes/vector_agg/exec.h @@ -31,7 +31,6 @@ typedef struct GroupingColumn Oid typid; int16 value_bytes; bool by_value; - int8 alignment_bytes; } GroupingColumn; typedef struct VectorAggState From 1f77422ea808b1ee48b4c821149985c0c604c398 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 10 Feb 2025 18:48:33 +0100 Subject: [PATCH 226/242] more tests for dictionary encoding --- tsl/test/expected/vector_agg_groupagg.out | 154 ++++++++++++++++++---- tsl/test/sql/vector_agg_groupagg.sql | 47 ++++++- 2 files changed, 173 insertions(+), 28 deletions(-) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index 93784426438..d734b6fae4e 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -3,6 +3,8 @@ -- LICENSE-TIMESCALE for a copy of the license. -- Check that the vectorized aggregation works properly in the GroupAggregate -- mode. +\pset null ¤ +set max_parallel_workers_per_gather = 0; create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); NOTICE: adding not-null constraint to column "t" @@ -17,7 +19,7 @@ select case when xfast = 13 then null else xfast end, xfast * 7 + xslow * 3 from generate_series(10, 99) xfast, - generate_series(1, 10000) xslow + generate_series(1, 1000) xslow ; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 's'); @@ -28,20 +30,20 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; (1 row) set enable_hashagg to off; -set timescaledb.debug_require_vector_agg to 'allow'; +set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; - s | sum -----+----------- - 10 | 150715000 - 11 | 150785000 - 12 | 150855000 - 14 | 150995000 - 15 | 151065000 - 16 | 151135000 - 17 | 151205000 - 18 | 151275000 - 19 | 151345000 - 20 | 151415000 + s | sum +----+--------- + 10 | 1571500 + 11 | 1578500 + 12 | 1585500 + 14 | 1599500 + 15 | 1606500 + 16 | 1613500 + 17 | 1620500 + 18 | 1627500 + 19 | 1634500 + 20 | 1641500 (10 rows) reset timescaledb.debug_require_vector_agg; @@ -61,19 +63,119 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; set timescaledb.debug_require_vector_agg to 'require'; select s , sum(value) from groupagg group by s order by s nulls first limit 10; - s | sum -----+----------- - | 150925000 - 10 | 150715000 - 11 | 150785000 - 12 | 150855000 - 14 | 150995000 - 15 | 151065000 - 16 | 151135000 - 17 | 151205000 - 18 | 151275000 - 19 | 151345000 + s | sum +----+--------- + ¤ | 1592500 + 10 | 1571500 + 11 | 1578500 + 12 | 1585500 + 14 | 1599500 + 15 | 1606500 + 16 | 1613500 + 17 | 1620500 + 18 | 1627500 + 19 | 1634500 (10 rows) +reset timescaledb.debug_require_vector_agg; +-- More tests for dictionary encoding. +create table text_table(ts int); +select create_hypertable('text_table', 'ts', chunk_time_interval => 3); +NOTICE: adding not-null constraint to column "ts" + create_hypertable +------------------------- + (3,public,text_table,t) +(1 row) + +alter table text_table set (timescaledb.compress); +WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes +NOTICE: default segment by for hypertable "text_table" is set to "" +NOTICE: default order by for hypertable "text_table" is set to "ts DESC" +insert into text_table select 0 /*, default */ from generate_series(1, 1000) x; +select count(compress_chunk(x)) from show_chunks('text_table') x; + count +------- + 1 +(1 row) + +alter table text_table add column a text default 'default'; +alter table text_table set (timescaledb.compress, + timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a'); +insert into text_table select 1, '' from generate_series(1, 1000) x; +insert into text_table select 2, 'same' from generate_series(1, 1000) x; +insert into text_table select 3, 'different' || x from generate_series(1, 1000) x; +insert into text_table select 4, case when x % 2 = 0 then null else 'same-with-nulls' end from generate_series(1, 1000) x; +insert into text_table select 5, case when x % 2 = 0 then null else 'different-with-nulls' || x end from generate_series(1, 1000) x; +select count(compress_chunk(x)) from show_chunks('text_table') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg to 'require'; +select a, count(*) from text_table group by a order by a limit 10; + a | count +---------------+------- + | 1000 + default | 1000 + different1 | 1 + different10 | 1 + different100 | 1 + different1000 | 1 + different101 | 1 + different102 | 1 + different103 | 1 + different104 | 1 +(10 rows) + +select a, count(*) from text_table group by a order by a desc limit 10; + a | count +-------------------------+------- + ¤ | 1000 + same | 1000 + different-with-nulls1 | 1 + different-with-nulls101 | 1 + different-with-nulls103 | 1 + different-with-nulls105 | 1 + different-with-nulls107 | 1 + different-with-nulls109 | 1 + different-with-nulls11 | 1 + different-with-nulls111 | 1 +(10 rows) + +reset timescaledb.debug_require_vector_agg; +-- with NULLS FIRST +select count(decompress_chunk(x)) from show_chunks('text_table') x; + count +------- + 2 +(1 row) + +alter table text_table set (timescaledb.compress, + timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a nulls first'); +select count(compress_chunk(x)) from show_chunks('text_table') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg to 'require'; +select a, count(*) from text_table group by a order by a nulls first limit 10; + a | count +---------------+------- + ¤ | 1000 + | 1000 + default | 1000 + different1 | 1 + different10 | 1 + different100 | 1 + different1000 | 1 + different101 | 1 + different102 | 1 + different103 | 1 +(10 rows) + +reset timescaledb.debug_require_vector_agg; reset enable_hashagg; reset timescaledb.debug_require_vector_agg; +reset max_parallel_workers_per_gather; diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index d27a6b90095..89f5b4f5e18 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -5,6 +5,10 @@ -- Check that the vectorized aggregation works properly in the GroupAggregate -- mode. +\pset null ¤ + +set max_parallel_workers_per_gather = 0; + create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); @@ -14,7 +18,7 @@ select case when xfast = 13 then null else xfast end, xfast * 7 + xslow * 3 from generate_series(10, 99) xfast, - generate_series(1, 10000) xslow + generate_series(1, 1000) xslow ; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', @@ -22,7 +26,7 @@ alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = select count(compress_chunk(x)) from show_chunks('groupagg') x; set enable_hashagg to off; -set timescaledb.debug_require_vector_agg to 'allow'; +set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; @@ -34,7 +38,46 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; set timescaledb.debug_require_vector_agg to 'require'; select s , sum(value) from groupagg group by s order by s nulls first limit 10; +reset timescaledb.debug_require_vector_agg; + + +-- More tests for dictionary encoding. +create table text_table(ts int); +select create_hypertable('text_table', 'ts', chunk_time_interval => 3); +alter table text_table set (timescaledb.compress); + +insert into text_table select 0 /*, default */ from generate_series(1, 1000) x; +select count(compress_chunk(x)) from show_chunks('text_table') x; + +alter table text_table add column a text default 'default'; +alter table text_table set (timescaledb.compress, + timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a'); + +insert into text_table select 1, '' from generate_series(1, 1000) x; +insert into text_table select 2, 'same' from generate_series(1, 1000) x; +insert into text_table select 3, 'different' || x from generate_series(1, 1000) x; +insert into text_table select 4, case when x % 2 = 0 then null else 'same-with-nulls' end from generate_series(1, 1000) x; +insert into text_table select 5, case when x % 2 = 0 then null else 'different-with-nulls' || x end from generate_series(1, 1000) x; + +select count(compress_chunk(x)) from show_chunks('text_table') x; + +set timescaledb.debug_require_vector_agg to 'require'; +select a, count(*) from text_table group by a order by a limit 10; +select a, count(*) from text_table group by a order by a desc limit 10; +reset timescaledb.debug_require_vector_agg; + + +-- with NULLS FIRST +select count(decompress_chunk(x)) from show_chunks('text_table') x; +alter table text_table set (timescaledb.compress, + timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a nulls first'); +select count(compress_chunk(x)) from show_chunks('text_table') x; + +set timescaledb.debug_require_vector_agg to 'require'; +select a, count(*) from text_table group by a order by a nulls first limit 10; +reset timescaledb.debug_require_vector_agg; reset enable_hashagg; reset timescaledb.debug_require_vector_agg; +reset max_parallel_workers_per_gather; From a55cfc715ef5adefc194c103e36a355cf273c1d4 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 10 Feb 2025 18:51:59 +0100 Subject: [PATCH 227/242] add more tests --- tsl/test/expected/vector_agg_groupagg.out | 32 +++++++++++++++++++++++ tsl/test/sql/vector_agg_groupagg.sql | 8 +++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index d734b6fae4e..c81af496cac 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -177,5 +177,37 @@ select a, count(*) from text_table group by a order by a nulls first limit 10; reset timescaledb.debug_require_vector_agg; reset enable_hashagg; +-- TODO verify that this works with the serialized hash grouping strategy +set timescaledb.debug_require_vector_agg to 'forbid'; +select ts, a, count(*) from text_table group by ts, a order by ts, a limit 10; + ts | a | count +----+---------------+------- + 0 | default | 1000 + 1 | | 1000 + 2 | same | 1000 + 3 | different1 | 1 + 3 | different10 | 1 + 3 | different100 | 1 + 3 | different1000 | 1 + 3 | different101 | 1 + 3 | different102 | 1 + 3 | different103 | 1 +(10 rows) + +select a, ts, count(*) from text_table group by a, ts order by a desc, ts desc limit 10; + a | ts | count +-------------------------+----+------- + ¤ | 5 | 500 + ¤ | 4 | 500 + same-with-nulls | 4 | 500 + same | 2 | 1000 + different-with-nulls999 | 5 | 1 + different-with-nulls997 | 5 | 1 + different-with-nulls995 | 5 | 1 + different-with-nulls993 | 5 | 1 + different-with-nulls991 | 5 | 1 + different-with-nulls99 | 5 | 1 +(10 rows) + reset timescaledb.debug_require_vector_agg; reset max_parallel_workers_per_gather; diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 89f5b4f5e18..9a7907c50de 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -77,7 +77,13 @@ set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a nulls first limit 10; reset timescaledb.debug_require_vector_agg; - reset enable_hashagg; + + +-- TODO verify that this works with the serialized hash grouping strategy +set timescaledb.debug_require_vector_agg to 'forbid'; +select ts, a, count(*) from text_table group by ts, a order by ts, a limit 10; +select a, ts, count(*) from text_table group by a, ts order by a desc, ts desc limit 10; reset timescaledb.debug_require_vector_agg; + reset max_parallel_workers_per_gather; From 31b3b2703b4541930c4aa50effddb1fded0edb1d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:47:30 +0100 Subject: [PATCH 228/242] oops it doesn't work with the reverse order --- tsl/test/expected/vector_agg_groupagg.out | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index c81af496cac..8af77a6f53d 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -132,15 +132,15 @@ select a, count(*) from text_table group by a order by a desc limit 10; a | count -------------------------+------- ¤ | 1000 + same-with-nulls | 500 same | 1000 - different-with-nulls1 | 1 - different-with-nulls101 | 1 - different-with-nulls103 | 1 - different-with-nulls105 | 1 - different-with-nulls107 | 1 - different-with-nulls109 | 1 - different-with-nulls11 | 1 - different-with-nulls111 | 1 + different-with-nulls999 | 1 + different-with-nulls997 | 1 + different-with-nulls995 | 1 + different-with-nulls993 | 1 + different-with-nulls991 | 1 + different-with-nulls99 | 1 + different-with-nulls989 | 1 (10 rows) reset timescaledb.debug_require_vector_agg; From 35cdd733231529e850ffd63df340d2e7810abbc3 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:39:04 +0100 Subject: [PATCH 229/242] fixes for the reverse order --- tsl/src/nodes/vector_agg/plan.c | 15 ++++++++++++++ tsl/test/expected/vector_agg_groupagg.out | 25 ++++++++++++++++++++++- tsl/test/sql/vector_agg_groupagg.sql | 15 +++++++++++++- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index bb26d319016..3741275a594 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -740,6 +740,21 @@ try_insert_vector_agg_node(Plan *plan) return plan; } + /* + * The hash grouping strategies do not preserve the input key order when the + * reverse ordering is requested, so in this case they cannot work in + * GroupAggregate mode. + */ + if (grouping_type != VAGT_Batch && agg->aggstrategy != AGG_HASHED) + { + List *settings = linitial(custom->custom_private); + const bool reverse = list_nth_int(settings, DCS_Reverse); + if (reverse) + { + return plan; + } + } + /* * Build supplementary info to determine whether we can vectorize the * aggregate FILTER clauses. diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index 8af77a6f53d..38dd5751c2b 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -5,6 +5,7 @@ -- mode. \pset null ¤ set max_parallel_workers_per_gather = 0; +set enable_hashagg to off; create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); NOTICE: adding not-null constraint to column "t" @@ -29,7 +30,7 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; 2 (1 row) -set enable_hashagg to off; +vacuum analyze groupagg; set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; s | sum @@ -46,6 +47,24 @@ select s, sum(value) from groupagg group by s order by s limit 10; 20 | 1641500 (10 rows) +-- The hash grouping policies do not support the GroupAggregate mode in the +-- reverse order. +set timescaledb.debug_require_vector_agg to 'forbid'; +select s, sum(value) from groupagg group by s order by s desc limit 10; + s | sum +----+--------- + ¤ | 1592500 + 99 | 2194500 + 98 | 2187500 + 97 | 2180500 + 96 | 2173500 + 95 | 2166500 + 94 | 2159500 + 93 | 2152500 + 92 | 2145500 + 91 | 2138500 +(10 rows) + reset timescaledb.debug_require_vector_agg; select count(decompress_chunk(x)) from show_chunks('groupagg') x; count @@ -61,6 +80,7 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; 2 (1 row) +vacuum analyze groupagg; set timescaledb.debug_require_vector_agg to 'require'; select s , sum(value) from groupagg group by s order by s nulls first limit 10; s | sum @@ -128,6 +148,9 @@ select a, count(*) from text_table group by a order by a limit 10; different104 | 1 (10 rows) +-- The hash grouping policies do not support the GroupAggregate mode in the +-- reverse order. +set timescaledb.debug_require_vector_agg to 'forbid'; select a, count(*) from text_table group by a order by a desc limit 10; a | count -------------------------+------- diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 9a7907c50de..b0beef0ca2b 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -8,6 +8,7 @@ \pset null ¤ set max_parallel_workers_per_gather = 0; +set enable_hashagg to off; create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); @@ -24,17 +25,24 @@ from generate_series(10, 99) xfast, alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 's'); select count(compress_chunk(x)) from show_chunks('groupagg') x; +vacuum analyze groupagg; -set enable_hashagg to off; set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; +-- The hash grouping policies do not support the GroupAggregate mode in the +-- reverse order. +set timescaledb.debug_require_vector_agg to 'forbid'; +select s, sum(value) from groupagg group by s order by s desc limit 10; reset timescaledb.debug_require_vector_agg; + + select count(decompress_chunk(x)) from show_chunks('groupagg') x; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 's nulls first'); select count(compress_chunk(x)) from show_chunks('groupagg') x; +vacuum analyze groupagg; set timescaledb.debug_require_vector_agg to 'require'; select s , sum(value) from groupagg group by s order by s nulls first limit 10; @@ -63,7 +71,12 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a limit 10; + +-- The hash grouping policies do not support the GroupAggregate mode in the +-- reverse order. +set timescaledb.debug_require_vector_agg to 'forbid'; select a, count(*) from text_table group by a order by a desc limit 10; + reset timescaledb.debug_require_vector_agg; From 326a4523abb041bf4e1615b707ab495cd6663434 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:16:55 +0100 Subject: [PATCH 230/242] debug --- tsl/src/planner.c | 5 ++ tsl/test/expected/vector_agg_groupagg.out | 56 +++++++++++++++++++++++ tsl/test/sql/vector_agg_groupagg.sql | 7 +++ 3 files changed, 68 insertions(+) diff --git a/tsl/src/planner.c b/tsl/src/planner.c index 8160e78ee4c..30af0ad8292 100644 --- a/tsl/src/planner.c +++ b/tsl/src/planner.c @@ -236,6 +236,11 @@ tsl_postprocess_plan(PlannedStmt *stmt) { stmt->planTree = try_insert_vector_agg_node(stmt->planTree); } + else + { + /* FIXME */ + return; + } #ifdef TS_DEBUG if (ts_guc_debug_require_vector_agg != DRO_Allow) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index 38dd5751c2b..f447030cab3 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -6,6 +6,7 @@ \pset null ¤ set max_parallel_workers_per_gather = 0; set enable_hashagg to off; +set timescaledb.enable_vectorized_aggregation to off; create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); NOTICE: adding not-null constraint to column "t" @@ -132,7 +133,35 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; 2 (1 row) +vacuum analyze text_table; set timescaledb.debug_require_vector_agg to 'require'; +explain (verbose, costs off) +select a, count(*) from text_table group by a order by a limit 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: _hyper_3_7_chunk.a, (count(*)) + -> Finalize GroupAggregate + Output: _hyper_3_7_chunk.a, count(*) + Group Key: _hyper_3_7_chunk.a + -> Merge Append + Sort Key: _hyper_3_7_chunk.a + -> Partial GroupAggregate + Output: _hyper_3_7_chunk.a, PARTIAL count(*) + Group Key: _hyper_3_7_chunk.a + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk + Output: _hyper_3_7_chunk.a + -> Index Scan using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk + Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a + -> Partial GroupAggregate + Output: _hyper_3_9_chunk.a, PARTIAL count(*) + Group Key: _hyper_3_9_chunk.a + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk + Output: _hyper_3_9_chunk.a + -> Index Scan using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk + Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a +(21 rows) + select a, count(*) from text_table group by a order by a limit 10; a | count ---------------+------- @@ -151,6 +180,33 @@ select a, count(*) from text_table group by a order by a limit 10; -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; +explain (verbose, costs off) +select a, count(*) from text_table group by a order by a desc limit 10; + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit + Output: _hyper_3_7_chunk.a, (count(*)) + -> Finalize GroupAggregate + Output: _hyper_3_7_chunk.a, count(*) + Group Key: _hyper_3_7_chunk.a + -> Merge Append + Sort Key: _hyper_3_7_chunk.a DESC + -> Partial GroupAggregate + Output: _hyper_3_7_chunk.a, PARTIAL count(*) + Group Key: _hyper_3_7_chunk.a + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk + Output: _hyper_3_7_chunk.a + -> Index Scan Backward using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk + Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a + -> Partial GroupAggregate + Output: _hyper_3_9_chunk.a, PARTIAL count(*) + Group Key: _hyper_3_9_chunk.a + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk + Output: _hyper_3_9_chunk.a + -> Index Scan Backward using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk + Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a +(21 rows) + select a, count(*) from text_table group by a order by a desc limit 10; a | count -------------------------+------- diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index b0beef0ca2b..08768c8ce50 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -10,6 +10,8 @@ set max_parallel_workers_per_gather = 0; set enable_hashagg to off; +set timescaledb.enable_vectorized_aggregation to off; + create table groupagg(t int, s text, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); @@ -68,13 +70,18 @@ insert into text_table select 4, case when x % 2 = 0 then null else 'same-with-n insert into text_table select 5, case when x % 2 = 0 then null else 'different-with-nulls' || x end from generate_series(1, 1000) x; select count(compress_chunk(x)) from show_chunks('text_table') x; +vacuum analyze text_table; set timescaledb.debug_require_vector_agg to 'require'; +explain (verbose, costs off) +select a, count(*) from text_table group by a order by a limit 10; select a, count(*) from text_table group by a order by a limit 10; -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; +explain (verbose, costs off) +select a, count(*) from text_table group by a order by a desc limit 10; select a, count(*) from text_table group by a order by a desc limit 10; reset timescaledb.debug_require_vector_agg; From 5f2fdb2bb95a308c891eec5209b3b68c3814f446 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:49:29 +0100 Subject: [PATCH 231/242] cleanups --- tsl/src/nodes/decompress_chunk/exec.c | 7 +++- tsl/test/expected/vector_agg_groupagg.out | 50 +++++++++++++---------- tsl/test/sql/vector_agg_groupagg.sql | 4 +- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/tsl/src/nodes/decompress_chunk/exec.c b/tsl/src/nodes/decompress_chunk/exec.c index 2856a279aa1..413c014f4a5 100644 --- a/tsl/src/nodes/decompress_chunk/exec.c +++ b/tsl/src/nodes/decompress_chunk/exec.c @@ -522,7 +522,12 @@ decompress_chunk_explain(CustomScanState *node, List *ancestors, ExplainState *e ExplainPropertyBool("Batch Sorted Merge", dcontext->batch_sorted_merge, es); } - if (es->analyze && (es->verbose || es->format != EXPLAIN_FORMAT_TEXT)) + if (dcontext->reverse) + { + ExplainPropertyBool("Reverse", dcontext->reverse, es); + } + + if (es->analyze) { ExplainPropertyBool("Bulk Decompression", chunk_state->decompress_context.enable_bulk_decompression, diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index f447030cab3..c104acfd52d 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -135,32 +135,34 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; vacuum analyze text_table; set timescaledb.debug_require_vector_agg to 'require'; -explain (verbose, costs off) +explain (verbose, costs off, analyze, timing off, summary off) select a, count(*) from text_table group by a order by a limit 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit + Limit (actual rows=10 loops=1) Output: _hyper_3_7_chunk.a, (count(*)) - -> Finalize GroupAggregate + -> Finalize GroupAggregate (actual rows=10 loops=1) Output: _hyper_3_7_chunk.a, count(*) Group Key: _hyper_3_7_chunk.a - -> Merge Append + -> Merge Append (actual rows=11 loops=1) Sort Key: _hyper_3_7_chunk.a - -> Partial GroupAggregate + -> Partial GroupAggregate (actual rows=3 loops=1) Output: _hyper_3_7_chunk.a, PARTIAL count(*) Group Key: _hyper_3_7_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk (actual rows=3000 loops=1) Output: _hyper_3_7_chunk.a - -> Index Scan using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk + Bulk Decompression: true + -> Index Scan using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk (actual rows=3 loops=1) Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a - -> Partial GroupAggregate + -> Partial GroupAggregate (actual rows=9 loops=1) Output: _hyper_3_9_chunk.a, PARTIAL count(*) Group Key: _hyper_3_9_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk (actual rows=10 loops=1) Output: _hyper_3_9_chunk.a - -> Index Scan using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk + Bulk Decompression: true + -> Index Scan using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk (actual rows=1 loops=1) Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a -(21 rows) +(23 rows) select a, count(*) from text_table group by a order by a limit 10; a | count @@ -180,32 +182,36 @@ select a, count(*) from text_table group by a order by a limit 10; -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; -explain (verbose, costs off) +explain (verbose, costs off, analyze, timing off, summary off) select a, count(*) from text_table group by a order by a desc limit 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit + Limit (actual rows=10 loops=1) Output: _hyper_3_7_chunk.a, (count(*)) - -> Finalize GroupAggregate + -> Finalize GroupAggregate (actual rows=10 loops=1) Output: _hyper_3_7_chunk.a, count(*) Group Key: _hyper_3_7_chunk.a - -> Merge Append + -> Merge Append (actual rows=11 loops=1) Sort Key: _hyper_3_7_chunk.a DESC - -> Partial GroupAggregate + -> Partial GroupAggregate (actual rows=2 loops=1) Output: _hyper_3_7_chunk.a, PARTIAL count(*) Group Key: _hyper_3_7_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk (actual rows=2001 loops=1) Output: _hyper_3_7_chunk.a - -> Index Scan Backward using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk + Reverse: true + Bulk Decompression: true + -> Index Scan Backward using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk (actual rows=3 loops=1) Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a - -> Partial GroupAggregate + -> Partial GroupAggregate (actual rows=10 loops=1) Output: _hyper_3_9_chunk.a, PARTIAL count(*) Group Key: _hyper_3_9_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk + -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk (actual rows=1509 loops=1) Output: _hyper_3_9_chunk.a - -> Index Scan Backward using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk + Reverse: true + Bulk Decompression: true + -> Index Scan Backward using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk (actual rows=2 loops=1) Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a -(21 rows) +(25 rows) select a, count(*) from text_table group by a order by a desc limit 10; a | count diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 08768c8ce50..408d87469b0 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -73,14 +73,14 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; vacuum analyze text_table; set timescaledb.debug_require_vector_agg to 'require'; -explain (verbose, costs off) +explain (verbose, costs off, analyze, timing off, summary off) select a, count(*) from text_table group by a order by a limit 10; select a, count(*) from text_table group by a order by a limit 10; -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; -explain (verbose, costs off) +explain (verbose, costs off, analyze, timing off, summary off) select a, count(*) from text_table group by a order by a desc limit 10; select a, count(*) from text_table group by a order by a desc limit 10; From 28678d877f60a98bf8dac3375ca5d5416abc41d8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:15:54 +0100 Subject: [PATCH 232/242] integrate the changes from the bug fix --- .../nodes/vector_agg/grouping_policy_hash.h | 4 +- tsl/src/nodes/vector_agg/plan.c | 2 +- tsl/src/planner.c | 5 - tsl/test/expected/vector_agg_groupagg.out | 267 ++++++++---------- tsl/test/sql/vector_agg_groupagg.sql | 43 ++- 5 files changed, 155 insertions(+), 166 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 2d8c3538131..3516efb8896 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -43,7 +43,9 @@ typedef struct GroupingPolicyHash GroupingPolicyHash; * results are emitted into the output slot. This is done in the order of unique * grouping key indexes, thereby preserving the incoming key order. This * guarantees that this policy works correctly even in a Partial GroupAggregate - * node, even though it's not optimal performance-wise. + * node, even though it's not optimal performance-wise. We only support the + * direct order of records in batch though, not reverse. This is checked at + * planning time. */ typedef struct GroupingPolicyHash { diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 3741275a594..a41900febd4 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -506,7 +506,7 @@ get_vectorized_grouping_type(Agg *agg, CustomScan *custom, List *resolved_target * We support hashed vectorized grouping by one fixed-size by-value * compressed column. * We can use our hash table for GroupAggregate as well, because it preserves - * the input order of the keys. + * the input order of the keys, but only for the direct order, not reverse. */ if (num_grouping_columns == 1) { diff --git a/tsl/src/planner.c b/tsl/src/planner.c index 30af0ad8292..8160e78ee4c 100644 --- a/tsl/src/planner.c +++ b/tsl/src/planner.c @@ -236,11 +236,6 @@ tsl_postprocess_plan(PlannedStmt *stmt) { stmt->planTree = try_insert_vector_agg_node(stmt->planTree); } - else - { - /* FIXME */ - return; - } #ifdef TS_DEBUG if (ts_guc_debug_require_vector_agg != DRO_Allow) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index c104acfd52d..8bc71c7aef5 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -3,11 +3,12 @@ -- LICENSE-TIMESCALE for a copy of the license. -- Check that the vectorized aggregation works properly in the GroupAggregate -- mode. -\pset null ¤ +\pset null $ set max_parallel_workers_per_gather = 0; set enable_hashagg to off; -set timescaledb.enable_vectorized_aggregation to off; -create table groupagg(t int, s text, value int); +--set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.debug_require_vector_agg to 'forbid'; +create table groupagg(t int, s int, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); NOTICE: adding not-null constraint to column "t" create_hypertable @@ -17,11 +18,11 @@ NOTICE: adding not-null constraint to column "t" insert into groupagg select - xfast * 100 + xslow, + xslow * 10, case when xfast = 13 then null else xfast end, xfast * 7 + xslow * 3 from generate_series(10, 99) xfast, - generate_series(1, 1000) xslow + generate_series(1, 1487) xslow ; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 's'); @@ -36,16 +37,16 @@ set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; s | sum ----+--------- - 10 | 1571500 - 11 | 1578500 - 12 | 1585500 - 14 | 1599500 - 15 | 1606500 - 16 | 1613500 - 17 | 1620500 - 18 | 1627500 - 19 | 1634500 - 20 | 1641500 + 10 | 3423074 + 11 | 3433483 + 12 | 3443892 + 14 | 3464710 + 15 | 3475119 + 16 | 3485528 + 17 | 3495937 + 18 | 3506346 + 19 | 3516755 + 20 | 3527164 (10 rows) -- The hash grouping policies do not support the GroupAggregate mode in the @@ -54,19 +55,20 @@ set timescaledb.debug_require_vector_agg to 'forbid'; select s, sum(value) from groupagg group by s order by s desc limit 10; s | sum ----+--------- - ¤ | 1592500 - 99 | 2194500 - 98 | 2187500 - 97 | 2180500 - 96 | 2173500 - 95 | 2166500 - 94 | 2159500 - 93 | 2152500 - 92 | 2145500 - 91 | 2138500 + $ | 3454301 + 99 | 4349475 + 98 | 4339066 + 97 | 4328657 + 96 | 4318248 + 95 | 4307839 + 94 | 4297430 + 93 | 4287021 + 92 | 4276612 + 91 | 4266203 (10 rows) reset timescaledb.debug_require_vector_agg; +-- Also test the NULLS FIRST order. select count(decompress_chunk(x)) from show_chunks('groupagg') x; count ------- @@ -83,19 +85,19 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; vacuum analyze groupagg; set timescaledb.debug_require_vector_agg to 'require'; -select s , sum(value) from groupagg group by s order by s nulls first limit 10; +select s, sum(value) from groupagg group by s order by s nulls first limit 10; s | sum ----+--------- - ¤ | 1592500 - 10 | 1571500 - 11 | 1578500 - 12 | 1585500 - 14 | 1599500 - 15 | 1606500 - 16 | 1613500 - 17 | 1620500 - 18 | 1627500 - 19 | 1634500 + $ | 3454301 + 10 | 3423074 + 11 | 3433483 + 12 | 3443892 + 14 | 3464710 + 15 | 3475119 + 16 | 3485528 + 17 | 3495937 + 18 | 3506346 + 19 | 3516755 (10 rows) reset timescaledb.debug_require_vector_agg; @@ -134,98 +136,72 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; (1 row) vacuum analyze text_table; -set timescaledb.debug_require_vector_agg to 'require'; -explain (verbose, costs off, analyze, timing off, summary off) -select a, count(*) from text_table group by a order by a limit 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit (actual rows=10 loops=1) - Output: _hyper_3_7_chunk.a, (count(*)) - -> Finalize GroupAggregate (actual rows=10 loops=1) - Output: _hyper_3_7_chunk.a, count(*) - Group Key: _hyper_3_7_chunk.a - -> Merge Append (actual rows=11 loops=1) - Sort Key: _hyper_3_7_chunk.a - -> Partial GroupAggregate (actual rows=3 loops=1) - Output: _hyper_3_7_chunk.a, PARTIAL count(*) - Group Key: _hyper_3_7_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk (actual rows=3000 loops=1) - Output: _hyper_3_7_chunk.a - Bulk Decompression: true - -> Index Scan using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk (actual rows=3 loops=1) - Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a - -> Partial GroupAggregate (actual rows=9 loops=1) - Output: _hyper_3_9_chunk.a, PARTIAL count(*) - Group Key: _hyper_3_9_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk (actual rows=10 loops=1) - Output: _hyper_3_9_chunk.a - Bulk Decompression: true - -> Index Scan using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk (actual rows=1 loops=1) - Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a -(23 rows) +-- The following tests are collation-sensitive, so verify it all matches. +select table_schema, + table_name, + column_name, + collation_name +from information_schema.columns +where table_name = 'text_table' +order by table_schema, + table_name, + ordinal_position; + table_schema | table_name | column_name | collation_name +--------------+------------+-------------+---------------- + public | text_table | ts | $ + public | text_table | a | $ +(2 rows) + +select datcollate from pg_database where datname = current_database(); + datcollate +------------ + C.UTF-8 +(1 row) + +select 'different-with-nulls999' > 'different999'; + ?column? +---------- + f +(1 row) +select count(distinct a) from text_table; + count +------- + 1504 +(1 row) + +set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a limit 10; - a | count ----------------+------- - | 1000 - default | 1000 - different1 | 1 - different10 | 1 - different100 | 1 - different1000 | 1 - different101 | 1 - different102 | 1 - different103 | 1 - different104 | 1 + a | count +-------------------------+------- + | 1000 + default | 1000 + different-with-nulls1 | 1 + different-with-nulls101 | 1 + different-with-nulls103 | 1 + different-with-nulls105 | 1 + different-with-nulls107 | 1 + different-with-nulls109 | 1 + different-with-nulls11 | 1 + different-with-nulls111 | 1 (10 rows) -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; -explain (verbose, costs off, analyze, timing off, summary off) -select a, count(*) from text_table group by a order by a desc limit 10; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Limit (actual rows=10 loops=1) - Output: _hyper_3_7_chunk.a, (count(*)) - -> Finalize GroupAggregate (actual rows=10 loops=1) - Output: _hyper_3_7_chunk.a, count(*) - Group Key: _hyper_3_7_chunk.a - -> Merge Append (actual rows=11 loops=1) - Sort Key: _hyper_3_7_chunk.a DESC - -> Partial GroupAggregate (actual rows=2 loops=1) - Output: _hyper_3_7_chunk.a, PARTIAL count(*) - Group Key: _hyper_3_7_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_7_chunk (actual rows=2001 loops=1) - Output: _hyper_3_7_chunk.a - Reverse: true - Bulk Decompression: true - -> Index Scan Backward using compress_hyper_4_10_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_10_chunk (actual rows=3 loops=1) - Output: compress_hyper_4_10_chunk._ts_meta_count, compress_hyper_4_10_chunk._ts_meta_min_2, compress_hyper_4_10_chunk._ts_meta_max_2, compress_hyper_4_10_chunk.ts, compress_hyper_4_10_chunk._ts_meta_min_1, compress_hyper_4_10_chunk._ts_meta_max_1, compress_hyper_4_10_chunk.a - -> Partial GroupAggregate (actual rows=10 loops=1) - Output: _hyper_3_9_chunk.a, PARTIAL count(*) - Group Key: _hyper_3_9_chunk.a - -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_3_9_chunk (actual rows=1509 loops=1) - Output: _hyper_3_9_chunk.a - Reverse: true - Bulk Decompression: true - -> Index Scan Backward using compress_hyper_4_11_chunk__ts_meta_min_1__ts_meta_max_1__ts_idx on _timescaledb_internal.compress_hyper_4_11_chunk (actual rows=2 loops=1) - Output: compress_hyper_4_11_chunk._ts_meta_count, compress_hyper_4_11_chunk._ts_meta_min_2, compress_hyper_4_11_chunk._ts_meta_max_2, compress_hyper_4_11_chunk.ts, compress_hyper_4_11_chunk._ts_meta_min_1, compress_hyper_4_11_chunk._ts_meta_max_1, compress_hyper_4_11_chunk.a -(25 rows) - select a, count(*) from text_table group by a order by a desc limit 10; - a | count --------------------------+------- - ¤ | 1000 - same-with-nulls | 500 - same | 1000 - different-with-nulls999 | 1 - different-with-nulls997 | 1 - different-with-nulls995 | 1 - different-with-nulls993 | 1 - different-with-nulls991 | 1 - different-with-nulls99 | 1 - different-with-nulls989 | 1 + a | count +-----------------+------- + $ | 1000 + same-with-nulls | 500 + same | 1000 + different999 | 1 + different998 | 1 + different997 | 1 + different996 | 1 + different995 | 1 + different994 | 1 + different993 | 1 (10 rows) reset timescaledb.debug_require_vector_agg; @@ -246,22 +222,21 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a nulls first limit 10; - a | count ----------------+------- - ¤ | 1000 - | 1000 - default | 1000 - different1 | 1 - different10 | 1 - different100 | 1 - different1000 | 1 - different101 | 1 - different102 | 1 - different103 | 1 + a | count +-------------------------+------- + $ | 1000 + | 1000 + default | 1000 + different-with-nulls1 | 1 + different-with-nulls101 | 1 + different-with-nulls103 | 1 + different-with-nulls105 | 1 + different-with-nulls107 | 1 + different-with-nulls109 | 1 + different-with-nulls11 | 1 (10 rows) reset timescaledb.debug_require_vector_agg; -reset enable_hashagg; -- TODO verify that this works with the serialized hash grouping strategy set timescaledb.debug_require_vector_agg to 'forbid'; select ts, a, count(*) from text_table group by ts, a order by ts, a limit 10; @@ -280,19 +255,21 @@ select ts, a, count(*) from text_table group by ts, a order by ts, a limit 10; (10 rows) select a, ts, count(*) from text_table group by a, ts order by a desc, ts desc limit 10; - a | ts | count --------------------------+----+------- - ¤ | 5 | 500 - ¤ | 4 | 500 - same-with-nulls | 4 | 500 - same | 2 | 1000 - different-with-nulls999 | 5 | 1 - different-with-nulls997 | 5 | 1 - different-with-nulls995 | 5 | 1 - different-with-nulls993 | 5 | 1 - different-with-nulls991 | 5 | 1 - different-with-nulls99 | 5 | 1 + a | ts | count +-----------------+----+------- + $ | 5 | 500 + $ | 4 | 500 + same-with-nulls | 4 | 500 + same | 2 | 1000 + different999 | 3 | 1 + different998 | 3 | 1 + different997 | 3 | 1 + different996 | 3 | 1 + different995 | 3 | 1 + different994 | 3 | 1 (10 rows) reset timescaledb.debug_require_vector_agg; reset max_parallel_workers_per_gather; +reset timescaledb.debug_require_vector_agg; +reset enable_hashagg; diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 408d87469b0..01ff2590a89 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -5,23 +5,24 @@ -- Check that the vectorized aggregation works properly in the GroupAggregate -- mode. -\pset null ¤ +\pset null $ set max_parallel_workers_per_gather = 0; set enable_hashagg to off; -set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.enable_vectorized_aggregation to off; +--set timescaledb.debug_require_vector_agg to 'forbid'; -create table groupagg(t int, s text, value int); +create table groupagg(t int, s int, value int); select create_hypertable('groupagg', 't', chunk_time_interval => 10000); insert into groupagg select - xfast * 100 + xslow, + xslow * 10, case when xfast = 13 then null else xfast end, xfast * 7 + xslow * 3 from generate_series(10, 99) xfast, - generate_series(1, 1000) xslow + generate_series(1, 1487) xslow ; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', @@ -29,6 +30,7 @@ alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = select count(compress_chunk(x)) from show_chunks('groupagg') x; vacuum analyze groupagg; + set timescaledb.debug_require_vector_agg to 'require'; select s, sum(value) from groupagg group by s order by s limit 10; @@ -36,10 +38,9 @@ select s, sum(value) from groupagg group by s order by s limit 10; -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; select s, sum(value) from groupagg group by s order by s desc limit 10; - reset timescaledb.debug_require_vector_agg; - +-- Also test the NULLS FIRST order. select count(decompress_chunk(x)) from show_chunks('groupagg') x; alter table groupagg set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 's nulls first'); @@ -47,7 +48,7 @@ select count(compress_chunk(x)) from show_chunks('groupagg') x; vacuum analyze groupagg; set timescaledb.debug_require_vector_agg to 'require'; -select s , sum(value) from groupagg group by s order by s nulls first limit 10; +select s, sum(value) from groupagg group by s order by s nulls first limit 10; reset timescaledb.debug_require_vector_agg; @@ -72,16 +73,30 @@ insert into text_table select 5, case when x % 2 = 0 then null else 'different-w select count(compress_chunk(x)) from show_chunks('text_table') x; vacuum analyze text_table; +-- The following tests are collation-sensitive, so verify it all matches. +select table_schema, + table_name, + column_name, + collation_name +from information_schema.columns +where table_name = 'text_table' +order by table_schema, + table_name, + ordinal_position; + +select datcollate from pg_database where datname = current_database(); + +select 'different-with-nulls999' > 'different999'; + +select count(distinct a) from text_table; + + set timescaledb.debug_require_vector_agg to 'require'; -explain (verbose, costs off, analyze, timing off, summary off) -select a, count(*) from text_table group by a order by a limit 10; select a, count(*) from text_table group by a order by a limit 10; -- The hash grouping policies do not support the GroupAggregate mode in the -- reverse order. set timescaledb.debug_require_vector_agg to 'forbid'; -explain (verbose, costs off, analyze, timing off, summary off) -select a, count(*) from text_table group by a order by a desc limit 10; select a, count(*) from text_table group by a order by a desc limit 10; reset timescaledb.debug_require_vector_agg; @@ -97,8 +112,6 @@ set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a nulls first limit 10; reset timescaledb.debug_require_vector_agg; -reset enable_hashagg; - -- TODO verify that this works with the serialized hash grouping strategy set timescaledb.debug_require_vector_agg to 'forbid'; @@ -107,3 +120,5 @@ select a, ts, count(*) from text_table group by a, ts order by a desc, ts desc l reset timescaledb.debug_require_vector_agg; reset max_parallel_workers_per_gather; +reset timescaledb.debug_require_vector_agg; +reset enable_hashagg; From 73faf1e9533c541d495d0b7949159c8385b69732 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:20:29 +0100 Subject: [PATCH 233/242] prepare to merge --- tsl/test/expected/vector_agg_groupagg.out | 34 ----------------------- tsl/test/sql/vector_agg_groupagg.sql | 17 ------------ 2 files changed, 51 deletions(-) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index 8bc71c7aef5..ffe5728c6c4 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -136,40 +136,6 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; (1 row) vacuum analyze text_table; --- The following tests are collation-sensitive, so verify it all matches. -select table_schema, - table_name, - column_name, - collation_name -from information_schema.columns -where table_name = 'text_table' -order by table_schema, - table_name, - ordinal_position; - table_schema | table_name | column_name | collation_name ---------------+------------+-------------+---------------- - public | text_table | ts | $ - public | text_table | a | $ -(2 rows) - -select datcollate from pg_database where datname = current_database(); - datcollate ------------- - C.UTF-8 -(1 row) - -select 'different-with-nulls999' > 'different999'; - ?column? ----------- - f -(1 row) - -select count(distinct a) from text_table; - count -------- - 1504 -(1 row) - set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a limit 10; a | count diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 01ff2590a89..164ee391941 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -73,23 +73,6 @@ insert into text_table select 5, case when x % 2 = 0 then null else 'different-w select count(compress_chunk(x)) from show_chunks('text_table') x; vacuum analyze text_table; --- The following tests are collation-sensitive, so verify it all matches. -select table_schema, - table_name, - column_name, - collation_name -from information_schema.columns -where table_name = 'text_table' -order by table_schema, - table_name, - ordinal_position; - -select datcollate from pg_database where datname = current_database(); - -select 'different-with-nulls999' > 'different999'; - -select count(distinct a) from text_table; - set timescaledb.debug_require_vector_agg to 'require'; select a, count(*) from text_table group by a order by a limit 10; From 22f12114be29bb050dbf9be005be4cdb3d5fc7a0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:22:51 +0100 Subject: [PATCH 234/242] fix --- tsl/test/sql/vector_agg_groupagg.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/test/sql/vector_agg_groupagg.sql b/tsl/test/sql/vector_agg_groupagg.sql index 164ee391941..7f9e1a0b20a 100644 --- a/tsl/test/sql/vector_agg_groupagg.sql +++ b/tsl/test/sql/vector_agg_groupagg.sql @@ -60,7 +60,7 @@ alter table text_table set (timescaledb.compress); insert into text_table select 0 /*, default */ from generate_series(1, 1000) x; select count(compress_chunk(x)) from show_chunks('text_table') x; -alter table text_table add column a text default 'default'; +alter table text_table add column a text collate "POSIX" default 'default'; alter table text_table set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a'); From 0e905c1c534125cf8b9358d77dec59bae1196b8f Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:24:22 +0100 Subject: [PATCH 235/242] fix --- tsl/src/nodes/vector_agg/plan.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 5f9c9874df8..ea65ae8f834 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -600,20 +600,6 @@ try_insert_vector_agg_node(Plan *plan, List *rtable) * GroupAggregate mode. */ if (grouping_type != VAGT_Batch && agg->aggstrategy != AGG_HASHED) - { - List *settings = linitial(custom->custom_private); - const bool reverse = list_nth_int(settings, DCS_Reverse); - if (reverse) - { - return plan; - } - } - - /* - * Build supplementary info to determine whether we can vectorize the - * aggregate FILTER clauses. - */ - if (grouping_type != VAGT_Batch && agg->aggstrategy != AGG_HASHED) { if (vqi.reverse) { From 7179faa98d5e452527eb68764ef7c5d9f2fdd816 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:38:26 +0100 Subject: [PATCH 236/242] fix --- tsl/test/expected/vector_agg_groupagg.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/test/expected/vector_agg_groupagg.out b/tsl/test/expected/vector_agg_groupagg.out index ffe5728c6c4..2d5f29b1225 100644 --- a/tsl/test/expected/vector_agg_groupagg.out +++ b/tsl/test/expected/vector_agg_groupagg.out @@ -121,7 +121,7 @@ select count(compress_chunk(x)) from show_chunks('text_table') x; 1 (1 row) -alter table text_table add column a text default 'default'; +alter table text_table add column a text collate "POSIX" default 'default'; alter table text_table set (timescaledb.compress, timescaledb.compress_segmentby = '', timescaledb.compress_orderby = 'a'); insert into text_table select 1, '' from generate_series(1, 1000) x; From 9dd63259287769a869bd421a8253e60433206f03 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 19 Feb 2025 17:42:43 +0100 Subject: [PATCH 237/242] Vectorized grouping by multiple column Paste the values together and use the umash hash of the resulting value for grouping, like we do for the text keys. --- tsl/src/nodes/vector_agg/grouping_policy.h | 3 +- .../nodes/vector_agg/grouping_policy_hash.c | 11 + .../nodes/vector_agg/grouping_policy_hash.h | 11 + .../nodes/vector_agg/hashing/CMakeLists.txt | 3 +- .../vector_agg/hashing/batch_hashing_params.h | 12 +- tsl/src/nodes/vector_agg/hashing/bytes_view.h | 24 + .../hashing/hash_strategy_serialized.c | 454 ++++ tsl/src/nodes/vector_agg/plan.c | 7 + tsl/test/expected/vector_agg_grouping.out | 1985 +++++++++++++++++ tsl/test/expected/vectorized_aggregation.out | 20 +- tsl/test/sql/CMakeLists.txt | 1 + tsl/test/sql/vector_agg_grouping.sql | 126 ++ tsl/test/sql/vectorized_aggregation.sql | 2 +- 13 files changed, 2644 insertions(+), 15 deletions(-) create mode 100644 tsl/src/nodes/vector_agg/hashing/bytes_view.h create mode 100644 tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c create mode 100644 tsl/test/expected/vector_agg_grouping.out create mode 100644 tsl/test/sql/vector_agg_grouping.sql diff --git a/tsl/src/nodes/vector_agg/grouping_policy.h b/tsl/src/nodes/vector_agg/grouping_policy.h index 9154c8dd500..16d634ad844 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy.h +++ b/tsl/src/nodes/vector_agg/grouping_policy.h @@ -66,7 +66,8 @@ typedef enum VAGT_HashSingleFixed2, VAGT_HashSingleFixed4, VAGT_HashSingleFixed8, - VAGT_HashSingleText + VAGT_HashSingleText, + VAGT_HashSerialized, } VectorAggGroupingType; extern GroupingPolicy *create_grouping_policy_batch(int num_agg_defs, VectorAggDef *agg_defs, diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 92ecfce11bc..7d34203a2a4 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -38,6 +38,7 @@ extern HashingStrategy single_fixed_4_strategy; extern HashingStrategy single_fixed_8_strategy; #ifdef TS_USE_UMASH extern HashingStrategy single_text_strategy; +extern HashingStrategy serialized_strategy; #endif static const GroupingPolicy grouping_policy_hash_functions; @@ -74,6 +75,9 @@ create_grouping_policy_hash(int num_agg_defs, VectorAggDef *agg_defs, int num_gr switch (grouping_type) { #ifdef TS_USE_UMASH + case VAGT_HashSerialized: + policy->hashing = serialized_strategy; + break; case VAGT_HashSingleText: policy->hashing = single_text_strategy; break; @@ -110,6 +114,13 @@ gp_hash_reset(GroupingPolicy *obj) policy->hashing.reset(&policy->hashing); + /* + * Have to reset this because it's in the key body context which is also + * reset here. + */ + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + policy->last_used_key_index = 0; policy->stat_input_valid_rows = 0; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index 3516efb8896..fa7792602d7 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -133,6 +133,17 @@ typedef struct GroupingPolicyHash uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; uint64 stat_consecutive_keys; + + /* + * FIXME all the stuff below should be moved out. + */ + + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; } GroupingPolicyHash; //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) diff --git a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt index 401e5f22025..f0e6dfe038b 100644 --- a/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt +++ b/tsl/src/nodes/vector_agg/hashing/CMakeLists.txt @@ -5,7 +5,8 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_common.c) if(USE_UMASH) - list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c) + list(APPEND SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_single_text.c + ${CMAKE_CURRENT_SOURCE_DIR}/hash_strategy_serialized.c) endif() target_sources(${TSL_LIBRARY_NAME} PRIVATE ${SOURCES}) diff --git a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h index ed4c0ed12bb..070c8bfaaae 100644 --- a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h +++ b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h @@ -18,6 +18,9 @@ typedef struct BatchHashingParams const uint64 *batch_filter; CompressedColumnValues single_grouping_column; + int num_grouping_columns; + const CompressedColumnValues *grouping_column_values; + GroupingPolicyHash *restrict policy; uint32 *restrict result_key_indexes; @@ -30,11 +33,16 @@ build_batch_hashing_params(GroupingPolicyHash *policy, TupleTableSlot *vector_sl BatchHashingParams params = { .policy = policy, .batch_filter = vector_slot_get_qual_result(vector_slot, &nrows), + .num_grouping_columns = policy->num_grouping_columns, + .grouping_column_values = policy->current_batch_grouping_column_values, .result_key_indexes = policy->key_index_for_row, }; - Assert(policy->num_grouping_columns == 1); - params.single_grouping_column = policy->current_batch_grouping_column_values[0]; + Assert(policy->num_grouping_columns > 0); + if (policy->num_grouping_columns == 1) + { + params.single_grouping_column = policy->current_batch_grouping_column_values[0]; + } return params; } diff --git a/tsl/src/nodes/vector_agg/hashing/bytes_view.h b/tsl/src/nodes/vector_agg/hashing/bytes_view.h new file mode 100644 index 00000000000..f7149c52568 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/bytes_view.h @@ -0,0 +1,24 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ +#pragma once + +#include + +#include + +typedef struct BytesView +{ + const uint8 *data; + uint32 len; +} BytesView; + +static pg_attribute_always_inline uint32 +hash_bytes_view(BytesView view) +{ + uint32 val = -1; + COMP_CRC32C(val, view.data, view.len); + return val; +} diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c new file mode 100644 index 00000000000..d09b6adbc64 --- /dev/null +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -0,0 +1,454 @@ +/* + * This file and its contents are licensed under the Timescale License. + * Please see the included NOTICE for copyright information and + * LICENSE-TIMESCALE for a copy of the license. + */ + +/* + * Implementation of column hashing for multiple serialized columns. + */ + +#include + +#include + +#include "bytes_view.h" +#include "compression/arrow_c_data_interface.h" +#include "nodes/decompress_chunk/compressed_batch.h" +#include "nodes/vector_agg/exec.h" +#include "nodes/vector_agg/grouping_policy_hash.h" +#include "template_helper.h" + +#include "batch_hashing_params.h" + +#include "umash_fingerprint_key.h" + +#define EXPLAIN_NAME "serialized" +#define KEY_VARIANT serialized +#define OUTPUT_KEY_TYPE text * + +static void +serialized_key_hashing_init(HashingStrategy *hashing) +{ + hashing->umash_params = umash_key_hashing_init(); +} + +static void +serialized_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTableSlot *vector_slot) +{ +} + +static pg_attribute_always_inline bool +byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) +{ + if (likely(bitmap == NULL)) + { + return true; + } + + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + return bitmap[byte_index] & mask; +} + +static pg_attribute_always_inline void +byte_bitmap_set_row_validity(uint8 *bitmap, size_t row_number, bool value) +{ + const size_t byte_index = row_number / 8; + const size_t bit_index = row_number % 8; + const uint8 mask = ((uint8) 1) << bit_index; + const uint8 new_bit = ((uint8) value) << bit_index; + + bitmap[byte_index] = (bitmap[byte_index] & ~mask) | new_bit; + + Assert(byte_bitmap_row_is_valid(bitmap, row_number) == value); +} + +static pg_attribute_always_inline void +serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, + void *restrict hash_table_key_ptr, bool *restrict valid) +{ + GroupingPolicyHash *policy = params.policy; + + text **restrict output_key = (text **) output_key_ptr; + HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; + + const int num_columns = params.num_grouping_columns; + + const size_t bitmap_bytes = (num_columns + 7) / 8; + + /* + * Loop through the grouping columns to determine the length of the key. We + * need that to allocate memory to store it. + * + * The key has the null bitmap at the beginning. + */ + size_t num_bytes = bitmap_bytes; + for (int column_index = 0; column_index < num_columns; column_index++) + { + const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; + + if (column_values->decompression_type == DT_Scalar) + { + if (!*column_values->output_isnull) + { + const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; + if (def->by_value) + { + num_bytes += def->value_bytes; + } + else + { + /* + * The default value always has a long varlena header, but + * we are going to use short if it fits. + */ + const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, unaligned. */ + const int total_bytes = value_bytes + VARHDRSZ_SHORT; + num_bytes += total_bytes; + } + else + { + /* Long varlena, requires alignment. */ + const int total_bytes = value_bytes + VARHDRSZ; + num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; + } + } + } + + continue; + } + + const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); + if (!is_valid) + { + continue; + } + + if (column_values->decompression_type > 0) + { + num_bytes += column_values->decompression_type; + } + else + { + Assert(column_values->decompression_type == DT_ArrowText || + column_values->decompression_type == DT_ArrowTextDict); + Assert((column_values->decompression_type == DT_ArrowTextDict) == + (column_values->buffers[3] != NULL)); + + const uint32 data_row = (column_values->decompression_type == DT_ArrowTextDict) ? + ((int16 *) column_values->buffers[3])[row] : + row; + const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; + + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, unaligned. */ + const int total_bytes = value_bytes + VARHDRSZ_SHORT; + num_bytes += total_bytes; + } + else + { + /* Long varlena, requires alignment. */ + const int total_bytes = value_bytes + VARHDRSZ; + num_bytes = TYPEALIGN(4, num_bytes) + total_bytes; + } + } + } + + /* + * The key has short or long varlena header. This is a little tricky, we + * decide the header length after we have counted all the columns, but we + * put it at the beginning. Technically it could change the length because + * of the alignment. In practice, we only use alignment by 4 bytes for long + * varlena strings, and if we have at least one long varlena string column, + * the key is also going to use the long varlena header which is 4 bytes, so + * the alignment is not affected. If we use the short varlena header for the + * key, it necessarily means that there were no long varlena columns and + * therefore no alignment is needed. + */ + const bool key_uses_short_header = num_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX; + num_bytes += key_uses_short_header ? VARHDRSZ_SHORT : VARHDRSZ; + + /* + * Use temporary storage for the new key, reallocate if it's too small. + */ + if (num_bytes > policy->num_tmp_key_storage_bytes) + { + if (policy->tmp_key_storage != NULL) + { + pfree(policy->tmp_key_storage); + } + policy->tmp_key_storage = MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes); + policy->num_tmp_key_storage_bytes = num_bytes; + } + uint8 *restrict serialized_key_storage = policy->tmp_key_storage; + + /* + * Build the actual grouping key. + */ + uint32 offset = 0; + offset += key_uses_short_header ? VARHDRSZ_SHORT : VARHDRSZ; + + /* + * We must always save the validity bitmap, even when there are no + * null words, so that the key is uniquely deserializable. Otherwise a key + * with some nulls might collide with a key with no nulls. + */ + uint8 *restrict serialized_key_validity_bitmap = &serialized_key_storage[offset]; + offset += bitmap_bytes; + + /* + * Loop through the grouping columns again and add their values to the + * grouping key. + */ + for (int column_index = 0; column_index < num_columns; column_index++) + { + const CompressedColumnValues *column_values = ¶ms.grouping_column_values[column_index]; + + if (column_values->decompression_type == DT_Scalar) + { + const bool is_valid = !*column_values->output_isnull; + byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); + if (is_valid) + { + const GroupingColumn *def = ¶ms.policy->grouping_columns[column_index]; + if (def->by_value) + { + memcpy(&serialized_key_storage[offset], + column_values->output_value, + def->value_bytes); + + offset += def->value_bytes; + } + else + { + /* + * The default value always has a long varlena header, but + * we are going to use short if it fits. + */ + const int32 value_bytes = VARSIZE_ANY_EXHDR(*column_values->output_value); + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, no alignment. */ + const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; + SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ_SHORT; + } + else + { + /* Long varlena, requires alignment. Zero out the alignment bytes. */ + memset(&serialized_key_storage[offset], 0, 4); + offset = TYPEALIGN(4, offset); + const int32 total_bytes = value_bytes + VARHDRSZ; + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ; + } + + memcpy(&serialized_key_storage[offset], + VARDATA_ANY(*column_values->output_value), + value_bytes); + + offset += value_bytes; + } + } + continue; + } + + const bool is_valid = arrow_row_is_valid(column_values->buffers[0], row); + byte_bitmap_set_row_validity(serialized_key_validity_bitmap, column_index, is_valid); + + if (!is_valid) + { + continue; + } + + if (column_values->decompression_type > 0) + { + Assert(offset <= UINT_MAX - column_values->decompression_type); + + switch ((int) column_values->decompression_type) + { + case 2: + memcpy(&serialized_key_storage[offset], + row + (int16 *) column_values->buffers[1], + 2); + break; + case 4: + memcpy(&serialized_key_storage[offset], + row + (int32 *) column_values->buffers[1], + 4); + break; + case 8: + memcpy(&serialized_key_storage[offset], + row + (int64 *) column_values->buffers[1], + 8); + break; + default: + pg_unreachable(); + break; + } + + offset += column_values->decompression_type; + + continue; + } + + Assert(column_values->decompression_type == DT_ArrowText || + column_values->decompression_type == DT_ArrowTextDict); + + const uint32 data_row = column_values->decompression_type == DT_ArrowTextDict ? + ((int16 *) column_values->buffers[3])[row] : + row; + const uint32 start = ((uint32 *) column_values->buffers[1])[data_row]; + const int32 value_bytes = ((uint32 *) column_values->buffers[1])[data_row + 1] - start; + + if (value_bytes + VARHDRSZ_SHORT <= VARATT_SHORT_MAX) + { + /* Short varlena, unaligned. */ + const int32 total_bytes = value_bytes + VARHDRSZ_SHORT; + SET_VARSIZE_SHORT(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ_SHORT; + } + else + { + /* Long varlena, requires alignment. Zero out the alignment bytes. */ + memset(&serialized_key_storage[offset], 0, 4); + offset = TYPEALIGN(4, offset); + const int32 total_bytes = value_bytes + VARHDRSZ; + SET_VARSIZE(&serialized_key_storage[offset], total_bytes); + offset += VARHDRSZ; + } + memcpy(&serialized_key_storage[offset], + &((uint8 *) column_values->buffers[2])[start], + value_bytes); + + offset += value_bytes; + } + + Assert(offset == num_bytes); + + if (key_uses_short_header) + { + SET_VARSIZE_SHORT(serialized_key_storage, offset); + } + else + { + SET_VARSIZE(serialized_key_storage, offset); + } + + DEBUG_PRINT("key is %d bytes: ", offset); + for (size_t i = 0; i < offset; i++) + { + DEBUG_PRINT("%.2x.", serialized_key_storage[i]); + } + DEBUG_PRINT("\n"); + + *output_key = (text *) serialized_key_storage; + + Assert(VARSIZE_ANY(*output_key) == num_bytes); + + /* + * The multi-column key is always considered non-null, and the null flags + * for the individual columns are stored in a bitmap that is part of the + * key. + */ + *valid = true; + + const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, + /* seed = */ -1ull, + serialized_key_storage, + num_bytes); + *hash_table_key = umash_fingerprint_get_key(fp); +} + +static pg_attribute_always_inline void +serialized_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, + text *output_key) +{ + /* + * We will store this key so we have to consume the temporary storage that + * was used for it. The subsequent keys will need to allocate new memory. + */ + Assert(policy->tmp_key_storage == (void *) output_key); + policy->tmp_key_storage = NULL; + policy->num_tmp_key_storage_bytes = 0; + + policy->hashing.output_keys[new_key_index] = PointerGetDatum(output_key); +} + +static void +serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) +{ + const int num_key_columns = policy->num_grouping_columns; + const Datum serialized_key_datum = policy->hashing.output_keys[current_key]; + const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); + PG_USED_FOR_ASSERTS_ONLY const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); + const uint8 *restrict ptr = serialized_key; + + /* + * We have the column validity bitmap at the beginning of the key. + */ + const int bitmap_bytes = (num_key_columns + 7) / 8; + Assert(bitmap_bytes <= key_data_bytes); + const uint8 *restrict key_validity_bitmap = serialized_key; + ptr += bitmap_bytes; + + DEBUG_PRINT("emit key #%d, with header %ld without %d bytes: ", + current_key, + VARSIZE_ANY(serialized_key_datum), + key_data_bytes); + for (size_t i = 0; i < VARSIZE_ANY(serialized_key_datum); i++) + { + DEBUG_PRINT("%.2x.", ((const uint8 *) serialized_key_datum)[i]); + } + DEBUG_PRINT("\n"); + + for (int column_index = 0; column_index < num_key_columns; column_index++) + { + const GroupingColumn *col = &policy->grouping_columns[column_index]; + const bool isnull = !byte_bitmap_row_is_valid(key_validity_bitmap, column_index); + + aggregated_slot->tts_isnull[col->output_offset] = isnull; + + if (isnull) + { + continue; + } + + Datum *output = &aggregated_slot->tts_values[col->output_offset]; + if (col->value_bytes > 0) + { + Assert(col->by_value); + Assert((size_t) col->value_bytes <= sizeof(Datum)); + *output = 0; + memcpy(output, ptr, col->value_bytes); + ptr += col->value_bytes; + } + else + { + Assert(col->value_bytes == -1); + Assert(!col->by_value); + if (VARATT_IS_SHORT(ptr)) + { + *output = PointerGetDatum(ptr); + ptr += VARSIZE_SHORT(ptr); + } + else + { + ptr = (const uint8 *) TYPEALIGN(4, ptr); + *output = PointerGetDatum(ptr); + ptr += VARSIZE(ptr); + } + } + } + + Assert(ptr == serialized_key + key_data_bytes); +} + +#include "hash_strategy_impl.c" diff --git a/tsl/src/nodes/vector_agg/plan.c b/tsl/src/nodes/vector_agg/plan.c index 8ae45d372d3..cd8842b27f0 100644 --- a/tsl/src/nodes/vector_agg/plan.c +++ b/tsl/src/nodes/vector_agg/plan.c @@ -396,7 +396,14 @@ get_vectorized_grouping_type(const VectorQualInfo *vqinfo, Agg *agg, List *resol #endif } +#ifdef TS_USE_UMASH + /* + * Use hashing of serialized keys when we have many grouping columns. + */ + return VAGT_HashSerialized; +#else return VAGT_Invalid; +#endif } /* diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out new file mode 100644 index 00000000000..a4bdc3bed86 --- /dev/null +++ b/tsl/test/expected/vector_agg_grouping.out @@ -0,0 +1,1985 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); +NOTICE: adding not-null constraint to column "s" + create_hypertable +----------------------- + (1,public,agggroup,t) +(1 row) + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; +insert into agggroup select * from source where s = 1; +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 1 +(1 row) + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1051 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; + count +------- + 2 +(1 row) + +vacuum freeze analyze agggroup; +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 'cint2', + 'cint4', + 'cint4, cint8', + 'cint8', + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint4, cint8, cint2', + 'x']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec +select count(*) from agggroup; + count +-------- + 200000 +(1 row) + +select cint2, count(*) from agggroup group by cint2 order by count(*), cint2 limit 10; + cint2 | count +--------+------- + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 + -15615 | 1 +(10 rows) + +select cint4, count(*) from agggroup group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 + -15760 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16383 | 7417 | 1 + -16383 | 8953 | 1 + -16382 | -8851 | 1 + -16382 | -8612 | 1 + -16382 | -5254 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 899 | 1 +(10 rows) + +select cint8, count(*) from agggroup group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+--------+------- + 0 | -16377 | 1 + 0 | -16376 | 1 + 0 | -16375 | 1 + 0 | -16373 | 1 + 0 | -16372 | 1 + 0 | -16371 | 1 + 0 | -16370 | 1 + 0 | -16369 | 1 + 0 | -16368 | 1 + 0 | -16367 | 1 +(10 rows) + +select s, ss, count(*) from agggroup group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select s, x, count(*) from agggroup group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 1 | 11 | 20000 + 2 | 11 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 +(10 rows) + +select ss, cint2, x, count(*) from agggroup group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+---+------- + 0 | -16377 | 0 | 1 + 0 | -16376 | 0 | 1 + 0 | -16375 | 0 | 1 + 0 | -16373 | 0 | 1 + 0 | -16372 | 0 | 1 + 0 | -16371 | 0 | 1 + 0 | -16370 | 0 | 1 + 0 | -16369 | 0 | 1 + 0 | -16368 | 0 | 1 + 0 | -16367 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19981 + 4 | 4 | 19981 + 0 | 0 | 20000 + 5 | 5 | 20000 + 6 | 6 | 20000 + 7 | 7 | 20000 + 8 | 8 | 20000 + 9 | 9 | 20000 +(10 rows) + +select ss, x, cint2, count(*) from agggroup group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+--------+------- + 0 | 0 | -16377 | 1 + 0 | 0 | -16376 | 1 + 0 | 0 | -16375 | 1 + 0 | 0 | -16373 | 1 + 0 | 0 | -16372 | 1 + 0 | 0 | -16371 | 1 + 0 | 0 | -16370 | 1 + 0 | 0 | -16369 | 1 + 0 | 0 | -16368 | 1 + 0 | 0 | -16367 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+--------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 2 | 0 | 0 | 0 | 1096 | -6638 | -5373 | 1 + 3 | 0 | 0 | 0 | -15920 | 13672 | -7109 | 1 + 4 | 0 | 0 | 0 | 14299 | -8187 | -4927 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 8 | 0 | 0 | 0 | -10427 | 876 | -12705 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 +(10 rows) + +select x, count(*) from agggroup group by x order by count(*), x limit 10; + x | count +----+------- + | 19 + 3 | 19981 + 4 | 19981 + 0 | 20000 + 5 | 20000 + 6 | 20000 + 7 | 20000 + 8 | 20000 + 9 | 20000 + 11 | 40019 +(10 rows) + +select count(cint2) from agggroup; + count +-------- + 199810 +(1 row) + +select cint2, count(cint2) from agggroup group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +--------+------- + | 0 + -16216 | 1 + -16071 | 1 + -15916 | 1 + -15892 | 1 + -15891 | 1 + -15732 | 1 + -15693 | 1 + -15637 | 1 + -15620 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + 8426 | 0 + -16350 | 1 + -16237 | 1 + -16144 | 1 + -15987 | 1 + -15925 | 1 + -15862 | 1 + -15849 | 1 + -15825 | 1 + -15804 | 1 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + +select cint8, count(cint2) from agggroup group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16342 | 1 + -16246 | 1 + -16197 | 1 + -16152 | 1 + -16064 | 1 + -15932 | 1 + -15908 | 1 + -15869 | 1 + -15819 | 1 + -15753 | 1 +(10 rows) + +select s, cint2, count(cint2) from agggroup group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select s, x, count(cint2) from agggroup group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 19 + 4 | 11 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 1 | 11 | 19981 + 2 | 11 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+--------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 + 0 | -16377 | 0 | 1 +(10 rows) + +select ss, s, count(cint2) from agggroup group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 19 + | 3 | 19 + 3 | 3 | 19962 + 4 | 4 | 19962 + 0 | 0 | 19981 + 5 | 5 | 19981 + 6 | 6 | 19981 + 7 | 7 | 19981 + 8 | 8 | 19981 + 9 | 9 | 19981 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+--------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 + 0 | 0 | -16377 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 +(10 rows) + +select x, count(cint2) from agggroup group by x order by count(cint2), x limit 10; + x | count +----+------- + | 19 + 3 | 19962 + 4 | 19962 + 0 | 19981 + 5 | 19981 + 6 | 19981 + 7 | 19981 + 8 | 19981 + 9 | 19981 + 11 | 39981 +(10 rows) + +select min(cint2) from agggroup; + min +-------- + -16383 +(1 row) + +select cint2, min(cint2) from agggroup group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +--------+-------- + -16383 | -16383 + -16382 | -16382 + -16381 | -16381 + -16380 | -16380 + -16379 | -16379 + -16378 | -16378 + -16377 | -16377 + -16376 | -16376 + -16375 | -16375 + -16374 | -16374 +(10 rows) + +select cint4, min(cint2) from agggroup group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+-------- + -16190 | -16383 + -13372 | -16383 + -10318 | -16383 + -9008 | -16383 + -3043 | -16383 + 6729 | -16383 + -14012 | -16382 + -8606 | -16382 + -3080 | -16382 + 2223 | -16382 +(10 rows) + +select cint4, cint8, min(cint2) from agggroup group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+-------- + -16190 | 13646 | -16383 + -13372 | 11094 | -16383 + -10318 | 6326 | -16383 + -9008 | 4390 | -16383 + -3043 | -1794 | -16383 + 6729 | 6717 | -16383 + -14012 | -9888 | -16382 + -8606 | -10357 | -16382 + -3080 | -15609 | -16382 + 2223 | 9035 | -16382 +(10 rows) + +select cint8, min(cint2) from agggroup group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+-------- + -1794 | -16383 + 4390 | -16383 + 6326 | -16383 + 6717 | -16383 + 11094 | -16383 + 13646 | -16383 + -15609 | -16382 + -10357 | -16382 + -9888 | -16382 + 206 | -16382 +(10 rows) + +select s, cint2, min(cint2) from agggroup group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+--------+-------- + 0 | -16383 | -16383 + 4 | -16383 | -16383 + 5 | -16383 | -16383 + 6 | -16383 | -16383 + 2 | -16382 | -16382 + 7 | -16382 | -16382 + 8 | -16382 | -16382 + 2 | -16381 | -16381 + 3 | -16381 | -16381 + 4 | -16381 | -16381 +(10 rows) + +select s, ss, min(cint2) from agggroup group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select s, x, min(cint2) from agggroup group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 2 | 11 | -16382 + 7 | 7 | -16382 + 8 | 8 | -16382 + 3 | 3 | -16381 + 1 | 11 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+--------+----+-------- + 0 | -16383 | 0 | -16383 + 4 | -16383 | 4 | -16383 + 5 | -16383 | 5 | -16383 + 6 | -16383 | 6 | -16383 + 7 | -16382 | 7 | -16382 + 8 | -16382 | 8 | -16382 + 11 | -16382 | 11 | -16382 + 3 | -16381 | 3 | -16381 + 4 | -16381 | 4 | -16381 + 5 | -16381 | 5 | -16381 +(10 rows) + +select ss, s, min(cint2) from agggroup group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+-------- + 0 | 0 | -16383 + 4 | 4 | -16383 + 5 | 5 | -16383 + 6 | 6 | -16383 + 7 | 7 | -16382 + 8 | 8 | -16382 + 11 | 2 | -16382 + 3 | 3 | -16381 + 11 | 1 | -16378 + 9 | 9 | -16375 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+--------+-------- + 0 | 0 | -16383 | -16383 + 4 | 4 | -16383 | -16383 + 5 | 5 | -16383 | -16383 + 6 | 6 | -16383 | -16383 + 7 | 7 | -16382 | -16382 + 8 | 8 | -16382 | -16382 + 11 | 11 | -16382 | -16382 + 3 | 3 | -16381 | -16381 + 4 | 4 | -16381 | -16381 + 5 | 5 | -16381 | -16381 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+----+--------+--------+--------+-------- + 6194 | 0 | 0 | 0 | -13372 | 11094 | -16383 | -16383 + 17044 | 0 | 0 | 0 | -10318 | 6326 | -16383 | -16383 + 53843 | 4 | 4 | 4 | -9008 | 4390 | -16383 | -16383 + 60530 | 5 | 5 | 5 | 6729 | 6717 | -16383 | -16383 + 73208 | 6 | 6 | 6 | -3043 | -1794 | -16383 | -16383 + 74870 | 6 | 6 | 6 | -16190 | 13646 | -16383 | -16383 + 22836 | 2 | 11 | 11 | -3080 | -15609 | -16382 | -16382 + 29858 | 2 | 11 | 11 | -14012 | -9888 | -16382 | -16382 + 31516 | 2 | 11 | 11 | 6193 | 206 | -16382 | -16382 + 76781 | 7 | 7 | 7 | 9938 | 6519 | -16382 | -16382 +(10 rows) + +select x, min(cint2) from agggroup group by x order by min(cint2), x limit 10; + x | min +----+-------- + 0 | -16383 + 4 | -16383 + 5 | -16383 + 6 | -16383 + 11 | -16382 + 7 | -16382 + 8 | -16382 + 3 | -16381 + 9 | -16375 + | -16295 +(10 rows) + +select count(*) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select cint2, count(*) from agggroup where cint2 > 0 group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(*) from agggroup where cint2 > 0 group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup where cint2 > 0 group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 > 0 group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup where cint2 > 0 group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 > 0 group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(*) from agggroup where cint2 > 0 group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 > 0 group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 +(10 rows) + +select ss, s, count(*) from agggroup where cint2 > 0 group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 9 + | 3 | 9 + 11 | 2 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 +(10 rows) + +select x, count(*) from agggroup where cint2 > 0 group by x order by count(*), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select count(cint2) from agggroup where cint2 > 0; + count +------- + 99664 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 > 0 group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + 153 | 1 + 290 | 1 + 490 | 1 + 605 | 1 + 666 | 1 + 700 | 1 + 780 | 1 + 851 | 1 + 936 | 1 + 1001 | 1 +(10 rows) + +select cint4, count(cint2) from agggroup where cint2 > 0 group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16383 | 1 + -16380 | 1 + -16371 | 1 + -16368 | 1 + -16366 | 1 + -16365 | 1 + -16363 | 1 + -16360 | 1 + -16356 | 1 + -16350 | 1 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+-------+------- + -16383 | 4889 | 1 + -16382 | -8851 | 1 + -16382 | -4489 | 1 + -16382 | -470 | 1 + -16382 | 411 | 1 + -16382 | 8377 | 1 + -16382 | 8832 | 1 + -16382 | 15709 | 1 + -16380 | 1449 | 1 + -16379 | 1234 | 1 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 > 0 group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16382 | 1 + -16378 | 1 + -16372 | 1 + -16353 | 1 + -16342 | 1 + -16338 | 1 + -16337 | 1 + -16336 | 1 + -16330 | 1 + -16328 | 1 +(10 rows) + +select s, cint2, count(cint2) from agggroup where cint2 > 0 group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | 4 | 1 + 0 | 7 | 1 + 0 | 8 | 1 + 0 | 9 | 1 + 0 | 10 | 1 + 0 | 11 | 1 + 0 | 18 | 1 + 0 | 24 | 1 + 0 | 28 | 1 + 0 | 31 | 1 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 > 0 group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 > 0 group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 3 | | 9 + 4 | 11 | 9 + 2 | 11 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- + 0 | 4 | 0 | 1 + 0 | 7 | 0 | 1 + 0 | 8 | 0 | 1 + 0 | 9 | 0 | 1 + 0 | 10 | 0 | 1 + 0 | 11 | 0 | 1 + 0 | 18 | 0 | 1 + 0 | 24 | 0 | 1 + 0 | 28 | 0 | 1 + 0 | 31 | 0 | 1 +(10 rows) + +select ss, s, count(cint2) from agggroup where cint2 > 0 group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 11 | 4 | 9 + | 3 | 9 + 11 | 2 | 9868 + 3 | 3 | 9884 + 6 | 6 | 9890 + 4 | 4 | 9897 + 8 | 8 | 9898 + 7 | 7 | 9973 + 0 | 0 | 10012 + 9 | 9 | 10018 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- + 0 | 0 | 4 | 1 + 0 | 0 | 7 | 1 + 0 | 0 | 8 | 1 + 0 | 0 | 9 | 1 + 0 | 0 | 10 | 1 + 0 | 0 | 11 | 1 + 0 | 0 | 18 | 1 + 0 | 0 | 24 | 1 + 0 | 0 | 28 | 1 + 0 | 0 | 31 | 1 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +----+---+----+---+--------+-------+-------+------- + 1 | 0 | 0 | 0 | -15736 | 12910 | 3398 | 1 + 5 | 0 | 0 | 0 | 9267 | 6436 | 4859 | 1 + 6 | 0 | 0 | 0 | -5203 | 9870 | 12177 | 1 + 7 | 0 | 0 | 0 | 6620 | -781 | 5174 | 1 + 9 | 0 | 0 | 0 | -14954 | -1593 | 2257 | 1 + 10 | 0 | 0 | 0 | 10047 | -7626 | 3923 | 1 + 14 | 0 | 0 | 0 | -13766 | -398 | 4669 | 1 + 15 | 0 | 0 | 0 | -13009 | 14045 | 15101 | 1 + 19 | 0 | 0 | 0 | -16257 | 4566 | 7684 | 1 + 22 | 0 | 0 | 0 | -6345 | -8658 | 11755 | 1 +(10 rows) + +select x, count(cint2) from agggroup where cint2 > 0 group by x order by count(cint2), x limit 10; + x | count +----+------- + | 9 + 3 | 9884 + 6 | 9890 + 4 | 9897 + 8 | 9898 + 7 | 9973 + 0 | 10012 + 9 | 10018 + 5 | 10110 + 11 | 19973 +(10 rows) + +select min(cint2) from agggroup where cint2 > 0; + min +----- + 1 +(1 row) + +select cint2, min(cint2) from agggroup where cint2 > 0 group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 +(10 rows) + +select cint4, min(cint2) from agggroup where cint2 > 0 group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -12025 | 1 + -10344 | 1 + -4190 | 1 + -1493 | 1 + 1863 | 1 + 9242 | 1 + 11189 | 1 + 14078 | 1 + 15656 | 1 + -11410 | 2 +(10 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 > 0 group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -12025 | -2210 | 1 + -10344 | -13684 | 1 + -4190 | -2827 | 1 + -1493 | -1043 | 1 + 1863 | 7650 | 1 + 9242 | -9798 | 1 + 11189 | -5168 | 1 + 14078 | 9929 | 1 + 15656 | 12597 | 1 + -11410 | 6033 | 2 +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 > 0 group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -13684 | 1 + -9798 | 1 + -5168 | 1 + -2827 | 1 + -2210 | 1 + -1043 | 1 + 7650 | 1 + 9929 | 1 + 12597 | 1 + -13639 | 2 +(10 rows) + +select s, cint2, min(cint2) from agggroup where cint2 > 0 group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 1 | 1 | 1 + 2 | 1 | 1 + 3 | 1 | 1 + 5 | 1 | 1 + 7 | 1 | 1 + 8 | 1 | 1 + 1 | 2 | 2 + 3 | 2 | 2 + 7 | 2 | 2 + 9 | 2 | 2 +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 > 0 group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select s, x, min(cint2) from agggroup where cint2 > 0 group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 1 | 11 | 1 + 2 | 11 | 1 + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 > 0 group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 3 | 1 | 3 | 1 + 5 | 1 | 5 | 1 + 7 | 1 | 7 | 1 + 8 | 1 | 8 | 1 + 11 | 1 | 11 | 1 + 3 | 2 | 3 | 2 + 7 | 2 | 7 | 2 + 9 | 2 | 9 | 2 + 11 | 2 | 11 | 2 + 3 | 3 | 3 | 3 +(10 rows) + +select ss, s, min(cint2) from agggroup where cint2 > 0 group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 3 | 3 | 1 + 5 | 5 | 1 + 7 | 7 | 1 + 8 | 8 | 1 + 11 | 1 | 1 + 11 | 2 | 1 + 9 | 9 | 2 + 6 | 6 | 3 + 0 | 0 | 4 + 4 | 4 | 4 +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 > 0 group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 3 | 3 | 1 | 1 + 5 | 5 | 1 | 1 + 7 | 7 | 1 | 1 + 8 | 8 | 1 | 1 + 11 | 11 | 1 | 1 + 3 | 3 | 2 | 2 + 7 | 7 | 2 | 2 + 9 | 9 | 2 | 2 + 11 | 11 | 2 | 2 + 3 | 3 | 3 | 3 +(10 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 > 0 group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+----+--------+--------+-------+----- + 11611 | 1 | 11 | 11 | -12025 | -2210 | 1 | 1 + 28649 | 2 | 11 | 11 | -1493 | -1043 | 1 | 1 + 28786 | 1 | 11 | 11 | -4190 | -2827 | 1 | 1 + 41774 | 3 | 3 | 3 | 1863 | 7650 | 1 | 1 + 41779 | 3 | 3 | 3 | 14078 | 9929 | 1 | 1 + 51152 | 5 | 5 | 5 | 9242 | -9798 | 1 | 1 + 70932 | 7 | 7 | 7 | -10344 | -13684 | 1 | 1 + 86957 | 7 | 7 | 7 | 15656 | 12597 | 1 | 1 + 89689 | 8 | 8 | 8 | 11189 | -5168 | 1 | 1 + 22147 | 1 | 11 | 11 | -9569 | 9760 | 2 | 2 +(10 rows) + +select x, min(cint2) from agggroup where cint2 > 0 group by x order by min(cint2), x limit 10; + x | min +----+------ + 11 | 1 + 3 | 1 + 5 | 1 + 7 | 1 + 8 | 1 + 9 | 2 + 6 | 3 + 0 | 4 + 4 | 4 + | 4895 +(10 rows) + +select count(*) from agggroup where cint2 is null; + count +------- + 190 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- + | 190 +(1 row) + +select cint4, count(*) from agggroup where cint2 is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 1 + -16091 | 1 + -15799 | 1 + -15724 | 1 + -15328 | 1 + -15279 | 1 + -15063 | 1 + -14998 | 1 + -14949 | 1 + -14848 | 1 +(10 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 1 + -16091 | -4084 | 1 + -15799 | 12603 | 1 + -15724 | 15426 | 1 + -15328 | -6092 | 1 + -15279 | -3475 | 1 + -15063 | 3990 | 1 + -14998 | 14464 | 1 + -14949 | -10395 | 1 + -14848 | 3110 | 1 +(10 rows) + +select cint8, count(*) from agggroup where cint2 is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 1 + -15987 | 1 + -15904 | 1 + -15897 | 1 + -15761 | 1 + -15506 | 1 + -15346 | 1 + -14986 | 1 + -14811 | 1 + -14674 | 1 +(10 rows) + +select s, cint2, count(*) from agggroup where cint2 is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 19 + 1 | | 19 + 2 | | 19 + 3 | | 19 + 4 | | 19 + 5 | | 19 + 6 | | 19 + 7 | | 19 + 8 | | 19 + 9 | | 19 +(10 rows) + +select s, ss, count(*) from agggroup where cint2 is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select s, x, count(*) from agggroup where cint2 is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 19 + 1 | 11 | 19 + 2 | 11 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 +(10 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 19 + 3 | | 3 | 19 + 4 | | 4 | 19 + 5 | | 5 | 19 + 6 | | 6 | 19 + 7 | | 7 | 19 + 8 | | 8 | 19 + 9 | | 9 | 19 + 11 | | 11 | 38 +(9 rows) + +select ss, s, count(*) from agggroup where cint2 is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 19 + 3 | 3 | 19 + 4 | 4 | 19 + 5 | 5 | 19 + 6 | 6 | 19 + 7 | 7 | 19 + 8 | 8 | 19 + 9 | 9 | 19 + 11 | 1 | 19 + 11 | 2 | 19 +(10 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 19 + 3 | 3 | | 19 + 4 | 4 | | 19 + 5 | 5 | | 19 + 6 | 6 | | 19 + 7 | 7 | | 19 + 8 | 8 | | 19 + 9 | 9 | | 19 + 11 | 11 | | 38 +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 1 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 1 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 1 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 1 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 1 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 1 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 1 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 1 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 1 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 1 +(10 rows) + +select x, count(*) from agggroup where cint2 is null group by x order by count(*), x limit 10; + x | count +----+------- + 0 | 19 + 3 | 19 + 4 | 19 + 5 | 19 + 6 | 19 + 7 | 19 + 8 | 19 + 9 | 19 + 11 | 38 +(9 rows) + +select count(cint2) from agggroup where cint2 is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- + | 0 +(1 row) + +select cint4, count(cint2) from agggroup where cint2 is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +--------+------- + -16291 | 0 + -16091 | 0 + -15799 | 0 + -15724 | 0 + -15328 | 0 + -15279 | 0 + -15063 | 0 + -14998 | 0 + -14949 | 0 + -14848 | 0 +(10 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +--------+--------+------- + -16291 | 113 | 0 + -16091 | -4084 | 0 + -15799 | 12603 | 0 + -15724 | 15426 | 0 + -15328 | -6092 | 0 + -15279 | -3475 | 0 + -15063 | 3990 | 0 + -14998 | 14464 | 0 + -14949 | -10395 | 0 + -14848 | 3110 | 0 +(10 rows) + +select cint8, count(cint2) from agggroup where cint2 is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +--------+------- + -16026 | 0 + -15987 | 0 + -15904 | 0 + -15897 | 0 + -15761 | 0 + -15506 | 0 + -15346 | 0 + -14986 | 0 + -14811 | 0 + -14674 | 0 +(10 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- + 0 | | 0 + 1 | | 0 + 2 | | 0 + 3 | | 0 + 4 | | 0 + 5 | | 0 + 6 | | 0 + 7 | | 0 + 8 | | 0 + 9 | | 0 +(10 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select s, x, count(cint2) from agggroup where cint2 is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+----+------- + 0 | 0 | 0 + 1 | 11 | 0 + 2 | 11 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 +(10 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+----+------- + 0 | | 0 | 0 + 3 | | 3 | 0 + 4 | | 4 | 0 + 5 | | 5 | 0 + 6 | | 6 | 0 + 7 | | 7 | 0 + 8 | | 8 | 0 + 9 | | 9 | 0 + 11 | | 11 | 0 +(9 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- + 0 | 0 | 0 + 3 | 3 | 0 + 4 | 4 | 0 + 5 | 5 | 0 + 6 | 6 | 0 + 7 | 7 | 0 + 8 | 8 | 0 + 9 | 9 | 0 + 11 | 1 | 0 + 11 | 2 | 0 +(10 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+----+-------+------- + 0 | 0 | | 0 + 3 | 3 | | 0 + 4 | 4 | | 0 + 5 | 5 | | 0 + 6 | 6 | | 0 + 7 | 7 | | 0 + 8 | 8 | | 0 + 9 | 9 | | 0 + 11 | 11 | | 0 +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +-------+---+----+---+--------+--------+-------+------- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | 0 + 2102 | 0 | 0 | 0 | 11069 | 16047 | | 0 + 3153 | 0 | 0 | 0 | 6192 | 12700 | | 0 + 4204 | 0 | 0 | 0 | 4165 | -10102 | | 0 + 5255 | 0 | 0 | 0 | 16314 | 13418 | | 0 + 6306 | 0 | 0 | 0 | 701 | -3029 | | 0 + 7357 | 0 | 0 | 0 | 1115 | 4913 | | 0 + 8408 | 0 | 0 | 0 | 15553 | 1743 | | 0 + 9459 | 0 | 0 | 0 | -14640 | 11933 | | 0 + 10510 | 0 | 0 | 0 | -14725 | 6531 | | 0 +(10 rows) + +select x, count(cint2) from agggroup where cint2 is null group by x order by count(cint2), x limit 10; + x | count +----+------- + 0 | 0 + 11 | 0 + 3 | 0 + 4 | 0 + 5 | 0 + 6 | 0 + 7 | 0 + 8 | 0 + 9 | 0 +(9 rows) + +select min(cint2) from agggroup where cint2 is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- + | +(1 row) + +select cint4, min(cint2) from agggroup where cint2 is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +--------+----- + -16291 | + -16091 | + -15799 | + -15724 | + -15328 | + -15279 | + -15063 | + -14998 | + -14949 | + -14848 | +(10 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +--------+--------+----- + -16291 | 113 | + -16091 | -4084 | + -15799 | 12603 | + -15724 | 15426 | + -15328 | -6092 | + -15279 | -3475 | + -15063 | 3990 | + -14998 | 14464 | + -14949 | -10395 | + -14848 | 3110 | +(10 rows) + +select cint8, min(cint2) from agggroup where cint2 is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +--------+----- + -16026 | + -15987 | + -15904 | + -15897 | + -15761 | + -15506 | + -15346 | + -14986 | + -14811 | + -14674 | +(10 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- + 0 | | + 1 | | + 2 | | + 3 | | + 4 | | + 5 | | + 6 | | + 7 | | + 8 | | + 9 | | +(10 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select s, x, min(cint2) from agggroup where cint2 is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+----+----- + 0 | 0 | + 1 | 11 | + 2 | 11 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | +(10 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+----+----- + 0 | | 0 | + 3 | | 3 | + 4 | | 4 | + 5 | | 5 | + 6 | | 6 | + 7 | | 7 | + 8 | | 8 | + 9 | | 9 | + 11 | | 11 | +(9 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- + 0 | 0 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 11 | 1 | + 11 | 2 | +(10 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+----+-------+----- + 0 | 0 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | | + 7 | 7 | | + 8 | 8 | | + 9 | 9 | | + 11 | 11 | | +(9 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +-------+---+----+---+--------+--------+-------+----- + 1051 | 0 | 0 | 0 | -8612 | 14327 | | + 2102 | 0 | 0 | 0 | 11069 | 16047 | | + 3153 | 0 | 0 | 0 | 6192 | 12700 | | + 4204 | 0 | 0 | 0 | 4165 | -10102 | | + 5255 | 0 | 0 | 0 | 16314 | 13418 | | + 6306 | 0 | 0 | 0 | 701 | -3029 | | + 7357 | 0 | 0 | 0 | 1115 | 4913 | | + 8408 | 0 | 0 | 0 | 15553 | 1743 | | + 9459 | 0 | 0 | 0 | -14640 | 11933 | | + 10510 | 0 | 0 | 0 | -14725 | 6531 | | +(10 rows) + +select x, min(cint2) from agggroup where cint2 is null group by x order by min(cint2), x limit 10; + x | min +----+----- + 0 | + 11 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | +(9 rows) + +select count(*) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(*) from agggroup where cint2 is null and x is null group by cint2 order by count(*), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(*) from agggroup where cint2 is null and x is null group by cint4 order by count(*), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(*) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(*), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(*) from agggroup where cint2 is null and x is null group by cint8 order by count(*), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(*) from agggroup where cint2 is null and x is null group by s, cint2 order by count(*), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(*) from agggroup where cint2 is null and x is null group by s, ss order by count(*), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(*) from agggroup where cint2 is null and x is null group by s, x order by count(*), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(*) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(*), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(*) from agggroup where cint2 is null and x is null group by ss, s order by count(*), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(*) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(*), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(*) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(*), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(*) from agggroup where cint2 is null and x is null group by x order by count(*), x limit 10; + x | count +---+------- +(0 rows) + +select count(cint2) from agggroup where cint2 is null and x is null; + count +------- + 0 +(1 row) + +select cint2, count(cint2) from agggroup where cint2 is null and x is null group by cint2 order by count(cint2), cint2 limit 10; + cint2 | count +-------+------- +(0 rows) + +select cint4, count(cint2) from agggroup where cint2 is null and x is null group by cint4 order by count(cint2), cint4 limit 10; + cint4 | count +-------+------- +(0 rows) + +select cint4, cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by count(cint2), cint4, cint8 limit 10; + cint4 | cint8 | count +-------+-------+------- +(0 rows) + +select cint8, count(cint2) from agggroup where cint2 is null and x is null group by cint8 order by count(cint2), cint8 limit 10; + cint8 | count +-------+------- +(0 rows) + +select s, cint2, count(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by count(cint2), s, cint2 limit 10; + s | cint2 | count +---+-------+------- +(0 rows) + +select s, ss, count(cint2) from agggroup where cint2 is null and x is null group by s, ss order by count(cint2), s, ss limit 10; + s | ss | count +---+----+------- +(0 rows) + +select s, x, count(cint2) from agggroup where cint2 is null and x is null group by s, x order by count(cint2), s, x limit 10; + s | x | count +---+---+------- +(0 rows) + +select ss, cint2, x, count(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by count(cint2), ss, cint2, x limit 10; + ss | cint2 | x | count +----+-------+---+------- +(0 rows) + +select ss, s, count(cint2) from agggroup where cint2 is null and x is null group by ss, s order by count(cint2), ss, s limit 10; + ss | s | count +----+---+------- +(0 rows) + +select ss, x, cint2, count(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by count(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | count +----+---+-------+------- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, count(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by count(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | count +---+---+----+---+-------+-------+-------+------- +(0 rows) + +select x, count(cint2) from agggroup where cint2 is null and x is null group by x order by count(cint2), x limit 10; + x | count +---+------- +(0 rows) + +select min(cint2) from agggroup where cint2 is null and x is null; + min +----- + +(1 row) + +select cint2, min(cint2) from agggroup where cint2 is null and x is null group by cint2 order by min(cint2), cint2 limit 10; + cint2 | min +-------+----- +(0 rows) + +select cint4, min(cint2) from agggroup where cint2 is null and x is null group by cint4 order by min(cint2), cint4 limit 10; + cint4 | min +-------+----- +(0 rows) + +select cint4, cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint4, cint8 order by min(cint2), cint4, cint8 limit 10; + cint4 | cint8 | min +-------+-------+----- +(0 rows) + +select cint8, min(cint2) from agggroup where cint2 is null and x is null group by cint8 order by min(cint2), cint8 limit 10; + cint8 | min +-------+----- +(0 rows) + +select s, cint2, min(cint2) from agggroup where cint2 is null and x is null group by s, cint2 order by min(cint2), s, cint2 limit 10; + s | cint2 | min +---+-------+----- +(0 rows) + +select s, ss, min(cint2) from agggroup where cint2 is null and x is null group by s, ss order by min(cint2), s, ss limit 10; + s | ss | min +---+----+----- +(0 rows) + +select s, x, min(cint2) from agggroup where cint2 is null and x is null group by s, x order by min(cint2), s, x limit 10; + s | x | min +---+---+----- +(0 rows) + +select ss, cint2, x, min(cint2) from agggroup where cint2 is null and x is null group by ss, cint2, x order by min(cint2), ss, cint2, x limit 10; + ss | cint2 | x | min +----+-------+---+----- +(0 rows) + +select ss, s, min(cint2) from agggroup where cint2 is null and x is null group by ss, s order by min(cint2), ss, s limit 10; + ss | s | min +----+---+----- +(0 rows) + +select ss, x, cint2, min(cint2) from agggroup where cint2 is null and x is null group by ss, x, cint2 order by min(cint2), ss, x, cint2 limit 10; + ss | x | cint2 | min +----+---+-------+----- +(0 rows) + +select t, s, ss, x, cint4, cint8, cint2, min(cint2) from agggroup where cint2 is null and x is null group by t, s, ss, x, cint4, cint8, cint2 order by min(cint2), t, s, ss, x, cint4, cint8, cint2 limit 10; + t | s | ss | x | cint4 | cint8 | cint2 | min +---+---+----+---+-------+-------+-------+----- +(0 rows) + +select x, min(cint2) from agggroup where cint2 is null and x is null group by x order by min(cint2), x limit 10; + x | min +---+----- +(0 rows) + +reset timescaledb.debug_require_vector_agg; +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +------------------- + (3,public,long,t) +(1 row) + +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes +NOTICE: default segment by for hypertable "long" is set to "" +NOTICE: default order by for hypertable "long" is set to "t DESC" +select count(compress_chunk(x)) from show_chunks('long') x; + count +------- + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; + count +------- + 1 + 1 + 1 + 1 + 1 +(5 rows) + +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/expected/vectorized_aggregation.out b/tsl/test/expected/vectorized_aggregation.out index a55ef2b133e..db53ab631dc 100644 --- a/tsl/test/expected/vectorized_aggregation.out +++ b/tsl/test/expected/vectorized_aggregation.out @@ -541,7 +541,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; Output: _hyper_1_10_chunk.int_value, _hyper_1_10_chunk.segment_by_value (63 rows) --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; QUERY PLAN @@ -553,23 +553,23 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) Workers Planned: 2 -> Parallel Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, PARTIAL sum(_hyper_1_1_chunk.segment_by_value) - Group Key: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, (PARTIAL sum(_hyper_1_1_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk.int_value, _hyper_1_1_chunk.float_value, _hyper_1_1_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_11_chunk Output: compress_hyper_2_11_chunk._ts_meta_count, compress_hyper_2_11_chunk.segment_by_value, compress_hyper_2_11_chunk._ts_meta_min_1, compress_hyper_2_11_chunk._ts_meta_max_1, compress_hyper_2_11_chunk."time", compress_hyper_2_11_chunk.int_value, compress_hyper_2_11_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, PARTIAL sum(_hyper_1_2_chunk.segment_by_value) - Group Key: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, (PARTIAL sum(_hyper_1_2_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_2_chunk Output: _hyper_1_2_chunk.int_value, _hyper_1_2_chunk.float_value, _hyper_1_2_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_12_chunk Output: compress_hyper_2_12_chunk._ts_meta_count, compress_hyper_2_12_chunk.segment_by_value, compress_hyper_2_12_chunk._ts_meta_min_1, compress_hyper_2_12_chunk._ts_meta_max_1, compress_hyper_2_12_chunk."time", compress_hyper_2_12_chunk.int_value, compress_hyper_2_12_chunk.float_value - -> Partial HashAggregate - Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, PARTIAL sum(_hyper_1_3_chunk.segment_by_value) - Group Key: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value + -> Custom Scan (VectorAgg) + Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, (PARTIAL sum(_hyper_1_3_chunk.segment_by_value)) + Grouping Policy: hashed with serialized key -> Custom Scan (DecompressChunk) on _timescaledb_internal._hyper_1_3_chunk Output: _hyper_1_3_chunk.int_value, _hyper_1_3_chunk.float_value, _hyper_1_3_chunk.segment_by_value -> Parallel Seq Scan on _timescaledb_internal.compress_hyper_2_13_chunk diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 06b1c6ac9c5..b8171223e03 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -121,6 +121,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) feature_flags.sql vector_agg_default.sql vector_agg_filter.sql + vector_agg_grouping.sql vector_agg_text.sql vector_agg_memory.sql vector_agg_segmentby.sql) diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql new file mode 100644 index 00000000000..e087e54c48e --- /dev/null +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -0,0 +1,126 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER +-- helper function: float -> pseudorandom float [-0.5..0.5] +CREATE OR REPLACE FUNCTION mix(x anyelement) RETURNS float8 AS $$ + SELECT hashfloat8(x::float8) / pow(2, 32) +$$ LANGUAGE SQL; + +\set CHUNKS 2::int +\set CHUNK_ROWS 100000::int +\set GROUPING_CARDINALITY 10::int + +create table agggroup(t int, s int, + cint2 int2, cint4 int4, cint8 int8); +select create_hypertable('agggroup', 's', chunk_time_interval => :GROUPING_CARDINALITY / :CHUNKS); + +create view source as +select s * 10000 + t as t, + s, + case when t % 1051 = 0 then null + else (mix(s + t * 1019) * 32767)::int2 end as cint2, + (mix(s + t * 1021) * 32767)::int4 as cint4, + (mix(s + t * 1031) * 32767)::int8 as cint8 +from + generate_series(1::int, :CHUNK_ROWS * :CHUNKS / :GROUPING_CARDINALITY) t, + generate_series(0::int, :GROUPING_CARDINALITY - 1::int) s(s) +; + +insert into agggroup select * from source where s = 1; + +alter table agggroup set (timescaledb.compress, timescaledb.compress_orderby = 't', + timescaledb.compress_segmentby = 's'); + +select count(compress_chunk(x)) from show_chunks('agggroup') x; + +alter table agggroup add column ss int default 11; +alter table agggroup add column x text default '11'; + +insert into agggroup +select *, ss::text as x from ( + select *, + case + -- null in entire batch + when s = 2 then null + -- null for some rows + when s = 3 and t % 1051 = 0 then null + -- for some rows same as default + when s = 4 and t % 1057 = 0 then 11 + -- not null for entire batch + else s + end as ss + from source where s != 1 +) t +; +select count(compress_chunk(x)) from show_chunks('agggroup') x; +vacuum freeze analyze agggroup; + + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. Note that there are minor discrepancies +---- on float4 due to different numeric stability in our and PG implementations. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select + format('%sselect %s%s(%s) from agggroup%s%s%s;', + explain, + grouping || ', ', + function, variable, + ' where ' || condition, + ' group by ' || grouping, + format(' order by %s(%s), ', function, variable) || grouping || ' limit 10', + function, variable) +from + unnest(array[ + 'explain (costs off) ', + null]) explain, + unnest(array[ + 'cint2', + '*']) variable, + unnest(array[ + 'min', + 'count']) function, + unnest(array[ + null, + 'cint2 > 0', + 'cint2 is null', + 'cint2 is null and x is null']) with ordinality as condition(condition, n), + unnest(array[ + null, + 'cint2', + 'cint4', + 'cint4, cint8', + 'cint8', + 's, cint2', + 's, ss', + 's, x', + 'ss, cint2, x', + 'ss, s', + 'ss, x, cint2', + 't, s, ss, x, cint4, cint8, cint2', + 'x']) with ordinality as grouping(grouping, n) +where + true + and (explain is null /* or condition is null and grouping = 's' */) + and (variable != '*' or function = 'count') +order by explain, condition.n, variable, function, grouping.n +\gexec + +reset timescaledb.debug_require_vector_agg; + + +create table long(t int, a text, b text, c text, d text); +select create_hypertable('long', 't'); +insert into long select n, x, x, x, x from ( + select n, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n) t +; +insert into long values (-1, 'a', 'b', 'c', 'd'); +alter table long set (timescaledb.compress); +select count(compress_chunk(x)) from show_chunks('long') x; + +set timescaledb.debug_require_vector_agg = 'require'; +select count(*) from long group by a, b, c, d order by 1 limit 10; +reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vectorized_aggregation.sql b/tsl/test/sql/vectorized_aggregation.sql index e4388a60fe7..15336d16f95 100644 --- a/tsl/test/sql/vectorized_aggregation.sql +++ b/tsl/test/sql/vectorized_aggregation.sql @@ -65,7 +65,7 @@ SELECT sum(segment_by_value) FROM testtable GROUP BY float_value; :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value; --- Vectorization not possible with grouping by multiple columns +-- Vectorization possible with grouping by multiple columns :EXPLAIN SELECT sum(segment_by_value) FROM testtable GROUP BY int_value, float_value; From a25fc516a820ce2e7658c1421db8430549949c9c Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:20:51 +0100 Subject: [PATCH 238/242] tam tests --- tsl/test/expected/hypercore_vectoragg.out | 36 ++++++++++------------- tsl/test/sql/hypercore_vectoragg.sql | 6 ---- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/tsl/test/expected/hypercore_vectoragg.out b/tsl/test/expected/hypercore_vectoragg.out index 496d80e616c..8287a44ed93 100644 --- a/tsl/test/expected/hypercore_vectoragg.out +++ b/tsl/test/expected/hypercore_vectoragg.out @@ -314,13 +314,11 @@ select location, count(*) from aggdata where location=1 group by location; -- -- Test ordering/grouping on segmentby, orderby columns -- --- This grouping is currently NOT supported by VectorAgg --- set timescaledb.enable_vectorized_aggregation=true; explain (verbose, costs off) select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Limit Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (sum(_hyper_1_1_chunk.temp)) -> Sort @@ -330,9 +328,9 @@ select time, device, sum(temp) from aggdata where device is not null group by ti Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, sum(_hyper_1_1_chunk.temp) Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device -> Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, PARTIAL sum(_hyper_1_1_chunk.temp) - Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (PARTIAL sum(_hyper_1_1_chunk.temp)) + Grouping Policy: hashed with serialized key -> Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp Filter: (_hyper_1_1_chunk.device IS NOT NULL) @@ -344,7 +342,6 @@ select time, device, sum(temp) from aggdata where device is not null group by ti Filter: (_hyper_1_2_chunk.device IS NOT NULL) (21 rows) -set timescaledb.debug_require_vector_agg to 'forbid'; select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; time | device | sum ------------------------------+--------+----- @@ -355,11 +352,10 @@ select time, device, sum(temp) from aggdata where device is not null group by ti (4 rows) set timecaledb.enable_vectorized_aggregation=false; -reset timescaledb.debug_require_vector_agg; explain (verbose, costs off) select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------------- Limit Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (sum(_hyper_1_1_chunk.temp)) -> Sort @@ -369,9 +365,9 @@ select time, device, sum(temp) from aggdata where device is not null group by ti Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, sum(_hyper_1_1_chunk.temp) Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device -> Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, PARTIAL sum(_hyper_1_1_chunk.temp) - Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (PARTIAL sum(_hyper_1_1_chunk.temp)) + Grouping Policy: hashed with serialized key -> Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp Filter: (_hyper_1_1_chunk.device IS NOT NULL) @@ -395,8 +391,8 @@ select time, device, sum(temp) from aggdata where device is not null group by ti set timescaledb.enable_vectorized_aggregation=true; explain (verbose, costs off) select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (sum(_hyper_1_1_chunk.temp) FILTER (WHERE (_hyper_1_1_chunk.device IS NOT NULL))) -> Sort @@ -406,9 +402,9 @@ select time, device, sum(temp) filter (where device is not null) from aggdata gr Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, sum(_hyper_1_1_chunk.temp) FILTER (WHERE (_hyper_1_1_chunk.device IS NOT NULL)) Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device -> Append - -> Partial HashAggregate - Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, PARTIAL sum(_hyper_1_1_chunk.temp) FILTER (WHERE (_hyper_1_1_chunk.device IS NOT NULL)) - Group Key: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device + -> Custom Scan (VectorAgg) + Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, (PARTIAL sum(_hyper_1_1_chunk.temp) FILTER (WHERE (_hyper_1_1_chunk.device IS NOT NULL))) + Grouping Policy: hashed with serialized key -> Custom Scan (ColumnarScan) on _timescaledb_internal._hyper_1_1_chunk Output: _hyper_1_1_chunk."time", _hyper_1_1_chunk.device, _hyper_1_1_chunk.temp -> Partial HashAggregate @@ -418,7 +414,6 @@ select time, device, sum(temp) filter (where device is not null) from aggdata gr Output: _hyper_1_2_chunk."time", _hyper_1_2_chunk.device, _hyper_1_2_chunk.temp (19 rows) -set timescaledb.debug_require_vector_agg to 'forbid'; select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; time | device | sum ------------------------------+--------+----- @@ -430,7 +425,6 @@ select time, device, sum(temp) filter (where device is not null) from aggdata gr (5 rows) set timescaledb.enable_vectorized_aggregation=false; -reset timescaledb.debug_require_vector_agg; explain (verbose, costs off) select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; QUERY PLAN diff --git a/tsl/test/sql/hypercore_vectoragg.sql b/tsl/test/sql/hypercore_vectoragg.sql index 6bf52a6e9cc..c75fe32a2af 100644 --- a/tsl/test/sql/hypercore_vectoragg.sql +++ b/tsl/test/sql/hypercore_vectoragg.sql @@ -110,16 +110,12 @@ select location, count(*) from aggdata where location=1 group by location; -- -- Test ordering/grouping on segmentby, orderby columns -- --- This grouping is currently NOT supported by VectorAgg --- set timescaledb.enable_vectorized_aggregation=true; explain (verbose, costs off) select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; -set timescaledb.debug_require_vector_agg to 'forbid'; select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; set timecaledb.enable_vectorized_aggregation=false; -reset timescaledb.debug_require_vector_agg; explain (verbose, costs off) select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; select time, device, sum(temp) from aggdata where device is not null group by time, device order by time, device limit 10; @@ -127,11 +123,9 @@ select time, device, sum(temp) from aggdata where device is not null group by ti set timescaledb.enable_vectorized_aggregation=true; explain (verbose, costs off) select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; -set timescaledb.debug_require_vector_agg to 'forbid'; select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; set timescaledb.enable_vectorized_aggregation=false; -reset timescaledb.debug_require_vector_agg; explain (verbose, costs off) select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; select time, device, sum(temp) filter (where device is not null) from aggdata group by time, device order by time, device desc limit 10; From 18f2586482c21f67ac4184ca799af9d822c8c005 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:42:09 +0100 Subject: [PATCH 239/242] clang-tidy --- tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index d09b6adbc64..a53d4f86b35 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -361,7 +361,7 @@ serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restric *valid = true; const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, - /* seed = */ -1ull, + /* seed = */ ~0ULL, serialized_key_storage, num_bytes); *hash_table_key = umash_fingerprint_get_key(fp); From 1638c6244dd4bf70b2b19dda9052cd66464390fb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:46:01 +0100 Subject: [PATCH 240/242] changelog --- .unreleased/hash-grouping-multiple | 1 + 1 file changed, 1 insertion(+) create mode 100644 .unreleased/hash-grouping-multiple diff --git a/.unreleased/hash-grouping-multiple b/.unreleased/hash-grouping-multiple new file mode 100644 index 00000000000..56ae3608ea0 --- /dev/null +++ b/.unreleased/hash-grouping-multiple @@ -0,0 +1 @@ +Implements: #7754 Vectorized aggregation with grouping by several columns From e72559166a5c922e7b0311b63758e08434951aea Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:09:22 +0100 Subject: [PATCH 241/242] tests --- .../hashing/hash_strategy_serialized.c | 5 - tsl/test/expected/vector_agg_grouping.out | 145 ++++++++++++++++-- tsl/test/sql/vector_agg_grouping.sql | 48 +++++- 3 files changed, 174 insertions(+), 24 deletions(-) diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index a53d4f86b35..dd3aa5cd552 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -41,11 +41,6 @@ serialized_key_hashing_prepare_for_batch(GroupingPolicyHash *policy, TupleTableS static pg_attribute_always_inline bool byte_bitmap_row_is_valid(const uint8 *bitmap, size_t row_number) { - if (likely(bitmap == NULL)) - { - return true; - } - const size_t byte_index = row_number / 8; const size_t bit_index = row_number % 8; const uint8 mask = ((uint8) 1) << bit_index; diff --git a/tsl/test/expected/vector_agg_grouping.out b/tsl/test/expected/vector_agg_grouping.out index a4bdc3bed86..23b5a91a869 100644 --- a/tsl/test/expected/vector_agg_grouping.out +++ b/tsl/test/expected/vector_agg_grouping.out @@ -1948,6 +1948,8 @@ select x, min(cint2) from agggroup where cint2 is null and x is null group by x (0 rows) reset timescaledb.debug_require_vector_agg; +-- Test long text columns. Also make one of them a segmentby, so that we can +-- test the long scalar values. create table long(t int, a text, b text, c text, d text); select create_hypertable('long', 't'); NOTICE: adding not-null constraint to column "t" @@ -1956,15 +1958,15 @@ NOTICE: adding not-null constraint to column "t" (3,public,long,t) (1 row) -insert into long select n, x, x, x, x from ( - select n, repeat('1', 100 * 4 + n) x - from generate_series(1, 4) n) t +insert into long select n, a, x, x, x from ( + select n, 'short' || m a, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n, + generate_series(1, 4) m) t ; insert into long values (-1, 'a', 'b', 'c', 'd'); -alter table long set (timescaledb.compress); -WARNING: there was some uncertainty picking the default segment by for the hypertable: You do not have any indexes on columns that can be used for segment_by and thus we are not using segment_by for compression. Please make sure you are not missing any indexes -NOTICE: default segment by for hypertable "long" is set to "" -NOTICE: default order by for hypertable "long" is set to "t DESC" +insert into long values (-2, repeat('long', 1000), 'b', 'c', 'd'); +alter table long set (timescaledb.compress, timescaledb.compress_segmentby = 'a', + timescaledb.compress_orderby = 't desc'); select count(compress_chunk(x)) from show_chunks('long') x; count ------- @@ -1972,14 +1974,129 @@ select count(compress_chunk(x)) from show_chunks('long') x; (1 row) set timescaledb.debug_require_vector_agg = 'require'; -select count(*) from long group by a, b, c, d order by 1 limit 10; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +-- Various placements of long scalar column +select sum(t) from long group by a, b, c, d order by 1 limit 10; + sum +----- + -2 + -1 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 +(10 rows) + +select sum(t) from long group by d, b, c, a order by 1 limit 10; + sum +----- + -2 + -1 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 +(10 rows) + +select sum(t) from long group by d, b, a, c order by 1 limit 10; + sum +----- + -2 + -1 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 2 +(10 rows) + +-- Just the scalar column +select sum(t) from long group by a order by 1; + sum +----- + -2 + -1 + 10 + 10 + 10 + 10 +(6 rows) + +-- No scalar columns +select sum(t) from long group by b, c, d order by 1 limit 10; + sum +----- + -3 + 4 + 8 + 12 + 16 +(5 rows) + +reset timescaledb.debug_require_vector_agg; +-- Test various serialized key lengths. We want to touch the transition from short +-- to long varlena header for the serialized key. +create table keylength(t int, a text, b text); +select create_hypertable('keylength', 't'); +NOTICE: adding not-null constraint to column "t" + create_hypertable +------------------------ + (5,public,keylength,t) +(1 row) + +insert into keylength select t, 'a', repeat('b', t) from generate_series(1, 1000) t; +insert into keylength values (-1, '', ''); -- second chunk +alter table keylength set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 't desc'); +select count(compress_chunk(x)) from show_chunks('keylength') x; count ------- - 1 - 1 - 1 - 1 - 1 -(5 rows) + 2 +(1 row) + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; +select sum(t) from keylength group by a, b order by 1 desc limit 10; + sum +------ + 1000 + 999 + 998 + 997 + 996 + 995 + 994 + 993 + 992 + 991 +(10 rows) + +select sum(t) from keylength group by b, a order by 1 desc limit 10; + sum +------ + 1000 + 999 + 998 + 997 + 996 + 995 + 994 + 993 + 992 + 991 +(10 rows) reset timescaledb.debug_require_vector_agg; diff --git a/tsl/test/sql/vector_agg_grouping.sql b/tsl/test/sql/vector_agg_grouping.sql index e087e54c48e..5368e64d69a 100644 --- a/tsl/test/sql/vector_agg_grouping.sql +++ b/tsl/test/sql/vector_agg_grouping.sql @@ -111,16 +111,54 @@ order by explain, condition.n, variable, function, grouping.n reset timescaledb.debug_require_vector_agg; +-- Test long text columns. Also make one of them a segmentby, so that we can +-- test the long scalar values. create table long(t int, a text, b text, c text, d text); select create_hypertable('long', 't'); -insert into long select n, x, x, x, x from ( - select n, repeat('1', 100 * 4 + n) x - from generate_series(1, 4) n) t +insert into long select n, a, x, x, x from ( + select n, 'short' || m a, repeat('1', 100 * 4 + n) x + from generate_series(1, 4) n, + generate_series(1, 4) m) t ; insert into long values (-1, 'a', 'b', 'c', 'd'); -alter table long set (timescaledb.compress); +insert into long values (-2, repeat('long', 1000), 'b', 'c', 'd'); +alter table long set (timescaledb.compress, timescaledb.compress_segmentby = 'a', + timescaledb.compress_orderby = 't desc'); select count(compress_chunk(x)) from show_chunks('long') x; set timescaledb.debug_require_vector_agg = 'require'; -select count(*) from long group by a, b, c, d order by 1 limit 10; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +-- Various placements of long scalar column +select sum(t) from long group by a, b, c, d order by 1 limit 10; +select sum(t) from long group by d, b, c, a order by 1 limit 10; +select sum(t) from long group by d, b, a, c order by 1 limit 10; + +-- Just the scalar column +select sum(t) from long group by a order by 1; + +-- No scalar columns +select sum(t) from long group by b, c, d order by 1 limit 10; + +reset timescaledb.debug_require_vector_agg; + + +-- Test various serialized key lengths. We want to touch the transition from short +-- to long varlena header for the serialized key. +create table keylength(t int, a text, b text); +select create_hypertable('keylength', 't'); +insert into keylength select t, 'a', repeat('b', t) from generate_series(1, 1000) t; +insert into keylength values (-1, '', ''); -- second chunk +alter table keylength set (timescaledb.compress, timescaledb.compress_segmentby = '', + timescaledb.compress_orderby = 't desc'); +select count(compress_chunk(x)) from show_chunks('keylength') x; + +set timescaledb.debug_require_vector_agg = 'require'; +---- Uncomment to generate reference. +--set timescaledb.enable_vectorized_aggregation to off; set timescaledb.debug_require_vector_agg = 'allow'; + +select sum(t) from keylength group by a, b order by 1 desc limit 10; +select sum(t) from keylength group by b, a order by 1 desc limit 10; + reset timescaledb.debug_require_vector_agg; From bf33d24bd17d96c235c0a7db308648af61850cc8 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:45:12 +0100 Subject: [PATCH 242/242] move more things relevant for hashing to the hashing strategy --- .../nodes/vector_agg/grouping_policy_hash.c | 26 ++++++---------- .../nodes/vector_agg/grouping_policy_hash.h | 16 ---------- .../vector_agg/hashing/batch_hashing_params.h | 4 ++- .../vector_agg/hashing/hash_strategy_common.c | 2 +- .../vector_agg/hashing/hash_strategy_impl.c | 31 ++++++++++++------- .../hash_strategy_impl_single_fixed_key.c | 4 +-- .../hashing/hash_strategy_serialized.c | 29 ++++++++--------- .../hashing/hash_strategy_single_text.c | 10 +++--- .../vector_agg/hashing/hashing_strategy.h | 12 +++++++ 9 files changed, 67 insertions(+), 67 deletions(-) diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.c b/tsl/src/nodes/vector_agg/grouping_policy_hash.c index 7d34203a2a4..e810fd95b21 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.c +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.c @@ -114,15 +114,6 @@ gp_hash_reset(GroupingPolicy *obj) policy->hashing.reset(&policy->hashing); - /* - * Have to reset this because it's in the key body context which is also - * reset here. - */ - policy->tmp_key_storage = NULL; - policy->num_tmp_key_storage_bytes = 0; - - policy->last_used_key_index = 0; - policy->stat_input_valid_rows = 0; policy->stat_input_total_rows = 0; policy->stat_bulk_filtered_rows = 0; @@ -236,7 +227,7 @@ add_one_range(GroupingPolicyHash *policy, TupleTableSlot *vector_slot, const int * Remember which aggregation states have already existed, and which we * have to initialize. State index zero is invalid. */ - const uint32 last_initialized_key_index = policy->last_used_key_index; + const uint32 last_initialized_key_index = policy->hashing.last_used_key_index; Assert(last_initialized_key_index <= policy->num_allocated_per_key_agg_states); /* @@ -257,13 +248,13 @@ add_one_range(GroupingPolicyHash *policy, TupleTableSlot *vector_slot, const int * If we added new keys, initialize the aggregate function states for * them. */ - if (policy->last_used_key_index > last_initialized_key_index) + if (policy->hashing.last_used_key_index > last_initialized_key_index) { /* * If the aggregate function states don't fit into the existing * storage, reallocate it. */ - if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + if (policy->hashing.last_used_key_index >= policy->num_allocated_per_key_agg_states) { policy->per_agg_per_key_states[agg_index] = repalloc(policy->per_agg_per_key_states[agg_index], @@ -274,7 +265,8 @@ add_one_range(GroupingPolicyHash *policy, TupleTableSlot *vector_slot, const int agg_def->func.state_bytes * (last_initialized_key_index + 1) + (char *) policy->per_agg_per_key_states[agg_index]; agg_def->func.agg_init(first_uninitialized_state, - policy->last_used_key_index - last_initialized_key_index); + policy->hashing.last_used_key_index - + last_initialized_key_index); } /* @@ -292,7 +284,7 @@ add_one_range(GroupingPolicyHash *policy, TupleTableSlot *vector_slot, const int * Record the newly allocated number of aggregate function states in case we * had to reallocate. */ - if (policy->last_used_key_index >= policy->num_allocated_per_key_agg_states) + if (policy->hashing.last_used_key_index >= policy->num_allocated_per_key_agg_states) { Assert(new_aggstate_rows > policy->num_allocated_per_key_agg_states); policy->num_allocated_per_key_agg_states = new_aggstate_rows; @@ -432,7 +424,7 @@ gp_hash_should_emit(GroupingPolicy *gp) { GroupingPolicyHash *policy = (GroupingPolicyHash *) gp; - if (policy->last_used_key_index > UINT32_MAX - GLOBAL_MAX_ROWS_PER_COMPRESSION) + if (policy->hashing.last_used_key_index > UINT32_MAX - GLOBAL_MAX_ROWS_PER_COMPRESSION) { /* * The max valid key index is UINT32_MAX, so we have to spill if the next @@ -461,7 +453,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) policy->returning_results = true; policy->last_returned_key = 1; - const float keys = policy->last_used_key_index; + const float keys = policy->hashing.last_used_key_index; if (keys > 0) { DEBUG_LOG("spill after %ld input, %ld valid, %ld bulk filtered, %ld cons, %.0f keys, " @@ -482,7 +474,7 @@ gp_hash_do_emit(GroupingPolicy *gp, TupleTableSlot *aggregated_slot) } const uint32 current_key = policy->last_returned_key; - const uint32 keys_end = policy->last_used_key_index + 1; + const uint32 keys_end = policy->hashing.last_used_key_index + 1; if (current_key >= keys_end) { policy->returning_results = false; diff --git a/tsl/src/nodes/vector_agg/grouping_policy_hash.h b/tsl/src/nodes/vector_agg/grouping_policy_hash.h index fa7792602d7..9c8a48fa6bf 100644 --- a/tsl/src/nodes/vector_agg/grouping_policy_hash.h +++ b/tsl/src/nodes/vector_agg/grouping_policy_hash.h @@ -78,11 +78,6 @@ typedef struct GroupingPolicyHash */ HashingStrategy hashing; - /* - * The last used index of an unique grouping key. Key index 0 is invalid. - */ - uint32 last_used_key_index; - /* * Temporary storage of unique indexes of keys corresponding to a given row * of the compressed batch that is currently being aggregated. We keep it in @@ -133,17 +128,6 @@ typedef struct GroupingPolicyHash uint64 stat_input_valid_rows; uint64 stat_bulk_filtered_rows; uint64 stat_consecutive_keys; - - /* - * FIXME all the stuff below should be moved out. - */ - - /* - * Temporary key storages. Some hashing strategies need to put the key in a - * separate memory area, we don't want to alloc/free it on each row. - */ - uint8 *tmp_key_storage; - uint64 num_tmp_key_storage_bytes; } GroupingPolicyHash; //#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) diff --git a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h index 070c8bfaaae..0e836b29486 100644 --- a/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h +++ b/tsl/src/nodes/vector_agg/hashing/batch_hashing_params.h @@ -21,7 +21,8 @@ typedef struct BatchHashingParams int num_grouping_columns; const CompressedColumnValues *grouping_column_values; - GroupingPolicyHash *restrict policy; + GroupingPolicyHash *policy; + HashingStrategy *restrict hashing; uint32 *restrict result_key_indexes; } BatchHashingParams; @@ -32,6 +33,7 @@ build_batch_hashing_params(GroupingPolicyHash *policy, TupleTableSlot *vector_sl uint16 nrows; BatchHashingParams params = { .policy = policy, + .hashing = &policy->hashing, .batch_filter = vector_slot_get_qual_result(vector_slot, &nrows), .num_grouping_columns = policy->num_grouping_columns, .grouping_column_values = policy->current_batch_grouping_column_values, diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c index c743a3171e8..590da8fdcc7 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_common.c @@ -18,7 +18,7 @@ void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, uint16 nrows) { HashingStrategy *hashing = &policy->hashing; - const uint32 num_possible_keys = policy->last_used_key_index + 1 + nrows; + const uint32 num_possible_keys = hashing->last_used_key_index + 1 + nrows; if (num_possible_keys > hashing->num_allocated_output_keys) { diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c index 0cc6426cbae..73b35a0b30a 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl.c @@ -57,7 +57,17 @@ FUNCTION_NAME(hash_strategy_reset)(HashingStrategy *hashing) { struct FUNCTION_NAME(hash) *table = (struct FUNCTION_NAME(hash) *) hashing->table; FUNCTION_NAME(reset)(table); + + hashing->last_used_key_index = 0; + hashing->null_key_index = 0; + + /* + * Have to reset this because it's in the key body context which is also + * reset here. + */ + hashing->tmp_key_storage = NULL; + hashing->num_tmp_key_storage_bytes = 0; } static void @@ -76,8 +86,7 @@ FUNCTION_NAME(hash_strategy_prepare_for_batch)(GroupingPolicyHash *policy, static pg_attribute_always_inline void FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int end_row) { - GroupingPolicyHash *policy = params.policy; - HashingStrategy *hashing = &policy->hashing; + HashingStrategy *restrict hashing = params.hashing; uint32 *restrict indexes = params.result_key_indexes; @@ -90,7 +99,7 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e if (!arrow_row_is_valid(params.batch_filter, row)) { /* The row doesn't pass the filter. */ - DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", policy, row); + DEBUG_PRINT("%p: row %d doesn't pass batch filter\n", hashing, row); continue; } @@ -109,10 +118,10 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e /* The key is null. */ if (hashing->null_key_index == 0) { - hashing->null_key_index = ++policy->last_used_key_index; + hashing->null_key_index = ++hashing->last_used_key_index; } indexes[row] = hashing->null_key_index; - DEBUG_PRINT("%p: row %d null key index %d\n", policy, row, hashing->null_key_index); + DEBUG_PRINT("%p: row %d null key index %d\n", hashing, row, hashing->null_key_index); continue; } @@ -128,9 +137,9 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e */ indexes[row] = previous_key_index; #ifndef NDEBUG - policy->stat_consecutive_keys++; + params.policy->stat_consecutive_keys++; #endif - DEBUG_PRINT("%p: row %d consecutive key index %d\n", policy, row, previous_key_index); + DEBUG_PRINT("%p: row %d consecutive key index %d\n", hashing, row, previous_key_index); continue; } @@ -144,14 +153,14 @@ FUNCTION_NAME(fill_offsets_impl)(BatchHashingParams params, int start_row, int e /* * New key, have to store it persistently. */ - const uint32 index = ++policy->last_used_key_index; + const uint32 index = ++hashing->last_used_key_index; entry->key_index = index; - FUNCTION_NAME(key_hashing_store_new)(policy, index, output_key); - DEBUG_PRINT("%p: row %d new key index %d\n", policy, row, index); + FUNCTION_NAME(key_hashing_store_new)(hashing, index, output_key); + DEBUG_PRINT("%p: row %d new key index %d\n", hashing, row, index); } else { - DEBUG_PRINT("%p: row %d old key index %d\n", policy, row, entry->key_index); + DEBUG_PRINT("%p: row %d old key index %d\n", hashing, row, entry->key_index); } indexes[row] = entry->key_index; diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c index 1e0ddabc187..57d57bea3bb 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_impl_single_fixed_key.c @@ -53,10 +53,10 @@ FUNCTION_NAME(key_hashing_get_key)(BatchHashingParams params, int row, } static pg_attribute_always_inline void -FUNCTION_NAME(key_hashing_store_new)(GroupingPolicyHash *restrict policy, uint32 new_key_index, +FUNCTION_NAME(key_hashing_store_new)(HashingStrategy *restrict hashing, uint32 new_key_index, OUTPUT_KEY_TYPE output_key) { - policy->hashing.output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); + hashing->output_keys[new_key_index] = OUTPUT_KEY_TO_DATUM(output_key); } static void diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c index dd3aa5cd552..9d6be1dff09 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_serialized.c @@ -64,7 +64,7 @@ static pg_attribute_always_inline void serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restrict output_key_ptr, void *restrict hash_table_key_ptr, bool *restrict valid) { - GroupingPolicyHash *policy = params.policy; + HashingStrategy *hashing = params.hashing; text **restrict output_key = (text **) output_key_ptr; HASH_TABLE_KEY_TYPE *restrict hash_table_key = (HASH_TABLE_KEY_TYPE *) hash_table_key_ptr; @@ -173,16 +173,16 @@ serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restric /* * Use temporary storage for the new key, reallocate if it's too small. */ - if (num_bytes > policy->num_tmp_key_storage_bytes) + if (num_bytes > hashing->num_tmp_key_storage_bytes) { - if (policy->tmp_key_storage != NULL) + if (hashing->tmp_key_storage != NULL) { - pfree(policy->tmp_key_storage); + pfree(hashing->tmp_key_storage); } - policy->tmp_key_storage = MemoryContextAlloc(policy->hashing.key_body_mctx, num_bytes); - policy->num_tmp_key_storage_bytes = num_bytes; + hashing->tmp_key_storage = MemoryContextAlloc(hashing->key_body_mctx, num_bytes); + hashing->num_tmp_key_storage_bytes = num_bytes; } - uint8 *restrict serialized_key_storage = policy->tmp_key_storage; + uint8 *restrict serialized_key_storage = hashing->tmp_key_storage; /* * Build the actual grouping key. @@ -355,7 +355,7 @@ serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restric */ *valid = true; - const struct umash_fp fp = umash_fprint(params.policy->hashing.umash_params, + const struct umash_fp fp = umash_fprint(params.hashing->umash_params, /* seed = */ ~0ULL, serialized_key_storage, num_bytes); @@ -363,25 +363,26 @@ serialized_key_hashing_get_key(BatchHashingParams params, int row, void *restric } static pg_attribute_always_inline void -serialized_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, +serialized_key_hashing_store_new(HashingStrategy *restrict hashing, uint32 new_key_index, text *output_key) { /* * We will store this key so we have to consume the temporary storage that * was used for it. The subsequent keys will need to allocate new memory. */ - Assert(policy->tmp_key_storage == (void *) output_key); - policy->tmp_key_storage = NULL; - policy->num_tmp_key_storage_bytes = 0; + Assert(hashing->tmp_key_storage == (void *) output_key); + hashing->tmp_key_storage = NULL; + hashing->num_tmp_key_storage_bytes = 0; - policy->hashing.output_keys[new_key_index] = PointerGetDatum(output_key); + hashing->output_keys[new_key_index] = PointerGetDatum(output_key); } static void serialized_emit_key(GroupingPolicyHash *policy, uint32 current_key, TupleTableSlot *aggregated_slot) { + const HashingStrategy *hashing = &policy->hashing; const int num_key_columns = policy->num_grouping_columns; - const Datum serialized_key_datum = policy->hashing.output_keys[current_key]; + const Datum serialized_key_datum = hashing->output_keys[current_key]; const uint8 *serialized_key = (const uint8 *) VARDATA_ANY(serialized_key_datum); PG_USED_FOR_ASSERTS_ONLY const int key_data_bytes = VARSIZE_ANY_EXHDR(serialized_key_datum); const uint8 *restrict ptr = serialized_key; diff --git a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c index 5b54970b595..d48aa339474 100644 --- a/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c +++ b/tsl/src/nodes/vector_agg/hashing/hash_strategy_single_text.c @@ -89,9 +89,9 @@ single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restri } DEBUG_PRINT("%p consider key row %d key index %d is %d bytes: ", - params.policy, + hashing, row, - params.policy->last_used_key_index + 1, + hashing->last_used_key_index + 1, output_key->len); for (size_t i = 0; i < output_key->len; i++) { @@ -107,14 +107,14 @@ single_text_key_hashing_get_key(BatchHashingParams params, int row, void *restri } static pg_attribute_always_inline void -single_text_key_hashing_store_new(GroupingPolicyHash *restrict policy, uint32 new_key_index, +single_text_key_hashing_store_new(HashingStrategy *restrict hashing, uint32 new_key_index, BytesView output_key) { const int total_bytes = output_key.len + VARHDRSZ; - text *restrict stored = (text *) MemoryContextAlloc(policy->hashing.key_body_mctx, total_bytes); + text *restrict stored = (text *) MemoryContextAlloc(hashing->key_body_mctx, total_bytes); SET_VARSIZE(stored, total_bytes); memcpy(VARDATA(stored), output_key.data, output_key.len); - policy->hashing.output_keys[new_key_index] = PointerGetDatum(stored); + hashing->output_keys[new_key_index] = PointerGetDatum(stored); } /* diff --git a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h index bb1cfcb61a5..f34bdda5435 100644 --- a/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h +++ b/tsl/src/nodes/vector_agg/hashing/hashing_strategy.h @@ -49,6 +49,11 @@ typedef struct HashingStrategy uint64 num_allocated_output_keys; MemoryContext key_body_mctx; + /* + * The last used index of an unique grouping key. Key index 0 is invalid. + */ + uint32 last_used_key_index; + /* * In single-column grouping, we store the null key outside of the hash * table, and its index is given by this value. Key index 0 is invalid. @@ -63,6 +68,13 @@ typedef struct HashingStrategy */ struct umash_params *umash_params; #endif + + /* + * Temporary key storages. Some hashing strategies need to put the key in a + * separate memory area, we don't want to alloc/free it on each row. + */ + uint8 *tmp_key_storage; + uint64 num_tmp_key_storage_bytes; } HashingStrategy; void hash_strategy_output_key_alloc(GroupingPolicyHash *policy, uint16 nrows);