我们有很多这样的课程(数百万)
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操作。另外我需要快速检查db中是否存在单词(SELECT)。因为我有数百万条记录,所以也不是一件容易的事。你能建议什么?可以根据文件编写我的自定义解决方案吗?
答案 0 :(得分:2)
关系数据库应该能够轻松地每秒插入/更新1000-5000字,假设您没有创建太多的事务。
事务是ACID,“D”表示持久:当客户端收到事务提交的通知时,可以保证事务的影响已经存在于永久存储中(所以甚至如果在那个确切的时刻发生停电,交易将不会被“擦除”)。实际上,这意味着DBMS必须等待磁盘完成物理写入。
如果将每个插入/更新包装在自己的事务中,则还必须对每个插入/更新执行此等待。 OTOH,如果你在一次交易中包装许多插入/更新,你将不得不每整个“块”支付这个价格。
此外,由于B-Tree indexes的强大功能,检查数百万其他行中是否存在特定行是一个非常擅长的任务数据库。
至于数据库结构,你需要类似的东西:
你会像这样处理它(伪代码):
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支持它,请考虑将这两个表聚集在一起(aka。index-organized)。此外,如果您的DBMS支持它,请压缩POINT主索引(WORD_VALUE)的前沿,因为与该词相关的所有点都包含相同的值。