使用多个连接和条件优化 SQL 查询
Posted
技术标签:
【中文标题】使用多个连接和条件优化 SQL 查询【英文标题】:Optimizing SQL query with multiple joins and conditions 【发布时间】:2018-03-13 17:30:45 【问题描述】:我正在尝试找出一种方法来优化我的查询,因为我有一个庞大的数据库,因此执行脚本需要超过 48 小时。我尝试在所需的表中创建所有可能的索引。我什至尝试将查询分解为子查询,但执行时间的改进仍然没有运气。任何 cmets 或想法表示赞赏。这是我的查询:
SELECT distinct
etb.ID_Etab AS Siret
,ctt.DebutCTT AS DateMouvement
,ctt.L_Contrat_SQN
,ctt.Numero
,ctt.DebutCTT
,ctt_pcs.PcsEse
,ctt.DerDSN
,ctt.H_Etab_SQN
,ctt.H_Salarie_SQN
,ISNULL(ctt_nat.Nature, '') AS Nature,
ctt_dpp.DispPolitiquePublique,
ctt_det_exp.DetacheExpatrie,
ctt_SS.StatutSalarie,
ctt_stat.CodeStatutEmploi,SSS.Num_Inscr AS NIR_RECODE
FROM [dbo].[Lnk_Contrat] AS ctt
INNER JOIN [dbo].[LSat_Contrat_Etab] AS ctt_etb ON ctt.L_Contrat_SQN = ctt_etb.L_Contrat_SQN
INNER JOIN [dbo].[Hub_Etab] AS etb ON ctt_etb.Siret = etb.ID_Etab
INNER JOIN [dbo].[LSat_Contrat_PcsEse] AS ctt_pcs ON ctt.L_Contrat_SQN = ctt_pcs.L_Contrat_SQN and ctt.DebutCTT BETWEEN ctt_pcs.Debut AND ctt_pcs.Fin
INNER JOIN [dbo].[LSat_Contrat_Nature] AS ctt_nat ON ctt.L_Contrat_SQN = ctt_nat.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_nat.Debut AND ctt_nat.Fin AND ISNULL(ctt_nat.Nature, '') <>03
LEFT join Sat_Salarie_SNGI SSS ON SSS.H_Salarie_SQN=ctt.H_Salarie_SQN AND ctt.DebutCTT BETWEEN SSS.Debut AND SSS.Fin
Left JOIN dbo.LSat_Contrat_DispPoliPub AS ctt_dpp ON ctt_dpp.L_Contrat_SQN = ctt.L_Contrat_SQN
INNER JOIN dbo.LSat_Contrat_DetacheExpatrie AS ctt_det_exp ON ctt_det_exp.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_det_exp.Debut AND ctt_det_exp.Fin
INNER JOIN dbo.LSat_Contrat_StatutSalarie AS ctt_SS ON ctt_SS.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_SS.Debut AND ctt_SS.Fin
LEFT JOIN dbo.LSat_Contrat_StatutEmploiSalarie AS ctt_stat ON ctt_stat.L_Contrat_SQN = ctt.L_Contrat_SQN AND ctt.DebutCTT BETWEEN ctt_stat.Debut AND ctt_stat.Fin
WHERE
ctt.Creation_DTS > '1900-01-01'
AND ctt_etb.Debut = '1900-01-01'
AND ctt_etb.[Type] = 'AF'
AND ctt.DebutCTT >= ctt_etb.Debut
AND ctt.DebutCTT >= etb.PreDSN
AND ctt.debutCTT>=DATEADD(MONTH, -1, ctt.PreDSN)
AND ((ctt.DebutCTT BETWEEN ctt_dpp.Debut AND ctt_dpp.Fin) or ctt_dpp.Fin is null)
order by Siret,L_Contrat_SQN
DBCC TRACEOFF (610)
【问题讨论】:
你看过解释计划了吗? 您可能不想使用Between 进行优化。请参阅 clinomaniac 提议的执行计划。 mysql 还是 SQL Server?您的问题都已标记。 也许您应该尝试在堆栈溢出或类似内容上发布问题,解释问题所在并提供相关信息以供其他人建议 - 例如解释计划、表和索引结构、索引基数指标,但是一定要确保你不会做一些愚蠢的事情,比如添加不相关的标签。 删除DISTINCT
,您将真正看到大部分问题。其余部分在WHERE
子句中,可能在数据模型中。
【参考方案1】:
将SQL语句粘贴到Sql Server Management Studio中,点击“Display Estimated Execution Plan”。它显示了 Sql Server 将如何尝试执行您的句子,分析您的 Where(s) 和 Join(s) 的现有索引。
同时尝试升级你的硬件,因此每个 Sql 语句可能需要大量的内存和 cpu 周期,具体取决于记录的数量。
【讨论】:
我看到了执行计划并添加了所有必需的索引,但性能仍然没有提高。以上是关于使用多个连接和条件优化 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章