43

I need to load one column of strings from table on SqlServer into Array in memory using C#. Is there a faster way than open SqlDataReader and loop through it. Table is large and time is critical.

EDIT I am trying to build .dll and use it on server for some operations on database. But it is to slow for now. If this is fastest than I have to redesign the database. I tough there may be some solution how to speed thing up.

4

11 回答 11

56

数据阅读器

关于 SQL 的最快访问是使用SqlDataReader

剖析它

值得真正分析一下您的性能问题在哪里。通常,您认为性能问题所在的地方,在您对其进行分析后被证明是完全错误的。

例如,它可能是:

  1. 时间......查询运行所需的时间
  2. 时间......数据跨网络/进程边界复制所需的时间
  3. 时间...... .Net将数据加载到内存中
  4. 时间......你的代码需要做一些事情

单独分析其中的每一个将使您更好地了解瓶颈所在。对于分析您的代码,Microsoft 有一篇很棒的文章

缓存它

提高性能要考虑的事情是确定您是否每次都需要加载所有数据。可以缓存列表(或其中的一部分)吗?看看新的System.Runtime.Caching命名空间。

重写为 T-SQL

如果您正在执行纯粹的数据操作(正如您的问题所暗示的那样),您可以将使用数据的代码重写为 T-SQL 并在 SQL 上本地运行。这有可能会更快,因为您将直接处理数据而不是移动它。

如果您的代码有很多必要的过程逻辑,您可以尝试将 T-SQL 与CLR 集成混合使用,从而获得两全其美的好处。

这很大程度上取决于您的逻辑的复杂性(或更程序性)。

如果一切都失败了

如果所有区域都是最佳的(或尽可能接近),并且您的设计没有错误。我什至不会进行微优化,我只会向它扔硬件

什么硬件?尝试使用可靠性和性能监视器来找出瓶颈所在。您描述的问题最有可能出现在 HDD 或 RAM 上。

于 2010-09-16T11:31:47.947 回答
19

如果SqlDataReader速度不够快,也许您应该将您的东西存储在其他地方,例如(内存中)缓存。

于 2010-09-16T11:26:51.730 回答
18

不,它实际上不仅是最快的方式 - 它是唯一的(!)方式。无论如何,所有其他机制内部都使用 DataReader。

于 2010-09-16T11:23:19.060 回答
8

我怀疑这SqlDataReader和你得到的一样好。

于 2010-09-16T11:18:44.833 回答
5

SqlDataReader 是最快的方法。确保您使用按序号方法获取,而不是按列名获取。例如 GetString(1);

同样值得尝试的是在连接字符串中使用 MinPoolSize,以便池中始终存在一些连接。

于 2010-09-16T11:37:37.783 回答
3

SqlDataReader 将是最快的方法。通过使用适当的 Getxxx 方法来优化它的使用,该方法以序数作为参数。

如果速度不够快,请查看是否可以调整查询。在要检索的列上放置一个覆盖索引。通过这样做,Sql Server 只需要读取索引,而不必直接去表中检索所有需要的信息。

于 2010-09-16T12:07:20.757 回答
2

将一列行转换为一列,并且只有一行要读取呢?SqlDataReader对读取单行(System.Data.CommandBehavior.SingleRow的参数ExecuteReader)进行了优化,所以也许它可以提高一点速度。

我看到几个优点:

  • 单行改进,
  • 无需在每次迭代时访问数组 ( reader[0]),
  • 将一个数组 ( reader) 克隆到另一个数组可能比遍历元素并将每个元素添加到新数组更快。

另一方面,强制 SQL 数据库做更多的工作也有一个缺点。

于 2010-09-16T11:30:01.660 回答
1

需要考虑的一些可能影响速度的表面因素(除了数据读取器):

  1. 数据库查询优化
    • OrderBy 很贵
    • 不同的很贵
    • 行数很贵
    • GroupBy 很贵
    • 等等。有时你不能没有这些东西,但如果你可以在你的 C# 代码中处理其中一些东西,它可能会更快。
  2. 数据库表索引(对于初学者,您的 WHERE 子句中的字段是否被索引?)
  3. 数据库表数据类型(给定数据,您是否使用尽可能小的数据类型?)
  4. 为什么要将数据读取器转换为数组?
    • 例如,创建一个适配器/数据表是否同样有用,然后您就不需要将其转换为数组?
  5. 您是否研究过实体框架?(可能会更慢......但如果你没有选择,可能值得研究一下以确保)

只是随意的想法。不确定对您的情况有什么帮助。

于 2010-09-16T18:39:28.977 回答
1

“提供了一种从 SQL Server 数据库中读取只进的行流的方法” 这是对 MSDN 中 SqlDataReader 的使用。SqlDataReder 背后的数据结构只允许向前读取,它针对单向读取数据进行了优化。在我看来,我想使用 SqlDataReader 而不是 DataSet 来进行简单的数据读取。

于 2010-09-16T11:34:39.297 回答
1

您有 4 组开销 - 磁盘访问 - .net 代码 (cpu) - SQL 服务器代码 (cpu) - 在托管和非托管代码之间切换的时间 (cpu)

首先是

select * where column = “junk” 

对您来说足够快,如果不是唯一的解决方案是使磁盘更快。(您从 SQL Server 获取数据的速度比读取数据的速度要快)

您可以在 C# 中定义一个 Sql Server 函数,然后在列上运行该函数;抱歉,我不知道该怎么做。这可能比数据读取器更快。

如果您有多个 CPU,并且您知道表中间的值,则可以尝试使用多个线程。

您也许可以编写一些 TSQL,使用您知道是安全的分隔符将所有字符串组合成单个字符串。然后在 C# 中再次拆分字符串。这将减少托管代码和非托管代码之间的往返次数。

于 2010-09-16T14:44:32.580 回答
0

如果响应性是加载大量数据的问题,请考虑使用异步方法 - BeginReader。

我一直使用它在后台填充大型 GUI 元素,同时应用程序继续响应。

您还没有确切地说出这些数据有多大,或者为什么要将它们全部加载到数组中。

通常,对于大量数据,您可能希望将其保留在数据库中或让数据库完成繁重的工作。但是我们需要知道你正在做什么样的处理,需要一次将它们全部放在一个数组中。

于 2010-09-16T13:25:32.753 回答