【问题标题】:Optimisation of badly performing Linq query in C#C# 中性能不佳的 Linq 查询的优化
【发布时间】:2020-09-19 11:47:10
【问题描述】:

我得到了以下函数,_ContextdatabaseContextUsers 是数据库中的一个表。

该数据库包含约 100 万个条目。表 Users 的 Guid 已编入索引(参见下面显示的代码)。

如何优化GetUserByGuid 使其返回更快?截至目前,返回答案可能需要一分钟,这太慢了。

public void GetUserByGuid(string guid, int page, DateTime from, DateTime to)
{
    var users = _Context.Users
                        .Where(x => x.Guid.Equals(guid) && 
                                    (DateTime.Compare(from.Date, x.TimeDone.Date) <= 0) && 
                                    (DateTime.Compare(x.TimeDone.Date, to.Date) <= 0))
                        .OrderByDescending(x => x.TimeDone)
                        .Skip(page * 10)
                        .Take(10)
                        .ToList();
}

Users 表创建如下:

CREATE TABLE [dbo].[Users] 
(
    [Id]       INT IDENTITY (1, 1) NOT NULL,
    [TimeDone] DATETIME NOT NULL,
    [Guid]     CHAR(64) NOT NULL
);
GO

CREATE NONCLUSTERED INDEX [IX_TimeDone]
ON [dbo].[Users]([TimeDone] ASC) WITH (FILLFACTOR = 90);
GO

CREATE NONCLUSTERED INDEX [IX_Guid]
ON [dbo].[Users]([Guid] ASC) WITH (FILLFACTOR = 90);

【问题讨论】:

  • 能否添加生成的查询SQL?
  • guid 作为char(64) ??为什么这不是uniqueidentifier?另外:如果您坚持使用字符串 - 为什么这 64 个字符 长 - 并且长度固定(因此它将用空格填充到定义的长度)?常规 GUID 将是 36 个字符(包括破折号)......另外:CHAR 类型是非 Unicode - 而 C# 使用 Unicode - 所以你可能会招致代价高昂的“隐式类型”转换”在此处的查询中......

标签: c# sql-server performance linq .net-core


【解决方案1】:

不确定 EF 核心是否可以将 DateTime.Compare 转换为 SQL(如果不是,您使用的是 3.0 版本之前的 EF Core,它会将所有数据提取到内存中并在客户端执行所有操作),而您不这样做不需要它来比较您的 EF 查询中的日期时间,只需直接比较它们,仅处理 toDate 的日期部分添加一天并使用独占比较:

var fromDate = from.Date;
var toDate = to.Date.AddDays(1);
var users = _Context.Users.Where(x => x.Guid.Equals(guid) && 
                            (from.Date <= x.TimeDone) && 
                            (x.TimeDone < to.Date))
                            .OrderByDescending(x => x.TimeDone)
                            .Skip(page * 10)
                            .Take(10)
                            .ToList();

或者使用DbFunctions.DateDiffDay

DbFunctions.DateDiffDay(from, x.TimeDone) >= 0 
&& DbFunctions.DateDiffDay(x.TimeDone, to) >= 0 // if I have not messed the comparison order

【讨论】:

    猜你喜欢
    • 2022-12-13
    • 2013-06-10
    • 2010-09-08
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2019-04-15
    相关资源
    最近更新 更多