web-dev-qa-db-ja.com

高いPAGEIOLATCH_SHはサーバーで待機します

編集:

この質問は締め切られましたが、誰かのお役に立てば幸いです。

問題はディスク(クラスター)にあります。

PerfMonを使用して、いくつかのカウンター(ディスクの読み取りと書き込み)を作成でき、読み取りカウンターは100%に固定されています。

High readssp_WhoIsActive



PAGEIOLATCH_SH:Database_Name:1(*)

ここにいくつかの投稿があり、この警告はI/Oが高いためであると述べています。 SQL Server Books Onlineでは、SQL待機タイプPAGEIOLATCH_SHを次のように定義しています。

I/O要求にあるバッファのラッチでタスクが待機しているときに発生します。ラッチ要求は共有モードです。

この:

ユーザープロセスは、現在バッファキャッシュにないデータを要求します。その時点で– SQL Serverはバッファーページを割り当てようとします–データがディスクからバッファーキャッシュに移動される間、バッファー上に専用のPAGEIOLATCH_EXが作成されます。同時に、ユーザープロセスの観点から、バッファー上にPAGEIOLATCH_SHが作成されます。

インデックスと統計を作成し、SQL Serverプロファイラを使用して支援しました。

クエリを改善する方法はありますか?たくさんのANDsの処理を改善するにはどうすればよいですか?

この問題は1週間ほど発生しており、どうすればよいかわからない。

SELECT TOP 30 codCliente 
FROM (
    SELECT t1.CodCliente
        , codcampo
        , valor
        , t1.chavealeat 
    FROM tblCliente AS t1 WITH(NOLOCK) 
        INNER JOIN tblClienteDetalhe AS t2 WITH (NOLOCK) 
            ON t1.codcliente = t2.codcliente 
            AND CodCampo IN (-1, 4)
    WHERE codStatus IN(0)  
        AND t1.ChavePeriodo < getdate()
        AND t1.CodStatusLigacao = 0
        AND EXISTS (
            SELECT codcliente 
            FROM tblclientedetalhe WITH (NOLOCK) 
            WHERE codcampo = 3
                AND valor = '2' 
                AND codcliente = t1.codcliente
            )
        AND EXISTS (
            SELECT codcliente 
            FROM tblclientedetalhe WITH (NOLOCK) 
            WHERE codcampo = 6
                AND Convert(DateTime,Valor) BETWEEN '2015-03-01' AND '2015-03-31'
                AND DateDiff(day,Valor,GetDate()) > 15
                AND codcliente = t1.codcliente
            )
        AND NOT EXISTS (
            SELECT 0 
            FROM tblPesquisa WITH (NOLOCK)
            WHERE tblPesquisa.CodCliente = t1.CodCliente
            )
        AND EXISTS (
            SELECT codcliente 
            FROM tblclientedetalhe WITH (NOLOCK) 
            WHERE codcampo = 4
                AND valor = '161' 
                AND codcliente = t1.codcliente
            )
    ) AS Cliente 
PIVOT (
    MAX(Valor) 
    FOR codCampo in ([4])
    ) AS PivotTable
WHERE ([4] = '161')
ORDER BY chavealeat;

編集1:

私がコメントで以下に述べたように、この待機ステータスを持つ他のクエリがあります。私はそれが問題ではないことを確認するために仕事が完了するのを待っています。

Warninigs

1
Racer SQL

これは直接あなたの質問に答えないかもしれませんが、あなたはクエリに複数の潜在的な問題を抱えており、それらはすぐに私に見えます。

_AND Convert(DateTime,Valor) BETWEEN '2015-03-01' AND '2015-03-31'
AND DateDiff(day,Valor,GetDate()) > 15
_
  1. なぜCONVERT(DateTime, Valor)をしているのですか? ValorはテーブルのDateTimeタイプではありませんか?そうでなければ、あなたはそれを間違っています。

  2. 列(DateDiff(day, Valor, GetDate()))で関数を実行し、それを値と比較すると、SARG非対応になります。代わりにこれを試してください:

    AND Valor > DATEADD(DAY, -15, GETDATE())

  3. BETWEEN (x and y)は、思ったように機能しない場合があります。次の構成は、希望する正確な日付範囲を明示的に定義するため、使用する方がよいでしょう。

    _WHERE Valor >= '2015-03-01T00:00:00' AND Valor < '2015-04-01T00:00:00'_

  4. WITH (NOLOCK)は高速なボタンではありません! http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/ および http://sqlperformance.com/2015/04/t-sql-queriesを参照してください/ the-read-uncommitted-isolation-level ほとんどの場合それがスターターではない理由に関する優れた詳細については。

9
Max Vernon