一个30个小时查询的最佳架构

11

我有一个有趣的问题要解决。我的一个客户让我开发一款股票分析程序,其中包含近50年的大约1000个股票数据。我已经开发了一系列筛选器,可以应用于任何给定的日期以查看是否有任何交易机会。

我们希望对每支股票的每一天运行此筛选器。基本上是您所需的开始和结束日期类型报告。但是,每周筛选每个符号需要6分钟时间。我们估计需要约40个小时才能对我们的整个数据集运行报告。

最重要的要求是,我的客户能够从任何地方的任何计算机上操作应用程序(他经常旅行),因此我们是基于浏览器的。

为解决这个问题,我编写了一个异步方法来运行此报告,但应用程序池空闲计时器将终止该任务。我不想为了支持这一个报告而开始调整整个应用程序的超时时间(在使用活动交易之前,我们将对每种股票情况针对整个数据集运行多次)。

有没有人对支持超长异步处理的Web架构有任何一般性想法或经验?

谢谢

10个回答

17
作为一般建议,我建议使用独立的Windows服务、控制台应用程序或类似的应用程序来定期检查(轮询)数据库中的“待处理作业”,并更新数据库中的结果和进度信息。需要特别注意生命周期控制和日志记录。虽然这可能不是最佳方法,但我已经多次使用它并且非常可靠、可扩展,并且性能良好。最好将Web请求保持在一两分钟以内,因为它们从未被设计用于长时间的处理。这样您就可以每隔一分钟左右通过Web服务“检查”作业状态。
如果您对此有任何问题或想法,请发表评论,我很乐意提供帮助、解释或建议。
额外补充:我认为Windows服务使用较少!只需快速编写一个基础类或可重用的帮助方法集合,您就能运行一个记录、可靠、自动化、可配置、快速实现的进程。也很容易进行原型开发!

3
+1 表示支持一个 Windows 服务。这项工作不应该归于网络应用程序的工作量。 - p.campbell
1
+1,这就是服务的作用,完全同意,将其放入Web应用程序只是一种hack。 - andy
Kieren,感谢你的回答。是的,我认为你说的很对,这种方法与我们架构的其余部分保持一致。我们已经在运行Windows服务来管理市场关闭时的历史报价下载。而且,我唯一需要管理的超时时间是SQL的CommandTimeout,这非常简单。我可以让用户输入他们报告的参数,将它们存储在数据库中,在服务的上下文中调用并运行它们。我知道这个要求不仅仅能通过网页来解决。谢谢你 - 干得好! - Mike Malter

6

在后台运行服务并在请求时将单个结果集存档到只读结果表中,这样做有什么不可行之处吗?您是否需要实时运行查询?应用程序可以在服务生成结果页面时检索结果页面。


+1 - 我赞同这个观点。这么长的查询是否真的需要是即席查询?预先处理您的结果,并让 Web 服务检索缓存值,同时 OS 服务根据需要更新查询。 - Jordan Parmer
Mike和J - 我不想归档记录集,然后再检索它们。但是服务部分是一个非常好的想法。 - Mike Malter

5
听起来你正在对这些数据直接进行SQL查询。你是否考虑将数据加载到例如SQL Server Analysis Services中,并设置一个包含(首先)时间、股票和符号维度的立方体?根据查询的性质,你可能会得到相当合理的响应时间。关系数据库适用于在线事务处理(在某些负载和响应时间参数内),但分析工作有时需要数据仓库的方法和技术。(或者,也许是联想数据库...存在替代方案。)
然而,考虑到Murphy定律,你可能会遇到一些长时间运行的查询。不同的最终用户的数据是否有所不同?如果没有,为什么不预计算答案?如果按设计,基于HTTP的任何处理都不应该花费超过一分钟的时间!

Pontus,感谢您的想法。看起来这个要求似乎是SASS的一个需求,但由于我们正在运行数据过滤器,我希望采用一种方法,可以将它们简单地放入while循环中,并持续运行,直到开始日期> = 结束日期。无论是一天还是全部都可以。对于这份报告的查询时间并不是问题,因为这些是证明类型的报告,旨在验证50年期间交易活动的战略思考。因此,即使需要三天才能运行,重要的是该方法在非常大的历史数据集上得到验证。 - Mike Malter

