代码之家  ›  专栏  ›  技术社区  ›  Grammarian

为什么这个编译查询不能提高性能?

  •  3
  • Grammarian  · 技术社区  · 14 年前

    我正在尝试加速一个经常使用的查询。使用 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 回复  |  直到 7 年前
        1
  •  7
  •   Grammarian    14 年前

    多亏了奥兰多夫,我找到了答案 here (最后)。如果你 任何 对查询的更改,将放弃预编译语句。就我而言, FirstOrDefault() 正在更改基础查询。

    解决办法是打电话 AsEnumerable() 首先查询。通过呼叫 不可数() 预编译查询受到保护,并且 第一个或默认值() 在本地对结果执行 Linq.Enumerable.FirstOrDefault 而不是 Linq.Queryable.FirstOrDefault )

    最终结果:执行时间从45ms缩短到4ms.11x。

    public static Trade FindTradeByTradeTagCompiled(MyEntities entities, int tag)
    {
        IQueryable<Trade> tradeQuery = mCompiledFindTradeQuery(entities, tag);
    
        return tradeQuery.AsEnumerable().FirstOrDefault();
    }
    
        2
  •  5
  •   Marc Gravell    14 年前

    而不是 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));
    
        3
  •  4
  •   Dean Harding    14 年前

    查询总是“编译”的,只是如果不使用 CompiledQuery 然后它将按需编译。此外,还有 编译的查询 只在第一次执行时编译(区别在于 编译的查询 只编译一次,而“常规”方式将每次编译一次)。对于像您所得到的这样一个简单的查询,编译的开销可能非常小。

    你有关于 trade_tag 字段?这将为您提供最大的性能提升。

        4
  •  0
  •   Community Egal    7 年前

    不返回iQueryable,只需设置编译后的查询来直接返回单个trade对象。这比以前的解决方案干净得多。

    // 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

    推荐文章