为什么CompiledQuery没有提高性能?

时间:2010-04-12 23:46:07

标签: c# performance entity-framework compiled-query

我正在尝试加快常用的查询速度。使用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();
    }
}

4 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分: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));

答案 2 :(得分:4)

查询始终是“编译”的,只是如果你不使用CompiledQuery那么它将按需编译。此外,CompiledQuery仅在第一次执行时编译(不同之处在于CompiledQuery仅编译一次,而“常规”方式将每次编译)。对于像你这样的简单查询,编译的开销可能很小。

您有trade_tag字段的索引吗?这将为您提供最大的性能提升。

答案 3 :(得分:0)

只需设置已编译的查询以直接返回单个Trade对象,而不是返回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