Database SQL计数(*)实践的替代方案?

Database SQL计数(*)实践的替代方案?,database,postgresql,count,nosql,Database,Postgresql,Count,Nosql,我正在寻找对PostgreSQL/InnoDB MVCC COUNT(*)问题的改进,这时我发现了一篇关于实现。然而,作者发表的一项声明引起了我的注意: MySQL狂热者倾向于指出 PostgreSQL的慢计数()作为 然而,在现实世界中, count()不经常使用,如果 这是非常需要的,最好的数据库 系统为您提供了一个框架 建立一个变通方法 在设计应用程序时有没有跳过使用COUNT(*)的方法? 大多数应用程序的设计都是为了不需要它,这是真的吗?我在大多数页面上使用COUNT(),因为它们都需

我正在寻找对PostgreSQL/InnoDB MVCC COUNT(*)问题的改进,这时我发现了一篇关于实现。然而,作者发表的一项声明引起了我的注意:

MySQL狂热者倾向于指出 PostgreSQL的慢计数()作为 然而,在现实世界中, count()不经常使用,如果 这是非常需要的,最好的数据库 系统为您提供了一个框架 建立一个变通方法

在设计应用程序时有没有跳过使用COUNT(*)的方法?

大多数应用程序的设计都是为了不需要它,这是真的吗?我在大多数页面上使用
COUNT()
,因为它们都需要分页。这家伙在说什么?这就是为什么有些网站只有“下一个/上一个”链接的原因吗


将这一点带到NoSQL世界,是不是也必须在那里做一些事情,因为你不能很容易地计算()记录?

我想当作者说

however, in the real world, count() isn’t used very often
它们特别意味着不经常使用非限定的
计数(*)
,这是MyISAM优化的特定情况

我自己的经验证明了这一点——除了一些可疑的Munin插件,我想不起上次我是什么时候从某个表中选择count(*)的

例如,无论我在哪里进行分页,它通常都是一些搜索的输出。这意味着无论如何都会有一个WHERE子句来限制结果-因此我可能会从条件后面跟着选择的某个表中执行类似于选择计数(*)的操作。。。从某个表限制n偏移量m。这两个选项都不能使用“直接显示此表中的行数”快捷方式

现在,如果条件是纯索引条件,那么一些数据库可以合并覆盖索引的输出,以避免查看表数据。这肯定会减少所查看的块的数量。。。如果有效的话。例如,如果查询可以通过单个索引来满足,那么这可能只是一个胜利,这取决于db实现

尽管如此,情况并非总是如此——我们的许多表都有一个
活动
标志,该标志没有索引,但经常被过滤,因此无论如何都需要进行堆检查

如果您只需要了解一个表中是否有数据,Postgresql和许多其他系统会保留每个表的估计统计信息:您可以检查目录中的
reltuples
relpages
列,以估计表中有多少行以及占用了多少空间。只要~6个有效数字对您来说足够准确,并且正在更新的统计数据中的某些延迟是可以容忍的,这是可以接受的。在我记忆中的用例中(绘制集合中项目的数量),这对我来说是很好的

试图保持精确的行计数器是很棘手的。您引用的文章将行计数缓存在辅助表中,这带来了两个问题:

  • 填充辅助表的SELECT和INSERT之间的竞争条件(次要,您可以通过管理方式对此进行种子设定)
  • 一旦向主表中添加一行,辅助表中的行就有一个更新锁。现在,任何其他试图添加到主表的进程都必须等待
结果是并发事务被序列化,而不是能够并行运行,并且您已经失去了编写器不必阻止MVCC的任何一个好处-您应该合理地期望能够同时将两个独立的行插入到同一个表中

MyISAM可以缓存每个表的行数,因为当有人向其写入数据时,它会在表上附加独占锁(iirc)。InnoDB允许更细粒度的锁定——但它不尝试缓存表的行数。当然,如果你不关心并发性和/或事务,你可以走捷径。。。但接下来,您将不再关注Postgresql的主要目标,即数据完整性和ACID事务是主要目标


我希望这能给我们一些启示。我必须承认,我从来没有真正感觉到需要更快的“计数(*)”,所以在某种程度上,这只是一个“但它对我有用”的证明,而不是一个真正的答案。

当你问的更多的是应用程序设计而不是数据库问题时,还有更多关于如何在PostgreSQL中执行计数的详细信息,以及在中执行计数的替代方法。如果您必须快速计数某些东西,您可以使用触发器维护一个,参考文献中有示例。这会让你在插入/更新/删除端付出一点代价,作为加速的回报。不过,你必须事先知道,你最终想要多少才能让它起作用。

那篇文章是2007年的!!也许postgres改进了他的计数算法……在现实世界中,关系完整性通常比快速计数更重要。MySQL不得不放弃其旧教条,即RI不重要,并添加InnoDB。仅供参考,这不是关于PostgreSQL或MySQL的真正问题。这是关于如何,或者如果可能的话,设计一些不需要记录计数的东西。啊,我认为作者暗示他根本没有使用
COUNT()
函数。我也从未使用过毯子
从表中选择计数(*)。虽然我总是索引所有int列,这通常是我传递给COUNT()查询的WHERE部分的唯一内容。现在,更重要的是,您刚才说,通过使用作者,您实际上可以引入竞争条件,“并发事务被序列化,而不是能够并行运行”?您能再解释一下这一部分吗?基本上,您不能让两个事务同时修改同一行的同一版本。如果线程/事务A在某一行上进行了更新,则尝试更新或删除该行的任何其他事务都将阻塞,直到提交/中止。相比之下,两个线程将行插入t