2010-04-12 67 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 2010-04-12 23:49:04

+0

谢谢!答案就在那里。 – Grammarian 2010-04-13 00:38:19

回答

7

感谢orandov,我找到了答案here(最后)。如果您使任何更改为查询,则预编译语句将被丢弃。在我的情况下,FirstOrDefault()正在改变基础查询。

解决方法是首先在查询上调用AsEnumerable()。通过调用AsEnumerable(),预编译查询得到保护,并在结果上本地执行FirstOrDefault()(它被称为Linq.Enumerable.FirstOrDefault而不是Linq.Queryable.FirstOrDefault)。

最终结果:执行时间从45ms减少到4ms。快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 2010-04-13 00:37:42

+0

我认为这很好地回答了问题,即使FirstOrDefault是实际问题。这个问题从来没有问过为什么在100,000次调用中没有性能改进 - 这只是为什么编译不会比未编译的更快。因此,“他们实际上都是编译好的”答案非常合适。 – joniba 2011-05-24 17:09:49

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