2011-09-08 106 views
1

這是一個基於this question about query optimization的後續。SQLite觸發器優化

爲了快速做出選擇,如上所示,我嘗試在插入時使用觸發器預先計算一些數據。

基本上,我想保持給定列值的出現次數到給定的表中。

以下模式用於存儲的出現對於每個值:

CREATE TABLE valuecount (value text, count int) 
CREATE INDEX countidx ON t (count DESC) 
CREATE UNIQUE INDEX valueidx ON valuecount (value); 

這裏是我一直在測試觸發器:

CREATE TRIGGER counttrigger INSERT ON collection 
    FOR EACH ROW 
    BEGIN 
     INSERT OR REPLACE INTO valuecount VALUES 
     (NEW.value, coalesce((SELECT count + 1 FROM count WHERE valuecount.query LIKE 
     NEW.value), 1)); 
    END; 

在一個典型的插入collection表包含幾十萬行,在單個INSERT INTO ... SELECT ...聲明(我正在將數據從一個數據庫合併到另一個)。

的問題是,這個觸發器,插入300K行需要4個小時,而不是300毫秒......

有沒有辦法實現這個不犧牲性能?

預先感謝您的幫助,

+0

你可能會想嘗試,你新加入的更新,然後是INSERT SELECT FROM NEW的行不存在。 –

+0

你能舉個例子嗎? – Sylvain

+0

對不起,我不知道[此時SQLite僅支持FOR EACH ROW觸發器,而不是FOR EACH STATEMENT觸發器。](http://www.sqlite.org/lang_createtrigger.html)。在我使用的其他數據庫中,它們在「FOR EACH STATEMENT」作用域中運行,您可以在其中對正在更改的整個數據集執行操作。我沒有意識到SQLite的這種限制,所以你不能在我之前的評論中談論的。 –

回答

0

好吧,似乎使用觸發器並不是一個好主意。

因爲我正在合併來自不同數據庫的表,所以我在基於我正在合併的表的內容(在插入之前在一個語句中)完成valuecount表的插入操作。

因此,而不是一個觸發器,我只是有一個查詢,看起來像這樣,之前我INSERT INTO ... SELECT ...語句執行:

INSERT OR REPLACE INTO valuecount 
SELECT value, coalesce((SELECT count FROM valuecount WHERE valuecount.value = collection.value) + COUNT(value), COUNT(value)) 
FROM attached.collection GROUP BY value 
2

因爲從一個數據庫導入到另一個不常見任務的其他刀片,你可以推遲由觸發器提供直至導入完成邏輯?查看觸發器的性質,在導入所有數據後,您似乎可以爲每個查詢類型執行COUNT。這將大大減少整體查詢。

如果這是不可能的,有沒有辦法避免使用LIKE?這種操作比直接比較更昂貴。

+0

是的,正如顯然是一個錯誤在這裏,我的壞:) – Sylvain

+0

我目前正試圖插入(僅在300K行)之前做計數,並立即插入新的計數。 COUNT在合併後無法在整個數據庫上完成,因爲它佔用了太多時間(即使擁有數百萬行,它也需要快速)。 – Sylvain