Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak zautomatyzować zbieranie danych w rozwoju bazy danych SQL Server

Wprowadzenie

Często istnieje potrzeba kontrolowania wzrostu wszystkich tabel i plików we wszystkich bazach danych.

W tym artykule zbadamy przykład, jak zautomatyzować zbieranie danych na temat wzrostu tabel i plików bazy danych SQL Server.

Rozwiązanie

  1. Utwórz widok o rozmiarze wszystkich tabel dla każdej bazy danych
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    
    CREATE view [inf].[vTableSize] as
    with pagesizeKB as (
    	SELECT low / 1024 as PageSizeKB
    	FROM master.dbo.spt_values
    	WHERE number = 1 AND type = 'E'
    )
    ,f_size as (
    	select p.[object_id], 
    		   sum([total_pages]) as TotalPageSize,
    		   sum([used_pages])  as UsedPageSize,
    		   sum([data_pages])  as DataPageSize
    	from sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id
    	left join sys.internal_tables it on p.object_id = it.object_id
    	WHERE OBJECTPROPERTY(p.[object_id], N'IsUserTable') = 1
    	group by p.[object_id]
    )
    ,tbl as (
    	SELECT
    	  t.[schema_id],
    	  t.[object_id],
    	  i1.rowcnt as CountRows,
    	  (COALESCE(SUM(i1.reserved), 0) + COALESCE(SUM(i2.reserved), 0)) * (select top(1) PageSizeKB from pagesizeKB) as ReservedKB,
    	  (COALESCE(SUM(i1.dpages), 0) + COALESCE(SUM(i2.used), 0)) * (select top(1) PageSizeKB from pagesizeKB) as DataKB,
    	  ((COALESCE(SUM(i1.used), 0) + COALESCE(SUM(i2.used), 0))
    	    - (COALESCE(SUM(i1.dpages), 0) + COALESCE(SUM(i2.used), 0))) * (select top(1) PageSizeKB from pagesizeKB) as IndexSizeKB,
    	  ((COALESCE(SUM(i1.reserved), 0) + COALESCE(SUM(i2.reserved), 0))
    	    - (COALESCE(SUM(i1.used), 0) + COALESCE(SUM(i2.used), 0))) * (select top(1) PageSizeKB from pagesizeKB) as UnusedKB
    	FROM sys.tables as t
    	LEFT OUTER JOIN sysindexes as i1 ON i1.id = t.[object_id] AND i1.indid < 2
    	LEFT OUTER JOIN sysindexes as i2 ON i2.id = t.[object_id] AND i2.indid = 255
    	WHERE OBJECTPROPERTY(t.[object_id], N'IsUserTable') = 1
    	OR (OBJECTPROPERTY(t.[object_id], N'IsView') = 1 AND OBJECTPROPERTY(t.[object_id], N'IsIndexed') = 1)
    	GROUP BY t.[schema_id], t.[object_id], i1.rowcnt
    )
    SELECT
      @@Servername AS Server,
      DB_NAME() AS DBName,
      SCHEMA_NAME(t.[schema_id]) as SchemaName,
      OBJECT_NAME(t.[object_id]) as TableName,
      t.CountRows,
      t.ReservedKB,
      t.DataKB,
      t.IndexSizeKB,
      t.UnusedKB,
      f.TotalPageSize*(select top(1) PageSizeKB from pagesizeKB) as TotalPageSizeKB,
      f.UsedPageSize*(select top(1) PageSizeKB from pagesizeKB) as UsedPageSizeKB,
      f.DataPageSize*(select top(1) PageSizeKB from pagesizeKB) as DataPageSizeKB
    FROM f_size as f
    inner join tbl as t on t.[object_id]=f.[object_id]
    
    GO
  2. Utwórz konkretną bazę danych i określ tabelę do przechowywania informacji o wzroście wszystkich tabel bazy danych:
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    SET ANSI_PADDING ON
    GO
    
    CREATE TABLE [srv].[TableStatistics](
    	[Row_GUID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_TableStatistics_Row_GUID]  DEFAULT (newid()),
    	[ServerName] [nvarchar](255) NOT NULL,
    	[DBName] [nvarchar](255) NOT NULL,
    	[SchemaName] [nvarchar](255) NOT NULL,
    	[TableName] [nvarchar](255) NOT NULL,
    	[CountRows] [bigint] NOT NULL,
    	[DataKB] [int] NOT NULL,
    	[IndexSizeKB] [int] NOT NULL,
    	[UnusedKB] [int] NOT NULL,
    	[ReservedKB] [int] NOT NULL,
    	[InsertUTCDate] [datetime] NOT NULL CONSTRAINT [DF_TableStatistics_InsertUTCDate]  DEFAULT (getutcdate()),
    	[Date]  AS (CONVERT([date],[InsertUTCDate])) PERSISTED,
    	[CountRowsBack] [bigint] NULL,
    	[CountRowsNext] [bigint] NULL,
    	[DataKBBack] [int] NULL,
    	[DataKBNext] [int] NULL,
    	[IndexSizeKBBack] [int] NULL,
    	[IndexSizeKBNext] [int] NULL,
    	[UnusedKBBack] [int] NULL,
    	[UnusedKBNext] [int] NULL,
    	[ReservedKBBack] [int] NULL,
    	[ReservedKBNext] [int] NULL,
    	[AvgCountRows]  AS ((([CountRowsBack]+[CountRows])+[CountRowsNext])/(3)) PERSISTED,
    	[AvgDataKB]  AS ((([DataKBBack]+[DataKB])+[DataKBNext])/(3)) PERSISTED,
    	[AvgIndexSizeKB]  AS ((([IndexSizeKBBack]+[IndexSizeKB])+[IndexSizeKBNext])/(3)) PERSISTED,
    	[AvgUnusedKB]  AS ((([UnusedKBBack]+[UnusedKB])+[UnusedKBNext])/(3)) PERSISTED,
    	[AvgReservedKB]  AS ((([ReservedKBBack]+[ReservedKB])+[ReservedKBNext])/(3)) PERSISTED,
    	[DiffCountRows]  AS (([CountRowsNext]+[CountRowsBack])-(2)*[CountRows]) PERSISTED,
    	[DiffDataKB]  AS (([DataKBNext]+[DataKBBack])-(2)*[DataKB]) PERSISTED,
    	[DiffIndexSizeKB]  AS (([IndexSizeKBNext]+[IndexSizeKBBack])-(2)*[IndexSizeKB]) PERSISTED,
    	[DiffUnusedKB]  AS (([UnusedKBNext]+[UnusedKBBack])-(2)*[UnusedKB]) PERSISTED,
    	[DiffReservedKB]  AS (([ReservedKBNext]+[ReservedKBBack])-(2)*[ReservedKB]) PERSISTED,
    	[TotalPageSizeKB] [int] NULL,
    	[TotalPageSizeKBBack] [int] NULL,
    	[TotalPageSizeKBNext] [int] NULL,
    	[UsedPageSizeKB] [int] NULL,
    	[UsedPageSizeKBBack] [int] NULL,
    	[UsedPageSizeKBNext] [int] NULL,
    	[DataPageSizeKB] [int] NULL,
    	[DataPageSizeKBBack] [int] NULL,
    	[DataPageSizeKBNext] [int] NULL,
    	[AvgDataPageSizeKB]  AS ((([DataPageSizeKBBack]+[DataPageSizeKB])+[DataPageSizeKBNext])/(3)) PERSISTED,
    	[AvgUsedPageSizeKB]  AS ((([UsedPageSizeKBBack]+[UsedPageSizeKB])+[UsedPageSizeKBNext])/(3)) PERSISTED,
    	[AvgTotalPageSizeKB]  AS ((([TotalPageSizeKBBack]+[TotalPageSizeKB])+[TotalPageSizeKBNext])/(3)) PERSISTED,
    	[DiffDataPageSizeKB]  AS (([DataPageSizeKBNext]+[DataPageSizeKBBack])-(2)*[DataPageSizeKB]) PERSISTED,--shows as the casting is changed
    	[DiffUsedPageSizeKB]  AS (([UsedPageSizeKBNext]+[UsedPageSizeKBBack])-(2)*[UsedPageSizeKB]) PERSISTED,--shows as the casting is changed
    	[DiffTotalPageSizeKB]  AS (([TotalPageSizeKBNext]+[TotalPageSizeKBBack])-(2)*[TotalPageSizeKB]) PERSISTED,--shows as the casting is changed
     CONSTRAINT [PK_TableStatistics] 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]
    
    GO
    
    SET ANSI_PADDING ON
    GO

    TotalPageSizeKB wskazuje rozmiar tabeli.

    Suma TotalPageSizeKB wszystkich tabel bazy danych + rozmiar tabel systemowych =rozmiar danych bazy danych.

  3. Określ procedurę zbierania informacji:
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE PROCEDURE [srv].[InsertTableStatistics]
    AS
    BEGIN
    	SET NOCOUNT ON;
    	SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
    	declare @dt date=CAST(GetUTCDate() as date);
        declare @dbs nvarchar(255);
    	declare @sql nvarchar(max);
    
    	select [name]
    	into #dbs
    	from sys.databases;
    
    	while(exists(select top(1) 1 from #dbs))
    	begin
    		select top(1)
    		@dbs=[name]
    		from #dbs;
    
    		set @sql=
    		N'INSERT INTO [srv].[TableStatistics]
    	         ([ServerName]
    			   ,[DBName]
    	         ,[SchemaName]
    	         ,[TableName]
    	         ,[CountRows]
    	         ,[DataKB]
    	         ,[IndexSizeKB]
    	         ,[UnusedKB]
    	         ,[ReservedKB]
    			 ,[TotalPageSizeKB]
    			 ,[UsedPageSizeKB]
    			 ,[DataPageSizeKB])
    	   SELECT [Server]
    		  ,[DBName]
    	         ,[SchemaName]
    	         ,[TableName]
    	         ,[CountRows]
    	         ,[DataKB]
    	         ,[IndexSizeKB]
    	         ,[UnusedKB]
    	         ,[ReservedKB]
    			 ,[TotalPageSizeKB]
    			 ,[UsedPageSizeKB]
    			 ,[DataPageSizeKB]
    		FROM ['[email protected]+'].[inf].[vTableSize];';
    
    		exec sp_executesql @sql;
    
    		delete from #dbs
    		where [name][email protected];
    	end
    
    	drop table #dbs;
    
    	declare @dt_back date=CAST(DateAdd(day,-1,@dt) as date);
    
    	;with tbl1 as (
    		select [Date], 
    			   [CountRows],
    			   [DataKB],
    			   [IndexSizeKB],
    			   [UnusedKB],
    			   [ReservedKB],
    			   [ServerName], 
    			   [DBName], 
    			   [SchemaName], 
    			   [TableName],
    			   [TotalPageSizeKB],
    			   [UsedPageSizeKB],
    			   [DataPageSizeKB]
    		from [srv].[TableStatistics]
    		where [Date][email protected]_back
    	)
    	, tbl2 as (
    		select [Date], 
    			   [CountRows], 
    			   [CountRowsBack],
    			   [DataKBBack],
    			   [IndexSizeKBBack],
    			   [UnusedKBBack],
    			   [ReservedKBBack],
    			   [ServerName], 
    			   [DBName], 
    			   [SchemaName], 
    			   [TableName],
    			   [TotalPageSizeKBBack],
    			   [UsedPageSizeKBBack],
    			   [DataPageSizeKBBack]
    		from [srv].[TableStatistics]
    		where [Date][email protected]
    	)
    	update t2
    	set t2.[CountRowsBack]		=t1.[CountRows],
    		t2.[DataKBBack]			=t1.[DataKB],
    		t2.[IndexSizeKBBack]	=t1.[IndexSizeKB],
    		t2.[UnusedKBBack]		=t1.[UnusedKB],
    		t2.[ReservedKBBack]		=t1.[ReservedKB],
    		t2.[TotalPageSizeKBBack]=t1.[TotalPageSizeKB],
    		t2.[UsedPageSizeKBBack]	=t1.[UsedPageSizeKB],
    		t2.[DataPageSizeKBBack]	=t1.[DataPageSizeKB]
    	from tbl1 as t1
    	inner join tbl2 as t2 on t1.[Date]=DateAdd(day,-1,t2.[Date])
    	and t1.[ServerName]=t2.[ServerName]
    	and t1.[DBName]=t2.[DBName]
    	and t1.[SchemaName]=t2.[SchemaName]
    	and t1.[TableName]=t2.[TableName];
    
    	;with tbl1 as (
    		select [Date], 
    			   [CountRows], 
    			   [CountRowsNext],
    			   [DataKBNext],
    			   [IndexSizeKBNext],
    			   [UnusedKBNext],
    			   [ReservedKBNext],
    			   [ServerName], 
    			   [DBName], 
    			   [SchemaName], 
    			   [TableName],
    			   [TotalPageSizeKBNext],
    			   [UsedPageSizeKBNext],
    			   [DataPageSizeKBNext]
    		from [srv].[TableStatistics]
    		where [Date][email protected]_back
    	)
    	, tbl2 as (
    		select [Date], 
    			   [CountRows],
    			   [DataKB],
    			   [IndexSizeKB],
    			   [UnusedKB],
    			   [ReservedKB],
    			   [ServerName], 
    			   [DBName], 
    			   [SchemaName], 
    			   [TableName],
    			   [TotalPageSizeKB],
    			   [UsedPageSizeKB],
    			   [DataPageSizeKB]
    		from [srv].[TableStatistics]
    		where [Date][email protected]
    	)
    	update t1
    	set t1.[CountRowsNext]		=t2.[CountRows],
    		t1.[DataKBNext]			=t2.[DataKB],
    		t1.[IndexSizeKBNext]	=t2.[IndexSizeKB],
    		t1.[UnusedKBNext]		=t2.[UnusedKB],
    		t1.[ReservedKBNext]		=t2.[ReservedKB],
    		t1.[TotalPageSizeKBNext]=t2.[TotalPageSizeKB],
    		t1.[UsedPageSizeKBNext]	=t2.[UsedPageSizeKB],
    		t1.[DataPageSizeKBNext]	=t2.[DataPageSizeKB]
    	from tbl1 as t1
    	inner join tbl2 as t2 on t1.[Date]=DateAdd(day,-1,t2.[Date])
    	and t1.[ServerName]=t2.[ServerName]
    	and t1.[DBName]=t2.[DBName]
    	and t1.[SchemaName]=t2.[SchemaName]
    	and t1.[TableName]=t2.[TableName];
    END
    GO

    To rozwiązanie można zmodyfikować, aby gromadzić dane o rozmiarach tabel wszystkich baz danych ze wszystkich wymaganych instancji MS SQL Server.

  4. Zdefiniuj widok na podstawie zebranych informacji:
    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    create view [srv].[vTableStatisticsShort] as 
    with d as (select DateAdd(day,-1,max([Date])) as [Date] from [srv].[TableStatistics])
    SELECT t.[ServerName]
          ,t.[DBName]
          ,t.[SchemaName]
          ,t.[TableName]
          ,t.[CountRows]
          ,t.[DataKB]
          ,t.[IndexSizeKB]
          ,t.[UnusedKB]
          ,t.[ReservedKB]
          ,t.[InsertUTCDate]
          ,t.[Date]
          ,t.[CountRowsBack]
          ,t.[CountRowsNext]
          ,t.[DataKBBack]
          ,t.[DataKBNext]
          ,t.[IndexSizeKBBack]
          ,t.[IndexSizeKBNext]
          ,t.[UnusedKBBack]
          ,t.[UnusedKBNext]
          ,t.[ReservedKBBack]
          ,t.[ReservedKBNext]
          ,t.[AvgCountRows]
          ,t.[AvgDataKB]
          ,t.[AvgIndexSizeKB]
          ,t.[AvgUnusedKB]
          ,t.[AvgReservedKB]
          ,t.[DiffCountRows]
          ,t.[DiffDataKB]
          ,t.[DiffIndexSizeKB]
          ,t.[DiffUnusedKB]
          ,t.[DiffReservedKB]
          ,t.[TotalPageSizeKB]
          ,t.[TotalPageSizeKBBack]
          ,t.[TotalPageSizeKBNext]
          ,t.[UsedPageSizeKB]
          ,t.[UsedPageSizeKBBack]
          ,t.[UsedPageSizeKBNext]
          ,t.[DataPageSizeKB]
          ,t.[DataPageSizeKBBack]
          ,t.[DataPageSizeKBNext]
          ,t.[AvgDataPageSizeKB]
          ,t.[AvgUsedPageSizeKB]
          ,t.[AvgTotalPageSizeKB]
          ,t.[DiffDataPageSizeKB]
          ,t.[DiffUsedPageSizeKB]
          ,t.[DiffTotalPageSizeKB]
      FROM d
      inner join [SRV].[srv].[TableStatistics] as t on d.[Date]=t.[Date]
      where t.[CountRowsBack] is not null
    	and	t.[CountRowsNext] is not null
    GO

    Tutaj chciałbym zwrócić uwagę na Diff. Jeśli jest wyższy niż 0, oznacza to, że stół rośnie szybciej każdego dnia.

    Zbiórka powinna odbywać się raz na 24 godziny.

    W ten sam sposób możemy zautomatyzować zbieranie przyrostu plików wszystkich baz danych za pomocą następującego widoku:

    USE [DATABASE_NAME]
    GO
    
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    select	t2.[DB_Name] as [DBName]
    			,t1.FileId 
    			,t1.NumberReads
    			,t1.BytesRead
    			,t1.IoStallReadMS
    			,t1.NumberWrites
    			,t1.BytesWritten
    			,t1.IoStallWriteMS 
    			,t1.IoStallMS
    			,t1.BytesOnDisk
    			,t1.[TimeStamp]
    			,t1.FileHandle
    			,t2.[Type_desc]
    			,t2.[FileName]
    			,t2.[Drive]
    			,t2.[Physical_Name]
    			,t2.[Ext]
    			,t2.[CountPage]
    			,t2.[SizeMb]
    			,t2.[SizeGb]
    			,t2.[Growth]
    			,t2.[GrowthMb]
    			,t2.[GrowthGb]
    			,t2.[GrowthPercent]
    			,t2.[is_percent_growth]
    			,t2.[database_id]
    			,t2.[State]
    			,t2.[StateDesc]
    			,t2.[IsMediaReadOnly]
    			,t2.[IsReadOnly]
    			,t2.[IsSpace]
    			,t2.[IsNameReserved]
    			,t2.[CreateLsn]
    			,t2.[DropLsn]
    			,t2.[ReadOnlyLsn]
    			,t2.[ReadWriteLsn]
    			,t2.[DifferentialBaseLsn]
    			,t2.[DifferentialBaseGuid]
    			,t2.[DifferentialBaseTime]
    			,t2.[RedoStartLsn]
    			,t2.[RedoStartForkGuid]
    			,t2.[RedoTargetLsn]
    			,t2.[RedoTargetForkGuid]
    			,t2.[BackupLsn]
    from fn_virtualfilestats(NULL, NULL) as t1
    inner join [inf].[ServerDBFileInfo] as t2 on t1.[DbId]=t2.[database_id] and t1.[FileId]=t2.[File_Id]
    GO

Wynik

W tym artykule zbadaliśmy przykład automatycznego zbierania danych o rozmiarze i wzroście wszystkich tabel i plików SQL Server we wszystkich bazach danych. Zapewnia nam pełną kontrolę nad zmianą rozmiaru zarówno plików bazy danych, jak i jej tabel, a także podejmowanie w odpowiednim czasie działań w celu zmniejszenia tabeli lub pliku, zwiększenia urządzenia do przechowywania danych lub podzielenia informacji na wiele urządzeń do przechowywania danych.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lepsze techniki przycinania wiodących zer w SQL Server?

  2. Jakiś sposób na wstawienie lub aktualizację SQLBulkCopy, jeśli istnieje?

  3. Jak określić nazwę klucza podstawowego w EF-Code-First?

  4. Czy mogę połączyć się z SQL Server za pomocą uwierzytelniania Windows z aplikacji internetowej Java EE?

  5. SQL Server 2016:Utwórz bazę danych