为什么这个 CompiledQuery 没有提高性能?

发布于 2024-08-28 19:06:38 字数 1257 浏览 17 评论 0原文

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

I am trying to speed up an often used query. Using a CompiledQuery seemed to be the answer. But when I tried the compiled version, there was no difference in performance between the compiled and non-compiled versions.

Can someone please tell me why using Queries.FindTradeByTradeTagCompiled is not faster than 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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初见你 2024-09-04 19:06:38

感谢orandov,我在这里(最后)找到了答案。如果您对查询进行任何更改,预编译语句将被丢弃。就我而言,FirstOrDefault() 正在更改底层查询。

解决方案是首先在查询上调用 AsEnumerable()。通过调用 AsEnumerable(),预编译查询受到保护,并且 FirstOrDefault() 在结果上本地执行(它是针对 Linq.Enumerable.FirstOrDefault 调用的) code> 而不是 Linq.Queryable.FirstOrDefault)。

最终结果:执行时间从 45 毫秒减少到 4 毫秒。速度提高 11 倍。

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

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

Thanks to orandov, I found the answer here (at the end). If you make any changes to the query, the precompiled statement is discarded. In my case, FirstOrDefault() was changing the underlying query.

Solution was to call AsEnumerable() on the query first. By calling AsEnumerable() the precompiled query was protected, and FirstOrDefault() was executed locally on the results (it was called against Linq.Enumerable.FirstOrDefault rather than Linq.Queryable.FirstOrDefault).

Net result: execution time was reduced from 45ms to 4ms. 11x faster.

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

    return tradeQuery.AsEnumerable().FirstOrDefault();
}
岛歌少女 2024-09-04 19:06:38

您是否尝试过:而不是 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));

Rather than AsEnumerable (which won't limit the results at the database), have you tried:

// 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));
诠释孤独 2024-09-04 19:06:38

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

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

Queries are always "compiled" it's just that if you don't use the CompiledQuery then it'll be compiled on-demand. Also, the CompiledQuery is only compiled the first time it's executed anyway (the difference being that a CompiledQuery is only compiled once, whereas the 'regular' way will be compiled each time). For such a simple query like the one you've got, the overhead of compiling is probably quite small.

Do you have an index on the trade_tag field? That'll provide you with the biggest performance increase.

浸婚纱 2024-09-04 19:06:38

无需返回 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 编译性能

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文