可以为空的列占用PostgreSQL中的额外空间吗?

时间:2012-08-27 16:23:06

标签: postgresql database-design indexing null

我有一个包含7列的表,其中5列将为null。我将在inttextdatebooleanmoney数据类型上显示空列。该表将包含数百万行,其中包含许多空值。我担心空值会占用空间。

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

3 个答案:

答案 0 :(得分:41)

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

null位图(每行)仅在该行中至少有一列包含NULL值时才存在。这可能会导致具有9列或更多列的表中的悖论效应:将第一个NULL值分配给列可能会占用磁盘上的空间,而不是为其写入值。相反,在最后一列变为非空的情况下,将删除该行的空位图。

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

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

更多详情in the manual以及这些相关问题:

了解数据类型的对齐填充后,您可以进一步优化存储:

但是这种情况很少见,你可以节省大量的空间。通常,这不值得努力。

@Daniel已涵盖对索引大小的影响。

答案 1 :(得分:11)

NULL值是否到达索引或至少取决于索引的类型。 基本上,btreegist索引类型hash ,似乎是或{NO 用于gin索引类型,具体取决于PostgreSQL版本。

amindexnulls表中曾经有一个带有该信息的布尔列pg_catalog.pg_am,但它在9.1中消失了。可能是因为指数在PG改进中变得更加复杂。

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

但无论如何,如果你“只是”想要避免索引NULL,那么总是可以创建一个部分索引:

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

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

答案 2 :(得分:2)

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