Search code examples
countfirebirdinterbase

How to speed up Count(*) in Interbase/Firebird


Interbase is a generational database.

That's great because rollbacks are near instantaneous, but count(*) takes forever.
This is unlike e.g. MySQL where count can use an index.

I never knew why until I saw this:

Even when an index is available on the column or columns included in the COUNT, all records must be visited in order to see if they are visible under the current transaction isolation.

On wikipedia: http://en.wikipedia.org/wiki/InterBase

Any tips on how to do fast counting in Interbase/Firebird


Solution

  • According to this link: http://www.firebirdfaq.org/faq5/

    There is another solution. This one is by Ivan Prenosil, a long time Interbase and Firebird hacker. This solution only returns an approximate record count. As Ann W. Harrison kindly explains: Any record that has had its primary key modified will appear twice if the old version has not been garbage collected and deleted records will continue in the count until they are garbage collected.

    /* 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;
    

    This will only work on tables that have a primary key.