从存储过程获取数据到数据表时内存利用率高

问题描述 投票:0回答:1

我想处理数百万条记录并对其进行一些处理并将这些记录导出到 Excel 文件中。当我获取记录并将其填充到 DataTable 中时,它使用的内存非常高,大约 8 到 10GB。我的sql查询结果包含大约300列。

我尝试过批处理,也尝试过使用 SqlDataReader。无论是否采用批量方式,它占用的内存几乎相同,并且在使用 SqlDataReader 后,它不会影响内存。下面是我当前的代码。有什么办法可以阻止这种高利用率吗?

批量获取10000条记录

DataTable dt = new DataTable();
                for (int i = 0; i <= 0; i++)
                {
                    int startRow = 1;
                    int endRow = 10000;
                    for (int j = 0; (startRow == 1 || dt.Rows.Count >= 10000); j++)
                    {
                        dt = null;
                        dt = _dataService.SqlExecuteDT(data);
                        startRow = startRow + 10000;
                    }
                }

调用SP代码并填写数据表。

public static DataTable SqlExecuteDT(string spname, Dictionary<string, object> parameters, DBName dBName = DBName.DBCONN)
        {

            using (SqlConnection conn = new SqlConnection(DBConnection.GetConnectionString(dBName)))
            {
                using (SqlCommand cmd = new SqlCommand(spname, conn))
                {
                    cmd.CommandTimeout = Timeout;
                    cmd.CommandType = System.Data.CommandType.StoredProcedure;

                    if (parameters != null)
                    {
                        foreach (KeyValuePair<string, object> kvp in parameters)
                            cmd.Parameters.AddWithValue(kvp.Key, kvp.Value ?? DBNull.Value);
                    }

                    conn.Open();

                    // Use a forward-only, read-only data reader for memory efficiency
                    using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
                    {
                        // Retrieve column schema
                        DataTable schemaTable = reader.GetSchemaTable();

                        // Create DataTable to hold the data
                        DataTable dataTable = new DataTable();

                        // Add columns to DataTable based on schema
                        foreach (DataRow row in schemaTable.Rows)
                        {
                            string columnName = row["ColumnName"].ToString();
                            Type dataType = (Type)row["DataType"];
                            dataTable.Columns.Add(columnName, dataType);
                        }

                        // Populate DataTable with data
                        while (reader.Read())
                        {
                            DataRow dataRow = dataTable.NewRow();
                            for (int i = 0; i < reader.FieldCount; i++)
                            {
                                dataRow[i] = reader[i];
                            }
                            dataTable.Rows.Add(dataRow);
                        }

                        return dataTable;
                    }
                }
            }
        }
c# asp.net .net asp.net-core asp.net-web-api
1个回答
0
投票

您的

SqlExecuteDT
功能过于复杂。您需要的一切都可以通过
DataTable.Load
获得。

public static DataTable SqlExecuteDT(string spname, Dictionary<string, object?> parameters = null, DBName dBName = DBName.DBCONN)
{
    using var conn = new SqlConnection(DBConnection.GetConnectionString(dBName));
    using var cmd = new SqlCommand(spname, conn);
    cmd.CommandTimeout = Timeout;
    cmd.CommandType = System.Data.CommandType.StoredProcedure;

    if (parameters != null)
    {
        foreach (var kvp in parameters)
            cmd.Parameters.AddWithValue(kvp.Key, kvp.Value ?? DBNull.Value);
    }

    conn.Open();
    using SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);

    var table = new DataTable();
    table.Load(reader);
    return reader;
}

那么你的外循环就完全没有意义了。为什么会有一个循环呢?应该只是:

var dt = _dataService.SqlExecuteDT(SomeProcName);
© www.soinside.com 2019 - 2024. All rights reserved.