【发布时间】:2015-10-07 19:02:57
【问题描述】:
我们有一个表CroppedImage,其中有Id、PosX、PosY、Width、Heigth 列,数据类型为tinyint,另一列CroppedPicture,数据类型为varbinary .
这是临时的方式:
List<int> GetList = GetTopNecessaryImages();
for(int i = 0; i < 100; i++){
com.CommandText = "select * from CroppedImage where Id=" + GetList[i];
using (SqlDataReader objSqlDtReader = com.ExecuteReader())
{
while(objSqlDtReader.Read())
{
CropImage objCrop = new CropImage ();
CropImage.Img = (objSqlDtReader["CroppedPicture"]);
}
}
}
这是带有参数的预定义查询。
List<int> GetList = GetTopNecessaryImages();
for(int i = 0; i < 100; i++){
com.CommandText = "select * from CroppedImage where Id=@IdPar";
com.Parameters.AddWithValue("@IdPar", GetList[i]);
using (SqlDataReader objSqlDtReader = com.ExecuteReader())
{
while(objSqlDtReader.Read())
{
CropImage objCrop = new CropImage ();
CropImage.Img = (objSqlDtReader["CroppedPicture"]);
}
}
}
Image 字段小于 250KB。
我已经对它们进行了测试,并且在我的机器上没有发现任何差异,但是数据库管理员告诉我,即席查询比托管 SQL 的服务器上预定义的查询消耗更多的内存。
这是真的 ?这两个选项在性能上有什么不同吗?
【问题讨论】:
-
现实情况是您的 DBA 不正确。这些都是临时查询。 Ad-hoc 查询获取为它们创建的执行计划,并且它们像存储过程的执行计划一样被缓存。第二种方法是首选,因为您正在使用参数化查询并防止 sql 注入。我确实看到的是您正在使用 AddWithValue。这应该避免,因为它有时会出错。 blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
-
您的 DBA 的意思可能是,不必编译“预定义”(=预编译)视图(或存储过程或表值函数)。但是这样一个简单的查询在任何情况下都很快......(至少如果“Id”上有索引;-))
-
即使您的 DBA 意味着存储过程或视图,但这并不意味着它会神奇地更快。它们都归结为创建(或重用,如果存在)执行计划。
-
正如您所说,这些图像很小,您一次选择一个。发送的 250k 图像几乎没有 ram 消耗。一旦查询执行,sql server 就会将其丢弃。老实说,我认为最大的问题是您执行此过程 RBAR。您应该一次性提取所需的所有数据,而不是一遍又一遍地查询。这将大大减轻 sql 框的压力。
标签: sql sql-server ado.net sqldatareader datareader