2

我有一个填充了 360,000 行 SQL 数据的 DataTable(这是有意的)。但是,这会遇到 OOM 问题。

这就是我所拥有的,但是,我不确定在最后一个 1000 间隔之后如何处理任何事情。或者也许有更好的方法

int catchInt = 0;
string combineWhereClause = string.Empty;

for (int i = 0; i < ThousandLoopTable.Rows.Count; i++)
{
    catchInt++;
    combineWhereClause = combineWhereClause + 
                        "','" + 
                         ThousandLoopTable.Rows[i].ItemArray[0].ToString();

    if (catchInt >= 1000)
    {
        catchInt = 0;
        combineWhereClause = combineWhereClause.TrimStart('\'');
        combineWhereClause = combineWhereClause.TrimStart(',');

        Directory.CreateDirectory(ExportDirectory);
        SQLProcessing.SQLProcessor.MasterSqlConnection = 
            SQLProcessing.SQLProcessor.OpenMasterSqlConnection(SQLServer);
        DataTable dtTable = 
            SQLProcessing.SQLProcessor.QueryDataTable(sql_selectionquery);
        for (int m = 0; m < dtTable.Rows.Count; m++)
        {
            string FileName = dtTable.Rows[m].ItemArray[0].ToString() + ".txt";
            string OCR = dtTable.Rows[m].ItemArray[1].ToString();
            File.AppendAllText(ExportDirectory + "\\" + FileName, OCR);

        }

        combineWhereClause = string.Empty;
    }
}

因此,例如,如果有 3120 行,这将执行 3000,但不会执行最后 120 行。但是,我不确定如何处理最后 120 行,因为我真的不想在 for 循环中这样做我?

4

3 回答 3

2

您可以遵循一些简单的规则来避免 OutOfMemory 异常:

绝不

  1. 使用整个数据集
  2. 将整个数据集加载到内存中
  3. 执行阻塞服务器端数据库的长时间运行的事务代码

总是

  1. 处理小块数据
  2. 加载小块数据(分页模式)
  3. 运行非阻塞服务器代码
  4. 如果可以在服务器上做任何事情,让它完成工作

确保服务器上的数据不可变(没有人更改它)。如果这无法保证,您可能需要重新考虑您的架构并使用队列和附加表来处理数据。

于 2012-04-25T16:17:28.630 回答
2

考虑使用带有Take / Skip方法的 LINQ to SQL 。

于 2012-04-25T16:05:07.777 回答
0

可能有更好的方法来处理数据(请参阅其他答案),但我认为这是您当前方法所需要的:

不要catchInt为每个批次重置。相反,将其初始化为1并让它作为整个操作的计数器运行。然后将其更改if为:

if (catchInt % 1000 == 0 || catchInt == ThousandLoopTable.Rows.Count)
{
    // Execute your batch
}

这使用模数运算符来识别何时catchInt可被 1000 整除。

于 2012-04-25T16:40:11.080 回答