Maximum Columns per Table 250 – 1600 depending on column types
那么,根据列类型,我如何确定最大列?
Page Layout
.
>您可能知道,默认Postgresql块大小为8kB(8192字节).您还应该知道,在Postgresql表行中不能跨越块边界.
这已经为您提供了8192字节的大小限制.但…
>查看上面的页面布局,还有PageHeader的开销,在当前的Postgresql版本上是24字节.所以,我们剩下8168个字节.但…
>还有ItemIdData,它是指针数组.假设我们在此页面上只有1条记录,因此该条目仅占用4个字节(1个条目).所以,我们剩下8164个字节.但…
>每条记录还有一个RecordHeader,已知占用23个字节.所以,我们剩下8141个字节.但…
>在RecordHeader之后还有一个NULL位图,但我们假设我们已经使用NOT NULL约束定义了所有列.所以,这里有8141个字节.但…
>有这样的事情 – MAXALIGN.看看at this wonderful answer by Erwin.
我们这里说的是24 4 23 = 51.
现在一切都取决于系统上此参数的值.
如果它是32位,那么offset将与52对齐,这意味着我们又浪费了一个字节.
如果它是64位,那么offset将对齐到54,这意味着我们浪费了3个字节.
我的系统是64位的,所以我假设我们剩下8138个字节.
所以这就是我们留下的空间.现在一切都取决于我们选择的列的类型以及它们如何坐在一起(记住MAXALIGN的事情).让我们为所有列取int2.简单的计算表明我们应该能够挤入这种类型的4069列:所有列都是NOT NULL且属于同一类型.
简单的脚本:
echo "CREATE TABLE tab4069 (" > tab4069.sql for num in $(seq -f "%04g" 1 4069); do echo " col$num int2 not null," >> tab4069.sql; done echo " PRIMARY KEY (col0001) );" >> tab4069.sql
不过,如果您尝试创建此表,则会遇到错误:
ERROR: tables can have at most 1600 columns
有点搜索指向the similar question,并且在查看the sources of the PostgreSQL时,我们得到答案(第23到47行):
/* * MaxTupleAttributeNumber limits the number of (user) columns in a tuple. * The key limit on this value is that the size of the fixed overhead for * a tuple,plus the size of the null-values bitmap (at 1 bit per column),* plus MAXALIGN alignment,must fit into t_hoff which is uint8. On most * machines the upper limit without making t_hoff wider would be a little * over 1700. We use round numbers here and for MaxHeapAttributeNumber * so that alterations in HeapTupleHeaderData layout won't change the * supported max number of columns. */ #define MaxTupleAttributeNumber 1664 /* 8 * 208 */ /* * MaxHeapAttributeNumber limits the number of (user) columns in a table. * This should be somewhat less than MaxTupleAttributeNumber. It must be * at least one less,else we will fail to do UPDATEs on a maximal-width * table (because UPDATE has to form working tuples that include CTID). * In practice we want some additional daylight so that we can gracefully * support operations that add hidden "resjunk" columns,for example * SELECT * FROM wide_table ORDER BY foo,bar,baz. * In any case,depending on column data types you will likely be running * into the disk-block-based limit on overall tuple size if you have more * than a thousand or so columns. TOAST won't help. */ #define MaxHeapAttributeNumber 1600 /* 8 * 200 */
有许多可变长度类型,它们在实际值中执行1或4个字节的固定开销.这意味着你永远不会事先知道记录在获得实际价值之前需要多少空间.当然,这些值可以通过the TOAST单独存储,但通常是较大的值(总长度为2kB).
请查阅official docs on types以找出用于固定长度类型的空间.您还可以检查任何类型的pg_column_size()
函数的输出,尤其是对于复杂的类型,如数组,hstore或jsonb.
如果您想要对此主题有更完整的愿景,您将不得不深入了解更多细节.