预定义查询比使用ADO.NET的临时SQL查询更有效吗?

时间:2015-10-07 19:02:57

标签: sql sql-server ado.net sqldatareader datareader

我们有一个表CroppedImage,其中IdPosXPosYWidthHeigth列的数据类型为{{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的服务器上的预定义内存。 这是真的 ?这两个选项在性能方面有什么不同吗?

2 个答案:

答案 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