Отправляет email-рассылки с помощью сервиса Sendsay

Всё о документообороте

  Все выпуски  

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


Все о документообороте

Сайт рассылки
 



Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server с помощью LINQ
2014-09-23 10:00 noreply@blogger.com (Станислав Выщепан)
Доклад с таким длинным и непонятным названием я читал на SQL Server User Group 10 сентября в Москве. Ниже слайды запись доклада:

К сожалению, как обычно я не показал все что хотел, часть материала не попала на видео запись. Но я восполню этот недостаток.
Как вы думаете, можно ли на Linq делать запросы, которые работают быстрее рукопашных? Оказывается да, и очень просто.
Например надо сделать функцию, которая отбирает заказы по дате отгрузки. Если параметр указал, то выбрать заказы за эту дату. А если не указана дата, то выбрать все заказы, у которых дата отгрузки пустая. Обычный разработчик напишет такую процедуру:

CREATE PROCEDURE [dbo].[GetTransactionsByShipDate]
    @shipDate datetime
AS
    SELECT t.Id, t.ProductId, t.TransactionDate 
       from Transactions t
    where
        (@shipDate is not null 
          and t.ShippedDate = @shipDate) 
     or (@shipDate is null 
          and t.ShippedDate is null)

Эта процедура подвержена parameter sniffing problem. Проблема заключается в том, что план процедуры генерируется один раз при первом вызове с учетом фактических параметров при вызове. Если при первом вызове ShipDate был NULL (низкая селективность), то сгенерируется план с Index Scan. Если же первый вызов был с конкретным значением даты, то получится Index Seek, который будет неэффективно работать для значений с низкой селективностью.
Простой тест:
DBCC FREEPROCCACHE
GO

EXEC    [dbo].[GetTransactionsByShipDate] NULL
GO

declare @shipdate datetime = getdate()
EXEC    [dbo].[GetTransactionsByShipDate] @shipdate
GO

DBCC FREEPROCCACHE
GO

declare @shipdate datetime = getdate()
EXEC    [dbo].[GetTransactionsByShipDate] @shipdate
GO

EXEC    [dbo].[GetTransactionsByShipDate] NULL
GO

Результаты:
image
Как видите план оказывается далеко не оптимальным в обоих случаях.
А с помощью Linq можно написать так:
private static IQueryable<Transaction> GetValues(
    IQueryable<Transaction> query, 
    DateTime? dateTime)
{
    if (dateTime.HasValue)
    {
        return query.Where(t => t.ShippedDate == dateTime.Value);
    }
    else
    {
        return query.Where(t => t.ShippedDate == null);
    }
}
Тогда буду сгенерированы два разных запроса, каждый со своим, оптимальным для данного запроса, планом.
Более того, такая оптимизация для null value встроена в провайдер Linq2DB. Там можно непосредственно nullable значения подставлять в linq.
Более того, можно использовать filtered index, когда больше 2% значений по индексируемому полю равны NULL.


Результаты семинара “Поиск SharePoint”
2014-09-29 10:00 noreply@blogger.com (Станислав Выщепан)

Месяц назад прошел семинар по поиску в SharePoint 2013. В этот раз семинар был на полный день.  Видеозаписи доступны по ссылке http://gandjustas.justclick.ru/order/spsearch/.

В ходе семинара успели рассмотреть следующие темы:

  • Настройка Content By Search Web Part
  • Сценарии выборки данных (замена CAML)
  • Ранжирование результатов поиска
  • Настройки центра поиска и правил запросов

Отзывы некоторых участников:

Добрый день! Отличное мероприятия Стас, очень понравилось! Упорядочил для себя все знания по поиску, узнал парочку новых и интересных вещей. Также решил давно мучавшую меня проблему с необязательным условием и знаком «?» в выражении запроса поиска. С нетерпением жду следующего семинара =)

Борис Журкин, RTLabs

 

Из семинара получили развернутое и подробное (для первичного ознакомления, на мой взгляд, достаточно подробное ) описание возможностей поиска платформы Sharepoint 2013. Рассмотрели примеры использования в различных сценариях. В общем семинар был очень полезен, как вводная часть, для дальнейшей тесной работы с поиском. От семинара получил на 100% что ожидал.

