From 8272e103cb84fec65ba5d266582ecfb6ff386676 Mon Sep 17 00:00:00 2001
From: "dgrowley@gmail.com" <dgrowley@gmail.com>
Date: Wed, 31 Oct 2018 01:45:41 +1300
Subject: [PATCH v3] Add documentation section appendix detailing some
 limitations of PostgreSQL

---
 doc/src/sgml/dblimits.sgml | 125 +++++++++++++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml |   1 +
 doc/src/sgml/postgres.sgml |   1 +
 3 files changed, 127 insertions(+)
 create mode 100644 doc/src/sgml/dblimits.sgml

diff --git a/doc/src/sgml/dblimits.sgml b/doc/src/sgml/dblimits.sgml
new file mode 100644
index 0000000000..05634233ad
--- /dev/null
+++ b/doc/src/sgml/dblimits.sgml
@@ -0,0 +1,125 @@
+<!-- doc/src/sgml/dblimits.sgml -->
+
+<appendix id="dblimits">
+ <title>Database Limitations</title>
+
+ <para>
+ The following table describes the limits of <productname>PostgreSQL</productname>
+ </para>
+
+<table id="dblimits-table">
+ <title><productname>PostgreSQL</productname> limitations</title>
+ <tgroup cols="3">
+  <thead>
+   <row>
+    <entry>Item</entry>
+    <entry>Limit</entry>
+    <entry>Comment</entry>
+   </row>
+  </thead>
+
+  <tbody>
+     <row>
+      <entry>Maximum Database Size</entry>
+      <entry>Unlimited</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Number of Databases</entry>
+      <entry>Unlimited</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Relation Size</entry>
+      <entry>32 TB</entry>
+      <entry>Limited to 2^32 - 1 pages per relation.</entry>
+     </row>
+
+     <row>
+      <entry>Maximum Columns per Table</entry>
+      <entry>1600</entry>
+      <entry>Further limited by tuple size fitting on a single page. See note below</entry>
+     </row>
+
+     <row>
+      <entry>Maximum Field Size</entry>
+      <entry>1 GB</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Identifier Length</entry>
+      <entry>63 characters</entry>
+      <entry>Can be increased by recompiling <productname>PostgreSQL</productname></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Rows per Table</entry>
+      <entry>Unlimited</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Indexes per Table</entry>
+      <entry>Unlimited</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Indexed Columns</entry>
+      <entry>32</entry>
+      <entry>Can be increased by recompiling <productname>PostgreSQL</productname>. Limit includes
+      any <literal>INCLUDE</literal> columns</entry>
+     </row>
+
+     <row>
+      <entry>Maximum Partition Keys</entry>
+      <entry>32</entry>
+      <entry>Can be increased by recompiling <productname>PostgreSQL</productname></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Relations per Database</entry>
+      <entry>Unlimited</entry>
+      <entry></entry>
+     </row>
+
+     <row>
+      <entry>Maximum Partitions per Partitioned Relations</entry>
+      <entry>268,435,456</entry> <!-- limited by 1GB palloc limit for oids field in PartitionDesc -->
+      <entry>May be increased by using sub-partitioning</entry>
+     </row>
+     
+  </tbody>
+ </tgroup>
+</table>
+
+  <note>
+    <para>
+     The maximum number of columns for a table is further reduced as the tuple
+     being stored must fit on a single heap page.  Variable length fields such
+     as <literal>TEXT</literal>, <literal>VARCHAR</literal> and
+     <literal>CHAR</literal> can have their values stored out of line in the
+     table's TOAST table when the values are large enough to require it.  Only
+     an 18 byte pointer must remain inside the tuple in the table's heap.  For
+     shorter length variable length fields either a 4 byte or 1 byte field
+     header is used, and the value is stored inside the heap tuple.  Often this
+     can mean the actual maximum number of columns that you can store inside a
+     table is further reduced as the tuple can become too large to fit inside a
+     single 8192 byte heap page.  For example, excluding the tuple header, a
+     tuple made up of 1600 INT columns would consume 6400 bytes and could be
+     stored in a heap page, but a tuple of 1600 BIGINT columns would consume
+     12800 bytes, therefore not fit inside a heap page.
+    </para>
+
+    <para>
+     Columns which have been dropped from the table also contribute to the
+     maximum column limit, although the dropped column values for newly created
+     tuples are internally marked as NULL in the tuples null bitmap, which does
+     occupy space.
+    </para>
+  </note>
+
+</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 48ac14a838..be8d3d6800 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -185,6 +185,7 @@
 <!ENTITY release-old    SYSTEM "release-old.sgml">
 
 <!ENTITY acronyms   SYSTEM "acronyms.sgml">
+<!ENTITY dblimits   SYSTEM "dblimits.sgml">
 
 <!ENTITY features-supported   SYSTEM "features-supported.sgml">
 <!ENTITY features-unsupported SYSTEM "features-unsupported.sgml">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 0070603fc3..369eca61cf 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -268,6 +268,7 @@
   <title>Appendixes</title>
 
   &errcodes;
+  &dblimits;
   &datetime;
   &keywords;
   &features;
-- 
2.16.2.windows.1

