【问题标题】:Space used by nulls in database数据库中空值使用的空间
【发布时间】:2010-10-08 01:37:39
【问题描述】:

如果一列为空,是否会影响该列使用的空间? 列定义使用的空间是否固定? 这是否因数据库而异。 (我主要对 SQL Server 2000 感兴趣。)

澄清: 这个问题与列“可为空”时发生的情况无关(正如 Kritsen 和 gbn 指出的那样,这又要花一点钱)。问题是,当列实际上为空(在某些特定行中)时是否有任何保存。

...

Cadaeic 为 SQL Server 提供了答案,在 2008 版之前似乎在 SQL Server 中没有节省,而根据 Quassnoi 的说法,如果空列在最后,您可以在 Oracle 中节省。感谢您的回答,他们都很有帮助。

【问题讨论】:

    标签: sql sql-server database null


    【解决方案1】:

    SQL Server 有一个位来指示 NULL。如果列定义为 NOT NULL,则不使用该位

    VARCHAR 使用可变长度来存储数据(因此有指示实际数据长度的开销),而 CHAR 是固定宽度。

    因此,在此基础上,CHAR(1) NOT NULL 比 VARCHAR(1) NOT NULL “短”,因为 VARCHAR 需要长度指示符,而 CHAR 将始终只使用一个字节。

    编辑:请注意,具有允许 NULL 的 BIT 字段需要两个位来存储它!我经常看到没有考虑这个的BIT字段,不需要存储NULL但没有设置为NOT NULL所以无意中浪费了一点

    【讨论】:

      【解决方案2】:

      它存储在位图中,而不是作为列值。

      示例:一个名为 middle name 的可为空的 varchar 列

      • 第 1 行,“bob”存储为偏移量,3 个字节为 bob,2 个字节为“bob”长度
      • 第 2 行,NULL 行不是像“bob”那样存储为值,而是在行标题中

      除非你有一个非常小的表,比如单列 char(1),否则效率更高

      Link 1 Link 2

      【讨论】:

        【解决方案3】:

        Oracle 中,它取决于列的类型及其在行中的位置。

        如果NULL 列在行的最后,那么它们根本不占用任何空间。 Oracle 将总行大小添加到每一行,不适合的所有内容都被视为NULL

        如果在NULL 列之后有一些非NULL 数据,则将NULL 存储为0xFF 的单个字节(即NULL 类型)。

        空的VARCHAR2 等同于NULL。如果您测试从SELECT 列表返回的文字NULL 的类型,它将为您提供VARCHAR2(0)

        【讨论】:

          【解决方案4】:

          如果您使用 varchar 或 nvarchar 数据类型,则行使用的字节数会更少。这就是为什么您可以创建一个表(但不应该),它的潜在字节数多于实际存储在记录中的字节数。

          【讨论】:

            【解决方案5】:

            在列中存储 NULL 不会特别耗费或节省空间。对于定长数据,仍然保留整个空间。

            另一方面,可变长度数据只需要数据长度加上存储实际长度的开销。例如,一个 VARCHAR(n) 将使用 2 个字节的数据来表示实际长度,因此所需的存储空间始终为 n+2。

            另外,应该提到的是,如果 SET ANSI_PADDING ON,具有 NULL 值的 char(n) 将表现为 VARCHAR(n)。

            无论如何,在使用 SQL Server 2000 或 SQL Server 2005 时,您不会认识到存储 NULL 所节省的空间。SQL Server 2008 引入了稀疏列的概念,它可以为主要为 NULL 的列节省空间。

            【讨论】:

            • 如果零长度意味着空字符串,SQL 对空字符串使用什么?它们不一样。
            【解决方案6】:

            在 Oracle 11G 中,我也遇到了同样的情况。您无法通过将列设置为 NULL 来释放(检查 dba_segments)由现有行占用的空间,无论其位置如何,在中间或最后。

            UPDATE AUCORE_QA.SYSTEM_AUDIT_LOGS SET KEY=NULL;
            SELECT OWNER, TABLESPACE_NAME , SEGMENT_NAME,SEGMENT_TYPE,BYTES/1024/1024 MB
            FROM DBA_SEGMENTS 
            WHERE OWNER LIKE 'AUCORE_QA' AND SEGMENT_TYPE='TABLE' AND SEGMENT_NAME like '%AUDIT_LOG%'
            ORDER BY BYTES DESC;
            

            但是,我将列设置为“Nullable”,并且能够看到后续插入行的保存节省。

            ALTER TABLE SYSTEM_AUDIT_LOGS MODIFY KEY NULL;
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-12-26
              • 2013-04-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多