powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
4 сообщений из 4, страница 1 из 1
Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
    #38490301
Osho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Я пишу приложение на asp.net с использованием Entity Framework. Все Linq-запросы пишу сначала в LinqPad, затем уже запрос вставляю в приложение.

Код: c#
1.
2.
3.
4.
5.
6.
UploadedFileCompanyRelations
.Where(x=>x.UploadedFileId == 670)
.SelectMany(x=>x.Company.CompanySales.Where(s=>s.ProductId==4))
.Select(x=>x.SaleTaskRelations
.OrderByDescending(t => t.Task.Startline)
.FirstOrDefault(t => t.Task.Type == 6))



Запрос к базе данных:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
DECLARE @Type INT
DECLARE @UploadedId INT
DECLARE @ProductId INT
DECLARE @Progress INT
DECLARE @BranchId INT
DECLARE @SaleProgress INT

SET @Type = 6
SET @UploadedId = 670
SET @ProductId = 4
SET @Progress = 3
SET @BranchId = 1
SET @SaleProgress = 0

--select COUNT(*)
select sOut.ProgressId, t.Progress, t.Type, sp.ProgressType
from dbo.UploadedFileCompanyRelations as ufc
inner join dbo.Sales as sOut on sOut.CompanyId = ufc.CompanyId
inner join dbo.Companies as c on c.Id = ufc.CompanyId
inner join dbo.SaleProgresses as sp on sp.Id = sOut.ProgressId
outer apply
(select TOP 1 t.Type, t.Progress from dbo.Sales as s 
inner join dbo.SaleTaskRelations as strs on strs.SaleId = s.Id
inner join dbo.Tasks as t on t.Id = strs.TaskId
Where s.Id = sOut.Id and t.Type = @Type
Order by t.Startline desc) as t
where ufc.UploadedFileId = @UploadedId 
and @ProductId = sOut.ProductId 
and t.Progress != @Progress
and c.ProviderId = @BranchId 
and sp.ProgressType != @SaleProgress



Что мне удалось выяснить: при написании запроса без
Код: c#
1.
2.
3.
.Select(x=>x.SaleTaskRelations
.OrderByDescending(t => t.Task.Startline)
.FirstOrDefault(t => t.Task.Type == 6))



работает так как в разы быстрее, но без этого куска я получаю просто Sales.

Второй вопрос как переписать
Код: c#
1.
2.
3.
.Select(x=>x.SaleTaskRelations
.OrderByDescending(t => t.Task.Startline)
.FirstOrDefault(t => t.Task.Type == 6))



чтобы он работал также как и
Код: sql
1.
outer apply

в запросе T-SQL. Необходимый участок бд, ниже в изображении.
Если необходима дополнительная инфа с удовольствием допишу.
...
Рейтинг: 0 / 0
Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
    #38490425
Osho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Проблема решилась написанием sql-запроса в asp.net приложении:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
 var prId = new SqlParameter("@ProductId", productId);
            var fileId = new SqlParameter("@UploadedId", id);
            var tasktype = new SqlParameter("@Type", type);
            var brId = new SqlParameter("@BranchId", branchId);

            const string uncompleteQuery = "select COUNT(*) " +
                                 "from dbo.UploadedFileCompanyRelations as ufc " +
                                 "inner join dbo.Sales as sOut on sOut.CompanyId = ufc.CompanyId " +
                                 "inner join dbo.Companies as c on c.Id = ufc.CompanyId " +
                                 "inner join dbo.SaleProgresses as sp on sp.Id = sOut.ProgressId " +
                                 "outer apply " +
                                 "(select TOP 1 t.Type, t.Progress from dbo.Sales as s " +
                                 "inner join dbo.SaleTaskRelations as strs on strs.SaleId = s.Id " +
                                 "inner join dbo.Tasks as t on t.Id = strs.TaskId " +
                                 "Where s.Id = sOut.Id and t.Type = @Type " +
                                 "Order by t.Startline desc) as t " +
                                 "where ufc.UploadedFileId = @UploadedId " +
                                 "and @ProductId = sOut.ProductId " +
                                 "and c.ProviderId = @BranchId " ;

            var uncompleteStoredProcedure = _context.Database.SqlQuery<int>(uncompleteQuery + "and t.Progress != 3", new SqlParameter("@ProductId", productId), new SqlParameter("@UploadedId", id), new SqlParameter("@Type", type), new SqlParameter("@BranchId", branchId));

            var positiveStoredProcedure = _context.Database.SqlQuery<int>(uncompleteQuery + "and t.Progress = 3 and sp.ProgressType = 0", new SqlParameter("@ProductId", productId), new SqlParameter("@UploadedId", id), new SqlParameter("@Type", type), new SqlParameter("@BranchId", branchId));

            var unpositiveStoredProcedure = _context.Database.SqlQuery<int>(uncompleteQuery + "and t.Progress = 3 and sp.ProgressType != 0", new SqlParameter("@ProductId", productId), new SqlParameter("@UploadedId", id), new SqlParameter("@Type", type), new SqlParameter("@BranchId", branchId));



Код сам по себе громоздкий и местами нечитабельный, но теперь та же страница загружается за 1 секунду против 1,7 минуты:)
Неужели все настолько плохо в Linq C#?
...
Рейтинг: 0 / 0
Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
    #38491294
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Osho,
ну вы смотрели какой запрос то выходит после вашего Linq?

