Повысьте производительность запроса с помощью множества сопоставлений «один ко многим». - PullRequest
2 голосов
/ 29 июля 2011

Я использую Entity Framework для SQL Azure, и на одной странице моего приложения мы показываем пользователю довольно много связанных данных. На странице загружается до 30 элементов, но каждый элемент имеет 5 сопоставлений «один ко многим» с другими объектами. Время запроса находится на разумном уровне, но я теряю немного производительности при отображении объектов. (почти целую секунду).

Вот пример того, как выглядит мой объект

public class Task
{
    public string Name {get; set;}
    public string Status {get; set;}
    public DateTime DueDate {get; set;}
    public IEnumerable<TaskData> Data {get; set;}
    public IEnumerable<Transaction> Transactions {get; set;}
    public IEnumerable<File> Files {get; set;}
    public IEnumerable<Comment> Comments {get; set;}
    public IEnumerable<People> People {get; set;}
}

Задача имеет имя, статус и срок выполнения. Он также имеет много TaskData, которые являются пользовательскими парами имя / значение, много транзакций, которые показывают историю задачи, много файлов, много Комментарии и многие Люди, работающие над этим.

Мой EF-запрос выглядит примерно так.

var Items = context.Items.Include(x=>x.Data).Include(x=>x.Files).Include(x=>x.Comments).Include(x=>x.People).Where(some constraint).ToList();

Актуальность конкретной задачи зависит сначала от статуса, а затем от даты выполнения. Поэтому я создал переопределение IComparable для использования с сортировкой. Дело в том, что постраничные запросы не работают хорошо в этом сценарии, потому что сортировка не основана на int или дате (я прав?)

В остальной части нашего приложения мы показываем меньше информации о каждой задаче, и Linq2Entities работает просто отлично. Сопоставление объектов в этом случае убивает нас, хотя. Я пошел по пути прямого перехода к БД с Dapper, но картографирование один ко многим имеет свои предостережения. Для нескольких отношений я думаю, что это будет работать хорошо, но не для 5-6. Следующей вещью, на которую я посмотрел, был PetaPoco, но я не продвинулся слишком далеко, прежде чем подумал, что лучше сначала задать вопрос здесь.

Я с ума сошел, пытаясь вернуть столько данных? Каковы мои варианты получения максимальной производительности от этого? Я возьму немного сложности, так как это только одна область применения.

1 Ответ

2 голосов
/ 26 сентября 2011

Я готов поспорить, что ваш запрос EF возвращает слишком много данных.Дело в том, что «оптимальный» метод извлечения сильно зависит от типа и количества извлекаемых данных.

Зная, что заранее, вы можете настроить запросы, которые вы выполняете на основе ожидаемого набора данных.

Например ... если вы тянете только ограниченное количество сущностей с большим количеством субтитров, шаблон, который я здесь написал, хорошо работает:

Как мне отобразить списки вложенных объектовс Dapper

Если вы знаете, какие идентификаторы вы тянете, а их меньше 2000, вы можете сократить их все, запросив одну сетку и сопоставив, используя QueryMultiple например:

cnn.QueryMultiple(@"select * from Tasks where Id in @ids 
select * from Files where TaskId in @ids
.. etc ..", new {ids = new int[] {1,2,3}});

Если вы хотите набрать больший набор, вам может потребоваться пакетная обработка или поэтапная обработка.


Для вашего конкретного примера я бы запросил Tasks, чтобы получить все идентификаторы задач и данные, а затем сопоставил бы отношения, используя один QueryMultiple, для всех связанных таблиц.

...