it-swarm.com.de

Identifizieren nicht verwendeter gespeicherter Prozeduren

Im nächsten Jahr helfe ich dabei, mehrere SQL Server-Umgebungen zu bereinigen.

Wir haben ungefähr 10.000 gespeicherte Prozeduren und schätzen, dass nur ungefähr 1000 von ihnen regelmäßig verwendet werden, und weitere 200 oder so werden in seltenen Fällen verwendet, was bedeutet, dass wir viel Arbeit zu tun haben.

Da wir mehrere Abteilungen und Teams haben, die auf diese Datenbanken und Prozeduren zugreifen können, sind wir nicht immer diejenigen, die die Prozeduren aufrufen, was bedeutet, dass wir bestimmen müssen, welche Prozeduren aufgerufen werden. Darüber hinaus möchten wir dies über einige Monate und nicht über einige Tage ermitteln (was einige Möglichkeiten ausschließt).

Ein Ansatz hierfür ist die Verwendung von SQL Server Profiler und verfolgen Sie, welche Prozeduren aufgerufen werden, und vergleichen Sie sie mit der Liste der Prozeduren, die wir haben, während Sie markieren, ob die Prozeduren verwendet werden oder nicht. Von da an könnten wir die Prozeduren in ein anderes Schema verschieben, falls eine Abteilung schreit.

Ist die Verwendung von Profiler hier der effektivste Ansatz? Und/oder hat jemand von euch etwas Ähnliches getan und einen anderen/besseren Weg gefunden, dies zu tun?

25
Question3CPO

Sie können serverseitige Ablaufverfolgung (anders als bei Verwendung der Profiler-GUI, für die mehr Ressourcen erforderlich sind) während Ihres Tests oder Ihres Geschäftszyklus verwenden und nur Dinge erfassen, die mit SPs zusammenhängen. Anschließend können Sie dies zur weiteren Analyse in eine Tabelle oder in Excel laden.

Der zweite Ansatz besteht darin, DMV sys.dm_exec_procedure_stats zu verwenden (mit der Einschränkung, dass beim Neustart des SQL-Servers die Daten gelöscht werden).

Sie können sogar einen Job planen, um DMV-Daten in einer Tabelle zu erfassen, damit sie erhalten bleiben.

 -- 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;

Beziehen auf :

33
Kin Shah

Sie können diese Frage nützlich finden, es gilt für Tabellen und Spalten, schlägt jedoch die Verwendung eines Drittanbieter-Tools ApexSQL Clean vor, das auch nicht verwendete gespeicherte Prozeduren sowie alle Objekte finden kann, auf die von keinem anderen Objekt in verwiesen wird Datenbank oder in externen Datenbanken

Haftungsausschluss: Ich arbeite für ApexSQL als Support Engineer

11
Milica Medic

Wenn Sie mit SQL Server 2008+ arbeiten, können Sie auch erweiterte Ereignisse mit einem Histogrammziel verwenden. Möglicherweise wäre dies leichter als eine Spur.

AFAIK Sie müssten jedoch für jede Datenbank von Interesse eine andere Sitzung erstellen, da ich keinen Hinweis darauf sehen konnte, dass ein Bucketizing für mehrere Spalten möglich ist. Das folgende kurze Beispiel filtert nach 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

Und dann, nachdem einige gespeicherte Prozeduren in dieser Datenbank einige Male ausgeführt und die Daten mit abgerufen wurden

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'

Die Ausgabe ist

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

Zeigen, dass die Prozedur mit object_id von 1287675635 wurde zum Beispiel 36 Mal ausgeführt. Das asynchronous_bucketizer ist nur Speicher, daher ist es am besten, etwas einzurichten, das dies von Zeit zu Zeit abfragt und im dauerhaften Speicher speichert.

10
Martin Smith

Als Folge von Kins Drehbuch. Hier ist ein einfaches Skript zum Erstellen einer Tabelle, um die Verwendung im Laufe der Zeit zu verfolgen, und ein Skript zum regelmäßigen Aktualisieren.

--  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--  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
4
James White

Dieser Beitrag enthält auch ein Skript zum Suchen nicht verwendeter Objekte: Suchen der nicht verwendeten Datenbanktabellen in SQL Server Im Folgenden finden Sie das Skript aus dem Artikel. Ich habe den Tabellentyp "U" in den Typ "P" für gespeicherte Prozeduren geändert:

   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
0
Milica Medic