MCPcopy Create free account
hub / github.com/apache/impala / SampledNdvFinalize

Method SampledNdvFinalize

be/src/exprs/aggregate-functions-ir.cc:3177–3282  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

3175}
3176
3177BigIntVal AggregateFunctions::SampledNdvFinalize(FunctionContext* ctx,
3178 const StringVal& src) {
3179 SampledNdvState* state = reinterpret_cast<SampledNdvState*>(src.ptr);
3180
3181 // Generate 'num_points' data points with x=row_count and y=ndv_estimate. These points
3182 // are used to fit a function for the NDV growth and estimate the real NDV.
3183 constexpr int num_points =
3184 SampledNdvState::NUM_HLL_BUCKETS * SampledNdvState::NUM_HLL_BUCKETS;
3185 int64_t counts[num_points] = { 0 };
3186 int64_t ndvs[num_points] = { 0 };
3187
3188 int64_t min_ndv = numeric_limits<int64_t>::max();
3189 int64_t min_count = numeric_limits<int64_t>::max();
3190 // We have a fixed number of HLL intermediates to generate data points. Any unique
3191 // subset of intermediates can be combined to create a new data point. It was
3192 // empirically determined that 'num_data' points is typically sufficient and there are
3193 // diminishing returns from generating additional data points.
3194 // The generation method below was chosen for its simplicity. It successively merges
3195 // buckets in a rolling window of size NUM_HLL_BUCKETS. Repeating the last data point
3196 // where all buckets are merged biases the curve fitting to hit that data point which
3197 // makes sense because that's likely the most accurate one. The number of data points
3198 // are sufficient for reasonable accuracy.
3199 int pidx = 0;
3200 for (int i = 0; i < SampledNdvState::NUM_HLL_BUCKETS; ++i) {
3201 uint8_t merged_hll_data[DEFAULT_HLL_LEN];
3202 memset(merged_hll_data, 0, DEFAULT_HLL_LEN);
3203 StringVal merged_hll(merged_hll_data, DEFAULT_HLL_LEN);
3204 int64_t merged_count = 0;
3205 for (int j = 0; j < SampledNdvState::NUM_HLL_BUCKETS; ++j) {
3206 int bucket_idx = (i + j) % SampledNdvState::NUM_HLL_BUCKETS;
3207 merged_count += state->buckets[bucket_idx].row_count;
3208 counts[pidx] = merged_count;
3209 StringVal hll = StringVal(state->buckets[bucket_idx].hll, DEFAULT_HLL_LEN);
3210 HllMerge(ctx, hll, &merged_hll);
3211 ndvs[pidx] = HllFinalEstimate(merged_hll.ptr);
3212 ++pidx;
3213 }
3214 min_count = std::min(min_count, state->buckets[i].row_count);
3215 min_ndv = std::min(min_ndv, ndvs[i * SampledNdvState::NUM_HLL_BUCKETS]);
3216 }
3217 // Based on the point-generation method above the last elements represent the data
3218 // point where all buckets are merged.
3219 int64_t max_count = counts[num_points - 1];
3220 int64_t max_ndv = ndvs[num_points - 1];
3221
3222 // Scale all values to [0,1] since some objective functions require it (e.g., Sigmoid).
3223 double count_scale = max_count - min_count;
3224 double ndv_scale = max_ndv - min_ndv;
3225 if (count_scale == 0) count_scale = 1.0;
3226 if (ndv_scale == 0) ndv_scale = 1.0;
3227 double scaled_counts[num_points];
3228 double scaled_ndvs[num_points];
3229 for (int i = 0; i < num_points; ++i) {
3230 scaled_counts[i] = counts[i] / count_scale;
3231 scaled_ndvs[i] = ndvs[i] / ndv_scale;
3232 }
3233
3234 // List of objective functions. Curve fitting will select the best values for the

Callers

nothing calls this directly

Calls 12

maxFunction · 0.85
StringValClass · 0.85
HllMergeFunction · 0.85
minFunction · 0.85
ObjectiveFunctionClass · 0.85
moveFunction · 0.85
push_backMethod · 0.80
LmsFitMethod · 0.80
GetYMethod · 0.80
beginMethod · 0.45
endMethod · 0.45
GetErrorMethod · 0.45

Tested by

no test coverage detected