【问题标题】:Listing more than 10 million records from Oracle With C#使用 C# 列出来自 Oracle 的超过 1000 万条记录
【发布时间】:2012-01-09 12:51:48
【问题描述】:

我有一个包含超过 1 亿条记录的数据库。我正在运行一个包含超过 1000 万条记录的查询。这个过程需要太多时间,所以我需要缩短这个时间。我想将获得的记录列表保存为 csv 文件。我怎样才能尽可能快速和优化地做到这一点?期待您的建议。谢谢。

【问题讨论】:

  • 请发布表结构、现有查询和 C# 代码的详细信息。加上“太多时间”对您的场景意味着什么的想法。性能主要与上下文有关。
  • 还发布您用于选择数据的标准...这可能会影响表分区、索引等。
  • 为什么你真的需要显示或导出这么多数据?最终用户真的要阅读或分析 1000 万条记录吗?与其只是给出通常的解决方案并仅仅满足客户的要求,我建议您应该向客户询问业务端或最终要求并进行处理。
  • 其他:你的文件格式是固定的吗?目的是什么?请记住,即使您在 Excel 2007 中打开该 CSV,Excel 也无法(据我所知)处理 1000 万行。 2007 年之前的限制是 65000(!)
  • @TathagatVerma:99% 的生成 CSV 是关于将数据发送到另一个应用程序/系统

标签: c# performance oracle


【解决方案1】:

“这个过程耗时太长,所以我需要缩短这个时间。”

这个过程由三个子过程组成:

  1. 检索 > 10m 条记录
  2. 将记录写入文件
  3. 通过网络传输记录(我的假设是您正在使用本地客户端处理远程数据库)

任何或所有这些问题都可能成为瓶颈。所以,如果你想减少总运行时间,你需要弄清楚时间花在了哪里。您可能需要检测您的 C# 代码以获取指标。

如果事实证明查询是问题所在,那么您将需要对其进行调整。索引在这里没有帮助,因为您要检索表的一大块 (> 10%),因此提高全表扫描的性能会有所帮助。例如增加内存以避免磁盘排序。并行查询可能很有用(如果您有企业版并且有足够的 CPU)。还要检查问题不是硬件问题(主轴争用、不可靠的互连等)。

写入文件会是问题吗?也许您的磁盘由于某种原因(例如碎片)很慢,或者您正在与写入同一目录的其他进程竞争。

通过网络传输大量数据显然是一个潜在的瓶颈。您确定您只是向客户端发送相关数据吗?

另一种架构:使用 PL/SQL 将记录写入数据服务器上的文件,使用批量收集检索可管理的记录批次,然后通过 FTP 将文件传输到最后需要的位置先压缩它。

【讨论】:

    【解决方案2】:

    真正的问题是为什么您需要从数据库中读取如此多的行(以及如此大比例的基础数据集)。有很多方法可以避免这种情况,显而易见的是同步处理、消息队列和预整合。

    暂且不说……如果您要合并或筛选数据,那么在 PL/SQL 中实现大部分逻辑就不必通过网络传输数据(即使只是到本地主机,仍然有很大的开销)。同样,如果您只是想dump it out into a flat file,那么在 C# 中实现它对您没有任何帮助。

    【讨论】:

      【解决方案3】:

      您需要在 C# 中执行此操作的可能性很小。这是批量数据加载/导出的领域(常用于数据仓库场景)。

      许多(免费)工具(我想甚至是 Quest Software 的 Toad)会比您在任何平台上编写的工具更强大、更有效地做到这一点。

      我有一种预感,最终用户实际上并不需要这个(简单的观察是部门秘书实际上不需要邮寄副本;它太大而无用大大地)。

      我建议使用正确的工具来完成这项工作。不管你做什么,

      • 不要滚动您自己的数据类型转换
      • 使用带引号的文字的 CSV 并考虑转义其中的双引号
      • 考虑区域选项(IOW:始终使用 InvariantCulture 进行导出/导入!)

      【讨论】:

      • "将比您在任何平台上编写它更健壮、更有效地执行此操作。"你觉得这些工具是用什么写的?如果它们不在数据库引擎上运行,它们将使用相同的协议来获取数据。除非相关点是“你不能写”:)
      • @AlexNorcliffe:你明白了!在我不那么谦虚的观点中,具有适当经验水平的程序员不会问这个问题。
      • 我变得更谦虚了。如果我要重写那条评论,我觉得没有必要直截了当地说。为子孙后代保留它,​​以便我们可以看到人们学习。
      【解决方案4】:

      我假设您的查询已经被限制在您需要的行/列中,并且充分利用了索引。

      在这种规模下,唯一关键的事情是您不要尝试一次将其全部加载到内存中;所以忘记像DataTable 和大多数完整的ORM(通常尝试将行与身份管理器和/或变更管理器相关联)。您将不得不使用原始的IDataReader(来自DbCommand.ExecuteReader),或者在其top上构建非缓冲迭代器的任何API(有几个;我偏向于小巧玲珑)。出于编写 CSV 的目的,原始数据读取器可能没问题。

      除此之外:您无法让它更快,因为您受到带宽限制。获得它的唯一方法是在数据库服务器上创建 CSV 文件,这样就没有网络开销。

      【讨论】:

        猜你喜欢
        • 2014-07-09
        • 1970-01-01
        • 1970-01-01
        • 2012-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-14
        相关资源
        最近更新 更多