Вахтанг Барбакадзе, РТК

 

Пока мне не удалось применить полученные знания непосредственно на практике, т.к. наш корпоративный портал на SP 2010.

Однако материал оказался полезным для общего кругозора и понимания возможностей новой версии SP.

Вадим Титов, АВТОМИР

В этот раз с видеозаписью помог Александр Ульмаскулов, любезно предоставив видеокамеру. Записи вебинара теперь включают как экран, так и весь зал с хорошим звуком. Для примера – запись обсуждения на перерыве:

Ссылка на видеозаписи и слайды - http://gandjustas.justclick.ru/order/spsearch/

Приходите на следующий вебинар, буду рассказывать про построение ECM системы на базе SharePoint. Ориентировочно пройдет в середине ноября, чуть позже размещу анонс в блоге.



7 способов улучшить поля в формах SharePoint 2013
2014-10-01 10:00 noreply@blogger.com (Станислав Выщепан)

Кастомизация форм – очень больная тема в SharePoint. InfoPath фактически умер, новые способы кастомизации появятся не раньше следующего релиза (назначенного на конец 2015 года), а для использования SPServices нужен jQuery старой версии, что само по себе несет проблемы, так еще и требует знания отображаемых имен полей, что делает решение ненадежным. Подробнее в моем курсе по клиентской разработке SharePoint.

Создавая TypeScript-определения для клиентской библиотеки SharePoint  сделал несколько примеров полей. Недавно я провел большой рефакторинг и выделил кастомные поля в отдельные, повторно используемые функции.

Все функции содержатся в файле typescripttemplaes.ts. Тем, кто не пользуется TypeScript (зря!), можно скачать .js файл в том же каталоге.

Как пользоваться typescripttemplates:

  1. Скачать файл и добавить .js в проект
  2. Сделать свой файл скрипта для полей, такого вида:
    module _ {
        function init() {
            CSR.override()
                .lookupAddNew("Master", "Add New Master item", true)
                .register();        
        }
    
        SP.SOD.executeOrDelayUntilScriptLoaded(init, "typescripttemplates.ts");
    
        SP.SOD.executeOrDelayUntilScriptLoaded(function () {
            RegisterModuleInit(SPClientTemplates.Utility.ReplaceUrlTokens("~site/YOUR_SCRIPT_PATH.js"), init);
        }, "sp.js");
    } 
  3. Вписать адрес скрипта в ReplaceUrlTokens и вызовы функций между .override() и .register()
  4. В атрибут JSLink поля\формы\типа контента вписать строку такого вида: “~site/PATH/typescripttemplates.js|~site/YOUR_SCRIPT_PATH.js”.

Итак сами функции:

№1 Установка начального значения поля в формах

CSR.override()
   .setInitialValue("FieldInternalName", ANY_VALUE)
   .register();      

Пригодится когда значения полей передаются в Url или через локальный кеш. Значение нужно передавать во внутреннем формате, который использует CSR.

№2 Скрытие поля

CSR.override()
   .makeHidden("FieldInternalName")
   .register();      

Скрывает поле на форме, в представлении, и даже в режиме редактирования таблицы.

№3 Установка поля в Read-Only в формах

CSR.override()
   .makeReadOnly("FieldInternalName")
   .register();      

Заменяет контрол ввода на контрол отображения. Пока не работает в для поля выбора пользователя.

№4 Вычисляемое значение поля

CSR.override()
   .computedValue("Title", function(x) {return SPClientTemplates.Utility.ParseLookupValue(x).LookupValue; }, "SOME_LOOKUP_FIELD")
   .register();      

Автоматически задает значение поля при изменении в связанном поле.

№5 Добавление ссылки на добавление нового элемента в Lookup

CSR.override()
   .lookupAddNew("Master", "Add New Master item", true)
   .register();      

Добавляет рядом с Lookup-полем ссылку, которая открывает форму добавления в связанный список. Последний параметр задает открывать ли форму в диалоге или переходом на страницу формы

№6 Фильтрация Lookup

CSR.override()
   .filteredLookup("Master", '<BeginsWith><FieldRef Name ="Title" /><Value Type = "Text" >{Title}</Value></BeginsWith>')
   .register();      

