【问题标题】:Query runs faster in SQL Server than via ADO.NET command being sent查询在 SQL Server 中的运行速度比通过发送的 ADO.NET 命令快
【发布时间】:2012-11-08 05:12:29
【问题描述】:

所以我在我的 DL 中的 CRUD 方法中有以下内容,它带回了一个照片 blob:

    public static MemberPhoto RetrievePhoto(string customerID)
    {
        Database db = DatabaseFactory.CreateDatabase(Config.DbConnectionString);

        using (DbCommand cmd = db.GetSqlStringCommand(string.Format(@" SELECT  customerID,
                                                                                p.Photo as PhotoBlob

                                                                         FROM 
                                                                         SomeTable t

                                                                         WHERE 
                                                                         t.PhotoID = (SELECT MAX(t.PhotoID) FROM SomeTable t
                                                                                      WHERE t.customerID = @{0} 
                                                                                      GROUP BY t.CustomerID)", "customerID")))
        {
            try
            {
                db.AddInParameter(cmd, "@customerID", DbType.String, customerID);

                using (IDataReader reader = db.ExecuteReader(cmd))
                {
                    if (reader.Read())
                    {
                        Photo photo = new Photo();
                        photo.LoadFromDataReader(reader);
                        return photo;
                    }
                }
            }

所以它比我直接从管理工作室运行慢大约 10 秒:

SELECT  customerID,
    t.Photo as PhotoBlob

    FROM 
    SomeTable t

    WHERE 
    t.PhotoID = (SELECT MAX(t.PhotoID) FROM SomeTable t
              WHERE t.customerID = '0000900595555' 
              GROUP BY t.CustomerID)

我不知道是不是因为读者需要一段时间才能阅读 blob 并将其带回来还是什么?如果这是问题,你如何加快速度?它在数据库中的瞬间,我运行该查询,这是一个毫秒的结果计时。

更新:

更多信息;表中的字段类型是该 BLOB 的 SQL Sever 中的 Image 类型。

我还运行了我的单元测试,时间相同,即使在它到达我的 LoadFromReader 之后:

[Test]
public void GetMemberPhoto_ByContractNumber_ReturnsAValidMemberPhoto()
{
    // Arrange
    const string customerID = "0044664176";

    // Act
    DTO.MemberPhoto memberPhoto = MemberPhotoCRUD.RetrieveMemberPhotoFromBlob(customerID);

    //Assert
    Assert.IsNotNull(memberPhoto);
    Assert.IsTrue(memberPhoto.CustomerID > 0);
    Assert.IsNotNull(memberPhoto.PhotoBinary.Length > 0);
}

【问题讨论】:

  • 嗯...这真的不是苹果对苹果的比较。即便如此,您确实应该提供一些信息。 (1) 您的数据库列“照片”的数据类型是什么? (2) 您的测试中返回了多少条记录?
  • 自从我做 Max 以来,一直只返回一条记录。当我运行相同的查询时,Management Studio 中的时间为毫秒。
  • 这个苹果对橘子怎么样?您在谈论查询,因为查询与以任何方式运行的查询完全相同(来自 .NET 或 SQL Management Studio,它正在运行相同的查询)
  • 我指的是直接在数据库上运行查询而不是在代码中进行数据库调用。 10 秒的差异并不典型/正常,但在不知道返回数据的大小和类型的情况下,很难猜测瓶颈在哪里。
  • 您是否尝试分析您的数据库以查看数据库中查询所消耗的时间是否有任何差异...?这至少可以排除数据库的问题(或确认确实存在问题)。

标签: c# tsql ado.net database-performance


【解决方案1】:

您正在返回图像的 blob。 SSMS 实际上并没有获取所有数据 - 它会截断 [n][text]、[n][varchar](max)、image 和 varbinary(max) 的大值,因为您通常不会直接使用这些结果。听起来这是一个带宽问题。检查 blob 的大小 - 如果它非常大,这很可能。

异常表现的其他可能性:

  • 不同的隔离级别
  • 不同的SET 选项
  • 参数嗅探

另外 - 关于string.Format 的评论是正确的;它对你没有任何伤害,但它也没有任何有用的目的。就我个人而言,我只是将@customerID 直接写到查询中。否则它就像string.Format("this and {0}", "that") - 你也可以使用"this and that"。

也可能是在客户端处理图像的速度很慢。为了进行直接比较,您只需将数据获取为(例如)byte[]。您的 SSMS 比较不会将数据处理为 Photo 对象。可能是 this 操作缓慢,所以我会分析 photo.LoadFromDataReader(reader)。

【讨论】:

  • 是的,我明白你对 string.format 的看法。这只是 CodeGened 的东西。
  • 我刚刚检查了该 blob 的类型是 SQL 表中的 Image。我也刚刚将它部署到他们的开发服务器,相同的响应时间。我不认为他们的开发服务器或持有这些字段的服务器是否强大,但我会找出运行 SQL Server 的源服务器,看看这是否会导致延迟或不可能......??
  • 但同样不是来自 DataReader 的负载,我正在执行 GetByte。这种滞后发生在从发送 cmd 到它从 SQL 服务器返回的时间,在它进入 LoadFromDataReader 之前
  • 我开始注意到,即使它没有找到 blob,该查询也需要很长时间才能回到我的 CRUD 方法......所以不知道到底是什么原因造成的现在的延迟,特别是如果该 sql 调用在某些情况下没有找到记录但仍然滞后相同的时间。
  • @user1808194 你检查过我在要点中提到的事情吗?实际上,我将从最后一个(参数嗅探)开始 - 尝试将OPTION (OPTIMIZE FOR UNKNOWN) 添加到查询(和子查询)中。也只需检查索引等方面的查询。
【解决方案2】:

选择错误。不要使用 string.Format 并将WHERE t.customerID = @{0} 更改为WHERE t.customerID = @customerID。

现在注释掉photo.LoadFromDataReader(reader); 并运行您的测试。如果时间接近管理工作室的时间,则问题出在您的 LoadFromDataReader 方法中。

【讨论】:

  • 为什么不使用 string.format?我已经在我工作过的 .coms 上看到过 1000 次这种情况
  • 问题不是从阅读器加载,因为延时发生在阅读器加载之前...它需要 10 秒才能到达 loadfromreader 行
  • string.format 与性能无关。它只是在将 sql 命令发送到服务器之前替换文本。调用甚至不会发生,直到 ExecuteReader 命令,当 THEN 是它进行 sql 调用的地方,并且从那个点开始调用它返回到行 hoto.LoadFromDataReader(reader);是滞后的地方。同样,它不会在 LoadFromDataReader 中滞后,它会在调用 sql 命令(将其发送到数据库)和返回之间滞后。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
相关资源
最近更新 更多