2009-08-14 7 views
0
SELECT K.euclidNo,K.KlinikAdi,k.kisaAdi, 
(SELECT COUNT(1) FROM Seanslar AS S 
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id 
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id 
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND 
S.refKlinik_id = K.klinik_id AND 
S.durumuVT = 1 AND 
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND 
S.refFatura_id = F.fatura_id AND 
F.iptalEdenKullanici_id is null 
GROUP BY S.refKlinik_id) AS GecmisAydakiSeansSayisi, 
(
SELECT kdvDahilToplamTutar FROM BasilmisFaturalar AS BF 
INNER JOIN Faturalar AS F ON F.refBasilmisFatura_id = BF.basilmisFatura_id 
INNER JOIN Seanslar AS S ON S.refFatura_id = F.fatura_id 
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND 
S.refKlinik_id = K.klinik_id AND 
S.durumuVT = 1 AND 
S.refFatura_id = F.fatura_id AND 
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND 
BF.basilmisFatura_id = F.refBasilmisFatura_id AND 
F.iptalEdenKullanici_id is null 
GROUP by kdvDahilToplamTutar 
) as FaturaTutari, 
(
    SELECT (COUNT(1)*KUA.fiyat) as t FROM Seanslar AS S 
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id 
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id 
INNER JOIN KurumUrunAnlasmalari AS KUA ON KUA.urunAnlasma_id = S.refUrunAnlasma_id 
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND 
S.refKlinik_id = K.klinik_id AND 
S.durumuVT = 1 AND 
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND 
S.refFatura_id = F.fatura_id AND 
F.iptalEdenKullanici_id is null 
GROUP BY S.refKlinik_id,KUA.fiyat 
) AS SeansTutari 
FROM Klinikler AS K 
WHERE K.refKlinikGrup_id = 1 

このクエリは11秒間応答します。どうすればそれを最適化できますか?それは3または4秒に応答する必要があります。SQLクエリを分析して最適化するにはどうすればいいですか

あなたのお役に立てるThx。

答えて

2

問題がどこにあるのかを知る最良の方法は、クエリアナライザで実行することです。これにより、Show Execution Planオプションが有効になります。
(これは、使用しているSQL Serverのバージョンと、管理ツールを使用しているかどうかによって多少異なります)。

これを実行したら、画像内の各項目のコスト属性を見て、どれが最高かを確認します。それがあなたのボトルネックです。 インデックスを追加するか、SQLを変更して修正できます。

これは、クエリプランの各操作で使用される行の数です。これは、パフォーマンスに大きな影響を与える可能性があるためです。

3

あなたのサブクエリを置き換え:派生テーブルで

(
    SELECT (COUNT(1)*KUA.fiyat) as t FROM Seanslar AS S 
INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id 
INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id 
INNER JOIN KurumUrunAnlasmalari AS KUA ON KUA.urunAnlasma_id = S.refUrunAnlasma_id 
WHERE MONTH(S.tarihi)<MONTH(F.faturaTarihi) AND 
S.refKlinik_id = K.klinik_id AND 
S.durumuVT = 1 AND 
F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND 
S.refFatura_id = F.fatura_id AND 
F.iptalEdenKullanici_id is null 
GROUP BY S.refKlinik_id,KUA.fiyat 
) 

はklinik_idにKLINIKERに参加し、パフォーマンスが大規模に増やす必要があります。

例:

SELECT K.euclidNo,K.KlinikAdi,k.kisaAdi, IsNull(DeriveOne.ValCount, 0) AS GecmisAydakiSeansSayisi, 
.... 
FROM Klinikler AS K 
LEFT JOIN (SELECT S.RefKlinik_id, Count(*) AS ValCount, 
    FROM Seanslar AS S 
    INNER JOIN Faturalar AS F ON F.fatura_id = S.refFatura_id 
    INNER JOIN BasilmisFaturalar AS BF ON BF.basilmisFatura_id = F.refBasilmisFatura_id 
    WHERE MONTH(S.tarihi) < MONTH(F.faturaTarihi) AND 
    S.durumuVT = 1 AND 
    F.faturaTArihi BETWEEN '2009.06.01' AND '2009.06.30' AND 
    S.refFatura_id = F.fatura_id AND 
    F.iptalEdenKullanici_id is null 
    GROUP BY S.refKlinik_id) AS DeriveOne ON DeriveOne.RefKlinik_id = klinik_id 
WHERE K.refKlinikGrup_id = 1 
+0

私はできれば百回upvotesを与えるだろう。相関サブクエリは、回避するべきものとしてカーソルを上に置いています。 – HLGEM

+0

数年前にサブクエリの代わりに派生テーブルを使用するようにspを書き直すことで、10,000行に対して3秒から1/10秒以下にスピードを向上させることができました(悲しいことに、ハードウェア)。それがパフォーマンスの向上にどれくらい効果があるかです。 – MartW

0

クエリプランと実行計画が少し役立ちますが、それは、開発環境から本番環境に異なる場合があります。クエリを分割してパフォーマンスを調整することをお勧めします。あなたが追加することができ、ベストプラクティスのいくつかは、テーブルを前置

  1. です(NOLOCKを)追加
  2. 呼び出す などをヒント私が助けた

希望に役立つかもしれません。

+0

絶対に必要でない限り、NOLOCKを追加するのは悪い考えではありませんか? – Bravax

0

ここでは、SQL Server(2005またはそれ以上)に欠落しているインデックスを見つける本当に簡単な方法があります。あなたのリストの先頭にあるインデックスは、最も大きな利益をもたらします。あなたが大きな違いを生むものを欠いているなら、それはあなたに飛び出るはずです。

SELECT 
    migs.avg_total_user_cost * 
     (migs.avg_user_impact/100.0) * 
     (migs.user_seeks + migs.user_scans) AS improvement_measure, 
    'CREATE INDEX ' + UPPER(LEFT (PARSENAME(mid.statement, 1), 32)) + '_IXn' 
     + ' ON ' + mid.statement 
     + ' (' + ISNULL (mid.equality_columns,'') 
     + CASE WHEN mid.equality_columns IS NOT NULL 
      AND mid.inequality_columns IS NOT NULL THEN ',' ELSE '' END 
     + ISNULL (mid.inequality_columns, '') 
     + ')' 
     + ISNULL (' INCLUDE (' + mid.included_columns + ')', '') 
     AS create_index_statement, 
    migs.*, 
    mid.database_id, 
    mid.[object_id] 
FROM 
    sys.dm_db_missing_index_groups mig 
    INNER JOIN sys.dm_db_missing_index_group_stats migs 
     ON migs.group_handle = mig.index_group_handle 
    INNER JOIN sys.dm_db_missing_index_details mid 
     ON mig.index_handle = mid.index_handle 
WHERE migs.avg_total_user_cost * 
     (migs.avg_user_impact/100.0) * 
     (migs.user_seeks + migs.user_scans) > 10 
ORDER BY 
    migs.avg_total_user_cost * migs.avg_user_impact * 
    (migs.user_seeks + migs.user_scans) DESC 
0

管理スタジオで次のコマンドを実行します。

SET SHOWPLAN_ALL ON 

は、あなたのクエリを実行します。

これは、結果セットにクエリを変換するためにSQL Serverが実行する処理の詳細なリストを提供します。出力を見て、それが何を意味するのかを調べてみてください。私は一般的に "SCAN"を探します。それは遅い部分です。インデックスを使用するように書き直してみます。

関連する問題