2011-04-27 62 views
2

Interbase是一個世代數據庫。如何加快Interbase/Firebird中的計數(*)

這很棒,因爲回滾幾乎是瞬間的,但count(*)需要永遠。
這是不像例如,其中count可以使用索引的MySQL。

我從來不知道爲什麼,直到我看到了這一點:

即使索引可對列或包含在計數列,所有的記錄都必須爲了參觀,看看他們是下可見當前事務隔離。

維基百科:http://en.wikipedia.org/wiki/InterBase

如何做到快速計數的InterBase /火鳥

回答

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; 

這隻適用於具有主鍵的表格。

+0

@Hughes,感謝您的鏈接選擇它。 – Johan 2011-04-28 12:33:34

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

海事組織是一個糟糕的主意,特別是有很多「行動」的表格。對獨立的表進行併發操作時,都會嘗試在COUNTING_TABLE中寫入相同的記錄,這可能會導致鎖衝突。 – mghie 2011-06-08 20:45:14

+0

你說得對@mghie,但是如果它有很多動作,肯定會發生在非常短的交易中,從而最大限度地減少鎖定時間/衝突。在應用此工作周之前,您應該非常重視您的考慮因素。 – 2011-06-13 22:12:16