我在 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# 技能非常生疏,但希望这对您有用。