Вместо статического списка выбора связанного значения делает динамический запрос с помощью предиката. В предикат также можно указать ссылки на другие поля.

№7 Lookup на основе поиска

CSR.override()
   .seachLookup("LookupFieldInternalName")
   .register();      

Заменяет стандартный элемент выбора на компонент autofill, входящий в SharePoint. Для получения связанных элементов используется поиск. Будет работать даже для очень больших списков. В ближайшее время будет добавлена возможность указывать запрос, который выполняется при получении элементов.

Для этого поля надо в JSLink добавить ссылки на файлы autofill.js и sp.search.js – “~site/PATH/typescripttemplates.js|~site/YOUR_SCRIPT_PATH.js|autofill.js(d)|sp.search.js(d)”

Заключение

Качайте, пользуйтесь, пишите фидбек здесь и на сайте проекта - http://sptypescript.codeplex.com/workitem/list/basic. Кроме указанных выше готовых контролов, есть еще куча хелперов, которые вам помогут делать свои шаблоны полей.

Если хелперы будут популярны, то я выложу библиотеку в NuGet.



Семинар “Оптимизация ASP.NET приложений”
2014-10-02 10:00 noreply@blogger.com (Станислав Выщепан)
Быстродействие - это Фича. Для веб-приложений и сайтов это важнейшая фича. Быстрые сайты получают более высокие места в поисковой выдаче. Быстрые веб-приложения улучат восприятие пользователями. Масштабируемые приложения требуют меньше ресурсов и более эффективны с экономической точки зрения. Для любого веб-программиста умение делать быстрые и масштабируемые приложения является критически важным.

Но оптимизация веб-приложений — это не один навык, а целый комплекс, который включает клиентскую оптимизацию, оптимизацию работы с данными, оптимизацию архитектуры и инфраструктуры приложений, а также умение проводить нагрузочное тестирование и выявлять слабые места. Для ASP.NET это важно вдвойне, так как много фреймворков и компонент могут скрывать проблему, и докопаться до сути очень непросто. Но это того стоит!

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

Программа семинара:
  1. Введение в оптимизацию ASP.NET приложений
    • Почему нужно заниматься оптимизацией
    • Архитектура ASP.NET приложений
    • Измерение производительности ASP.NET приложений
    • Инструменты для нагрузочного тестирования веб-приложений
    • Основные подходы оптимизации веб-приложений
  2. Оптимизация инфраструктуры
    • Настройка IIS
    • Оптимизация статического контента
  3. Кеширование динамического контента
    • HTTP-кеширование
    • Серверное кеширование
    • Варьирование кэша на сервере
    • Использование кэша ASP.NET
    • Интеграция кэша ASP.NET и распределенного кэша
  4. Оптимизация работы с данными
    • Оптимизация Linq запросов
    • Оптимизация работы с базой на примере SQL Server
    • Оптимизация записи в СУБД
  5. Клиентская оптимизация
    • Минимизация и бандлинг
    • Оптимизация динамических изображений
    • Оптимизация загрузки страницы
    • Оптимизация выполнения скриптов
    • Оптимизация CSS
  6. Оптимизация серверного кода
    • Оптимизация веб-форм
    • Оптимизация WebAPI
    • Оптимизация .NET кода
Как видите - программа очень плотная и все надо успеть за один день. Так что не будет времени переливать из пустого в порожнее. Полученные знания вы сможете сразу же применить в своих проектах.

Семинар состоится 30 октября. Стоимость семинара - 10,000 рублей с человека.

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

Регистрируйтесь прямо сейчас, количество мест ограничено.
Перейти к заказу билетов







Подборка материалов о серверной оптимизации ASP.NET
2014-10-15 10:00 noreply@blogger.com (Станислав Выщепан)
В процессе подготовки семинара по оптимизации, который пройдет 30 октября 2014 года (регистрация тут - http://gandjustas.timepad.ru/event/150915/), я собрал ранее опубликованные материалы по серверной оптимизации ASP.NET приложений.
Серия постов о кешировании на хабре:
Оптимизация работы с данными:
Какие темы вам еще будут интересны?

 



 
 
С пожеланиями успехов,
Михаил Кузьмин
 

В избранное