2012-06-25 135 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)的前沿,因为与同一个单词有关的所有点都包含相同的值。


顺便说一句,上面的模型使用所谓的识别关系和自然键。使用代理键和非标识关系的替代模型是可能的,但会使您需要的处理复杂化。