You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中null值与空值分别占用多少存储空间?

NULL值存储空间占用规则详解

网上流传的「NULL值仅占用1bit存储空间」的说法只对了一半,这个描述只覆盖了NULL值的标记开销,没有考虑不同存储引擎、行格式、字段类型对应的实际占用差异,具体规则可以拆解为以下几部分:

  • 基础标记位开销
    所有支持NULL字段定义的关系型数据库,都会在每行数据的头部预留一块**NULL位图(Null Bitmap)**区域:只要建表时把字段设置为允许为NULL,不管这一行里这个字段实际存的是不是NULL,都会在这个位图里占1个bit的位置,用来标记当前行对应字段是否为NULL。这就是网上1bit说法的来源。
    需要注意的是,这个位图是按整行分配、按字节对齐的,不是给每个NULL值单独开辟空间:比如一行里一共有7个允许为NULL的字段,NULL位图总共占1字节;如果有9个允许为NULL的字段,NULL位图就会占2字节,不会真的只留9bit的零散空间。
  • 不同场景下NULL值的实际空间占用
    • 主流行式数据库默认行格式(比如InnoDB的DYNAMIC/COMPRESSED行格式、PostgreSQL默认行格式)场景下:
      定长类型字段(如INT、CHAR(10)、DATETIME)存NULL时,除了位图里的1bit标记,不会占用该字段对应的固定长度存储空间;变长类型字段(如VARCHAR、TEXT、BLOB)存NULL时,除了1bit标记,既不会占用内容存储区,也不会分配变长字段必备的长度标记位,没有额外空间开销。
    • 老旧行格式/存储引擎(比如InnoDB的REDUNDANT行格式、旧版本MyISAM引擎)场景下:
      定长字段存NULL时,依然会占满该类型对应的固定长度空间——比如INT字段存NULL照样占4字节,加上位图的1bit标记,总开销远大于1bit。这种设计是为了让每个字段的行内偏移量固定,简化行数据定位逻辑,不用额外做偏移量计算。
    • 列式存储引擎/格式(比如ClickHouse、Parquet、ORC)场景下:
      NULL值的标记是按列块单独存储的,会结合游程编码、位图压缩做优化,如果一个列块里NULL值占比很高,平均每个NULL的标记开销远小于1bit;极端情况下整列全为NULL时,几乎不占用实际数据存储空间。
  • 常见认知误区
    别把NULL和其他“空值类”的非NULL值搞混:比如空字符串''、数值0、无效时间戳0000-00-00都属于非NULL值,不会触发NULL位图的标记,会正常占用对应类型的存储空间。举个例子,VARCHAR类型存空字符串,至少要占1字节的长度标记位(用来标记内容长度为0),和NULL的存储开销完全不是一个量级。

内容的提问来源于stack exchange,提问作者Abhishek Bansal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:48:15