使用多个连接和条件优化 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 查询的主要内容,如果未能解决你的问题,请参考以下文章

将多条查询结果作为like查询条件

具有多个可能连接(或连接中的条件)的 SQL 查询

Oracle优化器的基础知识

Mysql查询详解(条件查询、子查询、模糊查询、连接查询。。。)

sql 各种连接的使用条件,

SQL多表链接查询、嵌入SELECT语句的子查询技术