从数据库加载数千个数据并处理它的有效方法

时间:2016-01-16 16:00:20

标签: c# datatable

我在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*/
                }
            }
        }
    }
}

现在这个过程的执行非常缓慢。我想知道有没有其他方法来实现这一目标。提前谢谢!

1 个答案:

答案 0 :(得分:2)

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

我在这个问题的答案基础上: Paginate rows from 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变量提供这些行。然后我们将这些行调整大小,然后继续循环。循环将继续,直到查询返回no用于pageSize的值取决于你,但作为一个例子,如果你有2GB的可用内存,并且每张照片是2MB,如果你的pageSize是1000行,你将非常粗略地使用所有内存。您希望使用基本少于所有可用内存,因为这不仅会减慢此过程,还会降低计算机上需要空闲内存的所有其他过程。

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