具有空值的 XML 字段的 table 会消耗一些 space?多少?

A table with a XML field with null value, consumes some space? How much?

是否有 "official benchmark" 或简单的经验法则来决定何时 space 或性能会受到影响?


我的 table 有很多简单的索引字段,

CREATE TABLE t (
  id serial PRIMARY KEY,
  name varchar(250) NOT NULL, 
  ...
  xcontent xml, -- the NULL use disk space?? cut performance?
  ...
  UNIQUE(name)
);

它是一种“sparse content”,许多 xcontent 值将是 NULL...因此,这些 XML NULL 会占用一些磁盘 space?


备注

我可以正常化,table t 现在将是 nt,

CREATE TABLE nt (
  id serial PRIMARY KEY,
  name varchar(250) NOT NULL, 
  ...
  UNIQUE(name)
);

CREATE TABLE nt2 (
  t_id int REFERENCES nt(id),
  xcontent xml NOT NULL
);

CREATE VIEW nt_full AS 
   SELECT nt.*, nt2.xcontnt FROM nt LEFT JOIN nt2 ON id=t_id;

那么,我需要这种复杂性吗?这个新的 table 安排将消耗更少的磁盘 spacess。

的使用
SELECT id, name FROM nt WHERE name>'john';      -- Q1A 
SELECT id, name FROM nt_full WHERE name>'john'; -- Q1B
SELECT id, name FROM t WHERE name>'john';       -- Q1C

SELECT id, xcontent FROM nt_full WHERE name>'john'; -- Q2A
SELECT id, xcontent FROM t WHERE name>'john';       -- Q2B

那么理论上Q1A vs Q1B vs Q1C的性能都是一样的?
Q2A 与 Q2B?

varchar 字段比内容多消耗 2 个字节。 所以如果你将它定义为 varchar(250) 并放入 10 个字符,它消耗 12 个字节 100 个字符占用 102 个字节 NULL 占用 2 个字节。没问题。

如果您在某些情况下需要存储大量 xml 数据 并最终使用(例如)blob 类型,你应该把它放在另一个 table 并保持您的主要 table 精简和快速

问题 "how much space does a null value take" 的答案是:根本没有 space - 至少不在 "data" 区域。

对于 table 中的每个可为空的列,行 header 中有一个 将列值标记为空(或非空) .因此,空值所采用的 "space" 已经存在于 header 行中 - 无论该列是否为空。

因此null "value" 不会在存储该行的数据块中占据任何space。

这在手册中有记载:http://www.postgresql.org/docs/current/static/storage-page-layout.html


如果超过一定的阈值(大约 2000 字节),Postgres 将不会在实际数据块中存储长字符串值(xml、varchar、text、json、...)。如果该值比该值长,它将存储在您实际数据的特殊存储区域 "away" 中。因此,将 table 拆分为两个具有 1:1 关系的 table 并不是你真正喜欢的。除非您要存储 lot 行(数亿),否则我怀疑您是否能够注意到差异 - 但这也取决于您的使用模式。

存储的数据"out-of-line"也会自动压缩。

关于这个的详细信息可以在手册中找到:http://www.postgresql.org/docs/current/static/storage-toast.html


单独 table 可能 是一个优势的一个原因是必要的 "vacuum" 清理。如果您将 XML 数据更新为 lot 但 table 的其余部分几乎没有变化,那么将其分成两个 table 可能会有所改善整体性能,因为 "XML table" 需要更少的 "maintenance" 而 "main" table 根本不会改变。