mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Apply the "nodeAgg" optimization to more of the builtin transition
functions. This patch optimizes int2_sum(), int4_sum(), float4_accum() and float8_accum() to avoid needing to copy the transition function's state for each input tuple of the aggregate. In an extreme case (e.g. SELECT sum(int2_col) FROM table where table has a single column), it improves performance by about 20%. For more complex queries or tables with wider rows, the relative performance improvement will not be as significant.
This commit is contained in:
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.113 2005/02/11 04:08:58 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.114 2005/04/06 23:56:07 neilc Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1902,8 +1902,6 @@ float8_accum(PG_FUNCTION_ARGS)
|
|||||||
float8 N,
|
float8 N,
|
||||||
sumX,
|
sumX,
|
||||||
sumX2;
|
sumX2;
|
||||||
Datum transdatums[3];
|
|
||||||
ArrayType *result;
|
|
||||||
|
|
||||||
transvalues = check_float8_array(transarray, "float8_accum");
|
transvalues = check_float8_array(transarray, "float8_accum");
|
||||||
N = transvalues[0];
|
N = transvalues[0];
|
||||||
@ -1914,15 +1912,35 @@ float8_accum(PG_FUNCTION_ARGS)
|
|||||||
sumX += newval;
|
sumX += newval;
|
||||||
sumX2 += newval * newval;
|
sumX2 += newval * newval;
|
||||||
|
|
||||||
transdatums[0] = Float8GetDatumFast(N);
|
/*
|
||||||
transdatums[1] = Float8GetDatumFast(sumX);
|
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||||
transdatums[2] = Float8GetDatumFast(sumX2);
|
* parameter in-place to reduce palloc overhead. Otherwise we
|
||||||
|
* construct a new array with the updated transition data and
|
||||||
|
* return it.
|
||||||
|
*/
|
||||||
|
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||||
|
{
|
||||||
|
transvalues[0] = N;
|
||||||
|
transvalues[1] = sumX;
|
||||||
|
transvalues[2] = sumX2;
|
||||||
|
|
||||||
result = construct_array(transdatums, 3,
|
PG_RETURN_ARRAYTYPE_P(transarray);
|
||||||
FLOAT8OID,
|
}
|
||||||
sizeof(float8), false /* float8 byval */ , 'd');
|
else
|
||||||
|
{
|
||||||
|
Datum transdatums[3];
|
||||||
|
ArrayType *result;
|
||||||
|
|
||||||
PG_RETURN_ARRAYTYPE_P(result);
|
transdatums[0] = Float8GetDatumFast(N);
|
||||||
|
transdatums[1] = Float8GetDatumFast(sumX);
|
||||||
|
transdatums[2] = Float8GetDatumFast(sumX2);
|
||||||
|
|
||||||
|
result = construct_array(transdatums, 3,
|
||||||
|
FLOAT8OID,
|
||||||
|
sizeof(float8), false /* float8 byval */ , 'd');
|
||||||
|
|
||||||
|
PG_RETURN_ARRAYTYPE_P(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -1935,8 +1953,6 @@ float4_accum(PG_FUNCTION_ARGS)
|
|||||||
sumX,
|
sumX,
|
||||||
sumX2,
|
sumX2,
|
||||||
newval;
|
newval;
|
||||||
Datum transdatums[3];
|
|
||||||
ArrayType *result;
|
|
||||||
|
|
||||||
transvalues = check_float8_array(transarray, "float4_accum");
|
transvalues = check_float8_array(transarray, "float4_accum");
|
||||||
N = transvalues[0];
|
N = transvalues[0];
|
||||||
@ -1950,15 +1966,35 @@ float4_accum(PG_FUNCTION_ARGS)
|
|||||||
sumX += newval;
|
sumX += newval;
|
||||||
sumX2 += newval * newval;
|
sumX2 += newval * newval;
|
||||||
|
|
||||||
transdatums[0] = Float8GetDatumFast(N);
|
/*
|
||||||
transdatums[1] = Float8GetDatumFast(sumX);
|
* If we're invoked by nodeAgg, we can cheat and modify our first
|
||||||
transdatums[2] = Float8GetDatumFast(sumX2);
|
* parameter in-place to reduce palloc overhead. Otherwise we
|
||||||
|
* construct a new array with the updated transition data and
|
||||||
|
* return it.
|
||||||
|
*/
|
||||||
|
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||||
|
{
|
||||||
|
transvalues[0] = N;
|
||||||
|
transvalues[1] = sumX;
|
||||||
|
transvalues[2] = sumX2;
|
||||||
|
|
||||||
result = construct_array(transdatums, 3,
|
PG_RETURN_ARRAYTYPE_P(transarray);
|
||||||
FLOAT8OID,
|
}
|
||||||
sizeof(float8), false /* float8 byval */ , 'd');
|
else
|
||||||
|
{
|
||||||
|
Datum transdatums[3];
|
||||||
|
ArrayType *result;
|
||||||
|
|
||||||
PG_RETURN_ARRAYTYPE_P(result);
|
transdatums[0] = Float8GetDatumFast(N);
|
||||||
|
transdatums[1] = Float8GetDatumFast(sumX);
|
||||||
|
transdatums[2] = Float8GetDatumFast(sumX2);
|
||||||
|
|
||||||
|
result = construct_array(transdatums, 3,
|
||||||
|
FLOAT8OID,
|
||||||
|
sizeof(float8), false /* float8 byval */ , 'd');
|
||||||
|
|
||||||
|
PG_RETURN_ARRAYTYPE_P(result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* Copyright (c) 1998-2005, PostgreSQL Global Development Group
|
* Copyright (c) 1998-2005, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.82 2005/04/04 23:50:27 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.83 2005/04/06 23:56:07 neilc Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2357,7 +2357,6 @@ numeric_stddev(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
int2_sum(PG_FUNCTION_ARGS)
|
int2_sum(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int64 oldsum;
|
|
||||||
int64 newval;
|
int64 newval;
|
||||||
|
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
@ -2370,22 +2369,39 @@ int2_sum(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_INT64(newval);
|
PG_RETURN_INT64(newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldsum = PG_GETARG_INT64(0);
|
/*
|
||||||
|
* If we're invoked by nodeAgg, we can cheat and modify out first
|
||||||
|
* parameter in-place to avoid palloc overhead. If not, we need to
|
||||||
|
* return the new value of the transition variable.
|
||||||
|
*/
|
||||||
|
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||||
|
{
|
||||||
|
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||||
|
|
||||||
/* Leave sum unchanged if new input is null. */
|
/* Leave the running sum unchanged in the new input is null */
|
||||||
if (PG_ARGISNULL(1))
|
if (!PG_ARGISNULL(1))
|
||||||
PG_RETURN_INT64(oldsum);
|
*oldsum = *oldsum + (int64) PG_GETARG_INT16(1);
|
||||||
|
|
||||||
/* OK to do the addition. */
|
PG_RETURN_POINTER(oldsum);
|
||||||
newval = oldsum + (int64) PG_GETARG_INT16(1);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int64 oldsum = PG_GETARG_INT64(0);
|
||||||
|
|
||||||
PG_RETURN_INT64(newval);
|
/* Leave sum unchanged if new input is null. */
|
||||||
|
if (PG_ARGISNULL(1))
|
||||||
|
PG_RETURN_INT64(oldsum);
|
||||||
|
|
||||||
|
/* OK to do the addition. */
|
||||||
|
newval = oldsum + (int64) PG_GETARG_INT16(1);
|
||||||
|
|
||||||
|
PG_RETURN_INT64(newval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
int4_sum(PG_FUNCTION_ARGS)
|
int4_sum(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int64 oldsum;
|
|
||||||
int64 newval;
|
int64 newval;
|
||||||
|
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
@ -2398,16 +2414,34 @@ int4_sum(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_INT64(newval);
|
PG_RETURN_INT64(newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
oldsum = PG_GETARG_INT64(0);
|
/*
|
||||||
|
* If we're invoked by nodeAgg, we can cheat and modify out first
|
||||||
|
* parameter in-place to avoid palloc overhead. If not, we need to
|
||||||
|
* return the new value of the transition variable.
|
||||||
|
*/
|
||||||
|
if (fcinfo->context && IsA(fcinfo->context, AggState))
|
||||||
|
{
|
||||||
|
int64 *oldsum = (int64 *) PG_GETARG_POINTER(0);
|
||||||
|
|
||||||
/* Leave sum unchanged if new input is null. */
|
/* Leave the running sum unchanged in the new input is null */
|
||||||
if (PG_ARGISNULL(1))
|
if (!PG_ARGISNULL(1))
|
||||||
PG_RETURN_INT64(oldsum);
|
*oldsum = *oldsum + (int64) PG_GETARG_INT32(1);
|
||||||
|
|
||||||
/* OK to do the addition. */
|
PG_RETURN_POINTER(oldsum);
|
||||||
newval = oldsum + (int64) PG_GETARG_INT32(1);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int64 oldsum = PG_GETARG_INT64(0);
|
||||||
|
|
||||||
PG_RETURN_INT64(newval);
|
/* Leave sum unchanged if new input is null. */
|
||||||
|
if (PG_ARGISNULL(1))
|
||||||
|
PG_RETURN_INT64(oldsum);
|
||||||
|
|
||||||
|
/* OK to do the addition. */
|
||||||
|
newval = oldsum + (int64) PG_GETARG_INT32(1);
|
||||||
|
|
||||||
|
PG_RETURN_INT64(newval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -2426,6 +2460,12 @@ int8_sum(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_DATUM(newval);
|
PG_RETURN_DATUM(newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that we cannot special-case the nodeAgg case here, as we
|
||||||
|
* do for int2_sum and int4_sum: numeric is of variable size, so
|
||||||
|
* we cannot modify our first parameter in-place.
|
||||||
|
*/
|
||||||
|
|
||||||
oldsum = PG_GETARG_NUMERIC(0);
|
oldsum = PG_GETARG_NUMERIC(0);
|
||||||
|
|
||||||
/* Leave sum unchanged if new input is null. */
|
/* Leave sum unchanged if new input is null. */
|
||||||
|
Reference in New Issue
Block a user