如何在Interbase / Firebird中加速Count(*)

问题描述 投票:2回答:3

Interbase是一个世代数据库。

太好了,因为回滚几乎是瞬时的,但是count(*)会花很长时间。这是unlike例如MySQL的count可以使用索引。

直到我看到这个,我才知道为什么:

即使在COUNT中包含的一个或多个列上有索引可用,也必须访问所有记录,以查看它们是否在当前事务隔离下可见。

在维基百科上:http://en.wikipedia.org/wiki/InterBase

有关在Interbase / Firebird中进行快速计数的任何技巧

count firebird interbase
3个回答
3
投票

根据此链接:http://www.firebirdfaq.org/faq5/

还有另一种解决方案。这是由长期存在的Interbase和Firebird黑客Ivan Prenosil制作的。此解决方案仅返回近似记录计数。正如安·哈里森(Ann W. Harrison)的友善解释:如果未对旧版本进行垃圾回收,则任何对其主键进行了修改的记录都会出现两次,并且删除的记录将继续计数,直到被垃圾回收为止。

/* first update the statistics */
UPDATE RDB$INDICES SET RDB$STATISTICS = -1;
COMMIT;

/* Display table names and record counts */
SELECT RDB$RELATIONS.RDB$RELATION_NAME,
CASE 
WHEN RDB$INDICES.RDB$STATISTICS = 0 THEN 0 
ELSE CAST(1 / RDB$INDICES.RDB$STATISTICS AS INTEGER) 
END 
FROM RDB$RELATIONS 
LEFT JOIN RDB$RELATION_CONSTRAINTS 
 ON RDB$RELATIONS.RDB$RELATION_NAME = RDB$RELATION_CONSTRAINTS.RDB$RELATION_NAME 
 AND RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
LEFT JOIN RDB$INDICES 
  ON RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME = RDB$INDICES.RDB$INDEX_NAME 
WHERE RDB$VIEW_BLR IS NULL AND RDB$RELATION_ID >= 128 
ORDER BY 1;

这仅适用于具有主键的表。


0
投票

您还可以为要计数的表创建2个触发器。此解决方案适用于一些特殊表,在这些表中您需要执行很多“操作”。

CREATE TRIGGER TABLE_BI0 ACTIVE BEFORE INSERT
BEGIN
   UPDATE COUNTING_TABLE
   SET LINES=LINES + 1
   WHERE TABLE='TABLE_NAME'; /* Table name here*/
END


CREATE TRIGGER TABLE_BD0 ACTIVE BEFORE DELETE
BEGIN
   UPDATE COUNTING_TABLE
   SET LINES=LINES - 1
   WHERE TABLE='TABLE_NAME'; /* Table name here*/
END

此后,当您需要了解该特殊表的计数时,只需从COUNTING_TABLE中选择它即可

SELECT LINES FROM COUNTING_TABLE
WHERE TABLE='TABLE_NAME' /* Table name here*/

0
投票

我尝试过Ivan Prenosil解决方案(在顶部)。该查询在FlameRobin上运行正常,但在我的delphi程序上却无法正常运行。

既不使用TClientDataset也不使用IbcQuery(来自devart)。该查询将返回一个EMPTY结果!!!

有人知道这个问题吗?谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.