从数据库中检索大量记录

时间:2011-03-28 23:42:05

标签: c# sql-server database wcf

在我的Windows应用程序中,有时我必须运行返回10000条记录的查询。我正在使用WCF服务来检索数据,有时因为数据量很大而非常慢。我正在使用SQL Server 2008数据库。

我想为我的sql查询检索100×100的记录,返回10000条记录。有办法处理这种情况吗? SQL游标可以满足这个要求吗?

基本上它与网格上的分页或实时渲染数据有些相似。但我希望在客户端机器出现之前就开始显示记录。当数据量巨大时,我习惯于创建用于数据检索的BackgroundWorker,但我不确定如何将这两种功能结合起来。如果你能给我看样品,那就太好了。

4 个答案:

答案 0 :(得分:2)

您可以使用带有Row_Number排名功能的公用表表达式......以下是我编写的一些代码中的示例:

CREATE PROCEDURE PagingSample
  @PageNumber int,
  @PageSize int
AS

WITH Results AS (
  SELECT 
    ROW_NUMBER() OVER(ORDER BY MR.MRN ASC) As RowNumber,
    MR.MRN
FROM 
  dbo.SomeTable MR WITH (NOLOCK)    
)

SELECT 
  R.RowNumber,
  R.MRN
FROM
  Results R
WHERE
  RowNumber > (@PageNumber * @PageSize) - @PageSize 
  AND RowNumber < (@PageNumber * @PageSize) + 1 

现在将页码和页面大小传递给sproc,如下所示:

Exec PagingSample @PageNumber = 3, @PageSize = 100

您将获得201到300的记录

答案 1 :(得分:2)

我有一个类似的问题,我不得不在WCF上传输数百万行。对我有用的是一个分块频道。

在服务器端,你的类实现了以下几点:

void InitQuery(QueryString); // initializes datareader that pulls result out of DB
YourClass[] GetChunk(int ChunkSize); // puts the next x elements from the reader into array. If it returns null you're done.

从客户端,您使用第一个设置查询,然后从第二个读取块。你不必担心sql查询中的分页等,只需从阅读器获取下一个x记录,将它们放入DataContract类并返回它。 SqlDataReader会跟踪您的位置。 (对于许多用户而言,这可能无法很好地扩展)

确保在服务器的调用之间保持代理服务器,因为它维护状态。查看SessionMode。

此外,通过TCP运行并摆弄安全设置,我获得了巨大的性能提升。

您没有提到您正在使用的内容,WinForms或WPF,但它们都支持将数据延迟加载到网格中的方法。你想从后台线程调用GetChunk,当它有结果时,将整个数组传递给UI线程,然后循环它。 (不要从后台线程循环它,因为你需要为数组中的每一行调用。这会很慢)

我努力学习一些东西,如果你需要任何细节,请告诉我。

答案 2 :(得分:1)

我认为不需要使用BackgroundWorker,因为需要使用页面加载数据。如果您希望在页面的其余部分之前显示您的数据,我想象的唯一方法是将几乎空的HTML页面发送回客户端,其中一些JS在页面加载时执行,然后返回到服务器获取网格数据(通过ajax)和页面的其余部分。这可能是一项繁琐而混乱的任务。

您可以采取的方法是仅加载网格数据第一页所需的记录。您可以考虑Google搜索结果,它不会将所有这些搜索结果加载到内存或您的页面中,只会加载第一页数据。当您需要更多结果时,它会检索它们。

要在特定记录范围内从您的数据库获取记录,您可以使用这样的查询来获取记录1到100.

SELECT UserID, FirstName
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY UserID, FirstName) AS ROW_NUM, UserID, FirstName
    FROM Users.Users
    ) as T1
WHERE T1.ROW_NUM BETWEEN 1 AND 100
ORDER BY T1.ROW_NUM

这个SQL显然会被放入存储过程并使用参数调用。

答案 3 :(得分:1)

我可能错了,所以我没有发布新帖子,而是发布了我的问题,这可能是对这篇文章的回答。

我认为最重要的是让用户第一眼看到他想要做的事情,如果他从数据库获取学生记录并且他必须获得1000个结果然后用户不愿意等待查询被处理因为我觉得重要的是你得到数据并尽快显示。

我认为查询应该被划分为数据范围并一次获取一小部分,但如果您使用点网框工作4.0,那么Parallel Loops将有助于此

我看到与常规循环相比性能良好