Я всегда много писал о SharePoint, но это далеко не единственная область, в которой я разбираюсь.
Сергей Олонцев, MVP по SQL Server, организует встречи SQL Server User Group в Москве. Ближайшая встреча будет 10 сентября и я буду выступать на ней с докладом: Оптимизация высоконагруженных ASP.NET приложений, работающих с MS SQL Server, с помощью LINQ.
Краткое описание доклада:
Вы разрабатываете веб-приложения и используете хранимые процедуры? Вы пишите SELECT … WITH(NOLOCK)? Вы считаете, что ORMы снижают быстродействие приложений? Тогда этот доклад для вас!
В докладе будут развенчаны популярные мифы о применении библиотек Object-Relational Mapping (ORM) в ASP.NET при работе с Microsoft SQL Server. Также будут рассмотрены конкретные методики увеличения быстродействия работы с данными в веб-приложениях.
Встреча пройдет в Microsoft Technology Center, м. Белорусская, ул. Лесная д. 9 10 сентября с 17:00 до 19:00.
На конференции DevCon, которую ежегодно организует Microsoft, в 2014 году я выступал аж с двумя докладами, оба были на тему Business Intelligence в SharePoint.
Недавно были опубликованы видеозаписи. Выложу их в блоге, чтобы проще было найти.
Первый доклад по Power Pivot в SharePoint 2013 (on-premises), в котором я показываю пример мини-erp решения для управленя отделом, которое можно собрать за несколько часов совершенно без программирования.
К сожалению, как обычно я не показал все что хотел, часть материала не попала на видео запись. Но я восполню этот недостаток.
Как вы думаете, можно ли на 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
Результаты:
Как видите план оказывается далеко не оптимальным в обоих случаях.
А с помощью Linq можно написать так:
Тогда буду сгенерированы два разных запроса, каждый со своим, оптимальным для данного запроса, планом.
Более того, такая оптимизация для null value встроена в провайдер Linq2DB. Там можно непосредственно nullable значения подставлять в linq.
Более того, можно использовать filtered index, когда больше 2% значений по индексируемому полю равны NULL.