Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将大型SQL server表拉入C进行分析_C#_Sql_Sql Server_Large Data - Fatal编程技术网

C# 如何将大型SQL server表拉入C进行分析

C# 如何将大型SQL server表拉入C进行分析,c#,sql,sql-server,large-data,C#,Sql,Sql Server,Large Data,我需要一些关于如何最好地解决这个问题的建议。我继承了一个从现有SQL server数据库构建报表实用程序的项目。数据库包含一个原始数据表,其中每个生产数据点都被转储。报告需要提供几个数据列的平均值和Cpk 原始数据表包含25列,包括ID列、LotID列和TimeStamp列,以及包含度量数据的5列。总的来说,该表似乎有2000多万条记录,基本上是一个巨大的平面文件 我需要做的是提供两种搜索方法;按日期范围和批次ID。一个批次ID可以保存多达200万条记录 我首先开发了一个使用简单选择查询的C应用

我需要一些关于如何最好地解决这个问题的建议。我继承了一个从现有SQL server数据库构建报表实用程序的项目。数据库包含一个原始数据表,其中每个生产数据点都被转储。报告需要提供几个数据列的平均值和Cpk

原始数据表包含25列,包括ID列、LotID列和TimeStamp列,以及包含度量数据的5列。总的来说,该表似乎有2000多万条记录,基本上是一个巨大的平面文件

我需要做的是提供两种搜索方法;按日期范围和批次ID。一个批次ID可以保存多达200万条记录

我首先开发了一个使用简单选择查询的C应用程序

SELECT * 
FROM tblRawData 
WHERE [LotID] = "XXXX"
然后使用SqlDataAdapter.Fill函数填充数据表。我还尝试了SqlDataReader并循环将结果填充到DataTable中

我所看到的最大问题是90%以上的内存使用率,其中大部分在SQL Server进程上,偶尔会出现内存不足警告,并且每个查询需要几分钟才能运行


作为一名SQL Server专家,我正在寻求关于这种方法是否合理的建议,或者我是否应该考虑做一些不同的事情?

2000万条记录通常不会被视为大量数据,除非您的服务器速度慢,或者您的数据集中有text/blob/nvarcharmax数据类型,如果可能的话,您应该避免这些数据类型。为了澄清varchar8000/nvarchar4000或更低版本,数据类型是可以的,因为它们不会被视为blob类型的存储—性能要慢得多的存储

有几种方法可以优化您的方法:

不要选择*。只回拉所需的字段,这将减少数据从SQL server中取出并移动到C应用程序中的传输时间。 在SQL server上执行处理。SQL Server的性能往往很高,但并不总是像C那么高。如果您的应用程序只需要答案,请考虑使用内置AVG函数进行平均。虽然我从来没有做过Cpk,但也可能有一种方法。此外,您还可以使用BETWEEN关键字来确定日期范围。 合理使用。不幸的是,正确的索引几乎是一门艺术。本质上,使用尽可能少的索引。始终有一个主聚集索引,然后针对重要数据聚合使用非聚集索引。索引会降低插入、更新和删除操作的速度,同时有时会提高选择操作的性能。在您的情况下,您可能需要在LotID上建立一个索引,或者LotID和timestamps/date字段的组合。 将数据分块。如果可行,一次只能拉出合理数量的行。在许多情况下,这是不可行的,但作为一种选择保持开放。您可以将数据分块到循环中,或者将数据拉入单独的结构中,例如表示为@tableName的内存中临时表,或者表示为tableName的服务器上临时表。各有利弊。服务器上的临时表可能更适合您的问题,因为它们不会占用太多内存。 如果您使用的是较新版本的SQL Server Management Studio,则会内置查询分析器/优化器。其他主要工具通常也具有此功能。它可以告诉你所有的时间都被发送到哪里,并经常建议使用索引。 因此,如果必须将大量数据拉入C,则只需在索引字段上进行选择,并尽可能只拉回最小的数据集


根据我的经验,将数据拉入C的所有形式都很快。这包括SqlDataAdapter、SQLDataReader,甚至实体框架的ORM。但是,如果要收回的数据集非常大,那么在较小的盒子上肯定会耗尽内存,并且必须等待将所有数据移出磁盘,磁盘速度成为性能的一个重要瓶颈,此外还有任何网络延迟。如果您有权访问SQL server box的资源管理器,则可以实时查看此信息。

是否需要在系统中显示这么多记录?或者你只需要做一些简单的计算?不要返回所有的记录。返回一个迭代器,该迭代器可以按顺序循环记录,一次只将一个迭代器加载到内存中。这就是DataReader的用途,而不是C的设计目的。SQL非常擅长通过其内置函数创建数据聚合,这样就不会将数百万行返回给客户端进行处理。创建一些视图或存储过程来为您进行处理。感谢您的详细解释!我将LotID和TimeStamp字段设置为非聚集索引,并看到select查询的边际收益。然后,我尝试仅在需要的数据字段上使用Avg和Stdev函数,然后使用
C面。虽然查询速度不快,但现在每批的查询时间已减少到1到1.5分钟。如何只提取所需字段?@edo101只需选择包含所需数据的列,而不是所有列。从表中选择columnNameA、columnNameB。