【发布时间】:2022-10-19 14:48:03
【问题描述】:
TLDR;我有一个位于 AWS 的 ASP.NET Core 5.0 API。它对 MSSQL db 进行大量调用以返回约 1-4k 行数据。单个请求很好,大约需要 500 毫秒,但是当多个请求大约在同一时间 (4-5) 进入时,请求会减慢到每次调用约 2000 毫秒。这是怎么回事?
没有什么比我上面所说的更多的了。我打开一个到我们的数据库的连接,然后初始化一个 SqlCommand。
using (var connection = new SqlConnection(dbConnection))
connection.Open();
using (SqlCommand command = new SqlCommand(strSQLCommand))
我已经尝试使用 SqlDataAdapter 填充数据表并使用 SqlDataReader 填充自定义对象,无论哪种方式我都会遇到类似的减速。如上所述,查询返回约 1-4k 行不同类型的数据。而Postman表示,解压后返回的Json数据大小约为1.95MB。仅当多个请求大约在同一时间进入时才会出现减速。我不知道与数据库的多个连接是否有问题,或者是否与数据大小和可用内存有关。分页不是一个选项,请求需要返回那么多数据。
这一切都发生在 HttpGet 函数中
[HttpGet]
[Route("Foo")]
[Consumes("application/json")]
[EnableCors("DefaultPolicy")]
public IActionResult Foo([FromHeader] FooRequest request)
{
///stuff
DataTable dt = new DataTable();
using (var connection = new SqlConnection(_dataDBConnection))
{
timer.Start();
connection.Open();
using (SqlCommand command = new SqlCommand(
"SELECT foo.name, bar.first, bar.second, bar.third, bar.fourth
FROM dbo.foo with(nolock)
JOIN dbo.bar with(nolock) ON bar.name = foo.name
WHERE bar.date = @date", connection))
{
command.Parameters.AddWithValue("@date", request.Date.ToString("yyyyMMdd"));
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
{
adapter.Fill(dt);
}
}
timer.Stop();
long elapsed = timer.ElapsedMilliseconds;
}
///Parse the data from datatable into a List<object> and return
///I've also used a DataReader to put the data directly into the List<object> but experienced the same slowdown.
///response is a class containing an array of objects that returns all the data from the SQL request
return new JsonResult(response);
}
任何见解将不胜感激!
--附加测试后编辑---
[HttpGet]
[Route("Foo")]
[Consumes("application/json")]
[EnableCors("DefaultPolicy")]
public IActionResult Foo([FromHeader] FooRequest request)
{
///stuff
using (var connection = new SqlConnection(_dataDBConnection))
{
connection.Open();
///This runs significantly faster
using (SqlCommand command = new SqlCommand(@"dbo.spGetFoo", connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@date", request.date.ToString("yyyyMMdd"));
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
///Add data to list to be returned
}
}
}
}
///Parse the data from datatable into a List<object> and return
///I've also used a DataReader to put the data directly into the List<object> but experienced the same slowdown.
///response is a class containing an array of objects that returns all the data from the SQL request
return new JsonResult(response);
}
【问题讨论】:
-
那么,大概您正在使网络或数据库服务器饱和;您有一个返回 1k-4k 行的查询;是否有可能不要那样做?或者至少:不是每次通话?也许是本地缓存,也许在服务器上做更多,所以你不需要取回所有东西?
-
@MarcGravell,在不过多涉及调用性质的情况下,我会说每个请求都是独一无二的,以至于缓存无济于事。并且需要所有数据。我们有一个 PHP api,我们正在用这个 asp.net 核心 API 替换它,而 PHP 似乎没有这个问题。所以,大概不是数据库问题。
-
是否可以获取整个 SQL 事务的代码块?
-
@Tachyon 我已经包含了上面的块,我认为我不应该分享我正在做的确切的 SQL 调用,但足以说它正在访问一个有几百万行的表,加入一个有十亿行的表,并返回几千行。直接在 SQL Management Server 中运行查询只需要几毫秒,所以我不认为查询本身是问题所在。
-
做了一些进一步的测试,即使我将 TOP 1 放入命令中以便它只检索第一行,我仍然会遇到减速。我还将它从适配器更改为 SqlDataReader,并且可以说减速发生在 command.ExecuteReader() 上。
标签: c# rest asp.net-core