我有一个包含7列的表,其中5列将为null。我将在int
,text
,date
,boolean
和money
数据类型上显示空列。该表将包含数百万行,其中包含许多空值。我担心空值会占用空间。
另外,你知道Postgres索引空值吗?我想阻止它索引空值。
答案 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
值是否到达索引或至少取决于索引的类型。
基本上,btree
和gist
索引类型是,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