从数据库加载数千个数据并对其进行处理的有效方法

本文关键字:处理 方法 有效 数据 加载 数据库 千个 | 更新日期: 2023-09-27 18:30:36

我在 Sql Server 2008 中有一个名为 PhotoStorages 的表,其中包含以下列。此表包含 5000 个数据。

PhotoStorageId              bigint
Photo                       image

目前我正在使用 C# 加载数据,如下所示

string sql = "SELECT * FROM PhotoStorages";
using (SqlCommand sqlCommand = new SqlCommand(sql))
{
    using (SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlCommand))
    {
        using (DataTable dataTable = new DataTable())
        {
            dataAdapter.Fill(dataTable);
            if (dataTable.Rows.Count > 0)
            {
                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    /*Resize the image and again update those resized image to the same database table*/
                }
            }
        }
    }
}

现在这个过程的执行非常慢。我想知道是否有其他方法可以实现这一目标。提前感谢!

从数据库加载数千个数据并对其进行处理的有效方法

可以使用 SQL Server 中的ROW_NUMBER函数将查询分解为较小的块,以便对结果进行分页。

我的答案基于这个问题:对 SQL 中的行进行分页

首先,您必须将查询转换为执行分页的查询:

string sql = @"SELECT
                *
              FROM
                (
                    SELECT
                        ROW_NUMBER() OVER(ORDER BY Id DESC) AS RowNumber,
                        *
                    FROM
                        PhotoStorages
                ) AS T
              WHERE
                RowNumber BETWEEN @start AND @start + @pageSize";

应更改ORDER BY Id以匹配查询的实际 ID 列。在特定情况下,您可以使用表中的任何列,因为您使用的是所有数据,因此您无需担心订单被退回。5000 行在宏伟的计划中并不大,但如果它是一个 100,000+ 行的大表,您将需要使用具有索引的列。并且不要使用二进制数据列。

然后,您可以在循环中运行查询:

var pageSize = 10;
var startAt = 0;
while(true) 
{
    using (SqlCommand sqlCommand = new SqlCommand(sql))
    {
        sqlCommand.Parameters.Add("@start", SqlDbType.Int).Value = startAt;
        sqlCommand.Parameters.Add("@pageSize", SqlDbType.Int).Value = pageSize;
        using (SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlCommand))
        {
            using (DataTable dataTable = new DataTable())
            {
                dataAdapter.Fill(dataTable);
                var rowCount = dataTable.Rows.Count;
                var startAt = startAt + rowCount;
                if (dataTable.Rows.Count > 0)
                {
                    for (int i = 0; i < dataTable.Rows.Count; i++)
                    {
                        /*Resize the image and again update those resized image to the same database table*/
                    }
                }
                else 
                {
                    break;
                }
            }
        }
    }
}

这个想法是选择一定数量的行(我们通过 pageSize 变量提供。然后,我们让这些行进行调整大小,并继续循环。循环将继续,直到查询不返回任何行。您用于pageSize的值取决于您,但例如,如果您有 2GB 的可用内存,并且每张照片为 2MB,如果您的 pageSize 为 1000 行,您将非常粗略地使用所有内存。您希望使用比所有可用内存少得多的内存,因为这不仅会减慢此过程的速度,还会减慢计算机上发生的需要可用内存的所有其他进程。

我的 C# 技能非常生疏,但希望这对您有用。