简体   繁体   中英

Optimisation of badly performing Linq query in C#

I got the following function, _Context is a databaseContext and Users is a table in the database.

The database consists of ~1 million entries. The Guid of the table Users is indexed (see code shown below).

How can I optimize GetUserByGuid so that it returns faster? As of now it can take up to a minute to return an answer, which is way too slow.

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();
}

The Users table is created as follows:

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);

Not sure that EF core can translate DateTime.Compare into SQL (and if not an you are using EF Core before 3.0 version it will fetch all the data into memory and will perform all operations on the client side) and you don't need it to compare datetimes in your EF query, just compare them directly, to handle the date part only for toDate add one day and use exclusive comparison:

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();

Or use DbFunctions.DateDiffDay :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM