在PostgreSQL中,可空列是否占用额外的空间?

我有一个7列的表,其中5个将是空的。 我会在inttextdatebooleanmoney数据types上有一个空列。 这个表格将包含数百万行与许多空值。 恐怕空值将占据空间。

另外,你知道Postgres是否索引空值? 我想阻止它索引空值。

基本上, NULL值占用NULL位图中的1位 。 但事情并不那么简单。

如果该行中至less有一列保存NULL值,则空位图 (每行)仅在那里。 这可能会导致在具有9列或更多列的表中产生悖论效应:将第一个NULL值分配给列可能占用磁盘空间而不是写入数值。 相反,在最后一列变为非空的情况下,该行的空位图被删除。

从物理上来说,初始的null位图在HeapTupleHeader (23字节)和实际的列数据之间占用1个字节 ,或者在行的OID (如果你仍然在使用它)之间占用1个字节总是MAXALIGN (通常是8个字节 )开始。 这会留下初始空位图使用的1个字节的填充。

实际上, 对于8列或更less的表,NULL存储是完全免费的
之后,另一个MAXALIGN字节(通常为8)被分配给下一个MAXALIGN * 8列(通常为64)。 等等。

手册中以及这些相关问题的更多细节:

  • 使用postgresql DB需要多less磁盘空间来存储NULL值?
  • 在PostgreSQL中不使用NULL仍然在头中使用NULL位图?
  • 我可以在Heroku的5 MB PostgreSQL中存储多less条logging?

一旦你理解了数据types的alignment填充,你可以进一步优化存储:

  • 计算和保存PostgreSQL中的空间

但是这种情况很less,可以节省大量的空间。 通常这是不值得的。

@丹尼尔已经涵盖了对索引大小的影响。

NULL值是否到达索引至less取决于索引的types。 基本上,对于btreegist索引types来说是YES ,对于hash来说是NO,对于依赖于PostgreSQL版本的gin索引types,似乎是YES或NO

amindexnullspg_catalog.pg_am表中有一个布尔列的amindexnulls ,它载有这些信息,但是它在9.1中没有了。 可能是因为指标在PG改进中变得更加复杂。

在你的数据的特定情况下,最好的方法是使用pg_relation_size('index_name')函数,在完全为NULL的内容和完全不为NULL的情况下,用你的确切的PG版本,确切的数据types来测量索引的大小差异,确切的索引types和定义。 而且知道这些参数的未来变化可能会改变结果。

但是在任何情况下,如果你只是想避免索引NULL,总是可以创build一个部分索引:

 CREATE INDEX partial_idx(col) ON table WHERE (col is not null) 

这将占用较less的空间,但这是否有助于查询的性能取决于这些查询。

我相信每个人都会使用该位图中的一个位。 看到这里: http : //www.postgresql.org/docs/9.0/static/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE