我有一个有 7 列的表,其中 5 列将为空。int
我将在、text
、date
、boolean
和money
数据类型上有一个空列。该表将包含数百万行,其中包含许多空值。恐怕空值会占用空间。
另外,你知道 Postgres 是否索引空值吗?我想防止它索引空值。
我有一个有 7 列的表,其中 5 列将为空。int
我将在、text
、date
、boolean
和money
数据类型上有一个空列。该表将包含数百万行,其中包含许多空值。恐怕空值会占用空间。
另外,你知道 Postgres 是否索引空值吗?我想防止它索引空值。
基本上,值在 NULL 位图中NULL
占据1 位。但这并不是那么简单。
空位图(每行)仅在该行中至少有一列包含NULL
值时才分配。这可能会在具有 9 列或更多列的表中导致看似自相矛盾的效果:将第一个NULL
值分配给列可能会比向其写入值占用更多的磁盘空间。相反,从行中删除最后一个 NULL 值也会删除 NULL 位图。
物理上,初始空位图在(23 字节)和实际列数据或行(如果您仍然应该使用它)之间占用1 个字节- 它始终以(通常为8 字节)的倍数开始。这会留下1 个字节的填充,供初始空位图使用。HeapTupleHeader
OID
MAXALIGN
实际上,对于 8 列或更少列的表(包括已删除但尚未清除的列) , NULL 存储是完全免费的。
之后,为接下来的列(通常为 64)MAXALIGN
分配另一个字节(通常为 8个)。MAXALIGN * 8
等等。
手册中和这些相关问题下的更多详细信息:
了解数据类型的对齐填充后,您可以进一步优化存储:
但是,您可以节省大量空间的情况很少见。通常不值得努力。
@Daniel已经涵盖了对索引大小的影响。
请注意,删除的列(尽管现在不可见)保留在系统目录中,直到重新创建表。那些僵尸可以强制分配(放大的)NULL 位图。看:
值是否NULL
到达索引至少取决于索引的类型。基本上,对于和索引类型,这将是YES,对于,对于索引类型,这似乎是 YES 或 NO ,具体取决于 PostgreSQL 版本。btree
gist
hash
gin
表格中曾经有一个布尔列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)
这将占用更少的空间,但这是否有助于查询的性能取决于这些查询。
我相信每个人都会在该行的位图中使用一个位。见这里:http ://www.postgresql.org/docs/9.0/static/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE