循环大量的记录

时间:2012-07-12 23:16:58

标签: c# winforms performance postgresql query-optimization

我有一个位于网络中的postgre服务器,我正在使用数据库。 我需要查看大量的记录(1mil +),每次选择都需要时间。

这是我目前的方法:

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++; 
}); 

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

1 个答案:

答案 0 :(得分:8)

优化要点:

  • 创建命名类型,并使用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);
});