Длинное название не влезло 
Станислав Выщепан
Обо мне 
• Консультант по архитектуре и разработке бизнес-приложений 
• 10 лет опыта в индустрии 
• 8 лет опыта в .NET и продуктах Microsoft 
• SharePoint Server MVP 
• Автор сообщества по SharePoint на Facebook 
• https://www.facebook.com/groups/sharepointrussian/ 
• Спикер, автор, занимаюсь opensource проектами 
• http://gandjustas.blogspot.ru 
• http://sptypescript.codeplex.com 
• http://spcafcontrib.codeplex.com
Почему веб-приложения 
• 99% бизнес-приложений основано на веб-технологиях 
• Масштабируемость 
• Работа в ограниченных ресурсах с высокими требованиям к 
быстродействию 
• Соотношения чтениязаписи - 982 в высоко инерактивных 
приложениях 
• В 90% случаев узкое место - база данных
Почему Linq и Entity Framework 
• Проверка запросов в момент компиляции 
• Декомпозиция запросов 
• Code-first создание базы данных 
• Интеграция в фреймворк
Хит-парад возражений 
1. Linq генерирует неэффективные SQL запросы 
2. Нельзя написать hint 
3. Медленный маппинг 
4. Медленная генерация SQL 
5. Хранимые процедуры работаю быстрее
Linq генерирует неэффективные SQL запросы 
• Неэффективные SQL-запросы генерируют люди, а не Linq 
• Основная причина – непонимание разницы в семантике 
• Есть ошибки и унаследованные проблемы в генераторе SQL 
• Мало 
• Легко обойти
Linq генерирует неэффективные SQL запросы 
public IEnumerable<DocumentDto> GetDocumentsToday() 
{ 
foreach (var item in Db.Documents.Where(x => x.CreatedOn.Date == DateTime.Today)) 
{ 
yield return Mapper.Map<Document, DocumentDto>(item); 
} 
}
Нельзя написать Hint 
• Зачем писать Hint? 
1. NOLOCK 
• Использовать уровни изоляции 
• Использовать RCSI (включено по умолчанию для code-first) 
2. JOININDEX HIHT 
• Сделать хорошие индексы, обновить статистику 
• Использовать plan_guide
Медленное ВСЕ 
• Протестируем… 
• Маппинг – меньше миллисекуны на объект 
• Генерация запроса - миллисекунды
Хранимые процедуры работаю быстрее 
• Неправда! 
• В .NET используется sp_executesql для выполнения 
параметризованных команд 
• Параметризованные планы кешируются
8 простых советов для повышения 
производительности приложения
№0 Отключить Lazy Load 
… и никогда не включать его
№1 Делать проекции 
• Меньше данных 
• Меньше чтений страниц 
• В случае blob и overflow полей 
• Больше возможности построить покрывающий индекс 
• Объекты не добавляются в контекст 
• Таки делать проекции!
№2 Ограничивать выборку 
• Никогда не тянуть все записи 
• Использовать разбиение по страницам 
• Entity Framework Profiler показывает такие места
№3 Использовать асинхронные запросы 
• Существующий синхронный код легко мигрировать 
• async в методах 
• .ToListAsync() в запросах 
• .SaveChangesAsync() для сохранения 
• await для методов 
• Снижает скорость! 
• Но увеличивает масштабируемость
№4 Не использовать функции и выражения 
в предикатах и соединениях 
• Функция в предикате ломает оптимизатор 
• В .NET легко сгенерировать функцию в запросе 
• Особенно для типа DateTime 
• Проверяйте запросы, которые идут в базу
№5 Не держать открытым IEnumerator 
больше, чем надо для получения данных 
• Пока открыт IEnumerator – открыт DataReader 
• Пока открыт DataReader – удерживаются ресурсы запроса 
• А если уровень изоляции Repeatable Read и выше, то и блокировки 
• Всегда делать .ToListAsync() перед обходи результатов 
• Не отдавать IQueryable<T> в генерацию View
№6 Использовать mapped функции там, 
где Linq не хватает 
• Основные кандидаты: 
• RANKING FUNCTIONS 
• Full Text Search
№7 Не более одного контекста на запрос 
• Использовать IoC – контейнеры
Заключение 
• Основные причины медленных запросов – программисты 
• Учить, а не ограждать 
• Скоро будет курс по оптимизации ASP.NET приложений «от и до» 
• Следите за анонсами на Facebook - 
https://www.facebook.com/groups/144858492215825/
Вопросы? 
Станислав Выщепан 
http://gandjustas.blogspot.com 
@gandjustas 
https://www.facebook.com/gandjustas 
stanislav.v@outlook.com

Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server с помощью LINQ

  • 1.
    Длинное название невлезло Станислав Выщепан
  • 2.
    Обо мне •Консультант по архитектуре и разработке бизнес-приложений • 10 лет опыта в индустрии • 8 лет опыта в .NET и продуктах Microsoft • SharePoint Server MVP • Автор сообщества по SharePoint на Facebook • https://www.facebook.com/groups/sharepointrussian/ • Спикер, автор, занимаюсь opensource проектами • http://gandjustas.blogspot.ru • http://sptypescript.codeplex.com • http://spcafcontrib.codeplex.com
  • 3.
    Почему веб-приложения •99% бизнес-приложений основано на веб-технологиях • Масштабируемость • Работа в ограниченных ресурсах с высокими требованиям к быстродействию • Соотношения чтениязаписи - 982 в высоко инерактивных приложениях • В 90% случаев узкое место - база данных
  • 4.
    Почему Linq иEntity Framework • Проверка запросов в момент компиляции • Декомпозиция запросов • Code-first создание базы данных • Интеграция в фреймворк
  • 5.
    Хит-парад возражений 1.Linq генерирует неэффективные SQL запросы 2. Нельзя написать hint 3. Медленный маппинг 4. Медленная генерация SQL 5. Хранимые процедуры работаю быстрее
  • 6.
    Linq генерирует неэффективныеSQL запросы • Неэффективные SQL-запросы генерируют люди, а не Linq • Основная причина – непонимание разницы в семантике • Есть ошибки и унаследованные проблемы в генераторе SQL • Мало • Легко обойти
  • 7.
    Linq генерирует неэффективныеSQL запросы public IEnumerable<DocumentDto> GetDocumentsToday() { foreach (var item in Db.Documents.Where(x => x.CreatedOn.Date == DateTime.Today)) { yield return Mapper.Map<Document, DocumentDto>(item); } }
  • 8.
    Нельзя написать Hint • Зачем писать Hint? 1. NOLOCK • Использовать уровни изоляции • Использовать RCSI (включено по умолчанию для code-first) 2. JOININDEX HIHT • Сделать хорошие индексы, обновить статистику • Использовать plan_guide
  • 9.
    Медленное ВСЕ •Протестируем… • Маппинг – меньше миллисекуны на объект • Генерация запроса - миллисекунды
  • 10.
    Хранимые процедуры работаюбыстрее • Неправда! • В .NET используется sp_executesql для выполнения параметризованных команд • Параметризованные планы кешируются
  • 11.
    8 простых советовдля повышения производительности приложения
  • 12.
    №0 Отключить LazyLoad … и никогда не включать его
  • 13.
    №1 Делать проекции • Меньше данных • Меньше чтений страниц • В случае blob и overflow полей • Больше возможности построить покрывающий индекс • Объекты не добавляются в контекст • Таки делать проекции!
  • 14.
    №2 Ограничивать выборку • Никогда не тянуть все записи • Использовать разбиение по страницам • Entity Framework Profiler показывает такие места
  • 15.
    №3 Использовать асинхронныезапросы • Существующий синхронный код легко мигрировать • async в методах • .ToListAsync() в запросах • .SaveChangesAsync() для сохранения • await для методов • Снижает скорость! • Но увеличивает масштабируемость
  • 16.
    №4 Не использоватьфункции и выражения в предикатах и соединениях • Функция в предикате ломает оптимизатор • В .NET легко сгенерировать функцию в запросе • Особенно для типа DateTime • Проверяйте запросы, которые идут в базу
  • 17.
    №5 Не держатьоткрытым IEnumerator больше, чем надо для получения данных • Пока открыт IEnumerator – открыт DataReader • Пока открыт DataReader – удерживаются ресурсы запроса • А если уровень изоляции Repeatable Read и выше, то и блокировки • Всегда делать .ToListAsync() перед обходи результатов • Не отдавать IQueryable<T> в генерацию View
  • 18.
    №6 Использовать mappedфункции там, где Linq не хватает • Основные кандидаты: • RANKING FUNCTIONS • Full Text Search
  • 19.
    №7 Не болееодного контекста на запрос • Использовать IoC – контейнеры
  • 20.
    Заключение • Основныепричины медленных запросов – программисты • Учить, а не ограждать • Скоро будет курс по оптимизации ASP.NET приложений «от и до» • Следите за анонсами на Facebook - https://www.facebook.com/groups/144858492215825/
  • 21.
    Вопросы? Станислав Выщепан http://gandjustas.blogspot.com @gandjustas https://www.facebook.com/gandjustas stanislav.v@outlook.com