简体   繁体   English

引发了类型为'System.OutOfMemoryException'的异常。 使用IDataReader时使用C#

[英]Exception of type 'System.OutOfMemoryException' was thrown. C# when using IDataReader

I have an application in which I have to get a large amount of data from DB. 我有一个应用程序,必须从数据库中获取大量数据。 Since it failed to get all of those rows (it's close to 2,000,000 rows...), I cut it in breaks, and I run each time the sql query and get only 200,000 rows each time. 由于它无法获取所有这些行(接近2,000,000行...),因此我将其中断,并且每次运行sql查询时都运行,每次仅获取200,000行。

I use DataTable to which I enter all of the data (meaning - all 2,000,000 rows should be there). 我使用要向其输入所有数据的DataTable(意思是-所有2,000,000行都应该存在)。

The first few runs are fine. 前几次运行很好。 Then it fails with the OutOfMemoryException. 然后它失败,并显示OutOfMemoryException。

My code works as following: 我的代码如下:

private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlConnection conn, DataTable dt, int prevRowCount)
    {
        if (string.IsNullOrEmpty(sql))
        {
            sql = generateSqlQuery(lastRowID);
        }

        if (conn.State == ConnectionState.Closed)
        {
            conn.Open();
        }

        using (IDbCommand cmd2 = conn.CreateCommand())
        {
            cmd2.CommandType = CommandType.Text;
            cmd2.CommandText = sql;
            cmd2.CommandTimeout = 0;

            using (IDataReader reader = cmd2.ExecuteReader())
            {
                while (reader.Read())
                {
                    DataRow row = dt.NewRow();
                    row["RowID"] = reader["RowID"].ToString();
                    row["MyCol"] = reader["MyCol"].ToString();
                    ... //In one of these rows it returns the exception.

                    dt.Rows.Add(row);
                }
            }
        }

        if (conn != null)
        {
            conn.Close();
        }

        if (dt.Rows.Count > prevRowCount)
        {
            lastRowID = dt.Rows[dt.Rows.Count - 1]["RowID"].ToString();
            sql = string.Empty;
            RunQueryAndAddToDT(sql, lastRowID, conn, dt, dt.Rows.Count);
        }
    }

It seems to me as if the reader keeps collecting rows, and that's why It throws an exception only in the third or second round. 在我看来,好像读者一直在收集行,这就是为什么它仅在第三轮或第二轮中引发异常。

Shouldn't the Using clean the memory as its done? 使用过程是否应该清除内存呢? What may solve my problem? 什么可以解决我的问题?

Note: I should explain - I have no other choice but get all of those rows to the datatable, Since I do some manipulation on them later, and the order of the rows is important, and I can't split it because sometimes I have to take the data of some rows and set it into one row and so on and so on, so I can't give it up. 注意:我应该解释-除了将所有这些行都放入数据表之外,我别无选择,因为以后我会对它们进行一些操作,所以行的顺序很重要,我无法拆分它,因为有时我会取一些行的数据并将其设置为一行,依此类推,以此类推,所以我不能放弃它。

Thanks. 谢谢。

Check that you are building a 64-bit process, and not a 32-bit one, which is the default compilation mode of Visual Studio. 检查您正在构建的是64位进程,而不是32位进程,这是Visual Studio的默认编译模式。 To do this, right click on your project, Properties -> Build -> platform target : x64. 为此,请在项目上,右键单击属性->构建->平台目标:x64。 As any 32-bit process, Visual Studio applications compiled in 32-bit have a virtual memory limit of 2GB. 与任何32位进程一样,以32位编译的Visual Studio应用程序的虚拟内存限制为2GB。

64-bit processes do not have this limitation, as they use 64-bit pointers, so their theoretical maximum address space is 16 exabytes (2^64). 64位进程没有此限制,因为它们使用64位指针,因此它们的理论最大地址空间为16艾字节(2 ^ 64)。 In reality, Windows x64 limits the virtual memory of processes to 8TB. 实际上,Windows x64将进程的虚拟内存限制为8TB。 The solution to the memory limit problem is then to compile in 64-bit. 然后,内存限制问题的解决方案是使用64位编译。

However, object's size in Visual Studio is still limited to 2GB, by default. 但是,默认情况下,Visual Studio中的对象大小仍限制为2GB。 You will be able to create several arrays whose combined size will be greater than 2GB, but you cannot by default create arrays bigger than 2GB. 您将能够创建多个阵列,其总大小将大于2GB,但是默认情况下您将无法创建大于2GB的阵列。 Hopefully, if you still want to create arrays bigger than 2GB, you can do it by adding the following code to you app.config file: 希望,如果您仍想创建大于2GB的阵列,可以通过将以下代码添加到app.config文件中来实现:

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

