2013-08-25 73 views
0

我正在編寫一個程序,它將結構化數據從(損壞)文件中恢復爲單個記錄,並將結果收集到sqlite數據庫中。如何防止將相同記錄添加到SQL數據庫

該程序被調用幾次,具有稍微不同的恢復參數。這導致通常恢復相同的文件,但有時會從文件中恢復不同的數據。

現在,我每次運行帶有不同參數的程序時,都應該只添加新的(不同的)找到的項目到同一個數據庫。

這意味着我需要一種快速的方式來判斷每個恢復的記錄是否已經存在於數據庫中,以便只有在數據庫中不存在時才添加它們。

我知道對於每一個我想添加的記錄,我都可以先對所有列做SELECT操作,看看數據庫中是否有匹配的記錄,只有在找不到相同的記錄時才添加新的記錄。

但是,由於我添加了10000個記錄,對這些記錄中的每一個做SELECT都對我來說效率很低(很慢)。

我不知道是否有更聰明的方法來處理這個問題? I.e,有沒有辦法告訴sqlite我不想重複條目,所以它會自動檢測並拒絕它們?我知道UNIQUE修飾符,但那不是因爲它適用於單列,不是嗎?我需要能夠說COL1 + COL2 + COL3的組合必須是唯一的。有沒有辦法做到這一點?

注意:我從不想更新任何現有記錄。我只想收集一組不同的記錄。

獎金部分 - 性能

在一個經典的編程語言,我會使用一個鍵值字典,其中的關鍵是所有記錄的值的總和。同樣,我可以爲每個添加的記錄計算哈希代碼,並首先查看哈希代碼。如果沒有匹配,那麼記錄肯定不在數據庫中;如果有匹配,我仍然需要在數據庫中搜索任何重複項。那肯定會更快,但我仍然懷疑sqlite是否可以讓這個效率更高。

回答

1

你可以使用UNIQUE列約束或宣佈一個多列唯一約束,你可以使用UNIQUE() ON CONFLICT

CREATE TABLE name (id int , UNIQUE (col_name1 type , col_name2 type) ON CONFLICT IGNORE) 

SQLite的表達具有唯一性約束的方法有兩種:主鍵和唯一。它們都創建一個索引,所以通過創建的索引進行查找。

+0

性能如何?它只是單獨搜索所有項目,還是會使用一些更智能(更快)的算法,例如像使用哈希來加快速度? –

+0

同時具有多列的UNIQUE:[對於表上的每個UNIQUE約束,每行必須具有由UNIQUE約束標識的列中唯一值的組合。](http://www.sqlite.org/lang_createtable.html) – danihp

+0

@ThomasTempelmann查找這是一個問題,如果你有該列的索引,你可以加快查找確定... – aleroot

2

嘗試:

sqlite> create table foo (
    ...>   a int, 
    ...>   b int, 
    ...>   unique(a, b) 
    ...>); 
sqlite> 
sqlite> insert into foo values(1, 2); 
sqlite> insert into foo values(2, 1); 
sqlite> insert into foo values(1, 2); 
Error: columns a, b are not unique 
sqlite> 
+0

好的,這解釋了語法。表現如何?看到我的評論@aleroot –

+0

@ThomasTempelmann,我無法幫助性能的一部分,我從來沒有使用過重的應用程序中的sqlite。 – 2013-08-25 15:17:33

1

如果你不想使用SQL的方式(在其他的答案中提到),你可以爲你的所有數據做一個選擇的程序啓動時,存儲在數據字典和與字典的工作確定哪些記錄插入到您的數據庫。

這種方法的好處是單選比許多小選擇要快得多。 缺點是,如果你沒有足夠的內存來存儲你的數據,它將無法正常工作。

+0

雖然這不是一個壞主意,但恐怕我的確可能會耗盡內存。因此,將記錄一個接一個地存儲在數據庫中。 *如果*我應該使用散列方法,但我可以使用您的建議將這些散列存儲在應用程序啓動時的本地內存中。除非看起來哈希值在數據庫中一樣快,否則這太過於誇張。 –

+0

@ThomasTempelmann - 從我無關的測試中,訪問內存比訪問數據庫要快得多(只要內存沒有緩存到磁盤)。 – asafrob

+0

嗯...儘管如此,sqlite數據庫也是如此。如果引擎寫得很好(我假設它是這樣的),它會使用內存映射文件I/O,讓文件像內存一樣被訪問(它可以從應用程序主內存中交換到磁盤) )。一個db索引不過是一個(排序的)二叉樹。它類似於什麼編程語言(即它們的支持庫)用於某些類型的鍵值字典(例如,C++ STL std :: map類似地工作)。儘管如此,解析SQL cmd還是有一些開銷。 –

相關問題