我们有一个表CroppedImage
,其中Id
,PosX
,PosY
,Width
,Heigth
列的数据类型为{{1数据类型为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"]);
}
}
}
字段小于250KB。
我已经对它们进行了测试,并且在我的机器上没有看到任何差异,但是数据库管理员告诉我,ad-hoc查询占用的内存多于托管SQL的服务器上的预定义内存。
这是真的 ?这两个选项在性能方面有什么不同吗?
答案 0 :(得分:1)
现实是您的DBA不正确。这些是两个临时查询。即席查询获得为其创建的执行计划,并且它们像存储过程的执行计划一样被缓存。第二种方法是首选的,因为您使用参数化查询并阻止sql注入。我看到的是你正在使用AddWithValue。这应该避免,因为它有时会弄错。
答案 1 :(得分:1)
实际上,您的DBA是正确的,但术语有点令人困惑。这是参数化查询与非参数化查询的问题。
对于参数化查询("select * from CroppedImage where Id=@IdPar"
),即使您使用不同的参数多次执行此查询,查询也只需要由SQL Server解析和编译一次。任何后续的查询执行都将从缓存中重用相同的查询计划。
相反,每次使用不同的"select * from CroppedImage where Id=" + GetList[i]
值执行时,非参数化查询(GetList[i]
)将被视为完全不同的查询。在这种情况下,查询将每次在SQL Server上进行解析和重新编译。这将消耗更多内存,因为数据库服务器现在必须缓存多个查询计划而不是单个查询计划。
对于少量查询,差异不会很明显。但是,只要您拥有大量的交易量,您就可以开始注意速度和内存的影响。
这是一篇有趣的文章,提供了有关此事的更多详细信息:Use SQL Parameters to Overcome Ad Hoc Performance Issues。