I think simply you run out of memory because your DataTable gets so large from all the rows you keep adding to it. 我认为您只是用光了内存,因为您的DataTable从您不断添加到它的所有行中变得如此之大。

You may want to try a different pattern in this case. 在这种情况下,您可能想尝试其他模式。

Instead of buffering your rows in a list (or DataTable), can you simply yield the rows as they are available for use when they arrive? 除了将行缓存在列表(或DataTable)中之外,您还可以简单地产生行,因为它们到达时可供使用吗?

Since you are using a DataTable , let me share a random problem that I was having using one. 由于您使用的是DataTable ,因此让我分享一个正在使用的随机问题。 Check your Build properties. 检查您的构建属性。 I had a problem with a DataTable throwing an out of memory exception randomly. 我有一个DataTable随机抛出内存不足异常的问题。 As it turned out, the project's Build Platform target was set to Prefer 32-bit . 事实证明,该项目的Build Platform目标设置为Prefer 32-bit Once I unselected that option, the random out of memory exception went away. 一旦取消选择该选项,随机内存不足异常就会消失。

You are storing a copy of the data to dt . 您正在将数据副本存储到dt You are simply storing so much that the machine is running out of memory. 您只是存储了太多内容,以致机器内存不足。 So you have few options: 因此,您有几种选择:

  • Increase the available memory. 增加可用内存。
  • Reduce the amount of data you are retrieving. 减少要检索的数据量。

To increase the available memory, you can add physical memory to the machine. 要增加可用内存,可以向计算机添加物理内存。 Note that a .NET process on a 32bit machine will not be able to access more than 2GB of memory though (3GB if you enable the 3GB switch in boot.ini ) so you may need to switch to 64bit (machine and process) if you wish to address more memory than that. 请注意,虽然32位计算机上的.NET进程将不能访问超过2GB的内存(如果在boot.ini启用了3GB开关,则将访问3GB),因此,如果您要切换到64位(计算机和进程),则可能需要希望解决更多的内存问题。

Retrieving less data is probably the way to go. 检索较少的数据可能是解决之道。 Depending upon what you are trying to achieve, you may be able to perform the task on subsets of the data (perhaps even on individual rows). 根据要实现的目标,您可能可以对数据子集(甚至可能对单个行)执行任务。 If you are performing some kind of aggregation (eg a producing a summary or report from the data) you may be able to employ Map-Reduce . 如果您正在执行某种聚合(例如,根据数据生成摘要或报告),则可以使用Map-Reduce

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 抛出了“System.OutOfMemoryException”类型的异常。 C# 使用内存流时 - Exception of type 'System.OutOfMemoryException' was thrown. C# when using Memory stream 读取大文件-System.OutOfMemoryException:引发了类型为&#39;System.OutOfMemoryException&#39;的异常。 在C#中 - Reading large file - System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. in C# c# System.OutOfMemoryException: 'System.OutOfMemoryException' 类型的异常被抛出。 - c# System.OutOfMemoryException: 'Exception of type 'System.OutOfMemoryException' was thrown.' 使用linq插入批量数据时发生错误{引发了&#39;System.OutOfMemoryException&#39;类型的异常。} - Error occured while inserting bulk data by using linq {Exception of type 'System.OutOfMemoryException' was thrown.} 在 C# 中引发了“System.OutOfMemoryException”类型的异常 - Exception of type 'System.OutOfMemoryException' was thrown in C# C#中引发了类型为&#39;System.OutOfMemoryException&#39;的异常 - Exception of type 'System.OutOfMemoryException' was thrown in C# 发生一个或多个错误。 (引发了“System.OutOfMemoryException”类型的异常。) - One or more errors occurred. (Exception of type 'System.OutOfMemoryException' was thrown.) System.OutOfMemoryException:angularjs中抛出了类型&#39;System.OutOfMemoryException&#39;的异常 - System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown in angularjs System.OutOfMemoryException:抛出了“System.OutOfMemoryException”类型的异常 - System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown “使用xmlserializer时抛出了类型&#39;System.OutOfMemoryException&#39;的异常 - “Exception of type 'System.OutOfMemoryException' was thrown” while using xmlserializer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM