我正在进行一些研究,以更好地了解SQL和使用DataTables。因此,我试图努力实现从MS SQL数据库读取数据并加载到datagridview中的良好性能。
我创建了一个SQL函数,并从我的工具中调用它,将结果加载到datatable中。如果我在SSMS中执行此函数,需要11-12秒才能加载结果(几乎有150万条记录),但是如果我使用编码的工具执行此函数,则需要超过30秒(仅用于执行DataTable.Load(SqlDataReader))。
到目前为止,我所做的是:
我已经进行了一些谷歌研究,这是我能找到的最好的结果。到目前为止,它运行得很好,但我想知道是否有可能更快地获取结果。有什么建议吗? 此外,我有一个内存问题。一旦我开始调用,工具将分配高达900MB的RAM,直到它获得所有条目。我已经设法在每次调用上面的函数时释放内存,但我认为,900MB相当多,并且另一个问题是,它不会释放所有所需的RAM。例如:当我启动工具时,它需要大约7MB的RAM,如果我第一次调用上面的方法,它将需要900MB。如果我再次调用它,它将释放大部分内存,但仍需要930MB。第三次960MB,依此类推。因此,每次调用它都会分配更多的内存,这将导致“系统内存不足”异常,如果此方法经常被调用。
非常感谢!
我创建了一个SQL函数,并从我的工具中调用它,将结果加载到datatable中。如果我在SSMS中执行此函数,需要11-12秒才能加载结果(几乎有150万条记录),但是如果我使用编码的工具执行此函数,则需要超过30秒(仅用于执行DataTable.Load(SqlDataReader))。
到目前为止,我所做的是:
private DataTable GetDataFromDB(string userId, string docId, DateTimeOffset date)
{
string cmd = String.Format("select * from dbo.GetData(@userId, @docId, @dueDate);");
using (SqlConnection conn = new SqlConnection(connectionString))
{
if (conn.State != ConnectionState.Open)
conn.Open();
SqlCommand command = new SqlCommand(cmd, conn);
if (String.IsNullOrEmpty(userId))
command.Parameters.AddWithValue("@userId", DBNull.Value);
else
command.Parameters.AddWithValue("@userId", userId);
if (String.IsNullOrEmpty(docId))
command.Parameters.AddWithValue("@docId", DBNull.Value);
else
command.Parameters.AddWithValue("@docId", docId);
command.Parameters.AddWithValue("@dueDate", dueDate);
SqlDataReader reader = command.ExecuteReader();
stopWatch.Reset();
stopWatch.Start();
table.BeginLoadData();
table.Load(reader, LoadOption.Upsert);
table.EndLoadData();
stopWatch.Stop();
reader.Close();
reader.Dispose();
conn.Close();
}
return table;
}
我已经进行了一些谷歌研究,这是我能找到的最好的结果。到目前为止,它运行得很好,但我想知道是否有可能更快地获取结果。有什么建议吗? 此外,我有一个内存问题。一旦我开始调用,工具将分配高达900MB的RAM,直到它获得所有条目。我已经设法在每次调用上面的函数时释放内存,但我认为,900MB相当多,并且另一个问题是,它不会释放所有所需的RAM。例如:当我启动工具时,它需要大约7MB的RAM,如果我第一次调用上面的方法,它将需要900MB。如果我再次调用它,它将释放大部分内存,但仍需要930MB。第三次960MB,依此类推。因此,每次调用它都会分配更多的内存,这将导致“系统内存不足”异常,如果此方法经常被调用。
非常感谢!
DataTable
非常低效,因为它需要尽可能通用--每个值都存储为Object
,每行都存储为Object
数组。一般来说,更聪明的使用DataTable
的方法是根本不使用它。直接从SqlDataReader
初始化对象--这需要更多的代码,不太方便,但可以节省大量内存和速度。在数据网格的特定情况下,您需要查看使它们虚拟化,以便不必始终存在所有数据。 - Jeroen MostertDataTable.Fill()
方法吗?另外,与其使用Select * from Query
的方式,其中只涉及3列数据,为什么不将查询改为只选择那3列,并添加一个更明确的筛选语句来定义Where
子句? - MethodMan