SQL Server查询太慢,缺少索引?

问题描述:

我正在使用SQL Server 2012,我有一个查询的搜索目的,但它需要太长的时间来执行..(30行= 6秒)SQL Server查询太慢,缺少索引?

我已经检查了执行计划,但他没有建议把索引,我不知道我可以如何加快查询。

这里是我的查询:

SELECT 
    dbo.tbRV.ID, dbo.tbRV.IDCompagnie, 
    dbo.tbPatient.Nom + N', ' + dbo.tbPatient.Prenom AS NomPrenomPatient, 
    dbo.tbRV.DateRV, dbo.tbRV.HeureDebut, 
    dbo.tbRV.IDRessource, 
    coalesce(dbo.tbRessource.Nom ,'') + ' ' + coalesce(dbo.tbRessource.Prenom,'') AS NomPrenomRessource, 
    dbo.tbPatient.NoApp, 
    dbo.tbPatient.NomEtablissement, dbo.tbPatient.Adresse1, 
    tbAdresse.Ville, dbo.tbPatient.TelephoneDomicile, 
    dbo.tbPatient.TelephoneTravail, 
    dbo.tbPatient.TelephonePortable, 
    case 
     when DD.id is not null then DD.description 
     else dbo.tbRVObjet.IDObjet 
    end as idobjet, 
    dbo.tbPatient.Nom_SansAccent, dbo.tbPatient.Prenom_SansAccent, 
    dbo.tbPatient.Nom, dbo.tbPatient.Prenom, 
    dbo.tbRV.IDPatient, dbo.tbPatient.NoAssuranceMaladie, 
    dbo.tbPatient.DateNaissance, dbo.tbRV.Transit, dbo.tbRV.Annuler, 
    tbAdresse.Pays, tbAdresse.Province, dbo.tbPatient.Adresse2, 
    dbo.tbPatient.CodePostal, 
    case 
     when AA.id is not null and AA.ID = tbrvobjet.ID then 1 else 0 end as onlyFirst 
FROM 
    tbPatient 
INNER JOIN 
    tbRV ON tbPatient.ID = tbRV.IDPatient 
INNER JOIN 
    tbRessource ON (tbRV.IDRessource = tbRessource.ID) AND (tbRV.IDCompagnie = tbRessource.IDCompagnie) 
INNER JOIN 
    tbRVObjet ON tbRV.ID = tbRVObjet.IDRV 
OUTER APPLY 
    dbo.fn_GetFirstIDRVObjet(tbrv.id) AA 
OUTER APPLY (SELECT A.ID, A.Description 
      FROM tbForfaitEntete A 
      WHERE A.ID = tbRVObjet.IDForfait 
       AND ISNULL(tbRVObjet.IsForfaitEntete, 0) = 1) DD 
OUTER APPLY (SELECT B.Description 
      FROM tbRVObjet A 
      JOIN tbForfaitEntete B ON (A.IDForfait = B.ID AND ISNULL(A.IsForfaitEntete, 0) = 1) 
      WHERE AA.ID = A.id) BB 
OUTER APPLY (SELECT tbPaysISO.Pays, tbProvinceISO.Province, tbVilleISO.Ville 
      FROM tbPaysISO 
      JOIN tbProvinceISO ON (tbPaysISO.Langue = tbProvinceISO.Langue) 
           AND (tbPatient.ProvinceISOChar = tbProvinceISO.ProvinceISOChar) 
      JOIN tbVilleISO ON (tbProvinceISO.Langue = tbVilleISO.Langue) 
          AND (tbPatient.IdVille = tbVilleISO.IDVille) 
      WHERE tbPaysISO.Langue = tbpatient.CodeLangue 
       AND tbPaysISO.PaysISOChar3 = tbpatient.PaysISOChar3) tbAdresse 

,这里是在XML的执行计划:

enter image description here

编辑:

这里是我的查询计划网址:https://www.brentozar.com/pastetheplan/?id=HkVYeasNW

这里是我的搜索查询:

Select 
    ID, IDPatient, NomPrenomPatient, DateNaissance, NoAssuranceMaladie, 
    NomEtablissement, Adresse1, Adresse2, NoApp, ville, province, pays, 
    CodePostal, TelephoneDomicile, TelephoneTravail, TelephonePortable, 
    DateRV, HeureDebut, IDObjet, IDRessource, NomPrenomRessource, 
    Annuler, Transit 
From 
    rqAfficheRechercheRV 
