4

我有很多数据需要根据一些简单的标准进行配对。有一个时间窗口(两条记录都有一个 DateTime 列),如果一条记录在时间上(5 秒内)非常接近另一条记录,则它是潜在匹配,时间最接近的记录被认为是完全匹配。还有其他领域也有助于缩小范围。

我编写了一个存储过程,它在将完整匹配的数据集返回到 C# 应用程序之前在服务器上执行此匹配。我的问题是,将 100 万 (x2) 行拉入并在 C# 中处理它们会更好,还是 sql server 更适合执行这种匹配?如果 Sql server 是,那么使用 datetime 字段配对数据的最快方法是什么?

现在我将表 1/表 2 中的所有记录选择到临时表中,遍历表 1 中的每条记录,在表 2 中查找匹配项并将匹配项(如果存在)存储在临时表中,然后删除两条记录在他们自己的临时表中。

我不得不为我正在写的游戏匆忙写这篇文章,所以请原谅糟糕的(非常糟糕的)程序......它有效,它只是非常低效!整个 SP 可在 pastebin 上找到:http: //pastebin.com/qaieDsW7

我知道 SP 写得不好,所以说“嘿,笨蛋……写得更好”没有帮助!我正在寻求改进它的帮助,或者关于我应该如何以不同的方式做整个事情的帮助/建议!我有大约 3/5 天的时间来重写它,我可以将截止日期推迟一点,但如果你们能及时帮助我,我宁愿不要!:)

谢谢!

4

4 回答 4

2

Ultimately, compiling your your data on the database side is preferable 99% of the time, as it's designed for data crunching (through the use of indexes, relations, etc). A lot of your code can be consolidated by the use of joins to compile the data in exactly the format you need. In fact, you can bypass almost all your temp tables entirely and just fill a master Event temp table.

The general pattern is this:

INSERT INTO #Events
SELECT <all interested columns>
FROM 
    FireEvent
    LEFT OUTER JOIN HitEvent ON <all join conditions for HitEvent>

This way you match all fire events to zero or more HitEvents. After our discussion in chat, you can even limit it to zero or one hit event by wrapping it in a subquery and using a window function for ROW_NUMBER() OVER (PARTITION BY HitEvent.EventID ORDER BY ...) AS HitRank and add a WHERE HitRank = 1 to the outer query. This is ultimately what you ended up doing and got the results you were expecting (with a bit of work and learning in the process).

于 2012-05-30T21:45:18.327 回答
2

如果数据已经在数据库中,那就是你应该做的工作。您绝对应该学习使用 SQL Server Management Studio 显示和查询计划,并能够注意到和优化嵌套循环等昂贵的计算。

您的任务可能不需要使用任何临时表。当临时表相对较小和/或重用率很高时,它们往往是有效的,这不是你的情况。

于 2012-05-29T21:39:33.420 回答
1

如果运行速度不够快并且不要用 C# 重写它,我建议您尝试优化存储过程。为什么要从 SQL Server 中传输数百万行?

不幸的是,我没有安装 SQL Server,因此无法测试您的脚本,但我没有看到任何 CREATE INDEX 语句。如果您不只是为了简洁而跳过它们,那么您肯定应该分析您的查询并查看需要哪些索引。

于 2012-05-29T21:33:39.870 回答
1

所以答案取决于几个因素,比如每个客户端/服务器可用的资源(内存/CPU/并发用户/并发进程等)

以下是一些基本规则,无论您使用什么,它们都会提高您的性能:

  • 将一百万行加载到 c# 程序中并不是一个好习惯。除非这是一个具有大量内存的独立进程。
  • Uniqueidentifiers 永远不会胜过 Integers。比较
  • 公用表表达式是快速执行匹配的一个很好的替代方案。如何使用CTE
  • 最后,您必须考虑输出。如果有影响用户界面的持续读写,那么你应该在内存中管理它(c#),否则所有的 CRUD 操作都应该保存在数据库中。
于 2012-05-29T21:47:28.350 回答