3

我发现创建触发器只是为了获取表的当前总行数而不执行 COUNT(*) FROM 表很麻烦。我在想他们为 Postgres 8.5 计划的索引组织表是否可以实现?

4

2 回答 2

3

我不会想到索引组织的表一定会更快地扫描以计算所有可见的元组。从逻辑上讲,它必须经过相同数量的数据,无论是组织成数据是在 b-tree 叶节点还是在现有的堆格式中。

目前,postgresql 索引只存储 [key,ctid] 对(本质上)。(一个 ctid 本质上是一个“rowid”——堆页号和元组行指针索引)所以你不能仅仅通过索引来计算表中的行数,因为你需要检查每个元组的 [xmin,xmax] - 这仅与数据一起保存在堆中。

您也可以将 [xmin,xmax] 放入索引中——对此的建议会不时出现。但这会使索引膨胀,并且为了有用,所有更新/删除都必须确保它们保持最新:这会导致问题,尤其是因为更新所涉及的工作现在已经扩大了一些倍通过表上的索引数。对于诸如 tsvector 上的重索引,或者基于昂贵的用户表达式的索引,这可能需要一段时间,并且在某些令人讨厌的情况下根本不起作用,行现在似乎在索引中是活动的,但在堆。这个练习的重点应该是允许数据库在可能的情况下完全依赖索引中的活跃度信息。

我想一种可能性是将索引标记为可选地具有 [xmin,xmax] - 例如仅以这种方式标记 pkey 索引。然后必须对计划者进行更改才能确定何时这是一个优势——这似乎是一项相当多的工作。

索引组织的表,如果它们像我相信它们在 Oracle(和 SQL Server,其中任何具有聚集索引的表基本上是索引组织的)中工作的那样工作,则通过将 [key,tuple] 存储在主键索引中来工作(并且大概[key,pkey] 在所有其他) - 没有 ctid,没有堆。所以“元组”将包含 [xmin,xmax,cminmax,natts,....] 等,您只需扫描索引即可满足“从表中选择计数(*)”。但这基本上与扫描堆上的元组相同——它们不会神奇地占用更少的空间,因为它们现在位于“索引”中。

AFAICT 索引组织表的主要原因是具有单个主键索引的小表将占用 1 页而不是 3 页,并且按主键进行索引扫描可能会更快一些。我似乎确实记得我为 IOT 提供的与 Oracle 相关的建议是,它们是为静态维度表设计的,而不是通用用途,部分原因是维护二级索引的成本(我不认为 Oracle 存储 [ key,pkey] 在 IOT 二级索引中,而是某种替代 rowid)。

于 2009-05-19T23:50:31.527 回答
0

这已经过时了,但是在 PostgreSQL 9.2 中,您可以获得仅索引扫描,它也可以执行 count(*)。

也可以看看,

于 2017-12-02T03:29:49.080 回答