次のスクリプトがあります。
-- available space in each of the database files
PRINT @@SERVERNAME
--SQLDWDEV01
USE [BodenStage]
GO
SELECT name
,(CAST(ROUND((size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0),2) AS NUMERIC(18,2))) AS AvailableSpaceInMB
,(CAST(ROUND((size/128.0 - FILEPROPERTY(name, 'SpaceUsed')/128.0)/1024.00,2) AS NUMERIC(18,2))) AS AvailableSpaceInGB
FROM sys.database_files;
GO
データやログファイルを縮小したくないので、必要な場合もあります。私のせいじゃない。
説明されているように、断片化を発生させずにデータファイルを圧縮する方法があります here :
切り捨て
ファイルの末尾にあるすべての空き領域をオペレーティングシステムに解放しますが、ファイル内のページ移動は実行しません。データファイルは、最後に割り当てられたエクステントにのみ縮小されます。
DBCC SHRINKFILE の結果をテーブルに保存するにはどうすればよいですか?
以下を参照してください DBCC SQLPERF の結果をテーブルに保存する1つの方法です。
select @@servername as [Server]
,db_name() as [database]
go
SET NOCOUNT ON
begin try
drop table #radhe
end try
begin catch
end catch
create table #radhe (
DatabaseName varchar(100)
, LOGSIZE_MB NUMERIC(18, 9)
, LOGSPACE_USED NUMERIC(18, 9)
, LOGSTATUS NUMERIC(18, 9))
INSERT #Radhe(DatabaseName, LOGSIZE_MB, LOGSPACE_USED, LOGSTATUS)
EXEC('DBCC SQLPERF(LOGSPACE);')
select DatabaseName,
LOGSIZE_GB=CONVERT(NUMERIC(18,2) ,ISNULL( ROUND(LOGSIZE_MB/1024.00,2),0)),
PERC_USED =CONVERT(NUMERIC(4,2) ,ISNULL( ROUND(LOGSPACE_USED,2),0))
from #radhe
order by logsize_mb desc
これで、DBCC SHRINKFILEコマンドが生成されました。
DECLARE @db VARCHAR(108)
DECLARE @dbid INT
DECLARE @amount INT
SELECT @db = 'MY_DATABASSEStage'
SELECT @dbid = DB_ID(@DB)
SELECT @amount = 0
SELECT SHRINKFILE_SCRIPT = 'USE ' + QUOTENAME( DB_NAME(smf.database_id)) + CHAR(10)
+ 'GO' + CHAR(10)
+ 'DBCC SHRINKFILE(''' + smf.name + '''' + ',' + CAST(@amount AS VARCHAR) + ', TRUNCATEONLY) WITH NO_INFOMSGS' + CHAR(10)
+ 'GO' + CHAR(10)
, *
FROM sys.master_files smf
WHERE smf.database_id = @dbid
上記のスクリプトにより、次の結果が生成されました。
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageStockLedger',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageStockLedgerArchive',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageProduct',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
これはスクリプトの1つの結果です-with no_infomsgs
を削除した後
同様の質問がありますが、私のケースに当てはまる答えはありません:
SQL Serverのユーザートランザクション間でログを縮小
結論
私の答えは問題なく機能しますが、srutzkyによって使用される方法ははるかに単純であり、機能します。リンクサーバーが必要です。
テストサーバーでは、次のスクリプトを使用してリンクサーバーを作成しています。
USE [master]
GO
IF NOT EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'TESTDBCC')
BEGIN
EXEC master.dbo.sp_addlinkedserver
@server = N'TESTDBCC',
@srvproduct=N'',
@provider=N'SQLNCLI11',
@datasrc=N'JPB01275\SQL2014',
@catalog=N'radhe'
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname=N'TESTDBCC',
@useself=N'True',
@locallogin=NULL,
@rmtuser=NULL,
@rmtpassword=NULL
END
GO
EXEC master.dbo.sp_serveroption
@server=N'TESTDBCC',
@optname=N'collation compatible',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'data access',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'dist',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'pub',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'rpc',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'rpc out',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'sub',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'connect timeout',
@optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'collation name',
@optvalue=null
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'lazy schema validation',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'query timeout',
@optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'use remote collation',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'remote proc transaction promotion',
@optvalue=N'false'
GO
上記のリンクサーバーを使用すると、次のようにデータを収集できます。
--Use the Linked Server via EXEC() AT
CREATE TABLE #ShrinkFileResults
(
[DBID] SMALLINT,
[FileID] INT,
[CurrentSize] INT,
[MinimumSize] INT,
[UsedPages] INT,
[EstimatedPages] INT
);
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [tempdb];
DBCC SHRINKFILE(N''tempdev'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [radhe];
DBCC SHRINKFILE(N''radhe_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [US16HSMMProduct_AFTER_CHANGES];
DBCC SHRINKFILE(N''US16HSMMProduct_AFTER_CHANGES_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [US16HSMMProduct_AFTER_CHANGES];
DBCC SHRINKFILE(N''US16HSMMProduct_AFTER_CHANGES_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
SELECT * FROM #ShrinkFileResults;
これは、_'remote proc transaction promotion'
_プロパティがfalse
に設定された「ループバック」リンクサーバーを使用することにより、いくらか簡単に実現できます。これにより、圧縮ファイル操作を実行できません_INSERT...EXEC
_オペレーションによって開始された暗黙のトランザクションをサイドステップすることによるユーザートランザクションエラーの内部。それ以外の場合、リンクサーバーでは、_'rpc out'
_プロパティをtrue
に設定するだけで済みます。 _'data access'
_および_'rpc'
_プロパティを有効にする必要はありません(少なくとも私にとっては)。
リンクサーバーを作成します
_USE [master];
DECLARE @LinkedServerName sysname;
SET @LinkedServerName = N'TestDBCC';
IF (NOT EXISTS (SELECT srv.name
FROM sys.servers srv
WHERE srv.server_id <> 0
AND srv.name = @LinkedServerName))
BEGIN
EXEC [master].dbo.sp_addlinkedserver
@server = @LinkedServerName, @srvproduct=N'', @provider=N'SQLNCLI11', @datasrc=N'DALI';
EXEC [master].dbo.sp_addlinkedsrvlogin
@rmtsrvname=@LinkedServerName,@useself=N'True',@locallogin=NULL,
@rmtuser=NULL,@rmtpassword=NULL;
END;
--EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
-- @optname=N'data access', @optvalue=N'true';
--EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
-- @optname=N'rpc', @optvalue=N'true'; -- is_remote_login_enabled
EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
@optname=N'rpc out', @optvalue=N'true';
EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
@optname=N'remote proc transaction promotion', @optvalue=N'false';
GO
_
EXEC() AT
を介してリンクサーバーを使用する
_CREATE TABLE #ShrinkFileResults
(
[DBID] SMALLINT,
[FileID] INT,
[CurrentSize] INT,
[MinimumSize] INT,
[UsedPages] INT,
[EstimatedPages] INT
);
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [tempdb];
DBCC SHRINKFILE(N''tempdev'', 0, TRUNCATEONLY);
') AT [TestDBCC];
SELECT * FROM #ShrinkFileResults;
_
これは、SQL Server 2012 SP3とSQL Server 2016 RTMの両方で機能しました。
[〜#〜]メモ[〜#〜]
OPENQUERY
を使用しても機能しません。最初に「メタデータ検出」エラーが発生します。これは、DBCC
呼び出しを、_WITH RESULT SETS
_オプションを使用する別のEXEC
でラップすることで解決できます。しかし、「OPENQUERYはオブジェクトが存在しないか、オブジェクトへのアクセス権がないため、オブジェクトを処理できません」というエラーを受け取ります。ただし、ファイルの論理名を圧縮に変更すると、DBCC
からその名前のファイルが見つからないというエラーと、OPENQUERY
からの2次エラーが発生します。呼び出しは結果セットを返しませんでした。これらはすべて、正しいファイル名でさらに遠くにあることを示しています。
この操作は、SQLCLRを介して簡単に実行することもできます。実際には、外部接続(コンテキスト接続ではない)を使用してUDF /スカラー関数を作成できます。これにより、SELECT
リストのセットベースの操作で呼び出すことができます。また、数行のコードしか必要とせず、_xp_cmdshell
_を有効にするか、リンクサーバーを作成する場合と比較して、セキュリティリスクを最小限に抑えることができます。
以下のプロセスは、dbcc shrinkfile
の結果をテーブルに保存する方法です
xp_cmdshell
の使用を有効にするしたがって、次のスクリプトが必要です。
-- To allow advanced options to be changed.
EXEC sp_configure 'show advanced options', 1
GO
-- To update the currently configured value for advanced options.
RECONFIGURE
GO
-- To enable the feature.
EXEC sp_configure 'xp_cmdshell', 1
GO
-- To update the currently configured value for this feature.
RECONFIGURE
GO
USE master
GO
-- Create the SQL login which will use xp_cmdshell.
CREATE LOGIN [SQL_User_Impresonated] WITH PASSWORD='Sql_P@ssword'
-- Create a proxy credential for xp_cmdshell assigned to a Domain/Windows account.
EXEC sp_xp_cmdshell_proxy_account 'DOMAIN\LOGINNAME', 'LOGINNAME_PASSWORD';
-- Grant database access to the SQL Server login account that you want to provide access.
EXEC sp_grantdbaccess 'SQL_User_Impresonated'
-- Grant execute permission on xp_cmdshell to the SQL Server login account.
GRANT exec ON sys.xp_cmdshell TO [SQL_User_Impresonated]
GO
--Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
--Configuration option 'xp_cmdshell' changed from 0 to 1. Run the RECONFIGURE statement to install.
----------------------------------------------------------------
-- GRANT THE REQUIRED PERMISSIONS TO LOGIN SQL_User_Impresonated
----------------------------------------------------------------
--=======================================================================================================
-- before schrinking the log, lets see how much space we are currently using
--=======================================================================================================
declare @Radhe table(
DatabaseName varchar(100)
, LOGSIZE_MB decimal(18, 9)
, LOGSPACE_USED decimal(18, 9)
, LOGSTATUS decimal(18, 9))
insert @Radhe(DatabaseName, LOGSIZE_MB, LOGSPACE_USED, LOGSTATUS)
EXEC('DBCC SQLPERF(LOGSPACE);')
select DatabaseName,
LOGSIZE_MB =CAST (ROUND(LOGSIZE_MB,2) AS NUMERIC(10,2)),
LOGSIZE_GB =CAST (ROUND(LOGSIZE_MB/1024.00,2)AS NUMERIC(10,2)),
LOGSPACE_USED =CAST(ROUND(LOGSPACE_USED,2)AS NUMERIC(10,2))
FROM @Radhe
order by logsize_mb desc
--=======================================================================================================
--=======================================================================================================
-- process to shrink the log file and show the outcome
--=======================================================================================================
DECLARE @sqlCommand VARCHAR(1000)
DECLARE @filePath VARCHAR(100)
DECLARE @fileName VARCHAR(100)
SET @filePath = 'C:\sqlBackup\'
SET @fileName = 'Shrink_' +
+ CONVERT(VARCHAR, GETDATE(), 112) + '_' +
RIGHT('00'+CAST(DATEPART(HOUR, GETDATE()) AS VARCHAR),2) + '_' +
RIGHT('00'+CAST(DATEPART(MINUTE,GETDATE()) AS VARCHAR),2) + '.txt'
PRINT @filePath + @filename
--SET @sqlCommand = 'sqlcmd -S "JPB01275\SQL2014" -U SQL_User_Impresonated -P Sql_P@ssword -N -C -d "Radhe" -o "C:\sqlBackup\shrink.txt" -Q "DBCC SHRINKFILE(''Radhe_log'',0, TRUNCATEONLY)"'
SET @sqlCommand = 'sqlcmd -S "JPB01275\SQL2014" -U SQL_User_Impresonated -P Sql_P@ssword -N -C -d "Radhe" -o ' + '"' + @FILEPATH + @fileName + '"' + ' -Q "DBCC SHRINKFILE(''Radhe_log'',0, TRUNCATEONLY)"'
--PRINT @sqlCommand
EXEC master..xp_cmdshell @sqlCommand
--select QUOTENAME(@@servername)
BEGIN TRY
DROP TABLE #RADHE
END TRY
BEGIN CATCH
END CATCH
CREATE TABLE #RADHE
(THE_LINE VARCHAR(500) NULL)
select @sqlCommand=
'BULK INSERT #RADHE ' + CHAR(10) +
'FROM ' + '''' + @FILEPATH + @fileName + '''' + CHAR(10) +
'WITH
(
ROWTERMINATOR =''\n''
)'
exec (@sqlCommand)
--querying an specific line of a heap
ALTER TABLE #RADHE
ADD ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED
BEGIN TRY
DROP TABLE #X
END TRY
BEGIN CATCH
END CATCH
BEGIN TRY
DROP TABLE #Y
END TRY
BEGIN CATCH
END CATCH
--=========================================================================================
-- CTE to extract all numbers from string: niikola
--=========================================================================================
Declare @txt varchar(4000)
Declare @num varchar(10) = '%[0-9.,]%'
Declare @oth varchar(10) = '%[^0-9.,]%'
SELECT @txt =THE_LINE
FROM #RADHE
WHERE ID = 3
Set @txt+='X'
;With a as (
Select 1 as i,
Substring(@txt,Patindex(@num,@txt),patindex(@oth,Substring(@txt,Patindex(@num,@txt),4000))-1) as num,
substring(@txt,Patindex(@num,@txt)+patindex(@oth,Substring(@txt,Patindex(@num,@txt),4000))-1,4000) as txt
Union All
Select i+1,
Substring(txt,Patindex(@num,txt),patindex(@oth,Substring(txt,Patindex(@num,txt),4000))-1),
substring(txt,Patindex(@num,txt)+patindex(@oth,Substring(txt,Patindex(@num,txt),4000))-1,4000)
from a
Where txt like '%[0-9]%'
)
Select IND=i, NUM=CAST( num AS INT)
INTO #Y
from a
Where num like '%[0-9]%'
CREATE TABLE #x
(
[DBID] int,
FileID int,
CurrentSize int,
MinimumSize int,
UsedPages int,
EstimatedPages int
)
-- Problems with the Insert
-- The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
-- Column name or number of supplied values does not match table definition.
-- select * from #y
INSERT INTO #x
(
[DBID],
FileID,
CurrentSize,
MinimumSize,
UsedPages,
EstimatedPages
)
SELECT *
FROM
(
SELECT IND,NUM
FROM #Y
) RADHE
PIVOT
(
SUM(NUM)
FOR IND IN ([1], [2], [3],[4], [5], [6])
) PIV;
--==============================================================================
-- the outpout of DBCC Shrinkfile
-- https://msdn.Microsoft.com/en-GB/library/ms189493.aspx
--Column name Description
--DbId Database identification number of the file the Database Engine tried to shrink.
--FileId The file identification number of the file the Database Engine tried to shrink.
--CurrentSize Number of 8-KB pages the file currently occupies.
--MinimumSize Number of 8-KB pages the file could occupy, at minimum. This corresponds to the minimum size or originally created size of a file.
--UsedPages Number of 8-KB pages currently used by the file.
--EstimatedPages Number of 8-KB pages that the Database Engine estimates the file could be shrunk down to.
--==============================================================================
use radhe
SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB
FROM sys.database_files;
--SELECT SUM(user_object_reserved_page_count) AS [user object pages used],
--(SUM(user_object_reserved_page_count)*1.0/128) AS [user object space in MB]
--FROM sys.dm_db_file_space_usage;
select *
FROM sys.dm_db_log_space_usage;
SELECT
the_database_name=db_name(dbid),
FileID,
CurrentSize,
MinimumSize,
UsedPages,
EstimatedPages
FROM #X