我们最近从数据库中删除了大量记录。删除后,从实体框架生成的此语句将超时。我们也为这些陈述设置了SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED。
实体框架代码
_emailSendResultsRepository.GetTable().Count(e => e.EmailId == email.Id && e.SendDate >= startDate);
生成此sql
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[EmailSendResults] AS [Extent1]
WHERE ([Extent1].[EmailId] = @p__linq__0) AND ( CAST( [Extent1].[SendDate] AS datetime2) >= @p__linq__1)
) AS [GroupBy1]
任何想法会导致超时?
答案 0 :(得分:1)
它可能无法直接帮助您,但请结帐:
Which method performs better: .Any() vs .Count() > 0?
如果没有像你所描述的任何性能问题,我将关于表中记录的存在的检查从.Count()更改为.Any()。但是,当你真的不需要确切的计数时,这可能只会对你有所帮助。另外我需要提一下,我目前不删除大表中的任何记录,通常我会在检查.count()之前执行.where()子句。
当您将查询更改为.Where()时,您可以在收集.Count()的详细信息之前尝试检查.Any()
var queryList = _emailSendResultsRepository.GetTable()
.Where(e => e.EmailId == email.Id)
.Where(e.SendDate >= startDate)
.ToList();
if (queryList.Any())
{
....
queryList.Count()....
....
}
在msdn forums的帖子中
有提到:
“但是,即使SELECT COUNT(*)FROM Table在大型表上效率也相当低,因为SQL Server会进行全表扫描。”
答案 1 :(得分:1)
实际上MarkusEgle,你提供的声明:
var queryList = messages
.Where(t => t.LogTimeStamp >= fromDate)
.Where(t => t.LogTimeStamp <= toDate)
.Where(t => t.LogType != stateInfoNoAuditFile)
.OrderBy(m => m.LogID)
.ToList();
执行查询并获取结果,因此如果您随后调用queryList.Count
它根本不接触数据库,它只计算列表中的对象(内存)。您应该删除ToList
以获得所需的结果。