数据库索引是不是与列数据占用相同数量的磁盘空间?

Posted

技术标签:

【中文标题】数据库索引是不是与列数据占用相同数量的磁盘空间?【英文标题】:Do DB indexes take same amount of disc space as column data?数据库索引是否与列数据占用相同数量的磁盘空间? 【发布时间】:2011-01-24 01:03:44 【问题描述】:

如果我有一个包含数据的表列并在该列上创建索引,该索引会占用与列本身相同的磁盘空间吗?

我很感兴趣,因为我想了解 b 树是否实际上将列数据的副本保存在叶节点中,或者它们是否以某种方式指向它?

很抱歉,如果这是“Java 会取代 XML 吗?”好问题。

更新:

使用单个 GUID 列创建了一个没有索引的表,添加了 1M 行 - 26MB

具有主键(聚集索引)的同一张表 - 25MB(甚至更小!),索引大小 - 176KB

具有唯一键的同一张表(非聚集索引) - 26MB,索引大小 - 27MB

因此,只有非聚集索引占用的空间与数据本身一样多。

所有测量均在 SQL Server 2005 中完成

【问题讨论】:

【参考方案1】:

从article 来看,事实上,它至少会占用与列中的数据相同的空间(无论如何,在 PostgreSQL 中)。 这篇文章还提出了一种减少磁盘和内存使用的策略。

检查自己的方法是使用例如derby DB,创建一个包含一百万行和一列的表,检查它的大小,在列上创建一个索引并再次检查它的大小。如果您花 10-15 分钟这样做,请告诉我们结果。 :)

【讨论】:

我认为这取决于索引的行数。例如,如果一个表包含 30 行但只有 2 行是可搜索的,那么这些特定行只需要 2 个 b 树。这就是为什么索引不会用于查找的行很重要。 @Evan:我不确定我是否遵循...您的意思是“取决于索引的列数”吗? 是的...我说列不是我;) 在这种情况下,当然,默认情况下索引不是“好”:它们是有代价的,无论是在 RAM 和磁盘(索引存储)方面还是在 CPU 周期方面(C- UD 操作需要更新索引)。 没错。因此,如果您有一个像 FIFO 任务队列这样的高吞吐量表,那么对任何列进行索引都会对性能产生负面影响。即使在写入率较低的表(例如持久数据存储)上,它也会节省一些时间/资源来排除您只希望在结果中可见的列。通常,外键几乎总是索引的好主意,因为连接上的每个额外外键查找都会向该查询添加额外的表搜索。联接会很快变得昂贵,这就是许多新的非 SQL 数据架构不允许它们的原因。【参考方案2】:

B-Tree 指向表中的行,但 B-Tree 本身仍然占用一些磁盘空间。

一些数据库,有嵌入主索引数据的特殊表。在 Oracle 中,它被称为 IOT——索引组织表。

常规表中的每一行都可以通过 B-Tree 用来识别行的内部 ID(但它是特定于数据库的)来识别。在 Oracle 中,它被称为 rowid,看起来像 AAAAECAABAAAAgiAAA :)

如果我有一个包含数据的表格列,并且 在该列上创建索引,将 索引占用相同数量的磁盘 空间作为列本身?

在基本的 B 树中,节点数与列中的项目数相同。

考虑1,2,3,4

    1 
  / 
2
   \ 3 
      \ 4

确切的空间还是会有点不同(索引可能有点大,因为它需要存储节点之间的链接,它可能没有完美平衡等等),我猜数据库可以使用优化来压缩部分的指数。但是索引和列数据的数量级应该是一致的。

【讨论】:

它是一种聚集索引吗? 我认为聚集索引存储实际数据,因为聚集索引的排序方式与数据相同。 是的,IOT 类似于聚集索引。表中的行在物理上重新排序。查询数据性能出色,但插入速度较慢。【参考方案3】:

我几乎可以肯定它完全依赖于数据库,但通常 – 是的,它们占用了额外的空间。发生这种情况有两个原因:

    这样你就可以利用事实 BTREE叶子中的数据被排序;

    您获得了查找速度优势,因为 你不必回头寻找 去取必要的东西。

PS 刚刚检查了我们的 mysql 服务器:对于 20GB 的表索引占用 10GB 空间:)

【讨论】:

以上是关于数据库索引是不是与列数据占用相同数量的磁盘空间?的主要内容,如果未能解决你的问题,请参考以下文章

为什么 delete 表数据,磁盘空间却还是被占用

Elasticsearch性能调优之磁盘读写性能优化

磁盘格式化磁盘挂载手动增加swap空间

为什么 delete 表数据,磁盘空间却还是被占用

查看SqlServer某张表的物理空间占用情况

对于mysql数据库优化的见解