3

我正在尝试加快经常使用的查询。使用 aCompiledQuery似乎是答案。但是当我尝试编译版本时,编译版本和非编译版本在性能上没有区别。

有人可以告诉我为什么 usingQueries.FindTradeByTradeTagCompiled不比 using 快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

4 回答 4

7

感谢 orandov,我在这里找到了答案(最后)。如果您对查询进行任何更改,预编译语句将被丢弃。就我而言,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();
}
于 2010-04-13T00:47:18.540 回答
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));
于 2010-04-13T03:51:28.247 回答
4

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

你有这个trade_tag领域的索引吗?这将为您提供最大的性能提升。

于 2010-04-12T23:52:30.300 回答
0

Instead of returning IQueryable, just set up the compiled query to return the single Trade object directly. This is a lot cleaner code than the previous solutions.

// 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);
}

Another example is here: Linq to SQL to Linq compiled performance

于 2016-12-19T19:17:00.773 回答