【问题标题】:Is SQL or C# faster at pairing?SQL 或 C# 的配对速度更快吗?
【发布时间】:2012-05-29 21:24:26
【问题描述】:

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

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

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

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

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

谢谢!

【问题讨论】:

  • 您绝对需要进行实验。最好在更小、更易于处理的测试集上。但我的猜测是,如果你做对了,SQL 将是明显的赢家......恕我直言......
  • 我过去做过类似的事情,我必须根据某种滑动窗口来匹配记录(尽管我必须使用不同步的时间源跨不同的数据源工作 [关闭几分钟] )。无论如何,我发现做到这一点的最简单方法是首先将所有数据按时间升序插入临时表(就像你正在做的那样),然后通过从中选择并将其连接回自身来对表进行修改来确定更新值。如果您对此技术有任何疑问,请联系我SO C# Chat
  • 也许您可以创建一个表值函数来进行匹配并将CROSS APPLY 与第一个表一起使用?无论如何,我想在服务器上这样做会更有效率。

标签: c# sql sql-server database c#-4.0


【解决方案1】:

最终,在 99% 的情况下,最好在数据库端编译您的数据,因为它是为数据处理而设计的(通过使用索引、关系等)。许多代码可以通过使用连接来合并,以完全按照您需要的格式编译数据。事实上,您可以完全绕过几乎所有的临时表,只需填写一个主事件临时表。

一般模式是这样的:

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

通过这种方式,您可以将所有火灾事件与零个或多个 HitEvents 匹配。在我们在聊天中讨论之后,您甚至可以通过将其包装在子查询中并为ROW_NUMBER() OVER (PARTITION BY HitEvent.EventID ORDER BY ...) AS HitRank 使用窗口函数并将WHERE HitRank = 1 添加到外部查询来将其限制为零或一个命中事件。这最终是您最终所做的事情并得到了您期望的结果(在此过程中进行了一些工作和学习)。

【讨论】:

    【解决方案2】:

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

    您的任务可能不需要使用任何临时表。当临时表相对较小和/或重用率较高时,临时表往往很有效,但您的情况并非如此。

    【讨论】:

    • 好的,那么您将如何查找此 SP 中的瓶颈?我听说过查询计划,但我以前不必使用它们,因为我的 SP 总是非常简单!你能给我一个白痴指南吗? :)
    • 放弃一切和谷歌“sql server show plan”或“query performance”!!!!!!现在。请 - 这很重要!恕我直言...
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      • 将一百万行加载到 c# 程序中并不是一个好的做法。除非这是一个具有大量内存的独立进程。
      • 唯一标识符的性能永远不会超过整数。 Comparisons
      • 公用表表达式是快速执行匹配的好选择。如何使用CTE
      • 最后你必须考虑输出。如果存在影响用户界面的持续读写,则应在内存中进行管理 (c#),否则所有 CRUD 操作都应保存在数据库中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-30
        • 1970-01-01
        • 1970-01-01
        • 2015-06-01
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多