在PostgreSQL中,可空列是否占用额外的空间?
我有一个7列的表,其中5个将是空的。 我会在int
, text
, date
, boolean
和money
数据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。 基本上,对于btree
和gist
索引types来说是YES ,对于hash
来说是NO,对于依赖于PostgreSQL版本的gin
索引types,似乎是YES或NO 。
amindexnulls
在pg_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