3
根据您的过滤器的具体情况,这似乎是一个可以从并行化中受益的任务 - 将查询分割成多个计算节点,在数据的子集(分片)上运行过滤器。 如果您的过滤器专注于分析大量时间数据上的一只股票,您可以将工作分配给股票符号,并让多个计算节点同时处理不同的股票符号。 如果您需要研究股票符号随时间变化的关系,则按时间间隔分割工作并在操作后合并结果(mapreduce)可能更有意义。 这是一种情况,投入更多硬件实际上可以显著改善响应时间。 以谷歌搜索引擎为例。
通常的警告适用:首先检查您当前的过滤器实现是否存在性能瓶颈。 确保您正在访问的表已经适当地索引等。 预先计算经常需要的计算的关系和摘要。 如果可以节省时间,存储就很便宜。
您的Web请求可以启动散布/聚集查询操作,将查询分发到云中可用的计算节点(Windows Azure、Google Apps、Amazon)。 给定足够的计算节点和适当的工作分配,您可以在几乎实时内获得响应。

dthorpe,是的,我们正在使用PLINQ和并行查询。但是,我还需要解决一些排序问题。在其中一个报告中,我将3个小时缩短为1/2小时。但每次运行报告时,我们都会得到不同的结果。因此,我需要进一步研究,但并行化目前不是优先事项或要求,但在未来可能会成为。再次感谢您的想法。 - Mike Malter

2

通常,超长的异步进程不会在网络上运行。

他的请求应该排队,另一个进程应该运行该作业并以用户将使用的格式存储数据。


2
六分钟筛选一周的数据?看起来您的数据库需要进行适当的索引调优。

2
请记住,“一周的数据”可能意味着很多不同的东西——仅仅是每天的收盘价(五个数据点),或者是每一个tick(可能高达数百万个数据点)。 - Bob Kaufman
这也取决于使用的软件/硬件和数据库设计。在我的职业生涯中,我见过许多愚蠢的方式构建数据库: ..一个只读表格拥有超过十亿行的数据库 ..一个小型数据库(<5GB),有许多数百个表和几十个关系,使用多列/非简单主键 - 它经常出现问题。工程师犯错误很容易,而对于那些缺乏经验的人来说,有很多东西可以学习。 "就这一次" 成为了后悔的信条。 - Hardryv
Friol,Bob是对的。我们正在处理数百万个点,因此需要过滤器,还有过滤器!我同意您关于适当索引调整的想法。每个存储过程都会分析其查询计划,我确实喜欢SQL 2008的功能,可以告诉您可能缺少哪些索引。 - Mike Malter

2

我建议你阅读这篇关于 异步存储过程执行 的文章。如果你的逻辑受到数据库限制(这几乎是肯定的),那么这就提供了一种完全可靠的方式来以异步方式启动计算任务,而且可以在故障转移情况下保持弹性。考虑到你的负载高度可并行化,你可以启动多个任务,例如为每个股票启动一个任务,可以参考后续文章 将参数传递给后台存储过程

顺便说一下,我知道至少有两家大型金融公司正在利用这种利用内置 SQL Server 异步激活的技术,处理与你完全相同的场景。


Remus,感谢你的文章,我一定会阅读。如果我理解正确,我们的数据库并不是逻辑绑定的。我认为存储过程就像矿山中的巨型蒸汽铲,它们是巨大的高度优化的机器,用于挖掘土壤以进行进一步的加工。在我们的情况下,Linq for SQL就是我们的铲子,我们使用Linq在二进制代码中进行大部分的附加过滤和分析。 - Mike Malter
你可以考虑使用同样的技术来利用外部激活器(External Activator)这种进程外服务:http://blogs.msdn.com/b/sql_service_broker/archive/2008/11/21/announcing-service-broker-external-activator.aspx。你需要一种可靠地调度计算(任务)的方法,而且迟早会在数据库中建立一个队列,所以最好从现在开始就着手处理。 - Remus Rusanu
我打算创建一个Windows服务来读取报告队列表。如果它开始变得庞大,并且看起来维护将成为一个问题,我们将考虑使用MSMQ。 - Mike Malter
感谢您的文章。我之前不知道 OUTPUT 子句。我们目前并没有从队列中删除记录,而是标记一个状态列并将其用作上下文。 - Mike Malter

