从DB中获取大约一百万条记录的最佳方法是什么?

时间:2010-10-16 17:30:13

标签: .net asp.net sql-server

我需要在网页上获取和显示数据,其记录数量可能因大约500条记录到100万条记录的过滤器而异。

缓存在这里有用,因为我认为记忆中的百万记录不是一个好主意。 SqldataReader

当然,分页是必须实现的。显示100万条记录是最糟糕的情况(使用案例中的愚蠢All filter。)。

我应该使用连接架构(SqlDataReader)还是断开连接的架构(DataSet)?

4 个答案:

答案 0 :(得分:11)

首先,想一想:显示100万条记录对任何用户都没有意义。因此,您必须考虑用户期望看到的内容。也许总结一下?!也许可以将这些记录分页为25或50或100条记录。这些方法中的任何一种都不需要您在内存中一次保存1 M条记录。

此外,当您对SQL数据库运行查询并使用SqlDataReader时,您将不会收到所有记录,而是SQL驱动程序将查询发送到SQL服务器,服务器将执行查询,准备结果在服务器上设置并创建只进游标。然后,每次在SqlDataReader上调用Read()时,驱动程序将一次获取一条记录。如果使用使用延迟执行的LINQ to SQL,则行为非常相似。结果集不会被完全转移,直到(或除非)您具体请求每一行。

因此,一个简单的分页查询就可以了。或者在其他情况下,某种汇总报告汇总来自这100万条记录的数据,一页或两页相关数据。

当然,如果你确实需要在页面中来回移动,那么某种缓存可能会有意义,但请再想一想:用户实际想要浏览100万条记录的频率 - 可能永远不会。 / p>

作为最后一点,如果你实现了分页 - 请确保用于实现分页的方法依赖于SQL Server一次发送一页数据而不是将所有100万条记录读入ASP.NET然后对数据的本地副本进行分页,因为这样效率很低且速度很慢。以下是执行分页的SQL Server查询示例:SO Question #109232

答案 1 :(得分:3)

我同意其他的回答者。显示1M记录是荒谬的。但是,您可以显示前X个记录,并翻阅。

技巧是在存储过程中进行提取

ALTER PROCEDURE [dbo].[MyHugeTable_GetWithPaging] 
( 
        @StartRowIndex      int, 
        @MaximumRows        int 
) 

AS 
SET NOCOUNT ON 

Select 
    RowNum, 
    [UserName]
From 
    (Select 
        [ID], 
        [UserName]
        Row_Number() Over(Order By [ID] Desc) As RowNum 
        From dbo.[MyHugeTable] t) 
As DerivedTableName 
Where RowNum Between @StartRowIndex And (@StartRowIndex + @MaximumRows) 

答案 2 :(得分:1)

如果您的服务器无法缓存100万条记录,您认为您的用户的网络浏览器将如何处理100万条记录的HTML记录呢?

考虑分页(here is an example with 1 million records

还要考虑用户永远不会想要超过30到50条记录。您要么显示的细节太低,要么需要更多过滤。

答案 3 :(得分:0)

我建议使用动态查询和分页。因此,当您单击特定页面时,仅为这些页面提取记录。要从特定范围从数据库中获取记录,请使用以下查询。

像这样。

Create proc Test

@take smallint,
@skip smallint,
@orderBy nvarchar(20),
@subscriptionid smallint,


as 

DECLARE @SQLQuery AS NVARCHAR(max)

SET @SQLQuery=' Select ROW_NUMBER() OVER (ORDER BY P.ProductId desc) as RowNum,* from product"

set @SQLQuery=@SQLQuery + ' and Subscriptionid='+CONVERT(nvarchar, @subscriptionid) 

set @SQLQuery= ';WITH Results_CTE AS ( '+@SQLQuery

    set @SQLQuery= @SQLQuery +' ) SELECT * FROM Results_CTE WHERE RowNum > '+CONVERT(nvarchar, @skip)+' AND RowNum <= '+CONVERT(nvarchar, @skip+@take)  --//paging';
END

EXECUTE sp_executesql @SQLQuery