C # EntityFramework эффективный способ получения данных (OrderBy + Distinct) - PullRequest
0 голосов
/ 01 мая 2018

Я хочу получить отдельных пользователей из БД с последним временем входа в систему. Мой код работает, но на финский уходит около 20 секунд. Могу ли я оптимизировать свой код?

var usersFromDb = _Context.Users
    .OrderByDescending(u => u.Time)
    .DistinctBy(u => u.ID).ToList();

Модель:

public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Client { get; set; }
        public DateTime Time { get; set; }

    }

В этой таблице около 100 тыс. Записей

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Вы должны добавить некластеризованный индекс для поля Time, чтобы оптимизировать работу OrderBy. Например, вы можете просто изменить свою модель следующим образом

public class User
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Client { get; set; }
    [Index]
    public DateTime Time { get; set; }

}

и применить миграцию к БД по следующему. В противном случае вы можете создать индекс в базе данных без изменения модели EF, просто выполните следующий SQL-запрос

CREATE INDEX IDX_Time ON Users (Time); 

Определение индекса для столбца сортировки улучшает результаты производительности.


Поскольку ID не является первичным ключом , необходимо создать индекс покрытия из двух столбцов, чтобы максимизировать производительность запроса

CREATE INDEX IDX_Time ON Users (Time, ID); 
0 голосов
/ 01 мая 2018

Если я что-то упустил, у пользователей уже должен быть уникальный идентификатор, поэтому отличительный является избыточным.

Я надеюсь, что оптимизатор SQL будет знать, что это кластеризованный индекс, но вы можете попробовать удалить его.

Вам нужно вернуть всех пользователей? Вы используете ленивую загрузку? Возможно, вы также извлекаете данные клиента, поэтому, возможно, стоит проверить профилировщик SQL Server, чтобы увидеть, что происходит.

Вы также можете просто вернуть нужные поля:

var usersFromDb = _Context.Users
    .Select(u => new MyUser
        {
            Id = u.ID,
            Name = u.Name,
            Time = u.Time
        }).
    .OrderByDescending(u => u.Time)
    .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...