sql >> データベース >  >> RDS >> Sqlserver

クエリ、ストアドプロシージャ、およびトリガー用のSQLServerパフォーマンスインジケーターの実装

    序文

    遅かれ早かれ、DB管理者はSQLServerクエリのパフォーマンスインジケータを必要としています。ご存知のとおり、プロファイラーを24時間実行すると、かなりのシステム負荷が発生するため、24時間年中無休で使用されるデータベースに最適なソリューションとは見なされません。

    では、SQL Serverクエリの状態をどのように検出できますか?人間の入力なしで、検出されたクエリ関連の問題のトレースを実行するにはどうすればよいですか?

    この記事では、クエリ、ストアドプロシージャ、トリガーのSQL Serverパフォーマンスインジケーターの実装と、トレース実行での使用法について説明します。

    解決策

    まず、クエリ、ストアドプロシージャ、トリガーのパフォーマンスインジケーターを実装するための一般的なアプローチを見てみましょう。

    1. 情報の収集と分析に必要なテーブルの作成。
    2. 情報収集のためのビューの作成。
    3. 情報収集のためのストアドプロシージャの作成。
    4. 情報出力用のビューの作成。

    それでは、実装について考えてみましょう。

    1.情報の収集と分析に必要なテーブルの作成。

    1.1。クエリの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOSET ANSI_PADDING ONGOCREATE TABLE [srv]。[SQL_StatementExecStat]([ID] [bigint] IDENTITY(1,1)NOT NULL、[InsertDate] [datetime] NULL、[QueryHash] [ binary](8)NULL、[ExecutionCount] [bigint] NULL、[TotalWorkerTime] [bigint] NULL、[StatementText] [nvarchar](max)NULL、[TotalElapsedTime] [bigint] NULL、CONSTRAINT [PK_SQL_StatementExecStat] PRIMARY KEY CLUSTERED( [ID] ASC)WITH(PAD_INDEX =OFF、STATISTICS_NORECOMPUTE =OFF、IGNORE_DUP_KEY =OFF、ALLOW_ROW_LOCKS =ON、ALLOW_PAGE_LOCKS =ON)ON [PRIMARY])ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GOSET ANSI_PADDING ONGO 

    1.2。ストアドプロシージャの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE[srv]。[SQL_ProcedureExecStat]([ID] [bigint] IDENTITY(1,1)NOT NULL、[InsertDate] [datetime] NULL、[database_id] [int] NULL、[object_id] [int] NULL、[ExecutionCount] [bigint] NULL、[TotalWorkerTime] [bigint] NULL、[TotalElapsedTime] [bigint] NULL、[TotalPhysicalReads] [bigint] NULL、[TotalLogicalReads] [bigint] NULL、 [TotalLogicalWrites] [bigint] NULL、CONSTRAINT [PK_SQL_ProcedureExecStat] PRIMARY KEY CLUSTERED([ID] ASC)WITH(PAD_INDEX =OFF、STATISTICS_NORECOMPUTE =OFF、IGNORE_DUP_KEY =OFF、ALLOW_ROW_LOCKS =ON、ALLOW_PAGE_LOCKS =プライマリ]GO

    1.3。トリガーの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [srv]。[SQL_TriggerExecStat]([ID] [bigint] IDENTITY(1,1)NOT NULL、[InsertDate] [datetime] NULL、[database_id] [int] NULL、[object_id] [int] NULL、[ExecutionCount] [bigint] NULL、[TotalWorkerTime] [bigint] NULL、[TotalElapsedTime] [bigint] NULL)ON [PRIMARY] GO 

    2.情報収集用のビューの作成(ここでは、無関係な情報を取り除くためのフィルターを挿入できます(たとえば、クエリやレプリケーショントリガーを使用したプロシージャなど)。
    2.1。クエリの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEview[srv]。[vStatementExecInfo]asinfo as(SELECT query_stats.query_hash AS QueryHash、SUM(query_stats.total_worker_time)/ SUM(query_stats.execution_count query_stats.execution_count)AS ExecutionCount、SUM(query_stats.total_worker_time)AS TotalWorkerTime、MIN(query_stats.statement_text)AS StatementText、MIN(query_stats.min_worker_time)AS MinWorkerTime、MAX(query_stats.max_worker_time)AS MaxWorkerTime、 TotalPhysicalReads、MIN(query_stats.min_physical_reads)AS MinPhysicalReads、MAX(query_stats.max_physical_reads)AS MaxPhysicalReads、SUM(query_stats.total_physical_reads)/ SUM(query_stats.execution_count) AS AvgPhysicalReads、SUM(query_stats.total_logical_writes)AS TotalLogicalWrites、MIN(query_stats.min_logical_writes)AS MinLogicalWrites、MAX(query_stats.max_logical_writes)AS MaxLogicalWrites、SUM(query_stats.total_logical_writes)/ SUM(query total_logical_reads)AS TotalLogicalReads、MIN(query_stats.min_logical_reads)AS MinLogicalReads、MAX(query_stats.max_logical_reads)AS MaxLogicalReads、SUM(query_stats.total_logical_reads)/ SUM(query_stats.execution_count)AS SUM(query_stats.execution_count)AS AvgLogicalReads、 query_stats.min_elapsed_time)AS MinElapsedTime、MAX(query_stats.max_elapsed_time)AS MaxElapsedTime、SUM(query_stats.total_elapsed_time)/ SUM(query_stats.execution_count)AS Av gElapsedTime、MIN(query_stats.creation_time)AS MinCreationTime、MAX(query_stats.last_execution_time)AS LastExecuteTimeFROM(SELECT QS.query_hash、QS.total_worker_time、QS.execution_count、QS.min_worker_time、QS.max_worker_time、 .total_physical_reads、QS.total_logical_writes、QS.min_logical_writes、QS.max_logical_writes、QS.min_logical_reads、QS.max_logical_reads、QS.total_logical_reads、QS.min_elapsed_time、QS.max_elapsed_time、QS.total_ 、QS.creation_time、QS.last_execution_time、SUBSTRING(ST.text、(QS.statement_start_offset / 2)+ 1、((CASE statement_end_offset WHEN -1 THEN DATALENGTH(ST.text)ELSE QS.statement_end_offset END --QS.statement_start_offset)/ 2)+ 1)AS statement_text FROM sys.dm_exec_query_stats AS QS CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle)as ST)as query_statsWHERE execute_count> 1and last_execution_time> =dateadd(hour、-3、getdate())GROUP BY query_stats.query_hash )select QueryHash、AvgCPU_Time、ExecutionCount、TotalWorkerTime、StatementText、MinWorkerTime、MaxWorkerTime、TotalPhysicalReads、MinPhysicalReads、MaxPhysicalReads、AvgPhysicalReads、TotalLogicalWrites、MinLogicalWrites、MaxLogicalWrites、AvgLogicalWrites、TotalLogicalReads AvgLogicalReads、TotalElapsedTime、MinElapsedTime、MaxElapsedTime、AvgElapsedTime、MinCreationTime、LastExecuteTimefrom infoGO 

    ここでは、次のシステムクエリが使用されます:sys.dm_exec_query_statsおよびsys.dm_exec_sql_text。
    2.2。ストアドプロシージャの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEview[srv]。[vProcedureExecInfo]asinfo as(SELECT procedure_stats.database_id AS database_id、procedure_stats.object_id AS object_id、MIN(procedure_stats.type)AS type、 .total_worker_time)/ SUM(procedure_stats.execution_count)AS AvgCPU_Time、SUM(procedure_stats.execution_count)AS ExecutionCount、SUM(procedure_stats.total_worker_time)AS TotalWorkerTime、MIN(procedure_stats.ProcedureText)AS ProcedureText (procedure_stats.max_worker_time)AS MaxWorkerTime、SUM(procedure_stats.total_physical_reads)AS TotalPhysicalReads、MIN(procedure_stats.min_ph ysical_reads)AS MinPhysicalReads、MAX(procedure_stats.max_physical_reads)AS MaxPhysicalReads、SUM(procedure_stats.total_physical_reads)/ SUM(procedure_stats.execution_count)AS AvgPhysicalReads、SUM(procedure_stats)AS AvgPhysicalReads、SUM(procedure_stats procedure_stats.max_logical_writes)AS MaxLogicalWrites、SUM(procedure_stats.total_logical_writes)/ SUM(procedure_stats.execution_count)AS AvgLogicalWrites、SUM(procedure_stats.total_logical_reads)AS TotalLogicalReads、MIN(procedure_stats。 SUM(procedure_stats.total_logical_reads)/ SUM(procedure_stats.execution_count)AS AvgLogicalReads、SUM(procedure_stats.total_elap sed_time)AS TotalElapsedTime、MIN(procedure_stats.min_elapsed_time)AS MinElapsedTime、MAX(procedure_stats.max_elapsed_time)AS MaxElapsedTime、SUM(procedure_stats.Time) procedure_stats.last_execution_time)AS LastExecuteTimeFROM(SELECT QS.database_id、QS.object_id、QS.type、QS.total_worker_time、QS.execution_count、QS.min_worker_time、QS.max_worker_time、QS.min_physical_reads、QS.max_physical_ total_logical_writes、 QS.min_logical_writes、QS.max_logical_writes、QS.min_logical_reads、QS.max_logical_reads、QS.total_logical_reads、QS.min_elapsed_time、QS.max_elapsed_time、QS.exec_elapsed_time、QS.cached_time、QS.last_exec QS CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle)as ST)asprocedure_statsWHEREexecution_count> 1and last_execution_time> =dateadd(hour、-3、getdate())GROUP BY database_id、object_id)select database_id、object_id、type、AvgCPU_Time、ExecutionCount、 TotalWorkerTime、ProcedureText、MinWorkerTime、MaxWorkerTime、TotalPhysicalReads、MinPhysicalReads、MaxPhysicalRead s、AvgPhysicalReads、TotalLogicalWrites、MinLogicalWrites、MaxLogicalWrites、AvgLogicalWrites、TotalLogicalReads、MinLogicalReads、MaxLogicalReads、AvgLogicalReads、TotalElapsedTime、MinElapsedTime、MaxElapsedTime、AvgElapsedTime、MinCachedTime、LastExecuteTimefrom 

    ここでは、次のシステムクエリが使用されます:sys.dm_exec_Procedure_statsおよびsys.dm_exec_sql_text。

    2.3。トリガーの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEview[srv]。[vTriggerExecInfo]asinfo as(SELECT procedure_stats.database_id AS database_id、procedure_stats.object_id AS object_id、MIN(procedure_stats.type)AS type、 .total_worker_time)/ SUM(procedure_stats.execution_count)AS AvgCPU_Time、SUM(procedure_stats.execution_count)AS ExecutionCount、SUM(procedure_stats.total_worker_time)AS TotalWorkerTime、MIN(procedure_stats.ProcedureText)AS ProcedureText (procedure_stats.max_worker_time)AS MaxWorkerTime、SUM(procedure_stats.total_physical_reads)AS TotalPhysicalReads、MIN(procedure_stats.min_phys ical_reads)AS MinPhysicalReads、MAX(procedure_stats.max_physical_reads)AS MaxPhysicalReads、SUM(procedure_stats.total_physical_reads)/ SUM(procedure_stats.execution_count)AS TotalPhysicalReads、SUM(procedure_stats procedure_stats.max_logical_writes)AS MaxLogicalWrites、SUM(procedure_stats.total_logical_writes)/ SUM(procedure_stats.execution_count)AS AvgLogicalWrites、SUM(procedure_stats.total_logical_reads)AS TotalLogicalReads、MIN(procedure_stats。 SUM(procedure_stats.total_logical_reads)/ SUM(procedure_stats.execution_count)AS AvgLogicalReads、SUM(procedure_stats.total_elapse d_time)AS TotalElapsedTime、MIN(procedure_stats.min_elapsed_time)AS MinElapsedTime、MAX(procedure_stats.max_elapsed_time)AS MaxElapsedTime、SUM(procedure_stats.total_elapsed_time)/ SUM(procedure_stats. procedure_stats.last_execution_time)AS LastExecuteTimeFROM(SELECT QS.database_id、QS.object_id、QS.type、QS.total_worker_time、QS.execution_count、QS.min_worker_time、QS.max_worker_time、QS.min_physical_reads、QS.max_physical_ total_logical_writes、QS .min_logical_writes、QS.max_logical_writes、QS.min_logical_reads、QS.max_logical_reads、QS.total_logical_reads、QS.min_elapsed_time、QS.max_elapsed_time、QS.total_elapsed_time、QS.cached_time、QS.last_exec CROSS APPLY sys.dm_exec_sql_text(QS.sql_handle)as ST)asprocedure_statsWHEREexecution_count> 1and last_execution_time> =dateadd(hour、-3、getdate())GROUP BY database_id、object_id)select database_id、object_id、type、AvgCPU_Time、ExecutionCount、TotalWorkerTime 、ProcedureText、MinWorkerTime、MaxWorkerTime、TotalPhysicalReads、MinPhysicalReads、MaxPhysicalReads、 AvgPhysicalReads、TotalLogicalWrites、MinLogicalWrites、MaxLogicalWrites、AvgLogicalWrites、TotalLogicalReads、MinLogicalReads、MaxLogicalReads、AvgLogicalReads、TotalElapsedTime、MinElapsedTime、MaxElapsedTime、AvgElapsedTime、MinCachedTime、LastExecuteTimefrom infoGO 
    ここでは、次のシステムクエリが使用されます:sys.dm_exec_trigger_statsおよびsys.dm_exec_sql_text。

    3.情報収集のためのストアドプロシージャの作成。

    3.1。クエリの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEPROCEDURE[srv]。[InsertForSQL_StatementExecStat]@koefdecimal(12,2)=0.0 –コレクション係数-より正確なコレクションのために実験的な方法で選択されます-ほとんどの場合場合によっては、0.0を設定できます。コレクションの実行頻度が5分を超えない場合。 -計算の精度は、収集頻度と収集係数によって異なります。 -収集の実行頻度が高いほど、収集係数の影響は少なくなります。ASBEGINSET NOCOUNT ON; @AvgCPU_Time bigint、@ MaxAvgCPU_Time bigint、@ AvgTotalWorkerTime bigint、@ MaxTotalWorkerTime bigint、@ AvgAvgElapsedTime bigint、@ MaxAvgElapsedTime bigint、@ AvgTotalElapsedTime bigint、@ MaxTotalElapsedTime bigint Time bigint、@ MaxTotalElapsedTime bigint select @AvgCPU_Time =AvgTotalWorkerTime =AVG(TotalWorkerTime)、@ MaxTotalWorkerTime =max(TotalWorkerTime)、@ AvgAvgElapsedTime =AVG(AvgElapsedTime)、@ MaxAvgElapsedTime =max(AvgElapsedTime)、@ AvgTotalElapsedTime =AVG(TotalElapsedTime)、@ MaxTotalElapsedTime; srv.SQL_StatementExecStat([InsertDate]、[QueryHash]、[ExecutionCount]、[TotalWorkerTime]、[StatementText]、[TotalElapsedTime])に挿入します。selectgetdate()、[QueryHash]、[ExecutionCount]、[TotalWorkerTime]、[StatementText] 、[TotalElapsedTime] from srv.vStatementExecInfo where(AvgCPU_Time> @AvgCPU_Time + @koef *(@MaxAvgCPU_Time-@AvgCPU_Time))または(TotalWorkerTime> @AvgTotalWorkerTime + @koef *(@MaxTotalWorkerTime-@AvgTotalWorkerTime))または(AvgE + @koef *(@MaxAvgElapsedTime-@AvgAvgElapsedTime))または(TotalElapsedTime> @AvgTotalElapsedTime + @koef *(@MaxTotalElapsedTime-@AvgTotalElapsedTime)); ENDGO 

    3.2。ストアドプロシージャの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEPROCEDURE[srv]。[InsertForProcedureExecStat]@koefdecimal(12,2)=0.0--コレクション係数-より正確なコレクションのために実験的な方法で選択されます--inほとんどの場合、コレクションの実行頻度が5分を超えない場合は、0.0を指定できます。 -計算の精度は、収集頻度と収集係数によって異なります。 -収集の実行頻度が高いほど、収集係数の影響は少なくなります。ASBEGINSET NOCOUNT ON; @AvgCPU_Time bigint、@ MaxAvgCPU_Time bigint、@ AvgTotalWorkerTime bigint、@ MaxTotalWorkerTime bigint、@ AvgAvgElapsedTime bigint、@ MaxAvgElapsedTime bigint、@ AvgTotalElapsedTime bigint、@MaxTotalElapsedTimebigintを宣言します。 @AvgCPU_Time =AVG(AvgCPU_Time)、@ MaxAvgCPU_Time =max(AvgCPU_Time)、@ AvgTotalWorkerTime =AVG(TotalWorkerTime)、@ MaxTotalWorkerTime =max(TotalWorkerTime)、@ AvgAvgElapsedTime =AVG(AvgElapsedTime)、@ MaxAvgElapsedTime =AvgTotalElapsedTime =AVG(TotalElapsedTime)、@ MaxTotalElapsedTime =max(TotalElapsedTime)from srv.vProcedureExecInfo; srv.SQL_ProcedureExecStatに挿入([InsertDate]、database_id、object_id、[ExecutionCount]、[TotalWorkerTime]、[TotalElapsedTime]、[TotalPhysicalReads]、[TotalLogicalReads]、[TotalLogicalWrites])select getdate()、database_id 、[TotalWorkerTime]、[TotalElapsedTime]、[TotalPhysicalReads]、[TotalLogicalReads]、[TotalLogicalWrites] from srv.vProcedureExecInfo where(AvgCPU_Time> @AvgCPU_Time + @koef *(@MaxAvgCPU_Time-@AvgCPU_Time))または( koef *(@MaxTotalWorkerTime-@AvgTotalWorkerTime))または(AvgElapsedTime> @AvgAvgElapsedTime + @koef *(@MaxAvgElapsedTime-@AvgAvgElapsedTime))または(TotalElapsedTime> @AvgTotalElapsedTime + @koef *(@MaxTotalEl apsedTime-@AvgTotalElapsedTime)); ENDGO 

    3.3。トリガーの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEPROCEDURE[srv]。[InsertForTriggerExecStat]@koefdecimal(12,2)=0.0--コレクション係数-より正確なコレクションのために実験的な方法で選択されます--inほとんどの場合、コレクションの実行頻度が5分を超えない場合は、0.0を指定できます。 -計算の精度は、収集頻度と収集係数によって異なります。 -収集の実行頻度が高いほど、収集係数の影響は少なくなります。ASBEGINSET NOCOUNT ON; @AvgCPU_Time bigint、@ MaxAvgCPU_Time bigint、@ AvgTotalWorkerTime bigint、@ MaxTotalWorkerTime bigint、@ AvgAvgElapsedTime bigint、@ MaxAvgElapsedTime bigint、@ AvgTotalElapsedTime bigint、@ MaxTotalElapsedTime bigint Time bigint、@ MaxTotalElapsedTime bigint select @AvgCPU_Time =AvgTotalWorkerTime =AVG(TotalWorkerTime)、@ MaxTotalWorkerTime =max(TotalWorkerTime)、@ AvgAvgElapsedTime =AVG(AvgElapsedTime)、@ MaxAvgElapsedTime =max(AvgElapsedTime)、@ AvgTotalElapsedTime =AVG(TotalElapsedTime)、@ MaxTotalElapsedTime; srv.SQL_TriggerExecStat([InsertDate]、database_id、object_id、[ExecutionCount]、[TotalWorkerTime]、[TotalElapsedTime])に挿入します。selectgetdate()、database_id、object_id、[ExecutionCount]、[TotalWorkerTime]、[TotalElapsedTime] where(AvgCPU_Time> @AvgCPU_Time + @koef *(@MaxAvgCPU_Time-@AvgCPU_Time))または(TotalWorkerTime> @AvgTotalWorkerTime + @koef *(@MaxTotalWorkerTime-@AvgTotalWorkerTime))または(AvgElapsedTime> @AvgAvgElapsedTime + @koef *(@ @AvgAvgElapsedTime))または(TotalElapsedTime> @AvgTotalElapsedTime + @koef *(@MaxTotalElapsedTime-@AvgTotalElapsedTime)); ENDGO 

    4.情報出力用のビューの作成。

    4.1。クエリの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEVIEW[srv]。[vStatementExecTotalInfo]asselectExecutionCount as Num、TotalWorkerTime as TotalWorkerTime、TotalElapsedTime as TotalElapsedTime、convert(decimal(8,2)、Avg_ convert(decimal(8,2)、AvgElapsedTime / 100000。)as AvgElapsedSec、...、QueryHash、StatementTextfrom[SRV]。[srv]。[vStatementExecInfo];GO

    4.2。ストアドプロシージャの場合:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEVIEW[srv]。[vProcedureExecTotalInfo]asselect ExecutionCount as Num、TotalWorkerTime as TotalWorkerTime、TotalElapsedTime as TotalElapsedTime、convert(decimal(8,2)、Avg 、convert(decimal(8,2)、AvgElapsedTime / 100000。)as AvgElapsedSec、...、database_id、object_id、db_name(database_id)as DB_Name、OBJECT_SCHEMA_NAME(object_id、database_id)as Schema_Name、object_name(object_id、database_id)as Procedure_Name [SRV]。[srv]。[vProcedureExecInfo];GO
    から

    4.3。トリガーのビューは、同様の方法で作成されます(必要な場合)。私の場合、トリガーに問題がある場合は、ストアドプロシージャとクエリを実行するとトリガーが表示されるため、トリガーをトレースする必要はありません。

    次の2つのパラメータは、実装されたビューにとって非常に重要です。

    1. AvgWorkerSec —クエリの実行時間(秒単位)。
    2. AvgElapsedSec —待機時間、または待機時間+AvgWorkerSec。

    ビューの結果に関しては、次の平等が重要です。

    AvgWorkerSec =AvgElapsedSec

    1. AvgWorkerSec> AvgElapsedSec –ここでは、クエリの実行時にプロセッサに大きな負荷がかかります(ウイルス対策ソフトウェアのスキャンが実行されていたため、プランの並列化の障害である可能性もあります)。
    2. AvgWorkerSec

    AvgWorkerSec =AvgElapsedSecが順守されている場合、長い実行時間はクエリ自体とその実行時間に関連しています。

    長いクエリ実行の基準は何ですか?

    この質問に対する絶対的な答えはありません。クエリの実行内容、クエリの使用場所と使用方法などによって異なります。

    アドホッククエリとストアドプロシージャについて、次の評価があります。

    1. 最大0.5–ストアドプロシージャに適しています。問題はありません(実行待機はありません)。
    2. 最大0.1–クエリに適しています。問題はありません(実行待機はありません)。
    3. 0.5 — 1.0 –ストアドプロシージャには適していません。問題があります(ユーザーに表示される実行待機はありませんが、まだ存在しており、解決策が必要です)。
    4. 0.1 — 0.5 —クエリに悪い、問題があります(ユーザーに表示される実行待機はありませんが、まだ存在しており、解決する必要があります)。
    5. 1.0以上–ストアドプロシージャには適していません。問題があります(ユーザーに表示される待機がある可能性が高いため、問題は早急に解決する必要があります)。
    6. 0.5を超える–クエリに悪い、問題があります(ユーザーに表示される待機がある可能性が高いため、問題は早急に解決する必要があります)。

    非アドホッククエリ(データアップロード、データロード)については、上記の評価は個別に選択されます。通常、アドホッククエリとストアドプロシージャの評価を大幅に上回ります。

    すべてのソフトウェアがストアドプロシージャを介して動作する場合、クエリの動作は常にストアドプロシージャの動作に影響を与えるため、ストアドプロシージャのみをトレースできます。そのため、ストアドプロシージャの実行の分析に落ち着きましょう。

    次のアルゴリズムに従って、後続の分析と自動トレースの実行のために、最も重いストアドプロシージャに関する情報を収集するためのシステムを作成しましょう。

    1.情報を保存するためのテーブルの作成:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE[srv]。[SQL_TopProcedureExecStat]([Row_GUID] [uniqueidentifier] NOT NULL、[SERVER] [nvarchar](255)NOT NULL、[DB_ID] [int] NOT NULL 、[OBJECT_ID] [int] NOT NULL、[ExecutionCount] [bigint] NOT NULL、[TotalWorkerTime] [bigint] NULL、[TotalElapsedTime] [bigint] NULL、[Func] [decimal](8、2)NULL、[AvgWorkerSec ] [decimal](8、2)NULL、[AvgElapsedSec] [decimal](8、2)NULL、[DB_NAME] [nvarchar](255)NULL、[SCHEMA_NAME] [nvarchar](255)NULL、[OBJECT_NAME] [ nvarchar](255)NULL、[InsertUTCDate] [datetime] NOT NULL、[TotalPhysicalReads] [bigint] NULL、[TotalLogicalReads] [bigint] NULL、[TotalLogicalWrites] [bigint] NULL、[AvgPhysicalReads] [bigint] NULL、[AvgLogicalReads ] [bigint] NULL、[AvgLogicalWrites] [bigint] NULL、[CategoryName] [nvarchar](255)NULL、CONSTRAINT [PK_ SQL_TopProcedureExecStat] PRIMARY KEY CLUSTERED([Row_GUID] ASC)WITH(PAD_INDEX =OFF、STATISTICS_NORECOMPUTE =OFF、IGNORE_DUP_KEY =OFF、ALLOW_ROW_LOCKS =ON、ALLOW_PAGE_LOCKS =ON)ON [PRIMARY])ON [PRIMARY] Proc ] ADD CONSTRAINT [DF_SQL_TopProcedureExecStat_Row_GUID] DEFAULT(newid())FOR [Row_GUID] GOALTERTABLE[srv]。[SQL_TopProcedureExecStat]ADDCONSTRAINT [DF_SQL_TopProcedureExecStat_SERVER] DEFAULT(@@ servername)FOR [SERVER] GOAL CONSTRAINT [DF_SQL_TopProcedureExecStat_InsertUTCDate] DEFAULT(getutcdate())FOR [InsertUTCDate] GO 

    2.情報を収集するためのストアドプロシージャの作成:

     USE [DATABASE_NAME] GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATEPROCEDURE[srv]。[InsertTopProcedureExecStat]@toptinyint =24 –レコードを保存する日数@CategoryName nvarchar(255)='AvgWorkerSec' –選択のカテゴリオン; INSERT INTO [srv]。[SQL_TopProcedureExecStat]([DB_ID]、[OBJECT_ID]、[ExecutionCount]、[TotalWorkerTime]、[TotalElapsedTime]、[AvgWorkerSec]、[AvgElapsedSec]、[DB_NAME]、[SCHEMA_NAME]、[_ InsertUTCDate、CategoryName、TotalPhysicalReads、TotalLogicalReads、TotalLogicalWrites、AvgPhysicalReads、AvgLogicalReads、AvgLogicalWrites)select top(@top)[database_id]、[object_id]、[Num]、[TotalWorkerTime]、[TotalWorkerTime]、[Total [DB_NAME]、[SCHEMA_NAME]、[PROCEDURE_NAME]、InsertUTCDate、C ategoryName ,TotalPhysicalReads ,TotalLogicalReads ,TotalLogicalWrites ,AvgPhysicalReads ,AvgLogicalReads ,AvgLogicalWrites from( select [database_id] ,[object_id] ,[Num] ,[TotalWorkerTime] ,[TotalElapsedTime] ,[AvgWorkerSec] ,[AvgElapsedSec] ,[DB_NAME] ,[SCHEMA_NAME] ,[PROCEDURE_NAME] ,getUTCDate() as InsertUTCDate ,@CategoryName as CategoryName ,TotalPhysicalReads ,TotalLogicalReads ,TotalLogicalWrites ,AvgPhysicalReads ,AvgLogicalReads ,AvgL ogicalWrites FROM [srv].[vProcedureExecTotalInfoHour] ) as t order by case @CategoryName when 'TotalWorkerTime' then TotalWorkerTime when 'TotalElapsedTime' then TotalElapsedTime when 'AvgWorkerSec' then AvgWorkerSec when 'AvgElapsedSec' then AvgElapsedSec when 'TotalPhysicalReads' then TotalPhysicalReads when 'TotalLogicalReads' then TotalLogicalReads when 'TotalLogicalWrites' then TotalLogicalWrites when 'AvgPhysicalReads' then AvgPhysicalReads when 'AvgLogicalReads' then AvgLogicalReads when 'AvgLogicalWrites' then AvgLogicalWrites end desc; declare @count int=(select count(*) from [srv].[SQL_TopProcedureExecStat] where [email protected]); declare @diff [email protected]@top;;with tbl_del as( select Row_GUID from [srv].[SQL_TopProcedureExecStat] where InsertUTCDate0) begin;with tbl_del as( select top(@diff) Row_GUID from [srv].[SQL_TopProcedureExecStat] where [email protected] order by case @CategoryName when 'TotalWorkerTime' then TotalWorkerTime when 'TotalElapsedTime' then TotalElapsedTime when 'AvgWorkerSec' then AvgWorkerSec when 'AvgElapsedSec' then AvgElapsedSec when 'TotalPhysicalReads' then TotalP hysicalReads when 'TotalLogicalReads' then TotalLogicalReads when 'TotalLogicalWrites' then TotalLogicalWrites when 'AvgPhysicalReads' then AvgPhysicalReads when 'AvgLogicalReads' then AvgLogicalReads when 'AvgLogicalWrites' then AvgLogicalWrites end ) delete from [srv].[SQL_TopProcedureExecStat] where Row_GUID in (select Row_GUID from tbl_del); end declare @DB_ID int declare @OBJECT_ID int declare @top1 int =3 declare @diff1 int declare @count1 int -- deletion of more than @top1 times repeats of the specific procedure select top (1) @count1 =tp.num ,@DB_ID =tp.DB_ID ,@OBJECT_ID =tp.OBJECT_ID from (select count(*) as num, DB_ID, OBJECT_ID from [srv].[SQL_TopProcedureExecStat] where [email protected] group by DB_ID, OBJECT_ID) as tp order by tp.num desc; set @diff1 =@count1 - @top1; if(@diff1)> 0 begin;with tbl_del as( select top(@diff1) Row_GUID from [srv].[SQL_TopProcedureExecStat] where DB_ID =@DB_ID and OBJECT_ID =@OBJECT_ID and [email protected] order by case @CategoryName when 'TotalWorkerTime' then TotalWorkerTime when 'TotalElapsedTime' then TotalElapsedTime when 'AvgWorkerSec' then AvgWorkerSec when 'AvgElapsedSec' then AvgElapsedSec when 'TotalPhysicalReads' then TotalPhysicalReads when 'TotalLogicalReads' then Tot alLogicalReads when 'TotalLogicalWrites' then TotalLogicalWrites when 'AvgPhysicalReads' then AvgPhysicalReads when 'AvgLogicalReads' then AvgLogicalReads when 'AvgLogicalWrites' then AvgLogicalWrites end ) delete from [srv].[SQL_TopProcedureExecStat] where Row_GUID in (select Row_GUID from tbl_del); end -- deletion of more than 1 repeats of the AvgWorkerSec parameter for the specific procedure if @CategoryName ='AvgWorkerSec' begin declare @AvgWorkerSec decimal(8,2) select top (1) @count1 =tp.num ,@DB_ID =tp.DB_ID ,@OBJECT_ID =tp.OBJECT_ID ,@AvgWorkerSec =tp.AvgWorkerSec from (select count(*) as num, DB_ID, OBJECT_ID, AvgWorkerSec from [srv].[SQL_TopProcedureExecStat] where [email protected] group by DB_ID, OBJECT_ID,AvgWorkerSec) as tp order by tp.num desc; set @diff1 =@count1 - 1; if(@diff1)> 0 begin;with tbl_del as( select top(@diff1) Row_GUID from [srv].[SQL_TopProcedureExecStat] where DB_ID =@DB_ID and OBJECT_ID =@OBJECT_ID and [email protected] and AvgWorkerSec =@AvgWorkerSec order by InsertUTCDate desc ) delete from [srv].[SQL_TopProcedureExecStat] where Row_GUID in (select Row_GUID from tbl_del); end end if @CategoryName ='AvgElapsedSec' begin declare @AvgElapsedSec decimal(8,2) select top (1) @count1 =tp.num ,@DB_ID =tp.DB_ID ,@OBJECT_ID =tp.OBJECT_ID ,@AvgElapsedSec =tp.AvgElapsedSec from (select count(*) as num, DB_ID, OBJECT_ID, AvgElapsedSec from [srv].[SQL_TopProcedureExecStat] where [email protected] group by DB_ID, OBJECT_ID,AvgElapsedSec) as tp order by tp.num desc; set @diff1 =@count1 - 1; if(@diff1)> 0 begin;with tbl_del as( select top(@diff1) Row_GUID from [srv].[SQL_TopProcedureExecStat] where DB_ID =@DB_ID and OBJECT_ID =@OBJECT_ID and [email protected] and AvgElapsedSec =@AvgElapsedSec order by InsertUTCDate desc ) delete from [srv].[SQL_TopProcedureExecStat] where Row_GUID in (select Row_GUID from tbl_del); end endENDGO

    It is better to run this stored procedure immediately after collecting information about the stored procedures (we can set up a task in Agent for running it every 5-10 minutes for queries, stored procedures and triggers):

    exec [srv].[InsertForSQL_StatementExecStat]; --collecting information about executed queriesexec [srv].[InsertForTriggerExecStat]; --collecting information about executed triggersexec [srv].[InsertForProcedureExecStat]; --collecting information about executed stored procedures--collecting information about the most heavy executed stored procedures, according to the criteriaexec [srv].[InsertTopProcedureExecStat] @[email protected], @CategoryName='AvgWorkerSec';exec [srv].[InsertTopProcedureExecStat] @[email protected], @CategoryName='AvgElapsedSec'

    3. Running trace (every 5-10 minutes with the help of the Agent tasks, preferably right after collecting information):

    USE [DATABASE_NAME];go--coefficient of transition value of indicatordeclare @koef_red numeric(8,3)=1.3; --if there are records with the indicator greater than or equal to the --preset indicator coefficient if(exists( SELECT top(1) 1 FROM [srv].[SQL_TopProcedureExecStat] where CategoryName='AvgElapsedSec' or CategoryName='AvgWorkerSec' group by CategoryName having avg([AvgElapsedSec])>[email protected]_red or avg([AvgWorkerSec])>[email protected]_red)) begin --running autorace exec .[srv].[AutoTrace]; end

    The auto-trace stored procedure is implemented on an individual basis.例:

    USE [DATABASE_NAME]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE PROCEDURE [srv].[AutoTrace] @maxfilesize bigint=200 --maximum file size in Mb ,@run_minutes int=60 --tracing length in minutes ,@file_patch nvarchar(255)=N'Path to directory' --directory for trace file ,@file_name nvarchar(255)=N'Profiler' --file name ,@res_msg nvarchar(255)=NULL output --result in the form of messagesASBEGIN SET NOCOUNT ON; declare @rc int; declare @TraceID int; if(@run_minutes>=1200) set @run_minutes=1200; --no longer than 20 hours! declare @finish_dt datetime=DateAdd(minute,@run_minutes,GetDate()); --execution end time --end of trace file declare @finish_dt_inc nvarchar(255)=N'_'+cast(YEAR(@finish_dt) as nvarchar(255))+'_'+cast(MONTH(@finish_dt) as nvarchar(255))+'_'+cast(DAY(@finish_dt) as nvarchar(255)); declare @File nvarchar(255)[email protected]@[email protected]_dt_inc; --full name of the trace file DECLARE @result bit; DECLARE @msgerrors nvarchar(255); DECLARE @oldDT datetime; --Getting the last date and time if(object_id('DATABASE_NAME.dbo.TraceTable')<>0) begin select @oldDT=max(StartTime) from DATABASE_NAME.dbo.TraceTable where StartTime is not null; end --select @oldDT; --If the last date and time is not specified or it is less than time of trace ending,trace is run. Otherwise, the trace was executed on this date. if(@oldDT is null or @oldDT=10) set @run_delay_hour_str=cast(@run_delay_hour as nvarchar(255)); --select @run_delay_hour, @run_delay_hour_str; --adding missing nulls for string representation of minutes if(@run_delay_minute=0) set @run_delay_minute_str='00'; else if(@run_delay_minute<10) set @run_delay_minute_str='0'+cast(@run_delay_minute as nvarchar(255)); else if(@run_delay_minute>=10) set @run_delay_minute_str=cast(@run_delay_minute as nvarchar(255)); --select @run_delay_minute, @run_delay_minute_str; --the hours:minutes string representation for the wait declare @run_delay_str nvarchar(255)[email protected]_delay_hour_str+':'[email protected]_delay_minute_str; --wait WAITFOR DELAY @run_delay_str; --select @run_delay_str; --deletion of the trace table, if it exists if(object_id('DATABASE_NAME.dbo.TraceTable')<>0) begin drop table DATABASE_NAME.dbo.TraceTable; end --creation and filling of the trace table from the trace file SELECT * INTO DATABASE_NAME.dbo.TraceTable FROM ::fn_trace_gettable(@File+'.trc', default); --adding extension to the full file set @[email protected]+'.trc'; --here, we need to insert code to delete the trace file declare @str_title nvarchar(max)='There was auto trace on the server'[email protected]@servername, @str_pred_mess nvarchar(max)='На '[email protected]@servername+'The auto trace has been run on the server. You can view the result in the Database_Name.dbo.TraceTable table; --here, we can send the auto trace run notification to administrator end --returning the result set @res_msg=N'ErrorCode='+cast(@rc as nvarchar(255))+'\r\n'+coalesce(@msgerrors, ''); endENDGO

    For more information on setting trace, refer to How to:Create a Trace (Transact-SQL).

    結論

    In this article, we considered an example of implementation of a system for collecting information about the state of a database, that does not load the system. In case of problem detection, this system runs the preset trace and saves results into a table. This approach can be extended to several servers. In this case, we need to collect information from all servers for subsequent sending of information to administrators.

    It is also important to remember about deletion of old data from the used tables. It is quite sufficient to store data within a month or two weeks.

    Also read:

    Implementing a Common MS SQL Server Performance Indicator

    References

    • sys.dm_exec_trigger_stats
    • sys.dm_exec_procedure_stats
    • sys.dm_exec_query_stats
    • sys.dm_exec_sql_text
    • How to:Create a Trace (Transact-SQL)

    1. OracleSQLで一重引用符を処理する方法

    2. Asinh()がPostgreSQLでどのように機能するか

    3. SQL Serverにリンクサーバーログインを追加する(T-SQLの例)

    4. OracleとKafkaを統合する方法