Привет Игорь,
Давно тебя не видно на этом форуме, но все же есть надежда что заглядываешь.
Предистория.
В текущем проекте у нас хитрая система защиты данных от непосвященных и данные выбираются в завивисмости от наличия или отсутствия опеределенной записи в других таблицах.
Мы на эти выборки джоинимся, делаем фильтрации, и тд. Классическая декомпозиция. И как результат в конечном запросе у нас получается от 3-х до 7 джоинов на ту же таблицу по Primary Key.
Подумалось что это совсем не проблема и SQL Server соптимизирует сие, но реальность оказалась не такой радужной. Все эти джоины процессаются и скорость запроса резко снижается.
Вот гипотетический Linq запрос, эмулирующий нашу ситуацию на Northwind:
var orders1 = from o in db.Orders
join c in db.Customers on o.CustomerID equals c.CustomerID
where c.CompanyName.StartsWith("A")
select o;
var orders2 = from o in db.Orders
join c in db.Customers on o.CustomerID equals c.CustomerID
where c.CompanyName.EndsWith("S")
select o;
var res = from od in db.OrderDetails
join o1 in orders1 on od.OrderID equals o1.OrderID
join o2 in orders2 on od.OrderID equals o2.OrderID
join c in db.Customers on o2.CustomerID equals c.CustomerID
select new
{
c.CompanyName,
o2.OrderDate,
o1.CustomerID
};
var str = res.ToString();
Какой SQL запрос имеем на выходе:
-- Northwind SqlServer.2012
SELECT
[c2].[CompanyName],
[o1].[OrderDate],
[o].[CustomerID]
FROM
[dbo].[Order Details] [od]
INNER JOIN [dbo].[Orders] [o]
INNER JOIN [dbo].[Customers] [c] ON [o].[CustomerID] = [c].[CustomerID]
ON [od].[OrderID] = [o].[OrderID]
INNER JOIN [dbo].[Orders] [o1]
INNER JOIN [dbo].[Customers] [c1] ON [o1].[CustomerID] = [c1].[CustomerID]
ON [od].[OrderID] = [o1].[OrderID]
INNER JOIN [dbo].[Customers] [c2] ON [o1].[CustomerID] = [c2].[CustomerID]
WHERE
[c1].[CompanyName] LIKE N'%S' AND [c].[CompanyName] LIKE N'A%'
Поизучал я твой код, и, надеюсь, нашел правильное место в SelectQueryOptimizer.cs. Пару дней помучался, и вот что получилось после моих оптимизаций:
-- Northwind SqlServer.2012
SELECT
[c].[CompanyName],
[o].[OrderDate],
[o].[CustomerID]
FROM
[dbo].[Order Details] [od]
INNER JOIN [dbo].[Orders] [o] ON [od].[OrderID] = [o].[OrderID]
INNER JOIN [dbo].[Customers] [c] ON [o].[CustomerID] = [c].[CustomerID]
WHERE
[c].[CompanyName] LIKE N'%S' AND [c].[CompanyName] LIKE N'A%'
Суть этого поста:
Не хочу на английском писать много текста в Github, сделаю линк на этот пост. Также не знаю как бы на это юнит тесты накатить.
Принимаешь ли ты еще пул реквесты, а то как то вяло у тебя с этим в последнее время? Очень бы хотелось чтобы ты проверил мои ченжи и залил в NuGet, меньше телодвижений с либами.
Спасибо!