From 0c5e9903ce274fc7554cc672ac0802348aed267a Mon Sep 17 00:00:00 2001 From: junhangis Date: Tue, 26 Jul 2022 21:57:58 +0800 Subject: [PATCH] improve the performance of computing the square root of numeric. before optimization: openGauss=# explain analyse select sqrt(t0) from t_numeric limit 10000000; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..292129.20 rows=8468656 width=5) (actual time=4.152..170690.136 rows=8388608 loops=1) -> Seq Scan on t_numeric (cost=0.00..292129.20 rows=8468656 width=5) (actual time=4.150..169250.862 rows=8388608 loops=1) Total runtime: 171767.268 ms (3 rows) Time: 171768.179 ms after optimization: openGauss=# explain analyse select sqrt(t0) from t_numeric limit 10000000; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Limit (cost=0.00..292129.20 rows=8468656 width=5) (actual time=3.850..129299.312 rows=8388608 loops=1) -> Seq Scan on t_numeric (cost=0.00..292129.20 rows=8468656 width=5) (actual time=3.848..127801.242 rows=8388608 loops=1) Total runtime: 130378.841 ms (3 rows) Time: 130379.709 ms --- src/common/backend/utils/adt/numeric.cpp | 47 +++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/common/backend/utils/adt/numeric.cpp b/src/common/backend/utils/adt/numeric.cpp index 6bb92a741..de521286c 100644 --- a/src/common/backend/utils/adt/numeric.cpp +++ b/src/common/backend/utils/adt/numeric.cpp @@ -154,6 +154,7 @@ static void zero_var(NumericVar* var); static const char* set_var_from_str(const char* str, const char* cp, NumericVar* dest); static void set_var_from_num(Numeric value, NumericVar* dest); static void set_var_from_var(const NumericVar* value, NumericVar* dest); +static void init_var_from_var(const NumericVar *value, NumericVar *dest); static char* get_str_from_var(NumericVar* var); static char* get_str_from_var_sci(NumericVar* var, int rscale); @@ -2594,7 +2595,7 @@ Datum numeric_sqrt(PG_FUNCTION_ARGS) */ init_var_from_num(num, &arg); - init_var(&result); + quick_init_var(&result); /* Assume the input was normalized, so arg.weight is accurate */ sweight = (arg.weight + 1) * DEC_DIGITS / 2 - 1; @@ -4165,6 +4166,27 @@ static void set_var_from_var(const NumericVar* value, NumericVar* dest) dest->digits = newbuf + 1; } +/* + * init_var_from_var() - + * + * init one variable from another - they must NOT be the same variable + */ +static void +init_var_from_var(const NumericVar *value, NumericVar *dest) +{ + init_alloc_var(dest, value->ndigits); + + dest->weight = value->weight; + dest->sign = value->sign; + dest->dscale = value->dscale; + + errno_t rc = memcpy_s(dest->digits, + value->ndigits * sizeof(NumericDigit), + value->digits, + value->ndigits * sizeof(NumericDigit)); + securec_check(rc, "\0", "\0"); +} + static void remove_tail_zero(char *ascii) { if (!HIDE_TAILING_ZERO || ascii == NULL) { @@ -5482,6 +5504,7 @@ static void div_var_fast(NumericVar* var1, NumericVar* var2, NumericVar* result, int var2ndigits = var2->ndigits; NumericDigit* var1digits = var1->digits; NumericDigit* var2digits = var2->digits; + int tdiv[NUMERIC_LOCAL_NDIG]; /* * First of all division by zero check; we must not be handed an @@ -5529,7 +5552,14 @@ static void div_var_fast(NumericVar* var1, NumericVar* var2, NumericVar* result, * position of dividend space. A final pass of carry propagation takes * care of any mistaken quotient digits. */ - div = (int*)palloc0((div_ndigits + 1) * sizeof(int)); + i = (div_ndigits + 1) * sizeof(int); + if (div_ndigits > NUMERIC_LOCAL_NMAX) { + div = (int *) palloc0(i); + } else { + errno_t rc = memset_s(tdiv, i, 0, i); + securec_check(rc, "\0", "\0"); + div = tdiv; + } for (i = 0; i < var1ndigits; i++) div[i + 1] = var1digits[i]; @@ -5672,7 +5702,9 @@ static void div_var_fast(NumericVar* var1, NumericVar* var2, NumericVar* result, } Assert(carry == 0); - pfree_ext(div); + if (div != tdiv) { + pfree_ext(div); + } /* * Finally, round the result to the requested precision. @@ -5850,12 +5882,8 @@ static void sqrt_var(NumericVar* arg, NumericVar* result, int rscale) (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION), errmsg("cannot take square root of a negative number"))); - init_var(&tmp_arg); - init_var(&tmp_val); - init_var(&last_val); - /* Copy arg in case it is the same var as result */ - set_var_from_var(arg, &tmp_arg); + init_var_from_var(arg, &tmp_arg); /* * Initialize the result to the first guess @@ -5867,7 +5895,8 @@ static void sqrt_var(NumericVar* arg, NumericVar* result, int rscale) result->weight = tmp_arg.weight / 2; result->sign = NUMERIC_POS; - set_var_from_var(result, &last_val); + init_var_from_var(result, &last_val); + quick_init_var(&tmp_val); for (;;) { div_var_fast(&tmp_arg, result, &tmp_val, local_rscale, true);