Почему этот CompiledQuery не дает улучшения производительности? - PullRequest
3 голосов
/ 13 апреля 2010

Я пытаюсь ускорить часто используемый запрос. Использование 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 голосов
/ 13 апреля 2010

Благодаря Орандову я нашел ответ здесь (в конце). Если вы внесете в запрос любые изменения, предварительно скомпилированный оператор будет отброшен. В моем случае 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();
}
5 голосов
/ 13 апреля 2010

Вместо 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));
4 голосов
/ 13 апреля 2010

Запросы всегда «компилируются», просто если вы не используете CompiledQuery, то они будут скомпилированы по требованию.Кроме того, CompiledQuery компилируется только в первый раз, когда все равно выполняется (разница в том, что CompiledQuery компилируется только один раз, тогда как «обычный» способ будет компилироваться каждый раз).Для такого простого запроса, как тот, который у вас есть, затраты на компиляцию, вероятно, довольно малы.

Есть ли у вас индекс в поле trade_tag?Это обеспечит вам самое большое увеличение производительности.

0 голосов
/ 19 декабря 2016

Вместо того, чтобы возвращать 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

...