SQL Server има оптимизация, която се нарича parameter sniffing, която запазва и кешира query планове при извикване и компилиране на stored procedure за конкретни параметри.
По подразбиране .NET приложенията използват малко по-различни параметри отколкото SSMS например:
За приложения:
1 |
set arithabort off |
за SSMS:
1 |
set arithabort on |
Съответно в някои случаи заявките се оптимизират грешно за .NET приложения (с arithabort off), но в SSMS работят наред, тъй като няма натрупана статистика, за да се оптимизират.
Бързо решение на проблема (временно!) е да се изпълни
1 |
DBCC FREEPROCCACHE |
Това изчиства кеша на сторнатите процедури и започва наново да се съхраняват. Тези статистики се пазят в паметта, поради което рестарт на сървъра също върши работа.
Има и други опции, като да се добавят различни опции към заявката като use recompile, option recompile, optimize for unknown и т.н.
По-глобално решение би било използването на Trace flag 4136 или
1 2 3 4 |
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">DATABASE</span> SCOPED CONFIGURATION { PARAMETER_SNIFFING <strong>=</strong> { <strong>ON</strong> | OFF | PRIMARY} } |
По-долу има подробна информация за този (и други случаи) и различни решения на проблема:
http://www.sommarskog.se/query-plan-mysteries.html
Сериозен недостатък при .NET приложения и EF е генерирането на dynamic SQL, който използва sp_executesql и лесно може да възникне такъв проблем.