diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 9c39e7d3b3..2fcfef76f9 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -34,6 +34,30 @@
 /* Divide by two and round towards positive infinity. */
 #define half_rounded(x)   (((x) + ((x) < 0 ? 0 : 1)) / 2)
 
+/*
+ * Units used in pg_size_pretty functions
+ */
+struct size_pretty_unit {
+	char	   *unit;			/* e.g bytes, kB, MB etc */
+	uint64		limit;			/* upper limit after reducing by shiftright
+								 * bits from previous units */
+	uint8		shiftRight;		/* number of bits to shift right by after
+								 * limit is exceeded */
+	uint8		multishift;		/* how many bits to shift "1" left by to make
+								 * one of these units. */
+	bool		doHalfRound;	/* perform halfround operation */
+};
+
+/* When adding units here also update the error message in pg_size_bytes */
+static const struct size_pretty_unit size_pretty_units[] = {
+	{"bytes", 10 * 1024, 9, 0, false}, /* keep one extra bit for rounding */
+	{"kB", 20 * 1024 - 1, 10, 10, true},
+	{"MB", 20 * 1024 - 1, 10, 20, true},
+	{"GB", 20 * 1024 - 1, 10, 30, true},
+	{"TB", 20 * 1024 - 1, 10, 40, true},
+	{NULL, 0, 0, 0, false}
+};
+
 /* Return physical size of directory contents, or 0 if dir doesn't exist */
 static int64
 db_dir_size(const char *path)
