2012-06-25 130 views
1

讓我們有很多這樣的類(百萬)數據庫選擇快速更新

class WordInfo 
{ 
    string Value; 
    string SomeOtherFeatures; 
    List<Point> Points; 
} 

而下面的代碼

private Dictionary<string, WordInfo> _dict; 

    public void ProcessData(IEnumerable<Tuple<string,int,int> words) 
    { 
     foreach(var word in words) 
     { 
      if(_dict.ContainsKey(word.Item1)) 
      { 
       _dict[word.Item1].Points.Add(new Point(word.Item2,word.Item3)); 
      } 
      else 
      { 
       _dict.Add(word.Item1, new WordInfo(....)) 
      } 
     } 
    } 


    Main() 
    { 
     while(true) 
     { 
      IEnumerable<Tuple<string,int,int> data = GetDataSomewhere(); 
      ProcessData(data); 
     } 
    } 

正如你可以看到這個代碼必須工作24 \ 7。主要問題是我不知道如何在數據庫中表示_dict(我存儲信息的地方)。我需要每秒處理1000-5000個字。關係數據庫不適合我的任務,對吧?那麼NoSQL呢?我需要快速的UPDATE和INSERT操作。另外我需要快速檢查是存在(SELECT)在分貝。因爲我有數百萬條記錄,這也不是微不足道的。你可以建議什麼?可能是基於文件寫我的自定義解決方案?

+0

如果你想持久;你將需要某種DBMS。如果你想要原始速度,你可以使用核心散列表。在這種情況下,幾Mword/s的速度是可能的。要實現一種持久性,您需要記錄添加/刪除操作,並定期將語料庫轉儲到磁盤。這將花費時間。 – wildplasser

回答

2

假設您不會創建太多事務,關係數據庫應該能夠輕鬆地插入/更新每秒1000-5000個字。

交易是ACID和「D」意思是耐用:當客戶端收到交易提交的通知時,確保交易的效果已經存在永久存儲器中(所以即使斷電在那個時刻發生,交易不會被「抹去」)。實際上,這意味着DBMS必須等待磁盤完成物理寫入。

如果您將每個插入/更新包裝在自己的事務中,您還必須對其中的每一個進行等待。 OTOH,如果您在一次交易中包裝很多插入/更新,您將不得不爲每個整塊「塊」支付一次這個價格。


此外,檢查特定行的其他數百萬人中的存在是一個任務數據庫是在非常好,這要歸功於B-Tree indexes力量。


至於數據庫的結構,你需要一些與此類似:

enter image description here

而且你會處理它像這(僞):

BEGIN TRANSACTION; 

foreach(var word in words) 
{ 
    try { 
     INSERT INTO WORD (WORD_VALUE, SOME_OTHER_FEATURES) VALUES (word.Item1, ...); 
    } 
    catch (PK violation) { 
     // Ignore it. 
    } 

    try { 
     INSERT INTO POINT (WORD_VALUE, X, Y) VALUES (word.Item1, word.Item2, word.Item3); 
    } 
    catch (PK violation) { 
     // Ignore it. 
    } 
} 

COMMIT; 

(注意:我假設你在初始插入之後永遠不會更新SOME_OTHER_FEATURES,如果你這樣做,上面的邏輯將更復雜)

如果您的DBMS支持它,請考慮將這兩個表集羣化(也就是說, index-organized)。另外,如果您的DBMS支持它,請壓縮POINT主索引(WORD_VALUE)的前沿,因爲與同一個單詞有關的所有點都包含相同的值。


順便說一句,上面的模型使用所謂的識別關係和自然鍵。使用代理鍵和非標識關係的替代模型是可能的,但會使您需要的處理複雜化。