预定义查询是否比使用 ADO.NET 的即席 SQL 查询更有效?

Is predefined query more efficient than ad-hoc SQL query using ADO.NET?

我们有一个 table CroppedImage,它有 IdPosXPosYWidthHeigth 列数据类型为 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是不正确的。这些都是临时查询。即席查询获得为它们创建的执行计划,并且它们像存储过程的执行计划一样被缓存。首选第二种方法,因为您正在使用参数化查询并防止 sql 注入。不过我看到的是您正在使用 AddWithValue。应该避免这种情况,因为它有时会出错。

实际上,您的 DBA 是正确的,尽管术语有点混乱。这更多是参数化查询与非参数化查询的问题。

在参数化查询("select * from CroppedImage where Id=@IdPar")的情况下,即使您使用不同的参数多次执行此查询,查询也只需要由SQL服务器解析和编译一次。查询的任何后续执行都将重用缓存中的相同查询计划。

相比之下,非参数化查询 ("select * from CroppedImage where Id=" + GetList[i]) 每次使用不同的 GetList[i] 值执行时都会被视为完全不同的查询。在这种情况下,每次都会在 SQL 服务器上解析和重新编译查询。这将消耗更多内存,因为数据库服务器现在必须缓存多个查询计划而不是一个。

对于少量查询,差异不会很明显。但是,一旦您的交易量很大,您可能会开始注意到对速度和内存的影响。

这是一篇有趣的文章,提供了有关此事的更多详细信息:Use SQL Parameters to Overcome Ad Hoc Performance Issues