为 ARRAY[] 列的默认值选择 NULL 与空数组 {} 时是否会影响磁盘空间?

Gol*_*Jer 2 postgresql storage

我的直觉是NULL将比{}用作ARRAY[]PostgreSQL 中列的默认值时占用的空间更少。

我对么?

AMG*_*AMG 5

你为什么不自己检查?

1 - 创建 2 个表:

CREATE TABLE TABLE1 (column1 int not null, column2 int[] default {});
CREATE TABLE TABLE2 (column1 int not null, column2 int[]);
Run Code Online (Sandbox Code Playgroud)

2 - 为每个表制作 100 万次插入:

insert into TABLE1(colulmn1) SELECT generate_series(1,1000000);
insert into TABLE2(colulmn1) SELECT generate_series(1,1000000);
Run Code Online (Sandbox Code Playgroud)

3 - 使用此查询检查表磁盘使用情况:(在https://wiki.postgresql.org/wiki/Disk_Usage 中找到)

SELECT *, pg_size_pretty(total_bytes) AS total
    , pg_size_pretty(index_bytes) AS INDEX
    , pg_size_pretty(toast_bytes) AS toast
    , pg_size_pretty(table_bytes) AS TABLE
  FROM (
  SELECT *, total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes FROM (
      SELECT c.oid,nspname AS table_schema, relname AS TABLE_NAME
              , c.reltuples AS row_estimate
              , pg_total_relation_size(c.oid) AS total_bytes
              , pg_indexes_size(c.oid) AS index_bytes
              , pg_total_relation_size(reltoastrelid) AS toast_bytes
          FROM pg_class c
          LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
          WHERE relkind = 'r' and relname in ('TABLE1','TABLE2')
  ) a
) a;
Run Code Online (Sandbox Code Playgroud)

4 - 只要你确信,就放下桌子:

DROP TABLE TABLE1;
DROP TABLE TABLE2;
Run Code Online (Sandbox Code Playgroud)


Gol*_*Jer 5

AMG 的回答效果很好,但它有一些错误/拼写/大小写错误。我尝试编辑它,但编辑被拒绝。

这是他的建议清理(可直接复制/粘贴到 SQL 编辑器中)和结果。

1 - 创建 2 个表:

CREATE TABLE TABLE_WITH_NULL (col1 int not null, col2 int[]);
CREATE TABLE TABLE_WITH_DEFAULT (col1 int not null, col2 int[] default '{}'::int[]);
Run Code Online (Sandbox Code Playgroud)


2 - 为每个表制作 100 万次插入:

INSERT INTO TABLE_WITH_NULL(col1) SELECT generate_series(1,1000000);
INSERT INTO TABLE_WITH_DEFAULT(col1) SELECT generate_series(1,1000000);
Run Code Online (Sandbox Code Playgroud)


3 - 使用此查询检查表磁盘使用情况:(在https://wiki.postgresql.org/wiki/Disk_Usage 中找到)

SELECT *, pg_size_pretty(total_bytes) AS total
    , pg_size_pretty(index_bytes) AS INDEX
    , pg_size_pretty(toast_bytes) AS toast
    , pg_size_pretty(table_bytes) AS TABLE
  FROM (
  SELECT *, total_bytes-index_bytes-COALESCE(toast_bytes,0) AS table_bytes FROM (
      SELECT c.oid,nspname AS table_schema, relname AS TABLE_NAME
              , c.reltuples AS row_estimate
              , pg_total_relation_size(c.oid) AS total_bytes
              , pg_indexes_size(c.oid) AS index_bytes
              , pg_total_relation_size(reltoastrelid) AS toast_bytes
          FROM pg_class c
          LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
          WHERE relkind = 'r' and relname in ('table_with_null','table_with_default')
  ) a
) a;
Run Code Online (Sandbox Code Playgroud)


4 - 有了答案,放下表格:

DROP TABLE TABLE_WITH_NULL;
DROP TABLE TABLE_WITH_DEFAULT;
Run Code Online (Sandbox Code Playgroud)


这是我的结果。(PostgreSQL 10.5)......

结果

所以这个问题的直接答案是空数组{}NULL.

进一步阅读:大表中完全空的列如何影响性能?