diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index f9eea76..ff66e7b 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -17767,6 +17767,9 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
     <primary>pg_relation_size</primary>
    </indexterm>
    <indexterm>
+    <primary>pg_size_bytes</primary>
+   </indexterm>
+   <indexterm>
     <primary>pg_size_pretty</primary>
    </indexterm>
    <indexterm>
@@ -17838,6 +17841,15 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
       </row>
       <row>
        <entry>
+        <literal><function>pg_size_bytes(<type>text</type>)</function></literal>
+        </entry>
+       <entry><type>bigint</type></entry>
+       <entry>
+         Converts a size in human-readable format with size units into bytes.
+       </entry>
+      </row>
+      <row>
+       <entry>
         <literal><function>pg_size_pretty(<type>bigint</type>)</function></literal>
         </entry>
        <entry><type>text</type></entry>
@@ -17968,8 +17980,16 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
 
    <para>
     <function>pg_size_pretty</> can be used to format the result of one of
-    the other functions in a human-readable way, using kB, MB, GB or TB as
-    appropriate.
+    the other functions in a human-readable way, using bytes, kB, MB, GB or TB
+    as appropriate.
+   </para>
+
+   <para>
+    <function>pg_size_bytes</> can be used to get a size in bytes as
+    bigint from a human-readable format for a comparison purposes (it is
+    the opposite to <function>pg_size_pretty</> function). The format is
+    fixed-point number with an optional size unit: bytes, kB, MB, GB or TB.
+    The unit string is case insensitive.
    </para>
 
    <para>
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 2084692..58481d7 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -25,6 +25,7 @@
 #include "storage/fd.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/guc.h"
 #include "utils/numeric.h"
 #include "utils/rel.h"
 #include "utils/relfilenodemap.h"
