首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >拿( 10 )和前10( SqlDataReader )?

拿( 10 )和前10( SqlDataReader )?
EN

Stack Overflow用户
提问于 2016-07-27 09:25:33
回答 2查看 1.5K关注 0票数 1

我有一个使用SqlDataReader读取数据并返回IEnumerable的方法,例如:

代码语言:javascript
复制
IEnumerable<string> LoadCustomers()
{
 using(SqlDataReader rdr = cmd.ExecuteReader())
 {
    while (rdr.Read())
    {
        yield return rdr.GetString(0); 
    }
 }
}

现在让我们假设我只需要最新的10个客户。我可以

代码语言:javascript
复制
LoadCustomers.Take(10)

或将10作为参数传递给sql并使我的sql

代码语言:javascript
复制
SELECT TOP 10 FROM Customers ORDER BY CreationDate DESC

根据this post,整个结果集将从server传输到客户端,即使数据中心只读取几行(只要连接打开)--我是否应该避免使用Take(10)方法,因为额外的数据无论如何都要传输给客户端,或者避免它是一个过早的优化(因为生成的返回代码将在读取10行之后关闭连接,然后数据传输无论如何都会停止)?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-29 10:48:59

由于优化是否“过早”是主观的,所以我选择将这个问题解释为“使用DataReader并在10行后停止读取与在查询中使用TOP(10)具有相同的性能特征吗?”

答案是否定的。将TOP(10)传递给服务器允许优化器调优读、内存授予、I/O缓冲区、锁定粒度和并行性,同时知道查询最多将返回10行(在本例中也是读取)。省略TOP意味着它必须为客户机将读取所有行的情况做好准备--不管您是否确实提前停止了。

不管读取与否,服务器都不会发送行。使用SqlDataReader拖动行在概念上是逐行操作:当您发出Reader.MoveNext时,您将从服务器获取下一行,并且只获取该行。但为了性能起见,在请求行之前会对行进行缓冲(无论是在服务器端,还是在网络缓冲区中)。因此,可以在第一次.MoveNext调用之后在缓冲区中检索100行,即使您只读取其中的10行。

关于开销,这并不是我最关心的问题,因为这些缓冲区最终都有固定的大小:无论有多少行,服务器都不会去缓冲结果集的所有行(这通常是非常低效的)。如果您只读取10行,那么如果查询运行完成,您的查询最终会返回1,000或1,000,000行,这在缓冲方面并不重要,而主要取决于查询计划。尽管如此,它确实增加了开销。

票数 2
EN

Stack Overflow用户

发布于 2016-07-27 10:09:57

您还可以使用分页Skip(0)并采取(10)更多的灵活性。

SQL SERVER 2012

代码语言:javascript
复制
SELECT name,
       CreationDate        
  FROM customer
 ORDER BY
       CreationDate      
OFFSET @skip ROWS
FETCH NEXT @take ROWS ONLY;

SQL 2005至2008

代码语言:javascript
复制
SET @take = (@skip + @take)

;WITH customer_page_cte AS
(SELECT 
        name, 
        CreationDate,
        ROW_NUMBER() OVER (ORDER BY CreationDate desc) AS RowNumber
 FROM customer
)

SELECT name, 
       CreationDate
  FROM customer_page_cte
 WHERE RowNumber > @skip AND RowNumber <= @take

使用SQL2012的C# -使用用于命令的存储过程:)

代码语言:javascript
复制
var command = @"SELECT name,
                       CreationDate        
                  FROM customer
                 ORDER BY
                       CreationDate      
                 OFFSET @skip ROWS
                 FETCH NEXT @take ROWS ONLY;";

            using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Stackoverflow;Integrated Security=True"))
            {
                conn.Open();
                using (var cmd = new SqlCommand(command, conn))
                {
                    cmd.Parameters.AddWithValue("skip", 0);
                    cmd.Parameters.AddWithValue("take", 10);

                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine(reader.GetString(0));
                    }
                }
            }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38608926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档