а так по теме как замутить OUTER APPLY
http://stackoverflow.com/questions/3014362/c-sharp-outer-apply-in-linq
...
Рейтинг: 0 / 0
Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
    #38491537
Osho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
handmadeFromRu,

Полный запрос Linq выглядит так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
UploadedFileCompanyRelations
.Where(x=>x.UploadedFileId == 670)
.SelectMany(x=>x.Company.CompanySales.Where(s=>s.ProductId==4))
.Select(x=>x.SaleTaskRelations
.OrderByDescending(t => t.Task.Startline)
.FirstOrDefault(t => t.Task.Type == 6))
.Where(x=>x.Task!=null)
.Select(x=>x.Task)
.Where(x=>x.Progress != 3)



Запрос Linq C# к базе:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
	COUNT(1) AS [A1]
	FROM     (SELECT 
		[Extent2].[Id] AS [Id]
		FROM  [dbo].[UploadedFileCompanyRelations] AS [Extent1]
		INNER JOIN [dbo].[Sales] AS [Extent2] ON ([Extent1].[CompanyId] = [Extent2].[CompanyId]) AND ( CAST( [Extent2].[ProductId] AS int) = @p__linq__1)
		WHERE [Extent1].[UploadedFileId] = @p__linq__0 ) AS [Project1]
	OUTER APPLY  (SELECT TOP (1) 
		[Extent3].[SaleId] AS [SaleId], 
		[Extent3].[TaskId] AS [TaskId], 
		[Extent4].[Id] AS [Id], 
		[Extent4].[Type] AS [Type]
		FROM  [dbo].[SaleTaskRelations] AS [Extent3]
		INNER JOIN [dbo].[Tasks] AS [Extent4] ON [Extent3].[TaskId] = [Extent4].[Id]
		WHERE ([Project1].[Id] = [Extent3].[SaleId]) AND ( CAST( [Extent4].[Type] AS int) = @p__linq__2) ) AS [Element1]
	INNER JOIN [dbo].[Tasks] AS [Extent5] ON [Element1].[TaskId] = [Extent5].[Id]
	LEFT OUTER JOIN [dbo].[Tasks] AS [Extent6] ON [Element1].[TaskId] = [Extent6].[Id]
	WHERE 3 <>  CAST( [Extent6].[Progress] AS int)
)  AS [GroupBy1]',N'@p__linq__1 int,@p__linq__0 int,@p__linq__2 int',@p__linq__1=4,@p__linq__0=670,@p__linq__2=3



В LinqPad:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
SELECT [t5].[Id], [t5].[AuthorId], [t5].[ResponsibleId], [t5].[DeptId], [t5].[FromDeptId], [t5].[Created], [t5].[Startline], [t5].[Assigned], [t5].[Completed], [t5].[Type], [t5].[Progress], [t5].[Body], [t5].[Number], [t5].[Ammount], [t5].[Renewal], [t5].[Period], [t5].[Payment], [t5].[Importance]
FROM [UploadedFileCompanyRelations] AS [t0]
INNER JOIN [Companies] AS [t1] ON [t1].[Id] = [t0].[CompanyId]
CROSS JOIN [Sales] AS [t2]
OUTER APPLY (
    SELECT TOP (1) [t4].[Id], [t4].[AuthorId], [t4].[ResponsibleId], [t4].[DeptId], [t4].[FromDeptId], [t4].[Created], [t4].[Startline], [t4].[Assigned], [t4].[Completed], [t4].[Type], [t4].[Progress], [t4].[Body], [t4].[Number], [t4].[Ammount], [t4].[Renewal], [t4].[Period], [t4].[Payment], [t4].[Importance]
    FROM [SaleTaskRelations] AS [t3]
    INNER JOIN [Tasks] AS [t4] ON [t4].[Id] = [t3].[TaskId]
    WHERE ([t4].[Type] = @p0) AND ([t3].[SaleId] = [t2].[Id])
    ORDER BY [t4].[Startline] DESC
    ) AS [t5]
WHERE ([t5].[Progress] <> @p1) AND ([t0].[UploadedFileId] = @p2) AND ([t2].[ProductId] = @p3) AND ([t2].[CompanyId] = [t1].[Id])
ORDER BY [t5].[Startline] DESC



За статью спасибо, но, к сожалению, там разбирается пример когда две таблицы соединены связью один-ко-многим, у меня связь Tasks - SaleTaskRelation - Sales. Поэтому приходится извращаться с множеством select.

Я переписал было запрос c GroupJoin, но запрос выполняется так же медленно, но при этом получаем кучу select в самом запросе SQL.

Запрос с GroupJoin:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
UploadedFileCompanyRelations
.Where(x=>x.UploadedFileId == 670)
.SelectMany(x=>x.Company.CompanySales.Where(s=>s.ProductId==4))
.GroupJoin(SaleTaskRelations, x => x.Id, strs => strs.SaleId,
                        (x, strs) => new { 
						progressType = x.Progress.ProgressType, 
						task = strs.OrderByDescending(t => t.Task.Startline)
                                .FirstOrDefault(t => t.Task.Type == 1).Task 
								}).Where(x=>x.task!= null)
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / Почему в Linq C# запрос выполняется медленнее, чем в LinqPAD? Как оптимизировать?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]