ServiceStack需要很长时间来执行存储过程
ServiceStack taking a long time to execute stored procedure
我已经通过 ORMLite 连接到我的 SQL Server 2014 数据库实现了 ServiceStack (v4.0.36)。我的网站上有一个搜索表单,它将任何填充的字段作为查询字符串参数传递给“/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 秒才能获得 return 结果(或者超时并断开连接)。如果我在 SQL 中执行相同的存储过程,我会立即得到结果(搜索字段和组合已编入索引)。
我注意到更改 web.config
后性能有所提高
<compilation targetFramework="4.5" debug="false"/>
...但我仍然对瓶颈发生在哪里感到困惑。任何帮助将不胜感激!
呐呐呐呐呐呐呐呐呐...蝙蝠侠! ?
更新:仅供参考,我通过独立的 AngularJS 网络应用程序连接到此服务,但在通过 Postman 等 REST 客户端测试服务时也会遇到缓慢或超时问题。谢谢。
更新 2:我启用了 Mini Profiler...延迟在 "Execute Service" 步骤中。这是一个示例搜索查询:
我将在 ORMLite 连接上打开 SQL 分析,然后 post 任何更新。
更新 3:不是很有帮助(我认为)...SQL Profiler 仅显示已执行的存储过程:
更新 4:有趣。所以我有 SSMS 的 SQL Server Profiler 运行 以及我打开 Mini Profiler 的请求,我还在运行存储过程的行上的服务实现中设置了一个断点。
当我加载页面时,立即命中断点。当我继续时,我在 SQL Server Profiler 中看到一条 "Audit Login" 消息。然后几分钟什么都没有,然后是一条带有存储过程和传递参数的 "RPC:Completed" 消息。
所以查询直到最后才到达 SQL,几乎立即 returned(正如预期的那样)。为什么 ServiceStack 提交请求和它在 SQL 服务器上实际执行之间有很大的延迟?一切都是本地的,所以我不认为网络问题是罪魁祸首。有人吗?
找到这个 link 并解决了我的问题:What is happening in debug compilation that is causing the query to take longer to execute?
存储过程返回了一个 bigint 数据类型,它映射到我的服务响应 POCO 中的字符串数据类型。我向存储过程添加了一个 CONVERT(varchar...) 语句,现在速度 运行 快多了。谢谢!
重新开业!很抱歉在这件事上如此草率。我的单一表单将所有参数提交给存储过程。我刚刚将 ORMLiteConfig 超时增加到 500 秒,并且注意到某些搜索需要大约 4 分钟才能完成。同样,在 SSMS returns 中执行相同的操作会立即产生结果。这是怎么回事??
添加一个额外的答案,因为确实有两个问题。真正的根源似乎与存储过程有关。我不知道为什么它不会一直导致问题,但我使用动态 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)
我的想法是 "OR" 运算符会先评估前半部分,如果前半部分为假,则永远不会尝试评估后半部分。也许这不是它的工作方式?无论如何,我最终将其重写为:
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
现在效果好多了。谢谢!
我已经通过 ORMLite 连接到我的 SQL Server 2014 数据库实现了 ServiceStack (v4.0.36)。我的网站上有一个搜索表单,它将任何填充的字段作为查询字符串参数传递给“/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 秒才能获得 return 结果(或者超时并断开连接)。如果我在 SQL 中执行相同的存储过程,我会立即得到结果(搜索字段和组合已编入索引)。
我注意到更改 web.config
后性能有所提高<compilation targetFramework="4.5" debug="false"/>
...但我仍然对瓶颈发生在哪里感到困惑。任何帮助将不胜感激!
呐呐呐呐呐呐呐呐呐...蝙蝠侠! ?
更新:仅供参考,我通过独立的 AngularJS 网络应用程序连接到此服务,但在通过 Postman 等 REST 客户端测试服务时也会遇到缓慢或超时问题。谢谢。
更新 2:我启用了 Mini Profiler...延迟在 "Execute Service" 步骤中。这是一个示例搜索查询:
我将在 ORMLite 连接上打开 SQL 分析,然后 post 任何更新。
更新 3:不是很有帮助(我认为)...SQL Profiler 仅显示已执行的存储过程:
更新 4:有趣。所以我有 SSMS 的 SQL Server Profiler 运行 以及我打开 Mini Profiler 的请求,我还在运行存储过程的行上的服务实现中设置了一个断点。
当我加载页面时,立即命中断点。当我继续时,我在 SQL Server Profiler 中看到一条 "Audit Login" 消息。然后几分钟什么都没有,然后是一条带有存储过程和传递参数的 "RPC:Completed" 消息。
所以查询直到最后才到达 SQL,几乎立即 returned(正如预期的那样)。为什么 ServiceStack 提交请求和它在 SQL 服务器上实际执行之间有很大的延迟?一切都是本地的,所以我不认为网络问题是罪魁祸首。有人吗?
找到这个 link 并解决了我的问题:What is happening in debug compilation that is causing the query to take longer to execute?
存储过程返回了一个 bigint 数据类型,它映射到我的服务响应 POCO 中的字符串数据类型。我向存储过程添加了一个 CONVERT(varchar...) 语句,现在速度 运行 快多了。谢谢!
重新开业!很抱歉在这件事上如此草率。我的单一表单将所有参数提交给存储过程。我刚刚将 ORMLiteConfig 超时增加到 500 秒,并且注意到某些搜索需要大约 4 分钟才能完成。同样,在 SSMS returns 中执行相同的操作会立即产生结果。这是怎么回事??
添加一个额外的答案,因为确实有两个问题。真正的根源似乎与存储过程有关。我不知道为什么它不会一直导致问题,但我使用动态 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)
我的想法是 "OR" 运算符会先评估前半部分,如果前半部分为假,则永远不会尝试评估后半部分。也许这不是它的工作方式?无论如何,我最终将其重写为:
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
现在效果好多了。谢谢!