2017-07-06 14 views
0

私は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

EDIT:https://www.brentozar.com/pastetheplan/?id=HkVYeasNW

は、ここに私のクエリプランのURLです210

ここに私の検索クエリです:

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情報のおかげで私の質問プランに入れました.PaysISOChar3のフィールドはvarcharフィールドです。 – alexandre

+0

通常、検索クエリにwhere句があります。これはテーブル内のすべてを返すようです。アプリケーションでフィルタリングしますか? – Jesse

答えて

1

長いクエリプランを読むのは本当に非常に時間がかかります。

あなたはレコードの数を含める必要があります。

i)がクラスタ化インデックスのスキャン - それは、その列を伝える条件が懸念欄場合、他のplaces.Evenに同様

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

のように検索引数可能ではありませんのでCIが、インデックスでは

A)を利用されていません索引ではないので、これをこれに変更してください。

b)カーディナリティ推定値が高い場合、インデックスは使用されていません。

II)私はあなたが再び適用され、この外側の内側tbRVObjet Aを使用するか、直接メインtbRVObjet

III以上から参加でき.AReあなたは必ずこの外側の適用BBクエリ)ホープのすべての列の使用に少し疑問を持っています結合条件はint、bit、dateなどです。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)注文をコメントアウトするとどうなりますか?

vi)外側にもdbo.fn_GetFirstIDRVObjetのコードを貼ることができます。

vii)outer apply tbAdresseの内部で再結合条件を再確認してください。余分な結合条件はありませんか。この外部適用の内側にあるこれらの表の関係については疑問があります。

VIII)それはonlyFirstは、単にAnd(onlyFirst = 1

IXを書くので、And isnull(onlyFirst,0) = 1を書くにはポイント0または1のどちらかではないということvety明らかである)あなた自身の

((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)あなたはWith (Nolock)を使用places.AlsoのほとんどでDBO接頭辞が欠けています

私は外部のすべての適用とその列をコメントアウトすることができると思います。プランをチェックし、インデックスを細かく修正してクエリを調整してから、外部のアプリケーションを順番に適用してプロセスを繰り返すようにしてください。

0

上記のクエリのビューでは、フィールド、外部キーON JOINの上、およびWHERE句内のフィールドにインデックスを持っていることを確認しています。索引のINCLUDE(葉レベル)にSELECTにフィールドを入れることで、カバリング索引を作成できます。既存の索引を調べて、重複する索引を作成していないことを確認します。システムがCPUボトルネックでないことを確認するために、次のクエリヒントを追加してみてください:OPTION(MAXDOP 1、RECOMPILE)。これはシリアルプランを強制します。場合によっては、新しいインデックスの推奨事項も表​​示されます。

関連する問題