Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server WHERE子句给出了糟糕的查询计划_Sql Server_Performance_Sql Server 2014_Where Clause_Sql Execution Plan - Fatal编程技术网

Sql server WHERE子句给出了糟糕的查询计划

Sql server WHERE子句给出了糟糕的查询计划,sql-server,performance,sql-server-2014,where-clause,sql-execution-plan,Sql Server,Performance,Sql Server 2014,Where Clause,Sql Execution Plan,我不确定如何优化此查询和/或索引以避免出现钝器命令提示 此主查询运行正常,当前在0秒内返回0行: SELECT S1.ID, S.LOAD_DATE, s.Deleted,S1.HUB_FORM_ID FROM #TMP S INNER JOIN HUB_FORM H1 ON H1.Form_ID = S.HUB_FORM_BK INNER JOIN HUB_ORG H2 ON H2.Organisation_ID = S.HUB_ORG_BK INNER JOIN HUB_PER

我不确定如何优化此查询和/或索引以避免出现钝器命令提示

此主查询运行正常,当前在0秒内返回0行:

SELECT  S1.ID, S.LOAD_DATE,  s.Deleted,S1.HUB_FORM_ID
FROM #TMP S

INNER JOIN HUB_FORM H1 ON 
H1.Form_ID = S.HUB_FORM_BK
INNER JOIN  HUB_ORG H2 ON 
H2.Organisation_ID = S.HUB_ORG_BK
INNER JOIN  HUB_PERSON H3 ON 
H3.person_id = S.HUB_PERSON_BK
INNER JOIN  HUB_EVENT H4 ON 
H4.job_id = S.HUB_EVENT_BK
INNER JOIN  HUB_WORKFLOW_STEP H5 ON 
H5.step_id = S.HUB_WORKFLOW_STEP_BK

INNER JOIN LNK_FORM_ENTITY S1 ON
H1.HUB_FORM_ID = S1.HUB_FORM_ID AND H2.HUB_ORG_ID = S1.HUB_ORG_ID AND H3.HUB_PERSON_ID = S1.HUB_PERSON_ID AND H4.HUB_EVENT_ID = S1.HUB_EVENT_ID AND H5.HUB_WORKFLOW_STEP_ID = S1.HUB_WORKFLOW_STEP_ID

INNER JOIN DK_SAT_LNK_FORM_ENTITY S2 ON 
 S1.ID = S2.Parent_ID
在S2.LOAD_DATE_上添加WHERE子句,使其在一两分钟后运行并停止运行

WHERE S2.LOAD_DATE_TO = '31/12/9999'
我不知道为什么会这样:

如果没有筛选器,则不会返回任何行,因此不会产生任何差异。 在没有日期过滤器的良好计划中,包含此字段的表所使用的索引已经包含该字段作为第二个关键字段,因此我认为任何额外的成本都可以忽略不计 注意-它并不总是返回0行,但无论是否返回行,它都需要在合理的时间内运行并完成

CREATE NONCLUSTERED INDEX [JM_TEST_190221_2] ON [dbo].[DK_SAT_LNK_FORM_ENTITY]
(
    [Parent_ID] ASC,
    [LOAD_DATE_TO] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
实时查询计划显示它在LNK_u和DK_u表以及随后的联接表中运行数百万行,而在原始计划中,它显示实际行数=56次执行-预期LNK_u表上有1行,DK_u表上有0行实际执行56次

如果我在WHERE子句之后添加选项FORCE ORDER,它将在0秒内再次运行,并使用与原始良好查询计划不同的查询计划

显然,这在短期内解决了这个问题,但我对使用这样一个直截了当的工具持谨慎态度,因为随着时间的推移,随着数据的变化,它可能并不总是最佳选择

编辑 我尝试过用全扫描更新统计数据,并重建关键索引,但没有效果

查询以下计划-收到任何提示或解释,不胜感激

原始良好计划实际计划:无WHERE条款:

终止点处实时查询计划的计划不佳:


带有强制顺序提示的好计划:

很明显,您的问题是HUB\u表单具有足够的选择性,它在一开始就将行限制为0。但是优化器没有意识到这一点,因此它正在颠倒连接的顺序

为了在不通过强制顺序敲打查询其余部分的情况下强制执行顺序,我们有两个选项:

预先计算TMP、HUB_表单与临时表或表变量的联接。这通常会导致相当多的额外IO。 更好的选择是说服优化器首先计算连接,但不使用显式提示。 这通常最好通过将联接放在具有SELECT TOP的子查询中来实现,但是您可能需要通过添加一个或两个进一步的联接来修改它

选择S1.ID、S.LOAD\u DATE、S.Deleted、S1.HUB\u FORM\u ID 从…起 选择顶部9223372036854775807 S* 来自TMP S 内连接毂\u表H1 H1.Form_ID=S.HUB_Form_BK s 内部连接中心组织H2打开 H2.organization\u ID=S.HUB\u ORG\u BK 内部连接轮毂\u人员H3打开 H3.person\u id=S.HUB\u person\u BK 内部连接集线器事件H4打开 H4.job\u id=S.HUB\u事件\u BK 内部连接中心\u工作流\u步骤H5打开 H5.step\u id=S.HUB\u工作流\u step\u BK 上的内部联接LNK_表单_实体S1 H1.HUB_FORM_ID=S1.HUB_FORM_ID和H2.HUB_ORG_ID=S1.HUB_ORG_ID和H3.HUB_PERSON_ID=S1.HUB_PERSON_ID和H4.HUB_EVENT_ID=S1.HUB_事件_ID和H5.HUB_工作流_步骤_ID=S1.HUB_工作流_步骤_ID 内部连接DK_SAT_LNK_FORM_实体S2 ON S1.ID=S2.Parent\u ID 如果这不起作用,您可以通过将顶部更改为一个变量,并在末尾添加一个OPTIMIZE FOR提示来说服它:

声明@topRows bigint=9223372036854775807; 选择S1.ID、S.LOAD\u DATE、S.Deleted、S1.HUB\u FORM\u ID 从…起 选择TOP@topRows S* 来自TMP S 内连接毂\u表H1 H1.Form_ID=S.HUB_Form_BK s 内部连接中心组织H2打开 ......... 为@topRows=1优化选项; 这会导致优化器认为它只会从联接中获得1行,但如果在运行时是这样的话,它实际上会允许更多的行


请注意,所有这些都不会改变查询的基本语义

要确认,您正在询问如何更好地优化正确返回0行的查询?它并不总是返回零行,但查询需要运行并完成。。。以及在合理的时间内是否返回行。是否尝试更新统计信息?也许有些桌子已经过时了。你重建索引了吗?我无法说出选择查询计划的内部原因,但执行引擎决定,对于带有WHERE子句的查询,更糟糕的计划更适合。似乎这些错误的选择可能发生在多个连接中。强制顺序选项的存在是有原因的,我想…我用完全扫描更新了所有统计数据并重建了关键索引,但不幸的是没有影响。应用强制顺序提示,有时乐观主义者会弄错,告诉它你想要它做什么没有错。这里的提示是有原因的。谢谢你的解释和建议。为了澄清这一点,HUB_表单没有足够的选择性,无法在开始时将行数减少到0—在原始查询中,它返回56行。我尝试了这两种建议,它们的效果和强制顺序一样好,虽然有细微的差别,但IO统计数据几乎相同。我对opt持谨慎态度 imizing为1,因为有时可能返回数千行。仍然肯定比当前情况计划2更可取,但我仍在犹豫,是否更可取强制命令,因为它在不同情况下保持最佳状态。