2012-08-27 43 views
18

我有一个7列的表,其中5个将为空。我将在int,text,date,booleanmoney数据类型上有空列。这张表格将包含数百万行有许多空值的行。恐怕空值将占据空间。在PostgreSQL中可空列是否占用额外的空间?

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

回答

34

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

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

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

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

更多细节in the manual并根据这些相关的问题:

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

但情况是罕见的,你可以节省大量的空间。通常这是不值得的。

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

+0

“对于8列或更少的表格,NULL存储空间是完全免费的。” - 如果只有一列保留为空,会怎么样?这意味着只有1个字节的空位图才会保存1位? – Dejell

+0

如果存在任何空值,并且有足够的字节来覆盖所有列,并且加上“MAXALIGN”的下一个倍数,则会出现空位图。 –

+0

谢谢欧文。仍然不确定 - 如果我没有任何空值,该怎么办?它仍然会在那里吗? (多对多表) – Dejell

11

NULL值是否到达索引或至少取决于索引的类型。 基本上,这将是YESbtreegist的索引类型,NOhash,它似乎YES或取决于PostgreSQL的版本NOgin索引类型。

pg_catalog.pg_am表中有一个布尔型列amindexnulls,它载有这些信息,但它已经在9.1中消失了。可能因为指标在PG改进中变得更加复杂。

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

但在任何情况下,如果你“只是”想避免索引空值,它总是可以创建一个部分索引:

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

这将需要更少的空间,但是否这是怎么回事帮助或不利用查询的性能取决于这些查询。

+7

+1有洞察力。对于部分索引,重要的是要注意,如果查询计划程序可以验证查询中是否包含该条件,那么它们只能被查询计划程序使用。查询规划器很聪明,但在这方面无法解决复杂的逻辑。或多或少逐字匹配'WHERE'子句以确保可以使用索引(可能有更多条件的“AND”编辑)。 [手册中的详细信息](http://www.postgresql.org/docs/current/interactive/indexes-partial.html)。 –

+0

很酷......谢谢您的深刻解答 – Luke101