Оптимизация INNER JOIN
От: Danchik Украина  
Дата: 11.02.16 14:12
Оценка: 99 (1)
Привет Игорь,

Давно тебя не видно на этом форуме, но все же есть надежда что заглядываешь.

Предистория.
В текущем проекте у нас хитрая система защиты данных от непосвященных и данные выбираются в завивисмости от наличия или отсутствия опеределенной записи в других таблицах.
Мы на эти выборки джоинимся, делаем фильтрации, и тд. Классическая декомпозиция. И как результат в конечном запросе у нас получается от 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, меньше телодвижений с либами.

Спасибо!
Re: Оптимизация INNER JOIN
От: IT Россия blogs.rsdn.ru
Дата: 11.02.16 15:16
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Давно тебя не видно на этом форуме, но все же есть надежда что заглядываешь.


У меня сейчас мегарелиз на работе и мегаремонт в доме. Но край уже вроде бы просматривается, так что кам бэк запланирован в скором будущем.

D>Принимаешь ли ты еще пул реквесты, а то как то вяло у тебя с этим в последнее время? Очень бы хотелось чтобы ты проверил мои ченжи и залил в NuGet, меньше телодвижений с либами.


Да, давай делай пул-реквест, я начну там всё потихоньку разгребать.
//rsdn.org/forum/images/bis.gif Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.