2010-04-12 1 views
3

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

Может кто-нибудь рассказать мне, почему использование Queries.FindTradeByTradeTagCompiled не быстрее, чем с использованием Queries.FindTradeByTradeTag?

static class Queries 
{ 
    // Pre-compiled query, as per http://msdn.microsoft.com/en-us/library/bb896297 
    private static readonly Func<MyEntities, int, IQueryable<Trade>> mCompiledFindTradeQuery = 
     CompiledQuery.Compile<MyEntities, int, IQueryable<Trade>>(
      (entities, tag) => from trade in entities.TradeSet 
           where trade.trade_tag == tag 
           select trade); 

    public static Trade FindTradeByTradeTagCompiled(MyEntities entities, int tag) 
    { 
     IQueryable<Trade> tradeQuery = mCompiledFindTradeQuery(entities, tag); 

     return tradeQuery.FirstOrDefault(); 
    } 

    public static Trade FindTradeByTradeTag(MyEntities entities, int tag) 
    { 
     IQueryable<Trade> tradeQuery = from trade in entities.TradeSet 
             where trade.trade_tag == tag 
             select trade; 

     return tradeQuery.FirstOrDefault(); 
    } 
} 
+1

Эта ссылка может помочь http://msdn.microsoft.com/en-us/magazine/ee336024.aspx – orandov

+0

Спасибо! Ответ был там. – Grammarian

ответ

7

Благодаря orandov, я нашел ответ here (в конце). Если вы делаете , любые меняются на запрос, прекомпилированный оператор отбрасывается. В моем случае FirstOrDefault() менял базовый запрос.

Решение должно было позвонить по телефону AsEnumerable() по запросу. Вызвав AsEnumerable(), предварительно скомпилированный запрос был защищен, и FirstOrDefault() был выполнен локально по результатам (он был вызван от Linq.Enumerable.FirstOrDefault, а не от Linq.Queryable.FirstOrDefault).

Чистый результат: время выполнения сократилось с 45 мс до 4 мс. 11 раз быстрее.

public static Trade FindTradeByTradeTagCompiled(MyEntities entities, int tag) 
{ 
    IQueryable<Trade> tradeQuery = mCompiledFindTradeQuery(entities, tag); 

    return tradeQuery.AsEnumerable().FirstOrDefault(); 
} 
4

Запросы всегда «скомпилированный» это просто, что, если вы не используете CompiledQuery, то он будет скомпилирован по требованию. Кроме того, CompiledQuery скомпилирован только в первый раз, когда он выполняется в любом случае (разница состоит в том, что CompiledQuery скомпилируется только один раз, тогда как «обычный» способ будет скомпилирован каждый раз). Для такого простого запроса, как тот, который у вас есть, накладные расходы на компиляцию, вероятно, довольно малы.

У вас есть какой-либо индекс на поле trade_tag? Это обеспечит вам наибольшее увеличение производительности.

+0

Спасибо за ваши комментарии общего характера, но вы вообще не ответили на вопрос. Да, есть индекс на trade_tag. Если запрос вызывается 100 000 раз (как и будет), накладные расходы не являются «довольно маленькими». – Grammarian

+0

Я думаю, что это очень хорошо отвечает на вопрос, даже если FirstOrDefault была реальной проблемой. Вопрос никогда не спрашивал, почему нет улучшения производительности в 100 000 звонков - именно поэтому компиляция не быстрее, чем не скомпилирована. Таким образом, ответ «они фактически скомпилированы» вполне подходит. – joniba

5

Вместо AsEnumerable (который не будет ограничивать результаты в базе данных), вы пробовали:

// Pre-compiled query, as per http://msdn.microsoft.com/en-us/library/bb896297 
private static readonly Func<MyEntities, int, IQueryable<Trade>> mCompiledFindTradeQuery = 
    CompiledQuery.Compile<MyEntities, int, IQueryable<Trade>>(
     (entities, tag) => (from trade in entities.TradeSet 
          where trade.trade_tag == tag 
          select trade).Take(1)); 
0

Вместо возвращения IQueryable, просто создать скомпилированный запрос, возвращающий единой торговли объект напрямую. Это намного более чистый код, чем предыдущие решения.

// Pre-compiled query, as per http://msdn.microsoft.com/en-us/library/bb896297 
private static readonly Func<MyEntities, int, Trade> mCompiledFindTradeQuery = 
    CompiledQuery.Compile<MyEntities, int, Trade>(
     (entities, tag) => (from trade in entities.TradeSet 
          where trade.trade_tag == tag 
          select trade).FirstOrDefault()); 

public static Trade FindTradeByTradeTagCompiled(MyEntities entities, int tag) 
{ 
    return mCompiledFindTradeQuery(entities, tag); 
} 

Другой пример здесь: Linq to SQL to Linq compiled performance

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

  • Нет связанных вопросов^_^