diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index a83feea396..f76b7bbbd0 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -301,6 +301,7 @@ struct NumericData
  * This is feasible because the digit buffer is separate from the variable.
  * ----------
  */
+#define FIXED_BUF_LEN 4
 typedef struct NumericVar
 {
 	int			ndigits;		/* # of digits in digits[] - can be 0! */
@@ -309,6 +310,8 @@ typedef struct NumericVar
 	int			dscale;			/* display scale */
 	NumericDigit *buf;			/* start of palloc'd space for digits[] */
 	NumericDigit *digits;		/* base-NBASE digits */
+	bool		is_allocated;	/* is buf palloc'd? */
+	NumericDigit fixed_buf[FIXED_BUF_LEN];
 } NumericVar;
 
 
@@ -414,18 +417,18 @@ typedef struct NumericSumAccum
  */
 static const NumericDigit const_zero_data[1] = {0};
 static const NumericVar const_zero =
-{0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data};
+{0, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_zero_data, false, {0}};
 
 static const NumericDigit const_one_data[1] = {1};
 static const NumericVar const_one =
-{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data};
+{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_one_data, false, {0}};
 
 static const NumericVar const_minus_one =
-{1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data};
+{1, 0, NUMERIC_NEG, 0, NULL, (NumericDigit *) const_one_data, false, {0}};
 
 static const NumericDigit const_two_data[1] = {2};
 static const NumericVar const_two =
-{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data};
+{1, 0, NUMERIC_POS, 0, NULL, (NumericDigit *) const_two_data, false, {0}};
 
 #if DEC_DIGITS == 4
 static const NumericDigit const_zero_point_nine_data[1] = {9000};
@@ -435,7 +438,7 @@ static const NumericDigit const_zero_point_nine_data[1] = {90};
 static const NumericDigit const_zero_point_nine_data[1] = {9};
 #endif
 static const NumericVar const_zero_point_nine =
-{1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data};
+{1, -1, NUMERIC_POS, 1, NULL, (NumericDigit *) const_zero_point_nine_data, false, {0}};
 
 #if DEC_DIGITS == 4
 static const NumericDigit const_one_point_one_data[2] = {1, 1000};
@@ -445,16 +448,16 @@ static const NumericDigit const_one_point_one_data[2] = {1, 10};
 static const NumericDigit const_one_point_one_data[2] = {1, 1};
 #endif
 static const NumericVar const_one_point_one =
-{2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data};
+{2, 0, NUMERIC_POS, 1, NULL, (NumericDigit *) const_one_point_one_data, false, {0}};
 
 static const NumericVar const_nan =
-{0, 0, NUMERIC_NAN, 0, NULL, NULL};
+{0, 0, NUMERIC_NAN, 0, NULL, NULL, false, {0}};
 
 static const NumericVar const_pinf =
-{0, 0, NUMERIC_PINF, 0, NULL, NULL};
+{0, 0, NUMERIC_PINF, 0, NULL, NULL, false, {0}};
 
 static const NumericVar const_ninf =
-{0, 0, NUMERIC_NINF, 0, NULL, NULL};
+{0, 0, NUMERIC_NINF, 0, NULL, NULL, false, {0}};
 
 #if DEC_DIGITS == 4
 static const int round_powers[4] = {0, 1000, 100, 10};
@@ -6871,10 +6874,23 @@ dump_var(const char *str, NumericVar *var)
 static void
 alloc_var(NumericVar *var, int ndigits)
 {
-	digitbuf_free(var->buf);
-	var->buf = digitbuf_alloc(ndigits + 1);
-	var->buf[0] = 0;			/* spare digit for rounding */
-	var->digits = var->buf + 1;
+	if (var->is_allocated)
+		digitbuf_free(var->buf);
+	if (ndigits < FIXED_BUF_LEN - 1)
+	{
+		init_var(var);
+		var->is_allocated = false;
+		var->fixed_buf[0] = 0;		/* spare digit for rounding */
+		var->digits = var->fixed_buf + 1;
+
+	}
+	else
+	{
+		var->is_allocated = true;
+		var->buf = digitbuf_alloc(ndigits + 1);
+		var->buf[0] = 0;			/* spare digit for rounding */
+		var->digits = var->buf + 1;
+	}
 	var->ndigits = ndigits;
 }
 
