通过HTTP API提供大量数据的体系结构

通过HTTP API提供大量数据的体系结构,api,architecture,reference,dataset,Api,Architecture,Reference,Dataset,我正在构建一个应用程序,通过RESTAPI提供大量数据,我正在寻找一些关于如何构建它的输入。我正在使用.NET(C#4.0)、ASP.NETMVC和SQLServer2008 现在,我在一个关系数据库中有大约40万行,其中+-5%是通过一个直接进入数据库的内部应用程序一天更新的。我需要通过返回自定义XML格式的RESTAPI来提供这些数据。但是,在输出数据之前,需要对数据进行处理。好的是,如果需要的话,我可以提前处理它 我编写了一个小POC,它获取数据,处理数据并将其缓存到本地XML文件中。由于

我正在构建一个应用程序,通过RESTAPI提供大量数据,我正在寻找一些关于如何构建它的输入。我正在使用.NET(C#4.0)、ASP.NETMVC和SQLServer2008

现在,我在一个关系数据库中有大约40万行,其中+-5%是通过一个直接进入数据库的内部应用程序一天更新的。我需要通过返回自定义XML格式的RESTAPI来提供这些数据。但是,在输出数据之前,需要对数据进行处理。好的是,如果需要的话,我可以提前处理它

我编写了一个小POC,它获取数据,处理数据并将其缓存到本地XML文件中。由于要进行处理,此过程大约需要一个小时才能处理所有400k行。缓存完成后,我只需在每个请求中返回物理文件

现在,我需要能够在数据在源中更新时更新数据,并更新缓存,这样我就不需要每次更新一行时都生成所有内容

我正在考虑使用AppFabric来保持内存缓存,并使用物理文件来确保在内存缓存耗尽的情况下,我不需要从头开始。一旦源代码中的一行被更新,我就会更新缓存并写入物理文件,以确保它是最新的

因此,我的主要来源将是AppFabric缓存,然后是物理缓存文件,作为最后手段,从数据库中重新生成文件,这将需要大约一个小时,并使调用该文件的人无法使用该文件

我对此不太满意,但这是我得到的。有什么建议吗


非常感谢

您可以将所有处理都放在数据库中吗?如果是真的,我认为你应该把所有的处理都放在那里。400k行是一小部分行,SQLserver可以处理得很好(一个小时太长了!)。尝试使用integration services来暂存表,并使用“设置处理”而不是游标/行处理来执行所有插入/更新/选择。
我的2美分。

您考虑过使用Linq到Xml吗

你会知道它是否符合你的其他限制条件,但这是我的2便士:

优点:

  • Xml是您的目标格式,因此转换没有问题
  • 它是可读的
  • 非常易于使用(积垢)
  • 加载/保存到文件将解决“重新启动服务时重新加载已处理的数据”问题
  • 具有相当高效的实现,这意味着它可以处理您的400k行(取决于您的记录大小)
  • 使用linq意味着您可以轻松地将其并行化(使用PLINQ),从而有效地使用您的内核
缺点:

  • 内存使用可能是个问题,但这取决于您的记录大小
以下内容(针对500k元件)在2secs中生成,并在0.5秒内在一个良好的开发盒上更新了所有元件的价格:

var root = new XElement("root");

for (int i = 0; i < 500000; i++)
{
    root.Add(new XElement("product", new XAttribute("name", "product_" + i),
                          new XElement("price", 13.0 + 1.0/(i + 1))));
}

foreach (XElement updateElem in root
    .Elements("product")
    .Where(x => x.Attribute("name").Value.StartsWith("product")))
{
    updateElem.Element("price").Value = "16.0";
}

root.Save(@"c:\temp\huge.xml");
var root=new-XElement(“根”);
对于(int i=0;i<500000;i++)
{
添加(新XElement(“产品”),新XAttribute(“名称”,“产品”+i),
新项目(“价格”,13.0+1.0/(i+1));
}
根目录中的foreach(XElement updateElem)
.要素(“产品”)
.Where(x=>x.Attribute(“name”).Value.StartsWith(“product”))
{
updateElem.Element(“price”).Value=“16.0”;
}
Save(@“c:\temp\maging.xml”);

感谢您对上述内容的澄清。这里有一个基于此的选项

向数据库中添加一个表。称之为加工产品(或价格,随便什么)。这个新表在产品中每行有一行(例如,源数据为1:1)。此新表中的每一行都包含相应源行的已处理数据

每次外部应用程序更新产品中的一行时,您只计算该行并更新产品中的相应行

以下是一些仅在新更新的条目上运行代码的方法:

  • 在程序中设置一个线程,每秒(或分钟)轮询一次DB,并对自一秒钟(或分钟)前起在最后一秒钟内更新的任何行运行处理逻辑。这意味着在更新产品行时保留时间戳(这可能是个好主意)
  • 如果不需要时间戳,请在Products表的DB中设置一个触发器,将更新的行添加到Products\u TopProcess表中。轮询并对其中出现的条目运行处理逻辑,然后从产品中删除\u ToProcess
  • 在products表上使用一个实际调用C代码的触发器:
这种方法使您的派生数据在逻辑上接近真实源(在具有源数据的数据库中),并减少您复制/格式化/处理数据的次数。同样重要的是,使用DB提供的久经考验的机制来检测/触发已更改的数据,可以避免编写大量自己的同步代码

现在,返回结果基本上是从已处理的产品中输出一个
select*。如果您只想返回特定产品的已处理数据,那么您拥有SQL和模式的全部功能;同样,用于排序。整个设置应该足够快,不需要在磁盘上缓存文件。事实上,如果你有足够的内存,MSSQL缓存可能会保留RAM中最多的/所有处理过的数据行,所以你很少需要做一个冷选择(如果你没有足够的RAM,考虑和你的时间相比,几个额外的GIG是值得的;在一个问题上扔硬件永远不会作弊)。p>

(但是,如果您真的想将其写入磁盘,您可以将每行记录的偏移量存储到物理文件中,并在更新相应的已处理数据行时快速更新文件中的各个数据。)

嘿,我的伙计!好久不见了,安?不幸的是,我不能:(它是一个.NET组件,负责处理。不过,谢谢!好久不见了,rsrs。让我再问你一个问题:你能重写这个.NET组件,只使用数据库吗?我是说,一些专业的