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

自動データ収集:MSSQLServerのデータベースファイルと論理ドライブ

    はじめに

    データベース管理者は、ディスクに空きがないことを知ることが重要です。したがって、各サーバーで手動で実行しないように、プロセスを自動化することをお勧めします。

    この記事では、論理ドライブとデータベースファイルに関する毎日の自動データ収集を実装する方法について説明します。

    ソリューション

    アルゴリズム:

    1.データストレージのテーブルを作成します:
    1.1。データベースファイルの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [srv].[DBFile](
        [DBFile_GUID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
        [Server] [nvarchar](255) NOT NULL,
        [Name] [nvarchar](255) NOT NULL,
        [Drive] [nvarchar](10) NOT NULL,
        [Physical_Name] [nvarchar](255) NOT NULL,
        [Ext] [nvarchar](255) NOT NULL,
        [Growth] [int] NOT NULL,
        [IsPercentGrowth] [int] NOT NULL,
        [DB_ID] [int] NOT NULL,
        [DB_Name] [nvarchar](255) NOT NULL,
        [SizeMb] [float] NOT NULL,
        [DiffSizeMb] [float] NOT NULL,
        [InsertUTCDate] [datetime] NOT NULL,
        [UpdateUTCdate] [datetime] NOT NULL,
        [File_ID] [int] NOT NULL,
     CONSTRAINT [PK_DBFile] PRIMARY KEY CLUSTERED 
    (
        [DBFile_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]
    
    GO
    
    ALTER TABLE [srv].[DBFile] ADD  CONSTRAINT [DF_DBFile_DBFile_GUID]  
    DEFAULT (newid()) FOR [DBFile_GUID]
    GO
    
    ALTER TABLE [srv].[DBFile] ADD  CONSTRAINT [DF_DBFile_InsertUTCDate]  
    DEFAULT (getutcdate()) FOR [InsertUTCDate]
    GO
    
    ALTER TABLE [srv].[DBFile] ADD  CONSTRAINT [DF_DBFile_UpdateUTCdate]  
    DEFAULT (getutcdate()) FOR [UpdateUTCdate]
    GO

    1.2。論理ドライブの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [srv].[Drivers](
        [Driver_GUID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
        [Server] [nvarchar](255) NOT NULL,
        [Name] [nvarchar](8) NOT NULL,
        [TotalSpace] [float] NOT NULL,
        [FreeSpace] [float] NOT NULL,
        [DiffFreeSpace] [float] NOT NULL,
        [InsertUTCDate] [datetime] NOT NULL,
        [UpdateUTCdate] [datetime] NOT NULL,
     CONSTRAINT [PK_Drivers] PRIMARY KEY CLUSTERED 
    (
        [Driver_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]
    
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_Driver_GUID]  
    DEFAULT (newid()) FOR [Driver_GUID]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_Server]  
    DEFAULT (@@servername) FOR [Server]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_TotalSpace]  
    DEFAULT ((0)) FOR [TotalSpace]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_FreeSpace]  
    DEFAULT ((0)) FOR [FreeSpace]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_DiffFreeSpace]  
    DEFAULT ((0)) FOR [DiffFreeSpace]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_InsertUTCDate]  
    DEFAULT (getutcdate()) FOR [InsertUTCDate]
    GO
    
    ALTER TABLE [srv].[Drivers] ADD  CONSTRAINT [DF_Drivers_UpdateUTCdate]  
    DEFAULT (getutcdate()) FOR [UpdateUTCdate]
    GO

    さらに、次の方法で事前に論理ドライブをテーブルに入力する必要があります。
    サーバー名–ボリュームラベル

    2.データベースファイルに関するデータ収集に必要なビューを作成します。

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE view [inf].[ServerDBFileInfo] as
    SELECT  @@Servername AS Server ,
            File_id ,--file_id in a database. Its main value always equals 1
            Type_desc ,--description of a file type
            Name as [FileName] ,--logic file name in a database
            LEFT(Physical_Name, 1) AS Drive ,--volume label where a database file is located
            Physical_Name ,--a full name of a file in the operating system
            RIGHT(physical_name, 3) AS Ext ,--file extension
            Size as CountPage, --current file size in pages of 8 Kb
            round((cast(Size*8 as float))/1024,3) as SizeMb, --file size in Mb
            Growth, --growth
            is_percent_growth, --growth in %
            database_id,
            DB_Name(database_id) as [DB_Name]
    FROM    sys.master_files--database_files
    GO

    ここでは、sys.master_filesシステムビューが使用されています。

    3.論理ドライブに情報を返すストアドプロシージャを作成します。

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    create procedure [srv].[sp_DriveSpace] 
        @DrivePath varchar(1024) --device (it is possible to set a volume label 'C:')
      , @TotalSpace float output --total volume in bytes
      , @FreeSpace float output  --free disk space in bytes
    as
    begin
    
      DECLARE @fso int
            , @Drive int
            , @DriveName varchar(255)
            , @Folder int
            , @Drives int
            , @source varchar(255)
            , @desc varchar(255)
            , @ret int
            , @Object int
      -- Create an object of a file system
      exec @ret = sp_OACreate 'Scripting.FileSystemObject', @fso output
      set @Object = @fso
      if @ret != 0
        goto ErrorInfo
    
      -- Get a folder on the specified path
      exec @ret = sp_OAmethod @fso, 'GetFolder', @Folder output, @DrivePath  
      set @Object = @fso
      if @ret != 0
        goto ErrorInfo
    
      -- Get a device
      exec @ret = sp_OAmethod @Folder, 'Drive', @Drive output
      set @Object = @Folder
      if @ret != 0
        goto ErrorInfo
    
      -- Determine the whole device storage space
      exec @ret = sp_OAGetProperty @Drive, 'TotalSize', @TotalSpace output
      set @Object = @Drive
      if @ret != 0
        goto ErrorInfo
    
      -- Determine a free space on a disk
      exec @ret = sp_OAGetProperty @Drive, 'AvailableSpace', @FreeSpace output
      set @Object = @Drive
      if @ret != 0
        goto ErrorInfo
    
      DestroyObjects:
        if @Folder is not null
          exec sp_OADestroy @Folder
        if @Drive is not null
          exec sp_OADestroy @Drive
        if @fso is not null
          exec sp_OADestroy @fso
    
        return (@ret)
    
      ErrorInfo:
        exec sp_OAGetErrorInfo @Object, @source output, @desc output
        print 'Source error: ' + isnull( @source, 'n/a' ) + char(13) + 'Description: ' + isnull( @desc, 'n/a' )
        goto DestroyObjects;
    end
    GO

    この手順の詳細については、次の記事を参照してください:T-SQLのディスク領域。

    4.データ収集用のストアドプロシージャを作成します:

    4.1。データベースファイルの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [srv].[MergeDBFileInfo]
    AS
    BEGIN
        SET NOCOUNT ON;
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
        ;merge [srv].[DBFile] as f
        using [inf].[ServerDBFileInfo] as ff
        on f.File_ID=ff.File_ID and f.DB_ID=ff.[database_id] and f.[Server]=ff.[Server]
        when matched then
            update set UpdateUTcDate    = getUTCDate()
                     ,[Name]            = ff.[FileName]         
                     ,[Drive]           = ff.[Drive]            
                     ,[Physical_Name]   = ff.[Physical_Name]    
                     ,[Ext]             = ff.[Ext]              
                     ,[Growth]          = ff.[Growth]           
                     ,[IsPercentGrowth] = ff.[is_percent_growth]    
                     ,[SizeMb]          = ff.[SizeMb]           
                     ,[DiffSizeMb]      = round(ff.[SizeMb]-f.[SizeMb],3)   
        when not matched by target then
            insert (
                    [Server]
                    ,[Name]
                    ,[Drive]
                    ,[Physical_Name]
                    ,[Ext]
                    ,[Growth]
                    ,[IsPercentGrowth]
                    ,[DB_ID]
                    ,[DB_Name]
                    ,[SizeMb]
                    ,[File_ID]
                    ,[DiffSizeMb]
                   )
            values (
                    ff.[Server]
                    ,ff.[FileName]
                    ,ff.[Drive]
                    ,ff.[Physical_Name]
                    ,ff.[Ext]
                    ,ff.[Growth]
                    ,ff.[is_percent_growth]
                    ,ff.[database_id]
                    ,ff.[DB_Name]
                    ,ff.[SizeMb]
                    ,ff.[File_id]
                    ,0
                   )
        when not matched by source and f.[Server][email protected]@SERVERNAME then delete;
    END
    
    GO

    4.2。論理ドライブの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [srv].[MergeDriverInfo]
    AS
    BEGIN
        SET NOCOUNT ON;
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
        declare @Drivers table (
                                [Server] nvarchar(255),
                                Name nvarchar(8),
                                TotalSpace float,
                                FreeSpace float,
                                DiffFreeSpace float NULL
                               );
        insert into @Drivers   (
                                [Server],
                                Name,
                                TotalSpace,
                                FreeSpace
                               )
        select                  [Server],
                                Name,
                                TotalSpace,
                                FreeSpace
        from                srv.Drivers
        where [Server][email protected]@SERVERNAME;
    
        declare @TotalSpace float;
        declare @FreeSpace float;
        declare @DrivePath nvarchar(8);
    
        while(exists(select top(1) 1 from @Drivers where DiffFreeSpace is null))
        begin
            select top(1)
            @DrivePath=Name
            from @Drivers
            where DiffFreeSpace is null;
    
            exec srv.sp_DriveSpace @DrivePath = @DrivePath
                             , @TotalSpace = @TotalSpace out
                             , @FreeSpace = @FreeSpace out;
    
            update @Drivers
            set [email protected]
               ,[email protected]
               ,DiffFreeSpace=case when FreeSpace>0 then round([email protected],3) else 0 end
            where [email protected];
        end
    
        ;merge [srv].[Drivers] as d
        using @Drivers as dd
        on d.Name=dd.Name and d.[Server]=dd.[Server]
        when matched then
            update set UpdateUTcDate = getUTCDate()
                     ,[TotalSpace]   = dd.[TotalSpace]   
                     ,[FreeSpace]    = dd.[FreeSpace]    
                     ,[DiffFreeSpace]= dd.[DiffFreeSpace];
    END
    
    GO

    5.データ出力用のビューを作成します:

    5.1。データベースファイルの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    create view [srv].[vDBFiles] as
    SELECT [DBFile_GUID]
          ,[Server]
          ,[Name]
          ,[Drive]
          ,[Physical_Name]
          ,[Ext]
          ,[Growth]
          ,[IsPercentGrowth]
          ,[DB_ID]
          ,[File_ID]
          ,[DB_Name]
          ,[SizeMb]
          ,[DiffSizeMb]
          ,round([SizeMb]/1024,3) as [SizeGb]
          ,round([DiffSizeMb]/1024,3) as [DiffSizeGb]
          ,round([SizeMb]/1024/1024,3) as [SizeTb]
          ,round([DiffSizeMb]/1024/1024,3) as [DiffSizeTb]
          ,round([DiffSizeMb]/([SizeMb]/100), 3) as [DiffSizePercent]
          ,[InsertUTCDate]
          ,[UpdateUTCdate]
      FROM [srv].[DBFile];
    
    GO

    5.2。論理ディスクの場合:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    create view [srv].[vDrivers] as
    select
          [Driver_GUID]
          ,[Server]
          ,[Name]
          ,[TotalSpace] as [TotalSpaceByte]
          ,[FreeSpace] as [FreeSpaceByte]
          ,[DiffFreeSpace] as [DiffFreeSpaceByte]
          ,round([TotalSpace]/1024, 3) as [TotalSpaceKb]
          ,round([FreeSpace]/1024, 3) as [FreeSpaceKb]
          ,round([DiffFreeSpace]/1024, 3) as [DiffFreeSpaceKb]
          ,round([TotalSpace]/1024/1024, 3) as [TotalSpaceMb]
          ,round([FreeSpace]/1024/1024, 3) as [FreeSpaceMb]
          ,round([DiffFreeSpace]/1024/1024, 3) as [DiffFreeSpaceMb]
          ,round([TotalSpace]/1024/1024/1024, 3) as [TotalSpaceGb]
          ,round([FreeSpace]/1024/1024/1024, 3) as [FreeSpaceGb]
          ,round([DiffFreeSpace]/1024/1024/1024, 3) as [DiffFreeSpaceGb]
          ,round([TotalSpace]/1024/1024/1024/1024, 3) as [TotalSpaceTb]
          ,round([FreeSpace]/1024/1024/1024/1024, 3) as [FreeSpaceTb]
          ,round([DiffFreeSpace]/1024/1024/1024/1024, 3) as [DiffFreeSpaceTb]
          ,round([FreeSpace]/([TotalSpace]/100), 3) as [FreeSpacePercent]
          ,round([DiffFreeSpace]/([TotalSpace]/100), 3) as [DiffFreeSpacePercent]
          ,[InsertUTCDate]
          ,[UpdateUTCdate]
      FROM [srv].[Drivers]
    GO

    6. SQL Serverエージェントでタスクを作成し、1日1回実行します。

    USE [DATABASE_NAME];
    GO
    
    exec srv.MergeDBFileInfo;
    exec srv.MergeDriverInfo;

    7.サーバーから出力されたすべてのデータを収集します。たとえば、SQLServerエージェントを使用してこれを行うことができます。

    8.レポートを生成して管理者に送信するためのストアドプロシージャを作成します。さまざまな方法で実装できるため、この特定の例で検討します。

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [srv].[GetHTMLTableShortInfoDrivers]
        @body nvarchar(max) OUTPUT
    AS
    BEGIN
        SET NOCOUNT ON;
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
        declare @tbl table (
                            Driver_GUID             uniqueidentifier
                            ,[Name]                 nvarchar(255)
                            ,[TotalSpaceGb]         float
                            ,[FreeSpaceGb]          float
                            ,[DiffFreeSpaceMb]      float
                            ,[FreeSpacePercent]     float
                            ,[DiffFreeSpacePercent] float
                            ,UpdateUTCDate          datetime
                            ,[Server]               nvarchar(255)
                            ,ID                     int identity(1,1)
                           );
    
        declare
        @Driver_GUID            uniqueidentifier
        ,@Name                  nvarchar(255)
        ,@TotalSpaceGb          float
        ,@FreeSpaceGb           float
        ,@DiffFreeSpaceMb       float
        ,@FreeSpacePercent      float
        ,@DiffFreeSpacePercent  float
        ,@UpdateUTCDate         datetime
        ,@Server                nvarchar(255)
        ,@ID                    int;
    
        insert into @tbl(
                            Driver_GUID             
                            ,[Name]                 
                            ,[TotalSpaceGb]         
                            ,[FreeSpaceGb]          
                            ,[DiffFreeSpaceMb]      
                            ,[FreeSpacePercent]     
                            ,[DiffFreeSpacePercent] 
                            ,UpdateUTCDate          
                            ,[Server]               
                        )
                select      Driver_GUID             
                            ,[Name]                 
                            ,[TotalSpaceGb]         
                            ,[FreeSpaceGb]          
                            ,[DiffFreeSpaceMb]      
                            ,[FreeSpacePercent]     
                            ,[DiffFreeSpacePercent] 
                            ,UpdateUTCDate          
                            ,[Server]
                from    srv.vDrivers
                where [DiffFreeSpacePercent]<=-5
                or [FreeSpacePercent]<=15
                order by [Server] asc, [Name] asc;
    
        if(exists(select top(1) 1 from @tbl))
        begin
            set @body='When analyzing I have got the data storage devices that either have free disk space less than 15%, or free space decreases over 5% a day:<br><br>'+'<TABLE BORDER=5>';
    
            set @[email protected]+'<TR>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'№ p/p';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'GUID';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'SEVER';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'TOM';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'VOLUME, GB.';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'FREE, GB.';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'FREE SPACE CHANGE, MB.';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'FREE, %';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'FREE SPACE CHANGE, %';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'<TD>';
            set @[email protected]+'UTC DETECTION TIME';
            set @[email protected]+'</TD>';
    
            set @[email protected]+'</TR>';
    
            while((select top 1 1 from @tbl)>0)
            begin
                set @[email protected]+'<TR>';
    
                select top 1
                @Driver_GUID            = Driver_GUID           
                ,@Name                  = Name                  
                ,@TotalSpaceGb          = TotalSpaceGb          
                ,@FreeSpaceGb           = FreeSpaceGb           
                ,@DiffFreeSpaceMb       = DiffFreeSpaceMb       
                ,@FreeSpacePercent      = FreeSpacePercent      
                ,@DiffFreeSpacePercent  = DiffFreeSpacePercent  
                ,@UpdateUTCDate         = UpdateUTCDate         
                ,@Server                = [Server]              
                ,@ID                    = [ID]                  
                from @tbl;
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@ID as nvarchar(max));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@Driver_GUID as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+coalesce(@Server,'');
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+coalesce(@Name,'');
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@TotalSpaceGb as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@FreeSpaceGb as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@DiffFreeSpaceMb as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@FreeSpacePercent as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+cast(@DiffFreeSpacePercent as nvarchar(255));
                set @[email protected]+'</TD>';
    
                set @[email protected]+'<TD>';
                set @[email protected]+rep.GetDateFormat(@UpdateUTCDate, default)+' '+rep.GetTimeFormat(@UpdateUTCDate, default);
                set @[email protected]+'</TD>';
    
                delete from @tbl
                where [email protected];
    
                set @[email protected]+'</TR>';
            end
    
            set @[email protected]+'</TABLE>';
    
            set @[email protected]+'<br><br>';
            To get the detailed information, refer to the view SRV.srv.vDrivers<br><br>
            To view the information on database files, refer to the view DATABASE_NAME.srv.vDBFiles';
        end
    END
    
    GO

    このストアドプロシージャは、空きディスク容量が15%未満であるか、空き容量が1日5%を超えて減少する論理ドライブに関するHTMLレポートを生成します。後者は、レコードの奇妙なアクティビティを示しています。これは、誰かがこのディスクにあまりにも多くの情報を頻繁に保存していることを意味します。次の理由で発生する可能性があります:

    1. ディスクを拡張するときです。
    2. 論理ドライブ上の未使用のファイルを削除する必要があります;
    3. ログファイル、および情報やその他のテーブルのファイルを消去および縮小します。

    ソリューション

    この記事では、ローカルドライブとデータベースファイルに関する毎日の自動データ収集システムを実装する例を分析しました。この情報により、どのディスクの空き領域が少ないか、およびどのデータベースファイルが大幅に増加しているかを事前に知ることができます。これにより、ディスクにスペースがない場合を回避し、プロセスがディスクに多くのスペースを必要とする理由を見つけることができます。

    また読む:

    MSSQLServerでのデータベーススキーマ変更の自動データ収集

    MSSQLServerで完了したタスクに関する自動データ収集


    1. mysqlでINNODBを有効にする方法

    2. SQLSELECTINTOステートメント

    3. MIN/MAXとORDERBYおよびLIMIT

    4. 15便利なMySQL/MariaDBパフォーマンスのチューニングと最適化のヒント