2011-04-04 79 views
2

我正在构建一个应用程序来通过REST API提供大量数据,我正在寻找一些有关如何构建它的输入。我正在使用.NET(C#4.0),ASP.NET MVC和Sql Server 2008.通过HTTP API提供大量数据的体系结构

现在我在关系数据库中有大约400k行,其中+ - 其中5%通过内部应用程序更新直接进入数据库。我需要通过REST API来提供这些数据,以返回XML的自定义格式。但是,在输出数据之前需要处理数据。好的是我可以在需要之前预先处理它。

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

现在我需要能够更新数据,因为它在源代码中得到更新并更新我的缓存,所以每次更新单行时都不需要生成所有内容。

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

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

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

非常感谢!

+0

很清楚的解释,但它留下了一个问题在我心中:是否从〜400k行生成的输出文件的一些组合关闭所有这些无效,无论是一行更改,还是这是一个可能发生的行按行? 如果这是以后的情况,可能的答案就是自身。 – coffeetocode 2011-04-08 22:55:16

+0

不,该过程产生的输出文件是输入行(产品,这与电子商务有关)的列表,其中一些数据被修改(价格)。所以如果一行更新,我只需要更新这一行。并非全部。 – tucaz 2011-04-10 18:32:40

回答

1

感谢您的澄清以上。这里有一个基于此的选项。

添加一个表到您的数据库。称之为Products_Processed(或价格,无论)。这个新表格对于产品中的每一行都有一行(例如,与源数据一一对应)。这个新表中的每一行都包含相应源行的处理数据。

每次通过外部应用程序更新Products中的一行时,您只需计算该行并更新Products_Processed中的相应行。

这里有一些方法可以得到一段代码运行的只是最近更新的条目:

  • 有程序中的一个线程轮询DB 1次(或分钟)运行在您的任何处理逻辑行在一秒钟(或分钟)之前的最后一秒更新。这意味着您在产品行更新的时候保留时间戳(无论如何,这可能是个好主意)。
  • 如果您不想要时间戳,请在产品表上的数据库中添加触发器,以将更新的行添加到Products_ToProcess表。民意调查和出现有条目运行处理逻辑,并从Products_ToProcess
  • 删除
  • 在实际调用你的C#代码的产品表使用触发器:Create and Run CLR SQLServer Trigger

这种方法可以使你得出的数据在逻辑上接近真实的来源(在带有源数据的数据库中)并减少了复制/格式化/处理数据的次数。另外,重要的是,使用经过验证的真实数据库提供的机制来检测/触发已更改的数据,将使您无法编写大量自己的同步代码。

现在,返回结果本质上是流出select * from Products_Processed。如果您想仅为特定产品返回已处理数据,则您拥有SQL和模式的全部功能;同样用于排序。整个设置应该足够快,以至于不需要将文件缓存在磁盘上。实际上,如果你有足够的空间,MSSQL缓存应该可以将大部分/全部已处理的数据行保留在RAM中,所以你很少需要做一个冷选择(如果你没有足够的RAM,那么考虑一下额外的演出与你的时间相比是值得的;把硬件扔在一个问题上也不会作弊;)。 (但是,如果您确实想将其写入磁盘,则可以将偏移量存储到每个行记录的物理文件中,并在更新相应的处理数据行时快速更新文件中的单个数据。)

+0

这是我使用的方法,唯一的区别是我将生成的数据保存在XDocument(作为@grzeg建议的+1)对象的内存中并更新它直接在产品发生变化时直接进行,我不希望将所有内容都存储在数据库中,以免在每次请求时为其生成XML。 – tucaz 2011-04-14 14:27:44

1

你可以把所有的处理在数据库中?如果属实,我认为你应该保留所有的处理。 400k行是少量行,SQLserver可以处理这种情况(一个小时太长了!)。尝试使用集成服务登台并使用“设置处理”执行所有插入/更新/选择,而不是使用光标/行处理。 我的2美分。

+0

嘿,我的男人!好久不见,安?不幸的是我不能:(它是一个处理.NET组件,谢谢,虽然! – tucaz 2011-04-04 17:24:27

+0

很长一段时间,rsrs。让我再问你一个问题:你可以重写这个.net组件来仅使用数据库吗?我的意思是,一些使用'set processing'而不是'row processing'进行处理的过程在数据库中加载一个包含所有应更新值的表,并使用一些连接/临时表,您可以根据此temp更新目标表表格或类似的东西在这种情况下设置处理是最好的方法 – rboaretto 2011-04-11 21:17:14

1

您是否想过使用Linq To Xml?

你会知道最好的它是否适合你的其他方面的限制,但这里是我的2便士:

优点:

  • XML是你的目标格式,所以没有与转换问题
  • 是可读
  • 非常容易使用(CRUD)
  • 加载/保存到文件将解决您的'重新加载服务重新启动时处理的数据'问题
  • 具有合理有效的实现,这意味着它可以处理您的400k行(取决于您的记录大小)。
  • 使用LINQ意味着你可以很容易地parallelise它(与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");