.NET 中有啥比 SqlDataReader 更快的吗?
Posted
技术标签:
【中文标题】.NET 中有啥比 SqlDataReader 更快的吗?【英文标题】:Is there anything faster than SqlDataReader in .NET?.NET 中有什么比 SqlDataReader 更快的吗? 【发布时间】:2011-04-13 04:03:05 【问题描述】:我需要使用 C# 将 SqlServer 表中的一列字符串加载到内存中的数组中。 有没有比打开 SqlDataReader 并循环遍历它更快的方法。 表很大,时间很关键。
编辑 我正在尝试构建 .dll 并在服务器上使用它来对数据库进行一些操作。但现在要放慢速度。如果这比我必须重新设计数据库最快。我很难有一些解决方案如何加快速度。
【问题讨论】:
【参考方案1】:数据阅读器
使用SqlDataReader 可以最快地访问 SQL。
描述它
值得真正分析一下您的性能问题出在哪里。通常,您认为存在性能问题的地方,在您对其进行概要分析后被证明是完全错误的。
例如它可能是:
-
运行查询所需的时间...
跨网络/进程边界复制数据所需的时间
.Net 将数据加载到内存所花费的时间
时间...你的代码需要用它来做某事
单独分析其中的每一个可以让您更好地了解瓶颈所在。对于分析您的代码,有一个great article from Microsoft
缓存它
提高性能的重点是确定如果您每次都需要加载所有数据。可以缓存列表(或其中的一部分)吗?看看新的System.Runtime.Caching 命名空间。
重写为 T-SQL
如果您正在执行纯粹的数据操作(如您的问题所示),您可以将使用数据的代码重写为 T-SQL 并在 SQL 上本地运行。这有可能会更快,因为您将直接处理数据而不是移动它。
如果您的代码有很多必要的过程逻辑,您可以尝试将 T-SQL 与 CLR Integration 混合使用,从而获得两全其美的好处。
这很大程度上归结于您的逻辑的复杂性(或更多的程序性质)。
如果一切都失败了
如果所有区域都是最佳的(或尽可能接近),并且您的设计没有错误。我什至不会进行微优化,我只会throw hardware at it。
什么硬件?试试reliability and performance monitor 找出瓶颈在哪里。您描述的问题最有可能出现在 HDD 或 RAM 上。
【讨论】:
我已经测试了一些东西,SqlDataReader 显然比 DataSet 快;)是的,加载时间是性能最差的。 而且我没有发送到客户端,.dll 与服务器在同一台机器上用于某些内部使用。 +1 表示“重写为 T-SQL”。理想的查询是只检索绝对必要的数据。如果您要检索 100k 行到客户端应用程序,然后在那里处理,那么也许您应该重新考虑您的逻辑。 向它扔硬件并没有真正的帮助。 SqlClient 使用基于数据包大小的内部缓冲区。最大数据包大小为 32768 字节,这将影响吞吐量。没有任何合理的硬件可以帮助你。 @JörgenSigvardsson - 这是假设您的性能问题与网络速度和数据量有关。可能是,但我会先看很多其他地方。【参考方案2】:如果SqlDataReader
不够快,也许您应该将您的内容存储在其他地方,例如(内存中)缓存。
【讨论】:
同意——你能提前加载数据并从内存中的集合中迭代吗?【参考方案3】:没有。它实际上不仅是最快的方式 - 它是唯一(!)方式。无论如何,所有其他机制在内部都使用 DataReader。
【讨论】:
【参考方案4】:我怀疑SqlDataReader
和你想得到的一样好。
【讨论】:
哈!是否有任何一个反对者愿意详细说明这个答案有什么问题?【参考方案5】:SqlDataReader 是最快的方法。确保您使用按序号方法获取,而不是按列名获取。例如获取字符串(1);
另外值得尝试的是在连接字符串中使用 MinPoolSize,以便池中始终存在一些连接。
【讨论】:
你能解释一下关于 MinPoolSize 的更多信息吗,我不明白这应该有什么帮助? .Net DB 连接在关闭后返回到连接池,然后在一段时间不活动后最终关闭底层 SQL 服务器连接。这会生成登录和注销事件。在某些情况下(不频繁的 Web 服务调用),在池中始终有一些准备好的连接以快速处理第一个请求而不是必须打开与 SQL 服务器的新连接可能是有益的。【参考方案6】:SqlDataReader 将是最快的方法。 优化使用,使用合适的Getxxx方法,参数为序数。
如果速度不够快,请查看是否可以调整查询。在要检索的列上放置一个覆盖索引。这样,Sql Server 只需要读取索引,而不必直接去表中检索所有需要的信息。
【讨论】:
查询只是一列选择,那里没有优化的地方,只能重新设计数据库;( @watbywbarif 即使在单列选择上,索引仍然会有所帮助 您是否创建了一个仅包含您选择的单列的索引?【参考方案7】:如果将一列行转换为一列,并且只有一行要读取呢? SqlDataReader
对读取单行进行了优化(ExecuteReader
的System.Data.CommandBehavior.SingleRow
参数),所以也许它可以提高一点速度。
我看到了几个优点:
单行改进, 无需在每次迭代时访问数组 (reader[0]
),
将一个数组 (reader
) 克隆到另一个数组可能比遍历元素并将每个元素添加到一个新数组更快。
另一方面,强制 SQL 数据库做更多的工作也有一个缺点。
【讨论】:
这听起来很奇怪,但是由于这个 .dll 在服务器上使用,似乎我通过 SqlDataReader 获得的数据比通过在 SQL 中构建一行更丰富。【参考方案8】:“提供了一种从 SQL Server 数据库中读取只进的行流的方法”这是对 MSDN 中的 SqlDataReader 的使用。 SqlDataReder 背后的数据结构只允许向前读取,它针对单向读取数据进行了优化。在我看来,我想使用 SqlDataReader 而不是 DataSet 来进行简单的数据读取。
【讨论】:
【参考方案9】:您有 4 组间接费用 - 磁盘访问 - .net 代码(CPU) - SQL 服务器代码(CPU) - 是时候在托管代码和非托管代码 (cpu) 之间切换了
首先是
select * where column = “junk”
对你来说足够快,如果不是唯一的解决方案就是让磁盘更快。 (您从 SQL Server 获取数据的速度比读取数据的速度更快)
您可以在 C# 中定义一个 Sql Server 函数,然后在列上运行该函数;抱歉,我不知道该怎么做。这可能比数据读取器更快。
如果您有多个 CPU,并且您知道表格中间的值,则可以尝试使用多个线程。
您可以编写一些 TSQL,使用您知道是安全的分隔符将所有字符串组合成一个字符串。然后在 C# 中再次拆分字符串。这将减少托管代码和非托管代码之间的往返次数。
【讨论】:
不知道 SqlDataReader 顺序读取时,更多线程如何加快数据加载速度? 每个线程都可以使用它自己的SqlDataReader,前提是你可以在“where”中定义线程之间的数据。 好主意,也许它可以帮助。 +1【参考方案10】:需要考虑的一些可能影响速度的表面因素(数据读取器除外):
-
数据库查询优化
OrderBy 很贵
不同的是昂贵的
RowCount 很昂贵
GroupBy 很昂贵
等。有时你不能没有这些东西,但如果你可以在你的 C# 代码中处理其中一些东西,它可能会更快。
数据库表索引(对于初学者,WHERE 子句中的字段是否被索引?)
数据库表数据类型(在给定数据的情况下,您是否使用尽可能小的数据类型?)
为什么要将数据读取器转换为数组?
例如,是否也可以创建一个适配器/数据表,然后您就不需要将其转换为数组?
您是否研究过实体框架? (可能会更慢......但如果你没有选择,可能值得研究一下以确保)
只是随机的想法。不确定什么对您的情况有帮助。
【讨论】:
排序、分组等在 C# 中比在 SQL 中处理得更快?这似乎不太可能,但也许你知道一些我不知道的事情。【参考方案11】:如果响应性是加载大量数据的问题,请考虑使用异步方法 - BeginReader。
我一直使用它在后台填充大型 GUI 元素,同时应用程序继续响应。
您还没有确切说明这些数据有多大,或者为什么要将它们全部加载到数组中。
通常,对于大量数据,您可能希望将其保留在数据库中或让数据库完成繁重的工作。但是我们需要知道您正在执行哪种处理,需要一次将所有处理都放在一个数组中。
【讨论】:
响应能力不是问题。以上是关于.NET 中有啥比 SqlDataReader 更快的吗?的主要内容,如果未能解决你的问题,请参考以下文章
有啥比 document.execCommand 更好的吗?