【问题标题】:Looping over large amount of records循环大量记录
【发布时间】:2012-07-12 23:16:57
【问题描述】:

我有一个位于网络中的 postgre 服务器,我正在使用数据库。 我需要检查大量记录(超过 100 万条),而且每次选择都需要时间。

这是我目前的方法:

DataSet ds = new psqlWork().getDataSet("SELECT * FROM z_sitemap_links"); 
DataTable dt = ds.Tables[0]; 
Parallel.ForEach(dt.AsEnumerable(), dr => 
{ 
    new Sitemap().runSitemap(dr[1].ToString(), counter); 
    counter++; 
}); 

但是当数据库大小增加时,这种方法(在我看来)不会那么有效。你能建议一个更好的方法吗?也许将数据拉到块中进行处理;虽然我现在不知道如何管理。

【问题讨论】:

  • "SELECT * FROM z_sitemap_links" 你真的需要所有的列吗?
  • 永远不要在大型​​数据库上使用SELECT *
  • 是的,表格只包含链接;没有别的
  • 所以只有一列?然后只需选择一列。另外,请参阅下面的注释,并提供适当的反馈。

标签: c# winforms performance postgresql query-optimization


【解决方案1】:

优化要点:

  • 创建命名类型,并使用 ADO.NET 读取命名类型,而不是使用 DataSetDataTable,这将减少一些内存占用。
  • 只提取您实际需要使用的记录(您通常不需要引入超过一百万条记录,但我们不知道您的业务逻辑)

澄清原始帖子的问题:

  • 您是否有理由说明将来无法扩展?
  • 您是如何处理利用Parallel.ForEach 的?如果底层系统有它的能力,你可能会很好地使用你现在拥有的方法。另请考虑,您可能应该分析实际性能,而不是仅仅猜测会发生什么。
DataSet ds = new psqlWork().getDataSet(@"
  SELECT * FROM z_sitemap_links 
  order by timestamp asc /*always order when skipping records so you get the same skips */
  LIMIT 100000 /* using these two with variables you could skip so many records /*
  OFFSET 100000 /* depending on what you're aiming for */
"); 
DataTable dt = ds.Tables[0]; 
Parallel.ForEach(dt.AsEnumerable(), dr => 
{ 
    new Sitemap().runSitemap(dr[1].ToString(), counter); 
    counter++; 
}); 

而且,如果你可以使用这样的东西:row_number() OVER (ORDER BY col1) AS i 那么你可以跳过计数器,因为当你选择返回的行时会为你提供,但我的 postgres 知识并没有告诉我这是否会从上面的代码中每次都是 1..100000,或者如果它是你想要的,但是Database Administrators 的人肯定知道。这意味着您的代码将变为:

Parallel.ForEach(recordList, record => 
{ 
    new Sitemap().runSitemap(record.FieldYouNeed, record.RowNumberFromDatabase);
}); 

【讨论】:

  • +1。特别是对于澄清的好点。帖子中的“(在我看来)”测量并不是非常令人信服的论点,即代码需要优化(甚至使用 Parallel.ForEach 来处理潜在的 I/O 绑定任务)。
猜你喜欢
  • 1970-01-01
  • 2011-09-08
  • 1970-01-01
  • 2019-05-11
  • 2011-10-03
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
相关资源
最近更新 更多