@@ -700,6 +701,161 @@ pg_size_pretty_numeric(PG_FUNCTION_ARGS)
 }
 
 /*
+ * Convert human readable size to int64.
+ *
+ * Due to support for decimal values and case insensitivity of units
+ * a function parse_int cannot be used.
+ */
+Datum
+pg_size_bytes(PG_FUNCTION_ARGS)
+{
+	text	   *arg = PG_GETARG_TEXT_PP(0);
+	char	   *str,
+			   *strptr;
+	char		saved_char;
+	char	   *startptr;
+	Numeric		num;
+	int64		result;
+	bool		error = false;
+	bool		main_digits = false;
+
+	str = text_to_cstring(arg);
+	strptr = str;
+
+	/* Skip leading spaces */
+	while (isspace((unsigned char) *strptr))
+		strptr++;
+
+	startptr = strptr;  /* save start of the non-empty string */
+
+	/* Part (1): leading sign indicator. */
+	if(*strptr == '-' || *strptr == '+')
+		strptr++;
+
+	/* Part (2): parse main digit string. */
+	if (isdigit((unsigned char) *strptr))
+	{
+		main_digits = true;
+		do
+			strptr++;
+		while (isdigit((unsigned char) *strptr));
+	}
+
+	/* Part (3): parse optional decimal portion. */
+	if (*strptr == '.')
+	{
+		strptr++;
+		if (isdigit((unsigned char) *strptr))
+		{
+			do
+				strptr++;
+			while (isdigit((unsigned char) *strptr));
+		}
+		else if(!main_digits)
+			error = true;
+	}
+	else if(!main_digits)
+		error = true;
+
+	if(!error && *strptr != '\0'
+		&& !isalpha((unsigned char) *strptr)
+		&& !isspace((unsigned char) *strptr))
+	{
+		error = true;
+	}
+
+	if(error || (startptr == strptr))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("invalid size: \"%s\"", str),
+				 (startptr == strptr) ? errdetail("Empty value not allowed") : 0));
+
+	saved_char = *strptr;
+	*strptr = '\0';
+
+	num = DatumGetNumeric(DirectFunctionCall3(numeric_in,
+						  CStringGetDatum(startptr), 0, -1));
+
+	*strptr = saved_char;
+
+	/* allow whitespace between number and unit */
+	while (isspace((unsigned char) *strptr))
+		strptr++;
+
+	/* Handle possible unit */
+	if (*strptr != '\0')
+	{
+		int			multiplier;
+		const char *hintmsg;
+		const int	skip_unit = -1; /* special value for skipping units usage */
+
+		startptr = strptr;
+		strptr = str + VARSIZE_ANY_EXHDR(arg) - 1;
+
+		/*
+		 * At that point startptr at the first letter of a non-empty unit,
+		 * strptr at the end of the string.
+		 * Let's trim unit, check for a correctness and get a multiplier.
+		 */
+
+		while(isspace((unsigned char) *strptr))
+			strptr--;
+
+		saved_char = *(++strptr);
+		*strptr = '\0';
+
+		/* Get a multiplier if unit is known, else returns 0. */
+		multiplier = parse_memory_unit(startptr, &hintmsg);
+
+		/*
+		 * "bytes" unit is not mentioned in memory_unit_conversion_table
+		 * thus is not supported by parse_memory_unit, so check it manually.
+		 */
+		if (!multiplier && (strcasecmp(startptr, "bytes") == 0))
+			multiplier = skip_unit;  /* also it marks a multiplier as "found" */
+
+		if (!multiplier)
+		{
+			/*
+			 * On error we allocate an extra buffer for reporting wrong unit
+			 * in errdetail because str must be restored for using it in errmsg.
+			 */
+			size_t		unitlen = (strptr - startptr) + 1;  /* with leading '\0' */
+			char	   *unitptr = (char *) palloc(unitlen);
+
+			memcpy(unitptr, startptr, unitlen);   /* copying with leading '\0'*/
+
+			*strptr = saved_char;
+
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("invalid size: \"%s\"", str),
+					 errdetail("Invalid size unit \"%s\"", unitptr),
+					 errhint("%s", _(hintmsg))));
+		}
+
+		if(multiplier != skip_unit)
+		{
+			Numeric		mul_num;
+			/*
+			 * Now, the multiplier is in KB units.
+			 * It should be multiplied by 1024 before usage.
+			 */
+			mul_num = DatumGetNumeric(DirectFunctionCall1(int8_numeric,
+									  Int64GetDatum(multiplier * 1024L)));
+
+			num = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
+								  NumericGetDatum(mul_num),
+								  NumericGetDatum(num)));
+		}
+	}
+
+	result = DatumGetInt64(DirectFunctionCall1(numeric_int8, NumericGetDatum(num)));
+
+	PG_RETURN_INT64(result);
+}
+
+/*
  * Get the filenode of a relation
  *
  * This is expected to be used in queries like
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 31a69ca..5748b20 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5273,6 +5273,33 @@ convert_from_base_unit(int64 base_value, int base_unit,
 
 
 /*
+ * Parse value as some known memory unit to its size in bytes.
+ * Used in pg_size_bytes function. Against convert_to_base_unit, a string
+ * comparation is case insensitive.
+ *
+ * Returns multiplier value if that is the appropriate result, otherwise returns
+ * zero and points hintmsg to a string for usiage as a hint in an error message.
+ */
+int
+parse_memory_unit(const char *unit, const char **hintmsg)
+{
+	int			i;
+
+	for (i = 0; *memory_unit_conversion_table[i].unit; i++)
+	{
+		const unit_conversion *conv = &memory_unit_conversion_table[i];
+
+		if (conv->base_unit == GUC_UNIT_KB && strcasecmp(unit, conv->unit) == 0)
+			return conv->multiplier;
+	}
+
+	*hintmsg = memory_units_hint;
+
+	return 0;
+}
+
+
+/*
  * Try to parse value as an integer.  The accepted formats are the
  * usual decimal, octal, or hexadecimal formats, optionally followed by
  * a unit name if "flags" indicates a unit is allowed.
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 1c0ef9a..f5580b1 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3601,6 +3601,8 @@ DATA(insert OID = 2288 ( pg_size_pretty			PGNSP PGUID 12 1 0 0 0 f f f f t f i s
 DESCR("convert a long int to a human readable text using size units");
 DATA(insert OID = 3166 ( pg_size_pretty			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 25 "1700" _null_ _null_ _null_ _null_ _null_ pg_size_pretty_numeric _null_ _null_ _null_ ));
 DESCR("convert a numeric to a human readable text using size units");
+DATA(insert OID = 3334 ( pg_size_bytes			PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 20 "25" _null_ _null_ _null_ _null_ _null_ pg_size_bytes _null_ _null_ _null_ ));
+DESCR("convert a size in human-readable format with size units into bytes");
 DATA(insert OID = 2997 ( pg_table_size			PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 20 "2205" _null_ _null_ _null_ _null_ _null_ pg_table_size _null_ _null_ _null_ ));
 DESCR("disk space usage for the specified table, including TOAST, free space and visibility map");
 DATA(insert OID = 2998 ( pg_indexes_size		PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 20 "2205" _null_ _null_ _null_ _null_ _null_ pg_indexes_size _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index affcc01..feaf2bd 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -473,6 +473,7 @@ extern Datum pg_relation_size(PG_FUNCTION_ARGS);
 extern Datum pg_total_relation_size(PG_FUNCTION_ARGS);
 extern Datum pg_size_pretty(PG_FUNCTION_ARGS);
 extern Datum pg_size_pretty_numeric(PG_FUNCTION_ARGS);
+extern Datum pg_size_bytes(PG_FUNCTION_ARGS);
 extern Datum pg_table_size(PG_FUNCTION_ARGS);
 extern Datum pg_indexes_size(PG_FUNCTION_ARGS);
 extern Datum pg_relation_filenode(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index e1de1a5..e0bcb3a 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -357,6 +357,7 @@ extern int	NewGUCNestLevel(void);
 extern void AtEOXact_GUC(bool isCommit, int nestLevel);
 extern void BeginReportingGUCOptions(void);
 extern void ParseLongOption(const char *string, char **name, char **value);
+extern int parse_memory_unit(const char *unit, const char **hintmsg);
 extern bool parse_int(const char *value, int *result, int flags,
 		  const char **hintmsg);
 extern bool parse_real(const char *value, double *result);
diff --git a/src/test/regress/expected/dbsize.out b/src/test/regress/expected/dbsize.out
index aa513e7..990964b 100644
--- a/src/test/regress/expected/dbsize.out
+++ b/src/test/regress/expected/dbsize.out
@@ -35,3 +35,117 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
  1000000000000000.5 | 909 TB         | -909 TB
 (12 rows)
 
+SELECT pg_size_bytes(size) FROM
+   (VALUES('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+          ('1TB'), ('3000 TB')) x(size);
+  pg_size_bytes   
+------------------
+                1
+              123
+             1024
+          1048576
+       1073741824
+       1610612736
+    1099511627776
+ 3298534883328000
+(8 rows)
+
+-- case insensitive units are supported
+SELECT pg_size_bytes(size) FROM
+   (VALUES('1'), ('123bYteS'), ('1kb'), ('1mb'), (' 1 Gb'), ('1.5 gB '),
+          ('1tb'), ('3000 tb')) x(size);
+  pg_size_bytes   
+------------------
+                1
+              123
+             1024
+          1048576
+       1073741824
+       1610612736
+    1099511627776
+ 3298534883328000
+(8 rows)
+
+-- negative numbers are supported
+SELECT pg_size_bytes(size) FROM
+   (VALUES('-1'), ('-123bytes'), ('-1kb'), ('-1mb'), (' -1 Gb'), ('-1.5 gB '),
+          ('-1tb'), ('-3000 TB')) x(size);
+   pg_size_bytes   
+-------------------
+                -1
+              -123
+             -1024
+          -1048576
+       -1073741824
+       -1610612736
+    -1099511627776
+ -3298534883328000
+(8 rows)
+
+-- different cases with allowed points
+SELECT pg_size_bytes(size) FROM
+   (VALUES('-1.'), ('-1.kb'), ('-1. kb'), ('-0. gb'),
+          ('-.1'), ('-.1kb'), ('-.1 kb'), ('-.0 gb')) x(size);
+ pg_size_bytes 
+---------------
+            -1
+         -1024
+         -1024
+             0
+             0
+          -102
+          -102
+             0
+(8 rows)
+
+--should fail
+SELECT pg_size_bytes('1 AB');
+ERROR:  invalid size: "1 AB"
+DETAIL:  Invalid size unit "AB"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('1 AB A');
+ERROR:  invalid size: "1 AB A"
+DETAIL:  Invalid size unit "AB A"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('1 AB A    ');
+ERROR:  invalid size: "1 AB A    "
+DETAIL:  Invalid size unit "AB A"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('9223372036854775807.9');
+ERROR:  bigint out of range
+SELECT pg_size_bytes('1 byte');  -- the singular "byte" is not supported
+ERROR:  invalid size: "1 byte"
+DETAIL:  Invalid size unit "byte"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('');
+ERROR:  invalid size: ""
+DETAIL:  Empty value not allowed
+SELECT pg_size_bytes('..');
+ERROR:  invalid size: ".."
+SELECT pg_size_bytes('-.');
+ERROR:  invalid size: "-."
+SELECT pg_size_bytes('-.kb');
+ERROR:  invalid size: "-.kb"
+SELECT pg_size_bytes('-. kb');
+ERROR:  invalid size: "-. kb"
+SELECT pg_size_bytes('.+912');
+ERROR:  invalid size: ".+912"
+SELECT pg_size_bytes('+912+ kB');
+ERROR:  invalid size: "+912+ kB"
+SELECT pg_size_bytes('++123 kB');
+ERROR:  invalid size: "++123 kB"
+-- pg_size_bytes uses memory_unit_conversion_table.
+-- Currently only TB unit and less are supported.
+-- When supported units are increase, update related documentation too.
+SELECT pg_size_bytes('1PB');
+ERROR:  invalid size: "1PB"
+DETAIL:  Invalid size unit "PB"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('1EB');
+ERROR:  invalid size: "1EB"
+DETAIL:  Invalid size unit "EB"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
+SELECT pg_size_bytes('1ZB');
+ERROR:  invalid size: "1ZB"
+DETAIL:  Invalid size unit "ZB"
+HINT:  Valid units for this parameter are "kB", "MB", "GB", and "TB".
diff --git a/src/test/regress/sql/dbsize.sql b/src/test/regress/sql/dbsize.sql
index c118090..aa635b8 100644
--- a/src/test/regress/sql/dbsize.sql
+++ b/src/test/regress/sql/dbsize.sql
@@ -10,3 +10,46 @@ SELECT size, pg_size_pretty(size), pg_size_pretty(-1 * size) FROM
             (10.5::numeric), (1000.5::numeric), (1000000.5::numeric),
             (1000000000.5::numeric), (1000000000000.5::numeric),
             (1000000000000000.5::numeric)) x(size);
+
+SELECT pg_size_bytes(size) FROM
+   (VALUES('1'), ('123bytes'), ('1kB'), ('1MB'), (' 1 GB'), ('1.5 GB '),
+          ('1TB'), ('3000 TB')) x(size);
+
+-- case insensitive units are supported
+SELECT pg_size_bytes(size) FROM
+   (VALUES('1'), ('123bYteS'), ('1kb'), ('1mb'), (' 1 Gb'), ('1.5 gB '),
+          ('1tb'), ('3000 tb')) x(size);
+
+-- negative numbers are supported
+SELECT pg_size_bytes(size) FROM
+   (VALUES('-1'), ('-123bytes'), ('-1kb'), ('-1mb'), (' -1 Gb'), ('-1.5 gB '),
+          ('-1tb'), ('-3000 TB')) x(size);
+
+-- different cases with allowed points
+SELECT pg_size_bytes(size) FROM
+   (VALUES('-1.'), ('-1.kb'), ('-1. kb'), ('-0. gb'),
+          ('-.1'), ('-.1kb'), ('-.1 kb'), ('-.0 gb')) x(size);
+
+--should fail
+SELECT pg_size_bytes('1 AB');
+SELECT pg_size_bytes('1 AB A');
+SELECT pg_size_bytes('1 AB A    ');
+SELECT pg_size_bytes('9223372036854775807.9');
+SELECT pg_size_bytes('1 byte');  -- the singular "byte" is not supported
+SELECT pg_size_bytes('');
+
+SELECT pg_size_bytes('..');
+SELECT pg_size_bytes('-.');
+SELECT pg_size_bytes('-.kb');
+SELECT pg_size_bytes('-. kb');
+
+SELECT pg_size_bytes('.+912');
+SELECT pg_size_bytes('+912+ kB');
+SELECT pg_size_bytes('++123 kB');
+
+-- pg_size_bytes uses memory_unit_conversion_table.
+-- Currently only TB unit and less are supported.
+-- When supported units are increase, update related documentation too.
+SELECT pg_size_bytes('1PB');
+SELECT pg_size_bytes('1EB');
+SELECT pg_size_bytes('1ZB');
