2009-11-23 3 views
1

У меня есть этот запрос, который выполняется, хотя Linq to Entities. При первом запуске запроса создается план выполнения, который занимает менее 2 минут. После того, как план кэшируется, запрос занимает 1 или 2 секунды. Проблема в том, что план продолжает восстанавливаться каждые несколько часов, и я не уверен, почему это было бы?Реконструкция выполнения запроса SQL Server

Это запрос linq, который мы используем, я знаю, что он выглядит сумасшедшим, но для чего нам это нужно, это наш единственный вариант.

var data = from row in mgr.ServiceDesk_RequestEvent 
    .Include("ServiceDesk_Event") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet.ServiceDesk_Rule") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet.ServiceDesk_Rule.ServiceDesk_RuleOperator") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet.ServiceDesk_Rule.ServiceDesk_RuleConstraintField") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet.ServiceDesk_Rule.ServiceDesk_RuleConstraintValue") 
    .Include("ServiceDesk_Event.ServiceDesk_SLAEventRule.ServiceDesk_RuleSet.ServiceDesk_Action") 
    .Include("ServiceDesk_Request") 
    .Include("ServiceDesk_Request.People_User") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestCategory") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestCategory.ServiceDesk_SLA") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestRole_Groups") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestRole_Groups.Security_Role.Security_UserRoles") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestRole_Groups.Security_Role.Security_UserRoles.Security_User") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestPriority") 
    .Include("ServiceDesk_Request.Offices_User") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestTechnicians") 
    .Include("ServiceDesk_Request.ServiceDesk_RequestTechnicians.People") 
    where row.Completed == false && row.Deleted == false 
    select row; 

Я не хочу вставлять созданный t-sql здесь, так как он довольно большой. Если у кого есть идеи, пожалуйста, не стесняйтесь вносить свой вклад.

Thank you.

+0

Вы правы. Это выглядит сумасшедшим. Вам действительно нужны все поля каждого объекта, в который вы включаете *, и * вы намерены обновлять каждый отдельный экземпляр * и *, который вы профилировали, и обнаружили, что это быстрее, чем загрузка индивидуального спроса? Это единственный разумный аргумент, который я могу придумать для этого, вместо того, чтобы проектировать (мой первый выбор для использования только для чтения) или разбить на более мелкие запросы. –

ответ

1

Возможная причина в том, что ваш сервер находится под давлением памяти, что заставляет кеш-план запроса перерабатываться быстрее.

Сколько оперативной памяти имеет сервер?

Повторяя ваш вопрос, эта строка немного беспокоит: «В первый раз, когда выполняется запрос, он генерирует план выполнения, который занимает чуть меньше 2 минут». 2 минуты в первый раз для простого запроса длительное время. Запускаете ли вы какие-либо другие приложения в ящике SQL Server (надеюсь, нет)?

Предлагаю вам монитор со встроенными счетчиками производительности: SQL Server, Plan Cache Counters.

Удаление планов выполнения из планов выполнения процедуры Cache

остаются в кэше процедуры до тех пор, есть достаточно памяти для хранения их. Когда существует давление памяти, модуль базы данных использует подход на основе затрат, чтобы определить, какое выполнение планирует удалить из процедуры кэш. Для принятия решения о затратах двигатель базы данных увеличивается, и уменьшает текущую переменную затрат для каждого плана выполнения в соответствии с следующими факторами.

Когда процесс пользователя вставляет план выполнения в кэш, пользовательский процесс устанавливает текущую стоимость , равной исходный запрос компилировать стоимости; для планов ad-hoc-исполнения пользовательский процесс устанавливает текущую стоимость ноль. После этого каждый раз, когда пользователь ссылается на план выполнения, , он сбрасывает текущую стоимость на исходную стоимость компиляции ; для ad-hoc выполнение планов пользовательского процесса увеличивает текущую стоимость. Для всех планов максимальное значение для текущей стоимости является исходной компиляцией .

При наличии давления памятиDatabase Engine отвечает путем удаления планов выполнения из процедуры кэш. Чтобы определить, какие планы на удалить, двигатель базы данных повторно проверяет состояние каждого исполнения планирует и удаляет планы, когда их текущая стоимость равна нулю.Выполнение план с нулевой текущей стоимостью не удален автоматически, когда память давление существует; он удаляется только , когда Database Engine изучает план , а текущая стоимость равна нулю. При изучении плана выполнения модуль базы данных подталкивает текущую стоимость к нулю, уменьшая текущую стоимость , если в настоящее время не используется запрос .

Двигатель базы данных повторно рассматривает планы выполнения до тех пор, пока не был удален, чтобы удовлетворить требованиям . В то время как имеется давление, план выполнения может имеет увеличенную и уменьшенную стоимость более одного раза. Когда давление памяти больше не существует, то компонент Database Engine прекращает снижение текущей стоимости неиспользованных планов выполнения и все планов выполнения остается в кэше процедуры, даже если их стоимость нуля.

Компонент Database Engine использует ресурс монитор и пользовательские темы, чтобы освободить память из кэша процедур в ответ на давление памяти. Контроллер ресурсов и пользовательские потоки могут изучить планы, выполняемые одновременно с уменьшить текущую стоимость для каждого неиспользованный план выполнения. Ресурс монитор удаляет планы выполнения от кэш процедур при глобальной памяти давление существует. Он освобождает память до , применяя политики для системной памяти, память процесса, память пула ресурсов, и максимальный размер для всех кешей.

Максимального размер для всех кэшей является функции размера пула буферов и не может превышать максимальную сервер памяти. Для получения дополнительной информации о настройке максимальной памяти сервера , см. Параметр максимальной памяти сервера в sp_configure (Transact-SQL).

Если вы еще не видели: Plan Caching in SQL Server 2008

+0

Сервер имеет 8 ГБ ОЗУ, но он не находится под большой нагрузкой. Но если есть способ подтвердить, что это было бы здорово. – Lukasz

1

This MSDN article хорошая ссылка на кэш плана выполнения. Одним из способов оптимизации использования плана выполнения является использование параметризованного SQL вместо жесткого/динамического SQL.

например.

SELECT * FROM MyTable WHERE [email protected] 

лучше

SELECT * FROM MyTable WHERE ID=1 

как же план может кэшировать и не использовать повторно, независимо от того, что значение @Id есть. Чем больше используется план выполнения, тем более вероятно, что он останется в кеше, поскольку он считается полезным.

Я не знаю тип оператора LINQ, но это стоит иметь в виду. Также, как сказал Митч, чем больше у вас памяти, тем больше вы можете хранить в кеше.

Также обратите внимание, что здесь работает не только кэширование плана выполнения.У вас также есть кеш данных, который имеет существенную разницу в производительности - как только вы выполнили запрос один раз, данные будут храниться в кеше данных, поэтому для последующих вызовов данные уже находятся в памяти - это источник большинства разница в производительности.

+0

LINQ to Entities генерирует параметризованный sql, поэтому я не думаю, что это проблема. Спасибо за статью! – Lukasz

+0

ах ок. Просто обратите внимание на мои последние изменения в кэше данных - это большая проблема для производительности – AdaTheDev

Смежные вопросы