Where 
    IDCompagnie = 1 
    And (isnull(NomPrenomRessource, '') + isnull(NoApp, '') + isnull(NomEtablissement, '') + isnull(Adresse1, '') + isnull(Ville, '') + isnull(TelephoneDomicile, '') + isnull(TelephoneTravail, '') + isnull(TelephonePortable, '') + isnull(IDObjet, '') + isnull(Nom_SansAccent, '') + isnull(Prenom_SansAccent, '') + isnull(Nom, '') + isnull(Prenom, '') + isnull(IDPatient, '') + isnull(NoAssuranceMaladie, '') + isnull(convert(varchar, DateNaissance), '') + isnull(Pays, '') + isnull(Province, '') + isnull(Adresse2, '') + isnull(CodePostal, '')) like '%881-1360%' 
    And isnull(onlyFirst,0) = 1 
Order by 
    Nom, Prenom, DateRV DESC, HeureDebut ASC 

rqAfficheRechercheRV是查询以上

+0

真的很难读你在截图的形式规划。你可以使用这个:https://www.brentozar.com/pastetheplan/?我假设你在ID字段上有聚簇索引,但Langue和PaysISOChar3字段上的索引是什么? –

+0

@JacobH我把我的查询计划在我的问题感谢information.PaysISOChar3字段这些都是varchar字段。 – alexandre

+0

平时对搜索查询有where子句,这似乎是在返回表的一切。你在应用程序中过滤吗? – Jesse

阅读这么长的查询计划真的非常费时。你不得不提及涉及的记录数。

我)聚集索引扫描 - 它告诉列是CI,但指标没有被利用

一)由于条件不关心是否可优化搜索栏像

ISNULL(tbRVObjet.IsForfaitEntete, 0) = 1 
instead write `(tbRVObjet.IsForfaitEntete = 1)` 

同样,在其他places.Even不索引然后也改变它到这个。

b)同样,当有很高的心脏估计值时,索引就不会被使用。

II)我在这外毫无疑问应用BB查询.ARe你相信你会再次使用tbRVObjet A这里面外申请,也可以直接加入从上述主要tbRVObjet

III)希望所有的列使用连接条件为int,位,日期等。如果存在varchar列,则表示DB设计中也存在问题。

IV),当这个东西真正属于查看那为什么不串连这里面 视图本身,

And (isnull(NomPrenomRessource, '') + isnull(NoApp, '') + isnull(NomEtablissement, '') + isnull(Adresse1, '') + isnull(Ville, '') + isnull(TelephoneDomicile, '') + isnull(TelephoneTravail, '') + isnull(TelephonePortable, '') + isnull(IDObjet, '') + isnull(Nom_SansAccent, '') + isnull(Prenom_SansAccent, '') + isnull(Nom, '') + isnull(Prenom, '') + isnull(IDPatient, '') + isnull(NoAssuranceMaladie, '') + isnull(convert(varchar, DateNaissance), '') + isnull(Pays, '') + isnull(Province, '') + isnull(Adresse2, '') + isnull(CodePostal, '')) like '%881-1360%' 

我怀疑这里。 v)当你点评订单时会发生什么,你不能没有它吗?

六)如果你可以把dbo.fn_GetFirstIDRVObjet代码也在里面外适用。

七)重新检查连接条件内outer apply tbAdresse .Are你肯定没有多余的加入condition.I有怀疑这些表是这里面外应用之间的相互关系。

八)这是vety清楚,onlyFirst为0或1,从而以书面And isnull(onlyFirst,0) = 1没有意义的,简单的写And(onlyFirst = 1

IX)检查括号这里的DIFF与自己的

((tbRV.IDRessource = tbRessource.ID) AND (tbRV.IDCompagnie = tbRessource.IDCompagnie)) 

和这里

((tbPaysISO.Langue = tbProvinceISO.Langue) 
           AND (tbPatient.ProvinceISOChar = tbProvinceISO.ProvinceISOChar)) 
      JOIN tbVilleISO ON ((tbProvinceISO.Langue = tbVilleISO.Langue) 
          AND (tbPatient.IdVille = tbVilleISO.IDVille)) 
      WHERE tbPaysISO.Langue = tbpatient.CodeLangue 
       AND tbPaysISO.PaysISOChar3 = tbpatient.PaysISOChar3 

X)你缺少DBO前缀大多数places.Also的使用With (Nolock)

我认为你可以注释掉所有外部应用及其column.Run查询检查计划,修复索引微调查询然后开始uncommneting外申请逐一重复这个过程。

视图请确保您有对连接上的字段,外键索引,并在WHERE子句中的字段。您可以通过将字段放在索引的INCLUDE(叶级)的SELECT中来创建一个覆盖索引。查看现有索引以确保不会创建重叠索引。尝试添加以下查询提示以确保您的系统不是CPU瓶颈:OPTION(MAXDOP 1,RECOMPILE),这将强制执行一个序列计划。有时候这也会给你新的索引建议。