From efed1dce93520bf33018021e5a85c39ace395b66 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 v4] Add documentation section appendix detailing some
 limitations of PostgreSQL

---
 doc/src/sgml/dblimits.sgml | 132 +++++++++++++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml |   1 +
 doc/src/sgml/postgres.sgml |   1 +
 3 files changed, 134 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..de8a5d35bd
--- /dev/null
+++ b/doc/src/sgml/dblimits.sgml
@@ -0,0 +1,132 @@
+<!-- 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>
+      <!-- limited by 1GB palloc limit for oids field in PartitionDesc -->
+      <entry>268,435,456</entry>
+      <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 <literal>INT</literal> columns
+     would consume 6400 bytes and could be stored in a heap page, but a tuple
+     of 1600 <literal>BIGINT</literal> 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 tuple's 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

