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

时间:2011-04-27 23:08:13

标签: count firebird interbase

Interbase是一个世代数据库。

这很好,因为回滚几乎是即时的,但count(*)需要永远 这不同,例如MySQL可以使用索引的MySQL。

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

  

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

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

有关如何在Interbase / Firebird中进行快速计数的任何提示

2 个答案:

答案 0 :(得分:3)

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

  

还有另一种解决方案。这个是由Ivan Prenosil长期担任的Interbase和Firebird黑客。此解决方案仅返回近似记录计数。正如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;
     

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

答案 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*/