1
我不知道为什么这里的每个回答都希望所有工作都在数据库中完成,但是作业控制应该在外部。这就像将汽车的点火钥匙放在外面一样。实际上,我知道为什么。你用wcf标记了这个问题。
而使用“计算节点”的建议刚好完成了我的流行语宾果游戏,谢谢dthorpe!你不需要“计算节点”,只需要核心。大多数关系型数据库管理系统都内置了PX(并行执行)。为什么要支付你每天使用的云计算费用,只需购买具有足够CPU的服务器即可,你会没问题的...不需要“散布收集”查询,只需打开PX...
Pontus指出了正确的方向。满足6分钟性能并担心如何安排时间表是你的问题。有很多策略可以将数据格式化以促进速度。索引、分区、立方体、IOTs。你可能正在进行两次排序而不是内存排序。你的统计数据可能已过期,导致了错误的计划。
我假设你还没有从这个问题的基调中进行过整个数据库调优。你真的应该发布一个数据库调优问题,并告诉我们你正在使用哪个RDBMS以及你已经调优到了什么程度。

1
因为数据库是数据存储的地方,50多年的数据将会是几千兆字节的海量数据,并且需要作为对象传递。我并不是说这是不可能的,但每种情况都有其自身的优点,可以在数据库内执行某些任务,而其他任务则在外部执行。在这种情况下,我会尽可能在数据库上执行尽可能多的过滤操作,然后将数据传递到报告类型服务器上进行报告生成。 - Ryk
Stephanie,我的想法和你一样。我们只是从我们的SQL Server数据库中提取股票数据,并在二进制代码中进一步处理它。实际上,这个项目上的数据库是我创建过的最简单的。我认为我们甚至可能只达到了第二正常形式。但数据的大小是巨大的。我认为我可以更好地澄清我的问题,说一个30多小时的过程,而不是一个30多小时的查询。谢谢你抽出时间与我分享你的想法。 - Mike Malter
Ryk,你误解了。我不同意的是but之后的部分。我反对在Windows或其他任何不在数据库中的地方将调度和控制作为服务。这是一个逗号,不是句号。 - Stephanie Page
迈克,啊,更有意义了。我在一家交易公司的IT部门工作了8年。我是为那些写“二进制代码”(就像你所说的)的博士们做数据库的人。现在你已经澄清了查询/处理行,“计算节点”就更有意义了——这正是我们所遇到的情况。我们有一批专门用于复制过程的服务器群和一个管理这些复制过程的调度程序。 - Stephanie Page
Stephanie,感谢你分享你的经验。很高兴知道我的小项目与那些大项目有些相似之处。 - Mike Malter

1

Mike,

回答这个问题有很多种方法,但我认为你应该问的更重要的问题是:为什么过滤股票需要6分钟?

是的,我知道你有50年的数据和很多股票,但它不应该花费6分钟。因此,更重要的是,我会查看特定表结构、索引以及查询和它正在做什么。

我曾经为一家类似的公司工作,他们的表格几乎每个都有100Gb。是的,是表格的大小,而不是整个数据库,在进行一些微调后,我们将需要15分钟以上的查询时间缩短到3秒钟。

如果你在运行SQL Server,我很乐意帮助你。请给我发电子邮件ryk99[at]hotmail[dot]com,我们可以从那里开始。


Ryk,感谢你提供帮助。筛选股票需要6分钟,因为有半打满足从今天到一年分析的条件和比较的过滤器。对我来说问题不在于执行查询所需的时间,而在于如何支持扩展。当我们需要检查整个数据集以制定交易策略时会发生什么?然而,之前有一个很好的建议是创建一个Windows服务并轮询参数表。我唯一需要担心的超时是SQL CommandTimeout。再次感谢。 - Mike Malter

0

你有没有考虑过使用 ETL 解决方案,比如 SSIS 来预填充你的数据?


不,我们还没有考虑过,部分原因是我对SSIS的经验很少。也许我应该研究一下它。 - Mike Malter
这个值得研究一下(这是SSIS应该用于的事情),尽管它有相当陡峭的学习曲线。如果你的SQL技能很扎实,那么你不会遇到太多问题,因为周围有很多好的资源。 - Mr Shoubs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接