AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 5455
Accepted
Jon of All Trades
Jon of All Trades
Asked: 2011-09-07 12:43:45 +0800 CST2011-09-07 12:43:45 +0800 CST 2011-09-07 12:43:45 +0800 CST

为什么一个表的数据空间可能会占用原始数据大小的 4 倍?

  • 772

我有一个包含 4.9 亿行和 55 GB 表空间的表,因此每行大约 167 个字节。该表包含三列: a VARCHAR(100)、 aDATETIME2(0)和 a SMALLINT。字段中文本的平均长度VARCHAR约为 21.5,因此原始数据应约为每行 32 个字节: 22+2 用于VARCHAR, 6 用于DATETIME2, 2 用于 16 位整数。

请注意,上面的空间只是数据,而不是索引。我正在使用属性下报告的值 | 存储 | 一般 | 数据空间。

当然必须有一些开销,但是每行 135 个字节似乎很多,尤其是对于一个大表。为什么会这样?有没有其他人见过类似的乘数?哪些因素会影响所需的额外空间量?

为了比较,我尝试创建一个包含两个INT字段和 1 M 行的表。所需的数据空间为 16.4 MB:每行 17 个字节,而原始数据为 8 个字节。另一个测试表使用与真实表相同的文本填充了一个INT和一个,每行使用 39 个字节(44 K 行),我预计会多出 28 个字节。VARCHAR(100)

所以生产表的开销要大得多。这是因为它更大吗?我希望索引大小大约为 N * log(N),但我不明白为什么实际数据所需的空间是非线性的。

提前感谢您的任何指点!

编辑:

列出的所有字段都是NOT NULL. VARCHAR真实表在字段和DATETIME2字段上按该顺序具有聚集的 PK 。对于这两个测试,第一个INT是(集群)PK。

如果重要:该表是 ping 结果的记录。这些字段是 URL、ping 日期/时间和延迟(以毫秒为单位)。数据会不断地添加,并且永远不会更新,但会定期删除数据以将其减少到每个 URL 每小时仅几条记录。

编辑:

这里的一个非常有趣的答案表明,对于具有大量读写的索引,重建可能没有好处。在我的情况下,消耗的空间是一个问题,但如果写入性能更重要,那么使用松弛的索引可能会更好。

sql-server-2008 disk-space
  • 3 3 个回答
  • 7357 Views

3 个回答

  • Voted
  1. Best Answer
    Mark Storey-Smith
    2011-09-08T13:20:45+08:002011-09-08T13:20:45+08:00

    在对原始问题的评论中进行了讨论后,在这种情况下,丢失的空间是由选择聚集键引起的,这导致了大量的碎片。

    在这些情况下,总是值得通过 sys.dm_db_index_physical_stats 检查碎片状态。

    编辑:在评论中更新

    平均页面密度(在重建聚集索引之前)为 24%,与原始问题完全吻合。这些页面只有 1/4 满,所以总大小是原始数据大小的 4 倍。

    • 11
  2. gbn
    2011-09-07T21:02:54+08:002011-09-07T21:02:54+08:00

    磁盘结构有开销:

    • 行标题
    • 空位图 + 指针
    • 可变长度列偏移
    • 行版本指针(可选)
    • ...

    取 2 x 4 字节 int 列,您有

    • 4字节行头
    • 指向 NULL 位图的 2 字节指针
    • 2 个 int 列 8 个字节
    • 3字节空位图

    哇 17 个字节!

    您可以对第二个测试表进行相同的操作,该表的开销与原始测试表一样:

    • 2 个字节用于可变长度列的计数
    • 每个可变长度列 2 个字节

    为什么有区别?另外(我不会链接到这些)

    • 您是否曾经重建索引以对其进行碎片整理?
    • 删除不回收空间
    • 如果您插入中间,数据页将拆分
    • 更新可能会导致前向指针(留下间隙)
    • 行溢出
    • 删除了没有索引重建或 DBCC CLEANTABLE 的 varchar 列
    • 堆或表(堆没有聚集索引 = 记录分散在各处)
    • RCSI 隔离级别(每行额外 14 字节)
    • varchar 中的尾随空格(SET ANSI_PADDING 默认为 ON)。使用 DATALENGTH 来检查,而不是 LEN
    • 运行 sp_spaceused 与@updateusage = 'true'
    • ...

    请参阅:SQL Server:如何创建一个填满 8 KB 页的表?

    从 SO:

    • https://stackoverflow.com/questions/4614771/sql-server-2008-how-much-space-does-this-occupy/4614799#4614799
    • https://stackoverflow.com/questions/3793022/how-to-come-to-limits-of-8060-bytes-per-row-and-8000-per-varchar-nvarchar-value/3793265#3793265
    • 7
  3. Aaron Bertrand
    2011-09-07T13:08:41+08:002011-09-07T13:08:41+08:00

    数据类型是否随时间变化?是否删除了可变长度列?索引是否经常进行碎片整理但从未重建?是否有很多行被删除或有很多可变长度列被显着更新?

    • 5

相关问题

  • 连接不同地理区域的数据库的最佳实践

  • 死锁的主要原因是什么,可以预防吗?

  • 我在索引上放了多少“填充”?

  • 是否有开发人员遵循数据库更改的“最佳实践”类型流程?

  • 从 SQL Server 2008 降级到 2005

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve