【问题标题】:ServiceStack taking a long time to execute stored procedureServiceStack 执行存储过程需要很长时间
【发布时间】:2015-01-26 11:03:45
【问题描述】:

我已经实现了 ServiceStack (v4.0.36),通过 ORMLite 连接到我的 SQL Server 2014 数据库。我的网站上有一个搜索表单,可以将任何填充的字段作为查询字符串参数传递给“/search”路由。我的请求 DTO 如下所示:

[Route("/search", "GET")]
public class SearchRequest
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ...
}

(总共有 8 个参数)然后我有一个服务,它调用 SQL 中的存储过程,传递所有参数,例如:

public class MyServices : Service
{
    public object Get(SearchRequest request)
    {
        using (var db = AppHostBase.Instance.Container.TryResolve<OrmLiteConnectionFactory>().OpenDbConnection())
        {
            List<SearchResponse> searchResults = db.SqlList<SearchResponse>("EXEC sp_web_ResultListByNameOrAddress @firstName, @lastName, ...",
                new
                {
                    firstName = request.FirstName,
                    lastName = request.LastName,
                    ...
                });

            return searchResults;
        }
    }
}

问题是,如果我通过网站进行搜索,最多需要 30 秒才能返回结果(或者超时并断开连接)。如果我在 SQL 中执行相同的存储过程,我会立即得到结果(搜索字段和组合被索引)。

我注意到更改 web.config 后性能有所提升

<compilation targetFramework="4.5" debug="false"/>

...但我仍然对瓶颈发生在哪里感到困惑。任何帮助将不胜感激!

呐呐呐呐呐呐呐呐呐呐...蝙蝠侠! ?

更新:仅供参考,我通过独立的 AngularJS Web 应用程序连接到此服务,但在通过 Postman 等 REST 客户端测试服务时也会遇到缓慢或超时问题。谢谢。

更新 2:我启用了 Mini Profiler...延迟出现在“执行服务”步骤中。这是一个示例搜索查询:

我将在 ORMLite 连接上打开 SQL 分析,然后发布任何更新。

更新 3:不是很有帮助(我认为)...SQL Profiler 只显示已执行的存储过程:

更新 4:有趣。所以我让 SSMS 的 SQL Server Profiler 与我的请求一起运行,同时打开了 Mini Profiler,我还在运行存储过程的行的服务实现中设置了一个断点。

当我加载页面时,断点立即被命中。当我继续时,我在 SQL Server Profiler 中看到“审核登录”消息。然后几分钟什么都没有,然后是“RPC:Completed”消息,其中包含存储的过程和传递的参数。

所以查询直到最后才到达 SQL,它几乎立即返回(正如预期的那样)。为什么 ServiceStack 提交请求和它在 SQL Server 上实际执行之间存在很大延迟?一切都是本地的,所以我不认为网络问题是罪魁祸首。有人吗?

【问题讨论】:

    标签: c# sql servicestack ormlite-servicestack sql-server-2014


    【解决方案1】:

    找到这个链接,它解决了我的问题:What is happening in debug compilation that is causing the query to take longer to execute?

    存储过程返回了一个 bigint 数据类型,该数据类型映射到我的服务响应 POCO 中的字符串数据类型。我在存储过程中添加了一个 CONVERT(varchar...) 语句,现在事情运行得更快了。谢谢!

    重新开放!很抱歉在这件事上如此草率。我的单一表单将所有参数提交给存储过程。我刚刚将 ORMLiteConfig 超时增加到 500 秒,并且注意到某些搜索大约需要 4 分钟才能完成。同样,在 SSMS 中执行相同的操作会立即返回结果。怎么回事?

    【讨论】:

    • 慢搜索是否有大量结果?还是他们的结果很慢?这将表明瓶颈是 SQL/ADO 执行步骤、复制到 DTO 步骤、序列化到 JSON 步骤还是 HTTP 网络传输。
    • 查看我原始帖子的更新以获取 ServiceStack 的迷你分析器的结果,但结果通常是单行。
    • 好的,我明白了。此时,我会尝试使用相同的 db/IDbConnection,但尝试使用 SqlDataReader 执行传统的 SqlCommand StoredProc 类型。我很想看看问题出在 ADO 执行中,还是在 OrmLite 代码中。
    【解决方案2】:

    添加一个额外的答案,因为确实有两个问题。真正的根似乎与存储过程有关。我不知道为什么它没有始终如一地导致问题,但我使用动态 SQL 对其进行了重建,只包含针对存在的参数的 WHERE 过滤器。最初,我有这样的事情:

    CREATE [sp_name]
        @Name varchar(60) NULL,
        @Address varchar(150) NULL
        ...
    AS
    BEGIN
        SELECT *
        FROM tbl_A a
        WHERE (@Name IS NULL OR a.Name = @Name)
            AND (@Address IS NULL OR a.Address = @Address)
    

    我的想法是“或”运算符会先评估前半部分,如果前半部分为假,则永远不要尝试评估后半部分。也许这不是它的工作方式?无论如何,我最终将其重写为:

    CREATE [sp_name]
        @Name varchar(60) NULL,
        @Address varchar(150) NULL
        ...
    AS
    BEGIN
        DECLARE @SQL NVARCHAR(4000);
        DECLARE @ParamDef NVARCHAR(4000);
    
        SELECT @ParamDef = ' 
            @NameParam varchar(60), 
            @AddressParam varchar(150),
        ';
    
        SELECT @SQL = N'
            SELECT *
            FROM tbl_A a
            WHERE 1=1';
    
        IF @Name IS NOT NULL
            SELECT @SQL = @SQL + N'
                AND a.Name = @NameParam ';
    
        IF @Address IS NOT NULL
            SELECT @SQL = @SQL + N'
                AND a.Address = @Address ';
    
        EXEC sp_executeSQL
            @SQL,
            @ParamDef,
            @NameParam = @Name,
            @AddressParam = @Address;
    END
    

    现在效果好多了。谢谢!

    【讨论】:

    猜你喜欢
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2017-07-10
    • 2011-03-12
    相关资源
    最近更新 更多