2014-12-11 2 views
0

Я вызываю простую хранимую процедуру, которая возвращает около 650 строк. Существует несколько объединений, и процедура занимает около 5-6 секунд. Нет проблем.Перечисление результатов хранимой процедуры EF

Перечисление результатов, однако, занимает около минуты.

using (var context = new DBContext()) 
{ 
    var results = context.GetResults(param); //5-6 seconds 
    var resultList = results.ToList(); //1 minute+ 
} 

Я не использую Entity Framework много, но это кажется ненормальным. Я делаю что-то неправильно? Есть ли что-то, что я могу посмотреть, чтобы ускорить это? Таблица огромна, но, как я ее читаю, этот код должен перечислять только 650 результатов ... которые совсем не требуют времени.

Примечание: Не уверен, если это связано, но время, которое требуется, чтобы выбрать все строки из указанной таблицы примерно одинакова (около минуты)

+0

Вы пытались выполнить свой прок. в sql-сервере? сколько времени требуется для завершения? –

+0

@ Selman22 Пару секунд. Чуть быстрее, чем первая строка, выполняющая его в коде. – aw04

+0

У меня есть теория, но я хочу знать: вы пробовали профилировать запрос? На какой из этих строк фактически выполняется процедура? Я уверен, что это после второго, но я ничего не знаю о '.GetResults()', поэтому я не могу быть на 100% уверен. – IronMan84

ответ

0

Решение моей проблемы состояло в том, чтобы отключить параметр sniffing, создав копию входного параметра.

alter procedure dbo.procedure 
    @param int 
as 
begin 
    set nocount on; 

    declare @paramCopy int 
    set @paramCopy = @param 

    ... 
0

Основываясь на своем недавнем редактирования, у меня есть представление о том, что происходит. Я думаю, что вызов .GetResults() просто требует, чтобы запрос был готов к запуску, используя отложенное выполнение. Только когда вы вызываете .ToList() в следующей строке, это фактически происходит и пытается самостоятельно создать сущности (отсюда разница во времени).

Так почему же так долго загружаться? Это может быть по ряду причин, в том числе:

  1. Возможно, у вас установлена ​​ленивая загрузка. Это приведет к тому, что все записи будут полностью загружены со всеми их соответствующими навигационными свойствами, и все это будет отслеживаться DbContext. Это составляет лот потребления памяти. Возможно, вы захотите рассмотреть вопрос о включении (но не всем нравится, когда включена ленивая загрузка).

  2. Вы позволяете трекеру отслеживать все записи, которые занимают память. Вместо этого, если данные, которые вы захватываете, все равно будут доступны для чтения, вам может потребоваться использовать AsNoTracking, как в this blog post. Это должно сократить время загрузки.

  3. Вы могли бы хватать много столбцов. Я не знаю, что возвращает ваша процедура, но если в ней много строк, с множеством разных столбцов, все данные, которые будут записаны в память, будут обрабатываться. Вместо этого вам может потребоваться только выбрать как можно меньше столбцов (используя .Select()до звонок до .ToList()), чтобы получить только то, что вам нужно.

+0

Хранимая процедура выполняется немедленно (по объекту ObjectContext.ExecuteFunction'), а противоположность ленивой загрузки - это * нет * загрузка (не загружаемая загрузка). –

Смежные вопросы