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

Luk*_*101 26 postgresql indexing null database-design

我有一个包含7列的表,其中5列将为null.我将有一个空列int,text,date,boolean,和money数据类型.该表将包含数百万行,其中包含许多空值.我担心空值会占用空间.

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

Erw*_*ter 42

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

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

物理上,初始空位图占用(23字节)和实际列数据之间的1个HeapTupleHeader字节或行OID(如果您仍应使用它) - 它始终MAXALIGN(通常为8个字节)的倍数开始.这留下了初始空位图使用的1字节填充.

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

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

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

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

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


Dan*_*ité 13

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

曾经有一个布尔值列amindexnullspg_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)
Run Code Online (Sandbox Code Playgroud)

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

  • +1洞察力.对于部分索引,请务必注意,如果查询计划程序可以验证查询中是否包含条件,则它们只能由查询计划程序使用.查询规划器很聪明,但在这方面无法解决复杂的逻辑.或多或少地逐字匹配`WHERE`子句以确保可以使用索引(可能`AND`-ed with more conditions).[手册中的详细信息](http://www.postgresql.org/docs/current/interactive/indexes-partial.html). (7认同)