Когда компиляция запросов LINQ to SQL повышает производительность
Я имел в виду статью, в которой основное внимание уделяется ускорению LINQ to SQL Queries. Один из методов, который он упоминает, - "Использовать скомпилированные запросы" и объясняет, как его использовать.
Я хотел видеть улучшение производительности скомпилированных запросов, и поэтому я попробовал тот же пример, предоставленный автором. Я использовал Northwind Db как datacontext. Я попробовал выполнить обычное выполнение и выполнил компиляцию и проверил их на LINQ PAD.
Сначала я попытался выполнить запрос без с помощью CompileQuery. Это заняло 2.065 секунды.
var oo = from o in Orders
where o.OrderDetails.Any (p => p.UnitPrice > 100)
select o;
oo.Dump ("Order items with unit price more than $100");
var oo1 = from o in Orders
where o.OrderDetails.Any (p => p.UnitPrice > 10)
select o;
oo1.Dump ("Order items with unit price more than $10");
Во-вторых, запросы с с помощью CompileQuery. Это заняло 2.100 секунд.
var oo = CompiledQuery.Compile ((TypedDataContext dc, decimal unitPrice) =>
from o in Orders
where o.OrderDetails.Any (p => p.UnitPrice > unitPrice)
select o
);
oo (this, 100).Dump ("Order items with unit price more than $100");
oo (this, 10).Dump ("Order items with unit price more than $10");
Повторное выполнение их несколько раз показало, что время, затраченное обоими подходами, почти одинаково.
Здесь мы видим только два выполнения запросов для каждого метода. Я попытался сделать 10 запросов для каждого из них. Но оба они закончили около 7 секунд.
Действительно ли предварительная компиляция запросов повышает производительность? Или я неправильно понимаю, что это условия использования?
Спасибо за ваше время и внимание.
Edit:
После прочтения принятого ответа читатели могут также захотеть пройти в этой статье, в котором приятно объясняется, как скомпилированные запросы повышают производительность.
Ответы
Ответ 1
Помните, что есть две основные части запроса LINQ, которые могут быть особенно дорогими:
- Компилирование выражений LINQ в SQL-выражение.
- Запуск инструкции SQL и получение результатов
В вашем случае у вас относительно простой запрос и очень медленное соединение с базой данных, некоторые очень большие наборы данных или таблицы, которые не индексируются оптимальным способом для запуска этого конкретного запроса. Или, может быть, комбинация из всех трех.
Таким образом, по сравнению с количеством времени, которое требуется для создания SQL для вашего запроса (возможно, 10-50 миллисекунд), второй шаг занимает столько времени (~ 1000 мс), что вы вряд ли заметите разницу.
Вы увидите значительные улучшения, если все условия верны:
- ваш запрос LINQ сложный,
- у вас есть быстрое соединение с вашей базой данных,
- сам запрос SQL быстро запускается в этой базе данных и
- набор результатов достаточно мал, что он быстро возвращается из базы данных.
На практике у меня были запросы, которые могут потребовать от 500 мс для компиляции, но всего несколько миллисекунд для фактического запуска. Обычно это случаи, когда я сосредотачиваюсь на предкомпиляции запросов.
Один из хороших способов заранее узнать, какой рост производительности вы можете ожидать от предварительно скомпилированных запросов, - это время второго экземпляра вашего запроса с использованием объекта Stopwatch
, а затем запустить сгенерированный SQL напрямую с помощью функции LINQPad Analyze SQL, Если SQL-запрос возвращается быстро, но запрос LINQ занимает много времени, это хороший кандидат для предварительной компиляции.