来年、私はいくつかのSQL Server環境をクリーンアップする取り組みを支援しています。
ストアドプロシージャは約10,000あり、定期的に使用されるのは約1000のみで、まれに200程度が使用されると見積もられているため、多くの作業が必要です。
これらのデータベースと手順にアクセスできる複数の部門とチームがあるため、手順を呼び出すのは常にではありません。つまり、呼び出される手順を決定する必要があります。さらに、数日ではなく数か月でこれを特定したいと考えています(これにより、いくつかの可能性が排除されます)。
これに対する1つのアプローチは、SQL Server Profiler
呼び出されているプロシージャを追跡し、プロシージャが使用されているかどうかをマークしながら、それらを現在のプロシージャのリストと比較します。それから、部門が叫んだ場合に備えて、手順を別のスキーマに移動できます。
ここでProfiler
を使用するのが最も効果的な方法ですか?そして/またはあなたは誰かが同じようなことをしていて、これを行う別の方法/より良い方法を見つけましたか?
テストまたはビジネスサイクル中に サーバーサイドトレース (より多くのリソースを必要とするプロファイラーGUIの使用とは異なります)を使用して、SPに関連するもののみをキャプチャできます。次に、それをテーブルまたはExcelにロードして、さらに分析できます。
2番目のアプローチは、DMVsys.dm_exec_procedure_statsを使用することです(ただし、SQLサーバーが再起動された場合、データはフラッシュされます)。
DMVデータをテーブルにキャプチャして永続化するジョブをスケジュールすることもできます。
-- Get list of possibly unused SPs (SQL 2008 only)
SELECT p.name AS 'SP Name' -- Get list of all SPs in the current database
FROM sys.procedures AS p
WHERE p.is_ms_shipped = 0
EXCEPT
SELECT p.name AS 'SP Name' -- Get list of all SPs from the current database
FROM sys.procedures AS p -- that are in the procedure cache
INNER JOIN sys.dm_exec_procedure_stats AS qs
ON p.object_id = qs.object_id
WHERE p.is_ms_shipped = 0;
参照する :
あなたは見つけることができます この質問 便利です、それはテーブルと列に適用されますが、未使用のストアドプロシージャや、データベース、または外部データベース
免責事項:私はApexSQLでサポートエンジニアとして働いています
SQL Server 2008以降を使用している場合は、拡張イベントを histogram target で使用することもできます。おそらく、これはトレースよりも軽量になるでしょう。
私の知る限り、複数の列でバケット化が可能であるという兆候が見られなかったため、関心のあるデータベースごとに異なるセッションを作成する必要があります。以下の簡単な例は、database_id=10
でフィルタリングします
CREATE EVENT SESSION [count_module_start_database_10]
ON SERVER
ADD EVENT sqlserver.module_start
(
WHERE (source_database_id=10)
)
ADD TARGET package0.asynchronous_bucketizer
( SET filtering_event_name='sqlserver.module_start',
source_type=0,
source='object_id',
slots = 10000
)
WITH (MAX_DISPATCH_LATENCY = 5 SECONDS)
GO
ALTER EVENT SESSION [count_module_start_database_10]
ON SERVER
STATE=START
そして、そのDBでいくつかのストアドプロシージャを数回実行し、次のコマンドでデータを取得した後
SELECT CAST(target_data as XML) target_data
FROM sys.dm_xe_sessions AS s
JOIN sys.dm_xe_session_targets t
ON s.address = t.event_session_address
WHERE s.name = 'count_module_start_database_10'
出力は
<HistogramTarget truncated="0" buckets="16384">
<Slot count="36">
<value>1287675635</value>
</Slot>
<Slot count="3">
<value>1271675578</value>
</Slot>
<Slot count="2">
<value>1255675521</value>
</Slot>
</HistogramTarget>
たとえば、object_id
が1287675635
のプロシージャが36回実行されたことを示します。 asynchronous_bucketizer
はメモリのみであるため、これを頻繁にポーリングして永続ストレージに保存するものをセットアップするのが最善です。
キンのスクリプトの続きとして。時間の経過とともに使用状況を追跡するためのテーブルを作成する簡単なスクリプトと、定期的に更新するスクリプトを次に示します。
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Create the use table
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CREATE TABLE [dbo].[_ProcedureUseLog](
[ObjectName] [nvarchar](255) NOT NULL,
[UseCount] [int] NULL,
[LastUse] [datetime] NULL,
[LastCache] [datetime] NULL,
CONSTRAINT [PK___PROCEDURE_USE] PRIMARY KEY CLUSTERED
(
[ObjectName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[_ProcedureUseLog] ADD CONSTRAINT [DF_Table_1_References] DEFAULT ((0)) FOR [UseCount]
GO
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Run this periodically to update the usage stats
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DECLARE @UsesTable TABLE
(
ObjectName nvarchar(255),
Executions int,
LastUse datetime,
LastCache datetime
)
INSERT INTO @UsesTable
SELECT p.name, qs.execution_count, qs.last_execution_time, qs.cached_time
FROM sys.procedures AS p LEFT OUTER JOIN
sys.dm_exec_procedure_stats AS qs ON p.object_id = qs.object_id
WHERE (p.is_ms_shipped = 0)
MERGE [dbo].[_ProcedureUseLog] AS [Target]
USING @UsesTable AS [Source]
ON Target.ObjectName = Source.ObjectName
WHEN MATCHED AND
( Target.LastCache <> Source.LastCache)
THEN UPDATE SET
Target.UseCount = Target.UseCount + Source.Executions,
Target.LastCache = Source.LastCache,
Target.LastUse = Source.LastUse
WHEN NOT MATCHED
THEN INSERT (ObjectName, UseCount, LastUse, LastCache)
VALUES (ObjectName, Executions, LastUse, LastCache);
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- This just shows what you've logged so far
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SELECT * FROM [_ProcedureUseLog] ORDER BY UseCount DESC
この投稿では、未使用のオブジェクトを検索するスクリプトも提供しています: SQL Serverで未使用のデータベーステーブルを検索します 以下は、記事のスクリプトです。テーブルのタイプを変更しました " U "からストアドプロシージャタイプ" P "へ:
USE DBName;
SELECT
ao.[name] [Table],
s.[name] [Schema],
[create_date] [Created],
[modify_date] [LastModified]
FROM
sys.all_objects ao JOIN sys.schemas s
ON ao.schema_id = s.schema_id
WHERE
OBJECT_ID NOT IN (
SELECT OBJECT_ID
FROM sys.dm_db_index_usage_stats
)
AND [type] = 'P'
ORDER BY
[modify_date] DESC