UPDATE:当前的linq代码添加到底部,寻找建议删除linq自动添加的子查询,因为它创建了一个糟糕的执行计划
我的查询运行时间超过25秒,但如果我可以在EXISTS语句中移动条件,它将在几毫秒内运行。
我希望有人帮助我在LINQ中生成所需的执行计划。
由LINQ制作的SQL:
SELECT TOP (50)
[Filter3].[id] AS [id],
[Filter3].[client_id] AS [client_id],
[Filter3].[status] AS [status],
[Filter3].[name1] AS [name],
[Filter3].[C1] AS [C1],
[Filter3].[fail_alert_ind] AS [fail_alert_ind],
[Filter3].[parent_group_exec_id] AS [parent_group_exec_id],
[Filter3].[C2] AS [C2],
[Filter3].[id1] AS [id1],
[Filter3].[case_group_ind] AS [case_group_ind],
[Filter3].[C3] AS [C3],
[Filter3].[execution_ratio] AS [execution_ratio],
[Filter3].[name] AS [name1],
[Filter3].[name3] AS [name2],
[Filter3].[status_color] AS [status_color],
[Filter3].[scheduled_start_time] AS [scheduled_start_time],
[Filter3].[C4] AS [C4],
[Filter3].[C5] AS [C5],
[Filter3].[name4] AS [name3],
[Filter3].[name2] AS [name4],
[Filter3].[C6] AS [C6],
[Filter3].[upload_ratio] AS [upload_ratio],
[Filter3].[id2] AS [id2],
[Filter3].[C7] AS [C7],
[Filter3].[hold_ind] AS [hold_ind],
[Filter3].[C8] AS [C8]
FROM ( SELECT [Project1].[id] AS [id], [Project1].[scheduled_start_time] AS [scheduled_start_time], [Project1].[parent_group_exec_id] AS [parent_group_exec_id], [Project1].[execution_ratio] AS [execution_ratio], [Project1].[hold_ind] AS [hold_ind], [Project1].[upload_ratio] AS [upload_ratio], [Project1].[name] AS [name], [Project1].[fail_alert_ind] AS [fail_alert_ind], [Project1].[id1] AS [id1], [Project1].[name1] AS [name1], [Project1].[case_group_ind] AS [case_group_ind], [Project1].[name2] AS [name2], [Project1].[client_id] AS [client_id], [Project1].[status] AS [status], [Project1].[id2] AS [id2], [Project1].[C1] AS [C1], [Project1].[C2] AS [C2], [Project1].[C3] AS [C3], [Project1].[C4] AS [C4], [Project1].[C5] AS [C5], [Project1].[C6] AS [C6], [Project1].[C7] AS [C7], [Project1].[C8] AS [C8], [Project1].[name3] AS [name3], [Project1].[status_color] AS [status_color], [Project1].[name4] AS [name4], row_number() OVER (ORDER BY [Project1].[id] ASC) AS [row_number]
FROM ( SELECT
[Extent1].[id] AS [id],
[Extent1].[scheduled_start_time] AS [scheduled_start_time],
[Extent1].[parent_group_exec_id] AS [parent_group_exec_id],
[Extent1].[execution_ratio] AS [execution_ratio],
[Extent1].[hold_ind] AS [hold_ind],
[Extent1].[upload_ratio] AS [upload_ratio],
[Extent2].[name] AS [name],
[Extent2].[fail_alert_ind] AS [fail_alert_ind],
[Extent3].[id] AS [id1],
[Extent3].[name] AS [name1],
[Extent3].[case_group_ind] AS [case_group_ind],
[Extent4].[name] AS [name2],
[Extent4].[client_id] AS [client_id],
[Extent4].[status] AS [status],
[Extent6].[id] AS [id2],
[Extent5].[first_name] + N' ' + [Extent5].[last_name] AS [C1],
CASE WHEN ([Extent1].[patriarch_id] IS NULL) THEN 0 ELSE [Extent1].[patriarch_id] END AS [C2],
N'Group' AS [C3],
[Extent8].[first_name] + N' ' + [Extent8].[last_name] AS [C4],
[Extent9].[first_name] + N' ' + [Extent9].[last_name] AS [C5],
CASE WHEN (1 = [Extent1].[uploaded]) THEN N'Yes' ELSE N'No' END AS [C6],
CASE WHEN ([Extent3].[external_test_mgmt_id] IS NOT NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C7],
CASE WHEN (1 = [Extent6].[accept_revisions_ind]) THEN 1 ELSE 0 END AS [C8],
[Extent7].[name] AS [name3],
[Extent7].[status_color] AS [status_color],
[Extent10].[name] AS [name4]
FROM [dbo].[group_execution] AS [Extent1]
INNER JOIN [dbo].[automation_sequence_status] AS [Extent2] ON [Extent1].[run_status_id] = [Extent2].[id]
INNER JOIN [dbo].[automation_sequences] AS [Extent3] ON [Extent1].[automation_sequence_id] = [Extent3].[id]
INNER JOIN [dbo].[project] AS [Extent4] ON [Extent3].[project_id] = [Extent4].[id]
INNER JOIN [dbo].[users] AS [Extent5] ON [Extent3].[last_modified_by_id] = [Extent5].[id]
INNER JOIN [dbo].[execution_schedule] AS [Extent6] ON [Extent1].[schedule_id] = [Extent6].[id]
LEFT OUTER JOIN [dbo].[automation_sequence_test_case_status] AS [Extent7] ON [Extent1].[runtime_case_grp_status] = [Extent7].[id]
LEFT OUTER JOIN [dbo].[users] AS [Extent8] ON [Extent1].[executed_by_id] = [Extent8].[id]
LEFT OUTER JOIN [dbo].[users] AS [Extent9] ON [Extent3].[created_by_id] = [Extent9].[id]
LEFT OUTER JOIN [dbo].[machines] AS [Extent10] ON [Extent1].[machine_id] = [Extent10].[id]
LEFT OUTER JOIN [dbo].[automation_sequence_executions] AS [Extent11] ON [Extent1].[holding_at_id] = [Extent11].[id]
LEFT OUTER JOIN [dbo].[group_execution] AS [Extent12] ON [Extent1].[holding_at_id] = [Extent12].[id]
) AS [Project1]
WHERE ((1 = [Project1].[client_id]) AND (1 = [Project1].[status]) AND ([Project1].[parent_group_exec_id] IS NULL) AND ([Project1].[name1] LIKE '%UAT%')) OR ( EXISTS (SELECT
1 AS [C1]
FROM (SELECT [Extent13].[id] AS [id3], [Extent13].[patriarch_id] AS [patriarch_id], [Extent13].[runtime_case_grp_status] AS [runtime_case_grp_status]
FROM [dbo].[automation_sequence_executions] AS [Extent13]
INNER JOIN [dbo].[automation_sequences] AS [Extent14] ON [Extent13].[automation_sequence_id] = [Extent14].[id]
WHERE [Extent14].[last_modified_by_id] IS NOT NULL ) AS [Filter1]
LEFT OUTER JOIN [dbo].[automation_sequence_test_case_status] AS [Extent15] ON [Filter1].[runtime_case_grp_status] = [Extent15].[id]
WHERE ((CASE WHEN ([Filter1].[patriarch_id] IS NULL) THEN [Filter1].[id3] ELSE [Filter1].[patriarch_id] END) = [Project1].[C2]) AND ((CASE WHEN ([Filter1].[patriarch_id] IS NULL) THEN [Filter1].[id3] ELSE [Filter1].[patriarch_id] END) = [Project1].[C2])
))
) AS [Filter3]
WHERE [Filter3].[row_number] > 0
ORDER BY [Filter3].[id] ASC
EXISTS中的Where子句是我所有问题的来源。它将where子句放在它正在生成的新子查询之外。
上面的例子:
WHERE((CASE WHEN([Filter1]。[patriarch_id]为空)然后[Filter1]。[id3] ELSE [Filter1]。[patriarch_id] END)= [Project1]。[C2])AND ((CASE WHEN([Filter1]。[patriarch_id] IS NULL)那么[Filter1]。[id3] ELSE [Filter1]。[patriarch_id] END)= [Project1]。[C2])
我希望EXISTS看起来像这样:
注意如何检查[Project1]。[C2]。
WHERE ((1 = [Project1].[client_id]) AND (1 = [Project1].[status]) AND ([Project1].[parent_group_exec_id] IS NULL) AND ([Project1].[name1] LIKE '%UAT%')) OR ( EXISTS (SELECT
1 AS [C1]
FROM (SELECT [Extent13].[id] AS [id3], [Extent13].[patriarch_id] AS [patriarch_id], [Extent13].[runtime_case_grp_status] AS [runtime_case_grp_status]
FROM [dbo].[automation_sequence_executions] AS [Extent13]
INNER JOIN [dbo].[automation_sequences] AS [Extent14] ON [Extent13].[automation_sequence_id] = [Extent14].[id]
WHERE [Extent14].[last_modified_by_id] IS NOT NULL
and
([Extent13].[patriarch_id] = [Project1].[C2])
) AS [Filter1]
LEFT OUTER JOIN [dbo].[automation_sequence_test_case_status] AS [Extent15] ON [Filter1].[runtime_case_grp_status] = [Extent15].[id]
))
CURRENT LINQ CODE
如果任何人有任何建议以防止创建子查询,那将是受欢迎的。
谢谢!
void Main()
{
Expression<Func<Contract_SeqExecution, bool>> globalFilter = r => r.ModifiedBy.Contains("w");
Contract_SeqExecution c = new Contract_SeqExecution();
//query root
Expression<Func<Contract_SeqExecution, bool>> rootFilter = x => x.client_id == 1 && x.project_status == true && x.parentId == null;
rootFilter = rootFilter.And(globalFilter);
IQueryable<Contract_SeqExecution> geRootResults = c.queryGroups(this);
IQueryable<Contract_SeqExecution> aseRootResults = c.queryTestCases(this);
var rootUnion = geRootResults.Concat(aseRootResults);
//end query root
//query descendants
Expression<Func<Contract_SeqExecution, bool>> descendantFilter = x => x.client_id == 1 && x.project_status == true && x.parentId != null;
descendantFilter = descendantFilter.And(globalFilter);
IQueryable<Contract_SeqExecution> geDescendantResults = c.queryGroups(this);
IQueryable<Contract_SeqExecution> aseDescendantResults = c.queryTestCases(this);
var descendantUnion = geDescendantResults.Concat(aseDescendantResults);
//end query descendants
//Perform the EXISTS statement in where clause. This is the problem code
Expression<Func<Contract_SeqExecution, bool>> childFilter = r => descendantUnion.Where(descendantFilter).Any(x=>x.patriarchId == r.ID);
rootFilter = rootFilter.Or(childFilter);
rootUnion = rootUnion.AsExpandable().Where(rootFilter);
rootUnion.OrderBy(r => r.ID).Skip(0).Take(50).Dump();
}
public class Contract_SeqExecution
{
public int ID { get; set; }
public string Name { get; set; }
public string DisplayName { get; set; }
public int SeqID { get; set; }
public int CaseGroupInd { get; set; }
public string CaseGroupText { get; set; }
public string ExecRatio { get; set; }
public string ModifiedBy { get; set; }
public string Project { get; set; }
public string Uploaded { get; set; }
public string UploadRatio { get; set; }
public bool FailedInd { get; set; }
public bool HoldInd { get; set; }
public int? parentId { get; set; }
public int patriarchId { get; set; }
public DateTime? SchedRunTime { get; set; }
//other fields
public string Machine {get;set;}
public int is_accepting_changes {get;set;}
public string holding_at_name {get;set;}
public string RunStatus {get;set;}
public string CaseGroupStatus {get; set;}
public string TCStatusColor {get; set;}
public string ExecutedBy {get;set;}
public string CreatedBy {get;set;}
public int? ScheduleID {get;set;}
public bool SeqUploaded {get;set;}
//end other fields
public int? parent_group_exec_id { get; set; }
public int client_id { get; set; }
public bool project_status { get; set; }
public IQueryable<Contract_SeqExecution> queryGroups(UserQuery context)
{
var result = (from ge in context.group_execution
join asstatus in context.automation_sequence_status on ge.run_status_id equals asstatus.id
join aseq in context.automation_sequences on ge.automation_sequence_id equals aseq.id
join p in context.project on aseq.project_id equals p.id
join es in context.execution_schedule on ge.schedule_id equals es.id
join exe_u in context.users on ge.executed_by_id equals exe_u.id
join create_u in context.users on aseq.created_by_id equals create_u.id
join modify_u in context.users on aseq.last_modified_by_id equals modify_u.id into modify_uSub
from modify_u in modify_uSub.DefaultIfEmpty()
join astcs in context.automation_sequence_test_case_status on ge.runtime_case_grp_status equals astcs.id into astcsSub
from astcs in astcsSub.DefaultIfEmpty()
join m in context.machines on ge.machine_id equals m.id into mSub
from m in mSub.DefaultIfEmpty()
join aseh in context.automation_sequence_executions on ge.holding_at_id equals aseh.id into asehSub
from aseh in asehSub.DefaultIfEmpty()
join geh in context.group_execution on ge.holding_at_id equals geh.id into gehSub
from geh in gehSub.DefaultIfEmpty()
select new Contract_SeqExecution
{
client_id = p.client_id,
project_status = p.status,
ID = ge.id,
Name = aseq.name,
ModifiedBy = modify_u.first_name + " " + modify_u.last_name,
FailedInd = asstatus.fail_alert_ind,
parentId = ge.parent_group_exec_id,
patriarchId = ge.patriarch_id ?? 0,
//other fields
SeqID = aseq.id,
CaseGroupInd = aseq.case_group_ind,
CaseGroupText = "Group",
ExecRatio = ge.execution_ratio,
RunStatus = asstatus.name,
CaseGroupStatus = astcs.name,
TCStatusColor = astcs.status_color,
SchedRunTime = ge.scheduled_start_time,
ExecutedBy = exe_u.first_name + " " + exe_u.last_name,
CreatedBy = create_u.first_name + " " + create_u.last_name,
Machine = m.name,
Project = p.name,
//InheritIDs = SqlFunctions.StringConvert((double)ase.id),
Uploaded = (ge.uploaded == true ? "Yes" : "No"),
UploadRatio = ge.upload_ratio,
ScheduleID = es.id,
SeqUploaded = (aseq.external_test_mgmt_id != null ? true : false),
HoldInd = ge.hold_ind,
//holding_at_id = ge.holding_at_id,
//holding_at_gih_id = null,
//holding_at_name = aseh.hold_name ?? geh.hold_name,
//contains_holds = ge.contains_holds
is_accepting_changes = (es.accept_revisions_ind == 1 ? 1 : 0)
//end other fields
});
return result;
}
public IQueryable<Contract_SeqExecution> queryTestCases(UserQuery context)
{
var result = (from ase in context.automation_sequence_executions
join asstatus in context.automation_sequence_status on ase.automation_sequence_status_id equals asstatus.id
join aseq in context.automation_sequences on ase.automation_sequence_id equals aseq.id
join p in context.project on aseq.project_id equals p.id
join modify_u in context.users on aseq.last_modified_by_id equals modify_u.id
join astcs in context.automation_sequence_test_case_status on ase.runtime_case_grp_status equals astcs.id into astcsSub
from astcs in astcsSub.DefaultIfEmpty()
join exe_u in context.users on ase.executed_by_id equals exe_u.id into exe_uSub
from exe_u in exe_uSub.DefaultIfEmpty()
join create_u in context.users on aseq.created_by_id equals create_u.id into create_uSub
from create_u in create_uSub.DefaultIfEmpty()
join m in context.machines on ase.machine_id equals m.id into mSub
from m in mSub.DefaultIfEmpty()
join es in context.execution_schedule on ase.schedule_id equals es.id into esSub
from es in esSub.DefaultIfEmpty()
select new Contract_SeqExecution
{
client_id = p.client_id,
project_status = p.status,
ID = ase.id,
Name = aseq.name,
ModifiedBy = modify_u.first_name + " " + modify_u.last_name,
FailedInd = asstatus.fail_alert_ind,
parentId = ase.parent_group_exec_id,
patriarchId = ase.patriarch_id ?? ase.id,
//other fields
SeqID = aseq.id,
CaseGroupInd = aseq.case_group_ind,
CaseGroupText = "Test Case",
ExecRatio = (asstatus.complete_ind == true && asstatus.id != 23 ? "1/1" : "0/1"),
RunStatus = asstatus.name,
CaseGroupStatus = astcs.name,
TCStatusColor = astcs.status_color,
SchedRunTime = ase.execution_start_time,
ExecutedBy = exe_u.first_name + " " + exe_u.last_name,
CreatedBy = create_u.first_name + " " + create_u.last_name,
Machine = m.name,
Project = p.name,
//InheritIDs = SqlFunctions.StringConvert((double)ase.id),
Uploaded = (ase.external_test_mgmt_id != null ? "Yes" : "No"),
UploadRatio = (ase.external_test_mgmt_id != null ? "1/1" : "0/1"),
ScheduleID = ase.schedule_id,
SeqUploaded = (aseq.external_test_mgmt_id != null ? true : false),
HoldInd = asstatus.hold_alert_ind,
//holding_at_id = ge.holding_at_id,
//holding_at_gih_id = null,
//holding_at_name = aseh.hold_name ?? geh.hold_name,
//contains_holds = ge.contains_holds
is_accepting_changes = (es.accept_revisions_ind == 1 ? 1 : 0)
//end other fields
});
return result;
}
}
答案 0 :(得分:0)
如果您将Where
条件descendantFilter
纳入Any
会怎样?
Expression<Func<Contract_SeqExecution, bool>> childFilter = r => descendantUnion.Any(descendantFilter.And(x=>x.patriarchId == r.ID));