@@ -535,37 +559,30 @@ pg_size_pretty(PG_FUNCTION_ARGS)
 {
 	int64		size = PG_GETARG_INT64(0);
 	char		buf[64];
-	int64		limit = 10 * 1024;
-	int64		limit2 = limit * 2 - 1;
+	uint32		i;
 
-	if (Abs(size) < limit)
-		snprintf(buf, sizeof(buf), INT64_FORMAT " bytes", size);
-	else
+	for (i = 0; size_pretty_units[i].unit != NULL; i++)
 	{
-		size >>= 9;				/* keep one extra bit for rounding */
-		if (Abs(size) < limit2)
-			snprintf(buf, sizeof(buf), INT64_FORMAT " kB",
-					 half_rounded(size));
-		else
+		/*
+		 * Use this set of units if the number is under the limit or there
+		 * is no other unit to use.
+		 */
+		if (Abs(size) < size_pretty_units[i].limit ||
+			size_pretty_units[i + 1].unit == NULL)
 		{
-			size >>= 10;
-			if (Abs(size) < limit2)
-				snprintf(buf, sizeof(buf), INT64_FORMAT " MB",
-						 half_rounded(size));
-			else
-			{
-				size >>= 10;
-				if (Abs(size) < limit2)
-					snprintf(buf, sizeof(buf), INT64_FORMAT " GB",
-							 half_rounded(size));
-				else
-				{
-					size >>= 10;
-					snprintf(buf, sizeof(buf), INT64_FORMAT " TB",
-							 half_rounded(size));
-				}
-			}
+			if (size_pretty_units[i].doHalfRound)
+				size = half_rounded(size);
+
+			snprintf(buf, sizeof(buf), INT64_FORMAT " %s", size,
+					 size_pretty_units[i].unit);
+			break;
 		}
+
+		/*
+		 * limit for the current unit has been exceeded.  Shift right by the
+		 * specified number of bits and try the next unit
+		 */
+		size >>= size_pretty_units[i].shiftRight;
 	}
 
 	PG_RETURN_TEXT_P(cstring_to_text(buf));
@@ -636,56 +653,34 @@ Datum
 pg_size_pretty_numeric(PG_FUNCTION_ARGS)
 {
 	Numeric		size = PG_GETARG_NUMERIC(0);
-	Numeric		limit,
-				limit2;
+	Numeric		limit;
 	char	   *result;
+	uint32		i;
 
-	limit = int64_to_numeric(10 * 1024);
-	limit2 = int64_to_numeric(10 * 1024 * 2 - 1);
-
-	if (numeric_is_less(numeric_absolute(size), limit))
+	for (i = 0; size_pretty_units[i].unit != NULL; i++)
 	{
-		result = psprintf("%s bytes", numeric_to_cstring(size));
-	}
-	else
-	{
-		/* keep one extra bit for rounding */
-		/* size >>= 9 */
-		size = numeric_shift_right(size, 9);
+		limit = int64_to_numeric(size_pretty_units[i].limit);
 
-		if (numeric_is_less(numeric_absolute(size), limit2))
-		{
-			size = numeric_half_rounded(size);
-			result = psprintf("%s kB", numeric_to_cstring(size));
-		}
-		else
+		/*
+		 * Use this set of units if the number is under the limit or there
+		 * is no other unit to use.
+		 */
+		if (numeric_is_less(numeric_absolute(size), limit) ||
+			size_pretty_units[i + 1].unit == NULL)
 		{
-			/* size >>= 10 */
-			size = numeric_shift_right(size, 10);
-			if (numeric_is_less(numeric_absolute(size), limit2))
-			{
+			if (size_pretty_units[i].doHalfRound)
 				size = numeric_half_rounded(size);
-				result = psprintf("%s MB", numeric_to_cstring(size));
-			}
-			else
-			{
-				/* size >>= 10 */
-				size = numeric_shift_right(size, 10);
-
-				if (numeric_is_less(numeric_absolute(size), limit2))
-				{
-					size = numeric_half_rounded(size);
-					result = psprintf("%s GB", numeric_to_cstring(size));
-				}
-				else
-				{
-					/* size >>= 10 */
-					size = numeric_shift_right(size, 10);
-					size = numeric_half_rounded(size);
-					result = psprintf("%s TB", numeric_to_cstring(size));
-				}
-			}
+
+			result = psprintf("%s %s", numeric_to_cstring(size),
+							  size_pretty_units[i].unit);
+			break;
 		}
+
+		/*
+		 * limit for the current unit has been exceeded.  Shift right by the
+		 * specified number of bits and try the next unit
+		 */
+		size = numeric_shift_right(size, size_pretty_units[i].shiftRight);
 	}
 
 	PG_RETURN_TEXT_P(cstring_to_text(result));
@@ -787,6 +782,7 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 	if (*strptr != '\0')
 	{
 		int64		multiplier = 0;
+		uint32		i;
 
 		/* Trim any trailing whitespace */
 		endptr = str + VARSIZE_ANY_EXHDR(arg) - 1;
@@ -797,21 +793,18 @@ pg_size_bytes(PG_FUNCTION_ARGS)
 		endptr++;
 		*endptr = '\0';
 
-		/* Parse the unit case-insensitively */
-		if (pg_strcasecmp(strptr, "bytes") == 0)
-			multiplier = (int64) 1;
-		else if (pg_strcasecmp(strptr, "kb") == 0)
-			multiplier = (int64) 1024;
-		else if (pg_strcasecmp(strptr, "mb") == 0)
-			multiplier = ((int64) 1024) * 1024;
-
-		else if (pg_strcasecmp(strptr, "gb") == 0)
-			multiplier = ((int64) 1024) * 1024 * 1024;
-
-		else if (pg_strcasecmp(strptr, "tb") == 0)
-			multiplier = ((int64) 1024) * 1024 * 1024 * 1024;
-
-		else
+		for (i = 0; size_pretty_units[i].unit != NULL; i++)
+		{
+			/* Parse the unit case-insensitively */
+			if (pg_strcasecmp(strptr, size_pretty_units[i].unit) == 0)
+			{
+				multiplier = ((int64) 1) << size_pretty_units[i].multishift;
+				break;
+			}
+		}
+		
+		/* Verify we found a valid unit in the loop above */
+		if (size_pretty_units[i].unit == NULL)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("invalid size: \"%s\"", text_to_cstring(arg)),
