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)。因为我有数百万条记录,所以这也不是微不足道的。你有什么建议?可以根据文件编写我的自定义解决方案吗?

4

1 回答 1

2

假设您没有创建太多事务,关系数据库应该能够轻松地每秒插入/更新 1000-5000 个单词。

事务是 ACID 并且“D”表示持久性:当客户端收到事务已提交的通知时,可以保证事务的效果已经在永久存储中(因此即使在那一刻发生断电,交易不会被“删除”)。实际上,这意味着 DBMS 必须等待磁盘完成物理写入。

如果您将每个插入/更新包装在其自己的事务中,您还必须为每个事务执行此等待。OTOH,如果您在单个事务中包含许多插入/更新,则您只需为整个“块”支付一次此价格。


此外,由于B-Tree 索引的强大功能,检查数百万其他行中是否存在特定行是数据库非常擅长的任务。


至于数据库结构,您需要类似于以下内容:

在此处输入图像描述

你会像这样处理它(伪代码):

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 支持它,请考虑将这两个表都设为集群(也称为索引组织)。此外,如果您的 DBMS 支持它,请压缩 POINT 的主索引 (WORD_VALUE) 的前沿,因为与同一单词相关的所有点都包含相同的值。


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

于 2012-06-26T09:48:24.743 回答