限制 EF 查询以保存 DTU
Throttling EF queries to save DTUs
我们有一个 asp.Net 应用程序使用托管在 Azure 中的 EF 6。除某些罕见的操作外,大部分时间数据库都以大约 20% DTU 使用率运行。
这些几乎就像 Excel 格式的数据库转储,比如拥有过去 X 年的所有订单等。(高级)用户可以触发这些订单,然后稍后通过电子邮件获得结果。
问题是这些查询用完了所有 DTU,整个应用程序进入爬网状态。我们想限制这些非关键查询,因为这是否需要 10-15 分钟的时间并不重要。
谷歌搜索我找到了减少 DEADLOCK_PRIORITY 的选项,但这不会解决用尽所有资源的问题。
感谢任何指点、想法或解决方案。
Optimizing is going to be hard as it is more or less a db dump.
Azure SQL 数据库没有 Resource Governor 可用,因此您必须在代码中处理此问题。
Azure SQL 数据库以 READ COMMITTED SNAPSHOT 模式运行,因此减慢从 table(或任何流式查询计划)转储数据的会话应该减少其 DTU 消耗而不会产生不利影响其他会话。
为此,请在读取查询结果的循环中等待,从 LINQ 查询返回的 IEnumerable<TEntity>
或从 ADO.NET [=14= 返回的 SqlDataReader
].
但是您必须直接循环播放流媒体结果。您不能先使用 IQueryable<TEntity>.ToList()
或 DataTable.Load()
、SqlDataAdapter.Fill()
等将查询结果复制到内存中,因为这样读取速度会尽可能快。
例如
var results = new List<TEntity>();
int rc = 0;
using (var dr = cmd.ExecuteReader())
{
while (dr.Read())
{
rc++;
var e = new TEntity();
e.Id = dr.GetInt(0);
e.Name = dr.GetString(1);
// ...
results.Add(e);
if (rc%100==0)
Thread.CurrentThread.Sleep(100);
}
}
或
var results = new List<TEntity>();
int rc = 0;
foreach (var e in db.MyTable.AsEnumerable())
{
rc++;
var e = new TEntity();
e.Id = dr.GetInt(0);
e.Name = dr.GetString(1);
// ...
results.Add(e);
if (rc%100==0)
Thread.CurrentThread.Sleep(100);
}
为了获得额外的奖励,请使用异步等待并将结果直接流式传输到客户端,而无需在内存中进行批处理。
或者,或者另外,您可以使用命名 Application Locks.
将可以同时执行转储的会话数限制为一个,或者每个 table 一个,等等
我们有一个 asp.Net 应用程序使用托管在 Azure 中的 EF 6。除某些罕见的操作外,大部分时间数据库都以大约 20% DTU 使用率运行。 这些几乎就像 Excel 格式的数据库转储,比如拥有过去 X 年的所有订单等。(高级)用户可以触发这些订单,然后稍后通过电子邮件获得结果。
问题是这些查询用完了所有 DTU,整个应用程序进入爬网状态。我们想限制这些非关键查询,因为这是否需要 10-15 分钟的时间并不重要。
谷歌搜索我找到了减少 DEADLOCK_PRIORITY 的选项,但这不会解决用尽所有资源的问题。
感谢任何指点、想法或解决方案。
Optimizing is going to be hard as it is more or less a db dump.
Azure SQL 数据库没有 Resource Governor 可用,因此您必须在代码中处理此问题。
Azure SQL 数据库以 READ COMMITTED SNAPSHOT 模式运行,因此减慢从 table(或任何流式查询计划)转储数据的会话应该减少其 DTU 消耗而不会产生不利影响其他会话。
为此,请在读取查询结果的循环中等待,从 LINQ 查询返回的 IEnumerable<TEntity>
或从 ADO.NET [=14= 返回的 SqlDataReader
].
但是您必须直接循环播放流媒体结果。您不能先使用 IQueryable<TEntity>.ToList()
或 DataTable.Load()
、SqlDataAdapter.Fill()
等将查询结果复制到内存中,因为这样读取速度会尽可能快。
例如
var results = new List<TEntity>();
int rc = 0;
using (var dr = cmd.ExecuteReader())
{
while (dr.Read())
{
rc++;
var e = new TEntity();
e.Id = dr.GetInt(0);
e.Name = dr.GetString(1);
// ...
results.Add(e);
if (rc%100==0)
Thread.CurrentThread.Sleep(100);
}
}
或
var results = new List<TEntity>();
int rc = 0;
foreach (var e in db.MyTable.AsEnumerable())
{
rc++;
var e = new TEntity();
e.Id = dr.GetInt(0);
e.Name = dr.GetString(1);
// ...
results.Add(e);
if (rc%100==0)
Thread.CurrentThread.Sleep(100);
}
为了获得额外的奖励,请使用异步等待并将结果直接流式传输到客户端,而无需在内存中进行批处理。
或者,或者另外,您可以使用命名 Application Locks.
将可以同时执行转储的会话数限制为一个,或者每个 table 一个,等等