1] Commands
1.1 DB Level
1.1.1 MODIFY / SHRINK FILE
ALTER DATABASE
Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044
MODIFY FILE (NAME
= Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044, FILEGROWTH = 128 MB);
ALTER DATABASE
Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044
MODIFY FILE (NAME
= Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044_log, FILEGROWTH = 64 MB);
USE Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044
DBCC Shrinkfile(NAME =
Application_de_service_de_recherche_CrawlStoreDB_9cb0fc22d2884dea9c3df8a1f7bd7044,8192)
1.1.2 DATA Used Space
-- tempdb only
select * from sys.dm_db_file_space_usage
;
-- in a db
dbcc showfilestats
-- know how
much free space exists in database and may be released using dbcc
shrinkdatabase
use <database>
go
EXEC sp_spaceused
go
1.1.3 DBCC SHRINKDATABASE
( database_name | database_id | 0
[
, target_percent ] [ , { NOTRUNCATE | TRUNCATEONLY } ] ) [ WITH NO_INFOMSGS ]
target_percent Is the
percentage of free space that you want left in the database file after the
database has been shrunk.
TRUNCATEONLY Releases all free space at
the end of the file to the operating system but does not perform any page
movement inside the file. The data file is shrunk only to the last allocated
extent. target_percent is ignored if specified with TRUNCATEONLY. TRUNCATEONLY is applicable only
to data files. The log files are not affected.
Option
|
Page Movement
|
Truncate File
|
Default TRUNCATE & MOVE
|
Y
|
Y
|
NO_TRUNCATE
|
Y
|
N
|
TRUNCATE_ONLY
|
N
|
Y
|
Note : MOVE is similar to Oracle 10g+ Table Shrink.
1.2 Table Level
1.2.1 DBCC CLEANTABLE Reclaims
space for dropped variable length columns and text columns.
( {
database_name | database_id | 0 } , { table_name |
table_id | view_name | view_id }
[
, batch_size ] ) [ WITH NO_INFOMSGS ]
1.2.2 DBCC SHOWCONTIG ('Policy')
use SMS
DBCC SHOWCONTIG ('Policy')
DBCC SHOWCONTIG scanning 'Policy'
table...
Table: 'Policy' (581577110); index
ID: 1, database ID: 6
TABLE level scan performed.
- Pages
Scanned................................: 288
- Extents
Scanned..............................: 44
- Extent
Switches..............................: 88
- Avg. Pages per
Extent........................: 6.5
- Scan Density [Best Count:Actual
Count].......: 40.45% [36:89]
- Logical Scan Fragmentation
..................: 20.49%
- Extent Scan Fragmentation
...................: 95.45%
- Avg. Bytes Free per
Page.....................: 2492.7
- Avg. Page Density
(full).....................: 69.20%
DBCC execution completed. If DBCC
printed error messages, contact your system administrator.
2] Get Table & Index Volume
2.1 Table & Index, using
« sp_spaceused »
[Taken from
Internet, thx]
use <database>
--CREATE
PROCEDURE GetAllTableSizes
--AS
/* Obtains spaced used data for ALL user
tables in the database */
DECLARE @TableName VARCHAR(100) --For
storing values in the cursor
--Cursor to
get the name of all user tables from the sysobjects listing
DECLARE tableCursor CURSOR
FOR select [name] from dbo.sysobjects
where OBJECTPROPERTY(id,
N'IsUserTable') = 1
FOR READ ONLY
--A
procedure level temp table to store the results
CREATE TABLE #TempTable
(
tableName varchar(100),
numberofRows integer,
reservedSize varchar(50),
dataSize varchar(50),
indexSize varchar(50),
unusedSize varchar(50)
)
--Open the
cursor
OPEN tableCursor
--Get the
first table name from the cursor
FETCH NEXT FROM
tableCursor INTO @TableName
--Loop
until the cursor was not able to fetch
WHILE (@@Fetch_Status >= 0)
BEGIN
--Dump the results of the
sp_spaceused query to the temp table
INSERT #TempTable
EXEC sp_spaceused @TableName
--Get the next table name
FETCH NEXT FROM tableCursor
INTO @TableName
END
--Get rid
of the cursor
CLOSE tableCursor
DEALLOCATE tableCursor
--Select
all records so we can use the reults
SELECT * FROM
#TempTable order by numberofRows
desc
--Final
cleanup!
DROP TABLE #TempTable
GO
Table
|
Rows
|
Reserved
|
Data
|
Index
|
unused
|
CI_SDMPackages
|
65018
|
2167008 KB
|
2134408 KB
|
28800 KB
|
3800 KB
|
Policy
|
39612
|
17476672 KB
|
17475840 KB
|
464 KB
|
368 KB
|
CI_CurrentSettingsComplianceStatusDetail
|
43590
|
74640 KB
|
49864 KB
|
21408 KB
|
3368 KB
|
Too bad, I
can’t sort on volume because « sp_spaceused » is giving me a varchar
result for sizes.
2.2 Table & Index, as a whole
– sort by Size_MB desc
-- Table Size
and Row count information
use <database>
go
SELECT
OBJECT_NAME(ps.[object_id]) AS
[Table] ,
ps.row_count AS [Rows],
SUM(ps.used_page_count)*8/1024
AS [Size_MB],
SUM(ps.reserved_page_count)*8/1024
AS [Reserved_MB],
SUM(ps.reserved_page_count-ps.used_page_count)*8/1024
AS [Unused_MB]
FROM
sys.dm_db_partition_stats AS ps
INNER JOIN sys.indexes AS i
ON i.[object_id] = ps.[object_id] AND i.index_id = ps.index_id
WHERE
-- i.type_desc IN (
'CLUSTERED', 'HEAP' ) AND
i.[object_id]
> 100 AND OBJECT_SCHEMA_NAME(ps.[object_id]) <>
'sys'
GROUP BY ps.[object_id],ps.row_count
ORDER BY [Size_MB]
DESC ;
Table
|
Rows
|
Size_MB
(Table + all Idx) |
Reserved_MB
|
Unused_MB
|
Policy
|
39613
|
17078
|
17078
|
0
|
CI_SDMPackages
|
65018
|
2112
|
2116
|
3
|
SW_LICENSING_PRODUCT_HIST
|
2810420
|
1502
|
1503
|
0
|
2.3 Reminder : Instance Level
- get DB Total volume / Data vol. / Log vol.
select a.name ,
( SELECT ceiling(SUM(size*8)/1024.) Total_mdf_ldf_MB_sz FROM sys.master_files c where a.database_id = c.database_id ) Total_sz_MB ,
( SELECT ceiling(SUM(size*8)/1024.) Total_ldf_MB_sz FROM sys.master_files c where a.database_id = c.database_id and type = '0' ) Total_Data_sz_MB ,
( SELECT ceiling(SUM(size*8)/1024.) Total_ldf_MB_sz FROM sys.master_files c where a.database_id = c.database_id and type = '1' ) Total_Log_sz_MB
from sys.databases a where a.name not in ('model','tempdb')
order by 2
2.4 Index Size
SELECT i.name
AS IndexName, SUM(page_count * 8)
AS IndexSizeKB
FROM sys.dm_db_index_physical_stats(db_id(), object_id('dbo.TableName'), NULL, NULL, 'DETAILED')
AS s JOIN sys.indexes AS i
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
GROUP BY i.name ORDER BY i.name
3] SCCM 2007 Table growth Bugs
3.0 SCCM Background
ConfigMgr (SCCM) CI & SDM Packages Definitions
First, some definitions.
CI – A CI is short for Configuration Item. A
configuration item generically is a discrete unit of configuration to assess
for compliance. They can contain one or more elements and their validation
criteria, and they typically define a unit of configuration you want to monitor
at the level of independent change.
SDM Package – A SDM package is short for Service Definition
Model. You may also hear the SDM Package described as using the SML –
service modeling language. SDM Packages link together with CI’s and
further describe how to effect whatever configuration it is that we wish to
evaluate or implement.
Backup and Recovery
Like any enterprise software, your site should be backed up to provide
recoverability in case of unexpected events. Backing up a SCCM 2007 site
involves backing up the database, the file system, and the registry all at the
same point in time - backing up just one of these elements is not sufficient to
restore a working site. SCCM 2007 uses the Volume Shadow Copy Service (VSS) to
take small, frequent snapshots of the necessary components, making it easier to
restore a failed site. The Site Repair Wizard walks you through the necessary
steps to complete the site recovery.
3.1 Bug # 1 : How to Fix 'ci_sdmpackages'
Table Growth
CI_SDMPackages growing rapidly at
Primary Site
table num_rows reservedS dataS indexS unusedS
CI_SDMPackages 79619 11566048 KB 11531704 KB 23288 KB 11056 KB
use SMS_ARB
go
dbcc cleantable ('SMS_ARB','ci_sdmpackages',1000)
GO
table num_rows reservedS dataS indexS unusedS
CI_SDMPackages 79619 4475232 KB 2593056 KB 23288 KB 1858888 KB
DBCC SHRINKDATABASE (SMS_ARB, 5);
GO
Result : 9 GB Freed
Not used :
alter index CI_SDMPackages_AK on ci_sdmpackages
reorganize with (lob_compaction=ON)
GO
alter index CI_SDMPackages_AK2 on ci_sdmpackages
reorganize with (lob_compaction=ON)
GO
alter index CI_SDMPackages_PK on ci_sdmpackages
reorganize with (lob_compaction=ON)
GO
3.2 Bug # 2 'policy' Table Growth
will
be resolved in FEP 2012
I was experiencing this issue with the same table and had to open a
ticket with Microsoft due to the lack of information from forums. Basically,
the engineer said it was a bug with FEP 2010. In our case, FEP was generating ALOT of notifications for "unknown
machine" and/or "unkown SMS application" in the 'dbo.Policy'
table creating orphaned CI's.
With MS approval : deletion of orphaned CIs
USE SMS
GO
-- orphaned
CIs : 29950 rows / 38710
select COUNT(PolicyID) from Policy
SELECT PolicyID FROM Policy
WHERE PolicyID NOT IN (SELECT
PolicyID FROM PolicyAssignment WHERE PADBID IN (SELECT
PADBID FROM ResPolicyMap))
AND PolicyID NOT IN (SELECT
ModelName FROM CI_ConfigurationItems)
AND PolicyID LIKE '%SUM_%'
select COUNT(PolicyID) from Policy
IF NOT
EXISTS(SELECT * from
sys.objects
so WHERE so.name='PolDelPolicy'
and so.type='U')
BEGIN
CREATE
TABLE PolDelPolicy (
PolicyID
varchar(512) primary
key not null,
RecordSize
int null,
DeleteTime
datetime null
);
END
IF EXISTS(SELECT * FROM
sys.objects
so WHERE so.name = 'Task_DeletePolicy'
AND so.type='P')
DROP PROCEDURE
Task_DeletePolicy
CREATE PROCEDURE
Task_DeletePolicy as
BEGIN
DECLARE
@cursor1 cursor
DECLARE
@PolicyID varchar(512)
DECLARE
@PolSize int
SET
@cursor1 = cursor FOR
SELECT PolicyID, DATALENGTH(Body)
dl
FROM
Policy
WHERE
PolicyID NOT IN (SELECT PolicyID FROM PolicyAssignment
WHERE
PADBID IN (SELECT PADBID FROM ResPolicyMap))
AND
PolicyID NOT IN (SELECT ModelName FROM CI_ConfigurationItems)
AND
PolicyID LIKE '%SUM_%'
OPEN
@cursor1
WHILE
1=1
BEGIN
FETCH
FROM @cursor1 INTO @PolicyID, @Polsize
IF
@@FETCH_STATUS <> 0
BREAK
BEGIN
TRANSACTION
IF
NOT EXISTS (SELECT PolicyID FROM PolDelPolicy
WHERE PolicyID=@PolicyID)
INSERT
INTO PolDelPolicy VALUES (@PolicyID,@PolSize,GETDATE())
DELETE
FROM Policy WHERE PolicyID=@PolicyID
COMMIT
TRANSACTION
END
CHECKPOINT
END
select COUNT(PolicyID) from PolDelPolicy
exec Task_DeletePolicy
sp_RENAME 'PolDelPolicy','PolDelPolicy_bak_210312'
--
Attention : changer une partie du nom de l'objet peut inhiber les scripts et
les procedures stockees.
CREATE TABLE PolDelPolicy (
PolicyID varchar(512)
primary key not null,
RecordSize int null,
DeleteTime datetime null
);
3.3 Schedule the fix in Weekly T-SQL tasks
use SMS_SAS
GO
exec Task_DeletePolicy
GO
dbcc cleantable
('SMS_SAS','ci_sdmpackages',1000)
GO
DBCC SHRINKDATABASE (SMS_SAS, 5);
GO
Conclusion
I got a big
volume decrease : 110 GB -> 56 GB
Tables
Policy : 60 -> 17 GB
Tables
CI_SDMPackages : 23 -> 8 GB
4] Radius Accounting Table is getting bigger and bigger
Radius Log
table gets bigger and bigger : NPSXML.dbo.accounting_data
- Actual size ( using 2.2 sql to get the info ): 43 GB
Table
|
Rows
|
Size_MB
(Table + all Idx) |
Reserved_MB
|
Unused_MB
|
accounting_data
|
62182415
|
43279
|
43291
|
12
|
- Data distribution [ Full Scan Table 1H15 ]
select COUNT(1) from
accounting_data where timestamp < dateadd(mm,-6,getdate()) -- 4 912 056
select COUNT(1) from
accounting_data where timestamp < dateadd(mm,-3,getdate()) -- 15 481 360 duration = 1H15
- Does the table have Index ?
use NPSXML
EXEC sp_helpindex 'dbo.accounting_data'
The object
'dbo.accounting_data' does not have any indexes, or you do not have
permissions.
What’s decided :
- Archive the table
- Remove very old rows ( < 9 months )
- Compress it
4.0 Archive table
-- Archive Log table :
-- sp_rename log ->
log_archive_0511_to_0512
-- CTAS log AS
log_arc_0511_to_0512 where 1 = 2 ;
sp_RENAME 'accounting_data'
, 'accounting_data_archive_0511_to_0512'
-- create
empty table
SELECT * INTO accounting_data FROM accounting_data_archive_0511_to_0512
WHERE 1=2
-- check
everything
select * from
INFORMATION_SCHEMA.TABLES where TABLE_NAME =
'accounting_data'
4.1 Massive Delete
4.1.1 Pre-requisite
-
Add index to speed up the scanning
process
--Non
Clustered Index
CREATE INDEX
IX_accounting_data_archive_0511_to_0512
ON accounting_data_archive_0511_to_0512 (timestamp); -- 1H20
SELECT *
FROM sys.indexes WHERE OBJECT_ID = OBJECT_ID('accounting_data_archive_0511_to_0512')
object_id
|
name
|
index_id
|
type
|
type_desc
|
2105058535
|
NULL
|
0
|
0
|
HEAP
|
2105058535
|
IX_accounting_data
archive_0511_to_0512 |
14
|
2
|
NONCLUSTERED
|
Note :
to revert it DROP INDEX
IX_accounting_data_archive_0511_to_0512
ON accounting_data_archive_0511_to_0512
-
Index size using sql from 2.1 (
sp_spaceused ) : 1.2 GB
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounting_data_archive_0511_to_0512
|
62 643 137
|
45843904 KB
|
44 648 944 KB
|
1 180 744 KB
|
14216 KB
|
accounting_data
|
28 136
|
22680 KB
|
22 608 KB
|
24 KB
|
48 KB
|
- How many rows to delete ( < 9 months ) ? [ Index Scan 3 seconds ! ]
select COUNT(1) from
accounting_data_archive_0511_to_0512
where timestamp
< dateadd(mm,-9,getdate())--
2 292 269
- Get DB space used
use NPSXML
go
sp_spaceused
base
|
db_size
|
unallocated_space
|
NPSXML
|
47 895.75 MB
|
346.80 MB
|
4.1.2 Bulk Delete 2 millions rows
( 3.65 % )
Each run Deletes at max 500 000 rows / Takes 2
to 3 minutes
Generates
around 400 MB of TLOG overall : 1500 MB -- 2753 MB 94 % ->
4225 MB 96 %
use NPSXML
-- Bulk
Delete
-- credit :
http://www.sqlteam.com/forums/post.asp?method=Reply&TOPIC_ID=62356&FORUM_ID=5
-- ORACSD
22/05/2012
--
@@ROWCOUNT function to return the number of deleted rows
DECLARE @intRowsToDelete int
DECLARE @intRowCount int
DECLARE @intErrNo int
DECLARE @intLoops int
DECLARE @dtLoop datetime
DECLARE @intProcCount int
-- DECLARE
@txtStatus varchar(255)
SET ROWCOUNT 100000 -- number of rows to be deleted each loop
--SET
ROWCOUNT 0 -- Reset batch size
to "all"
SELECT
@intRowCount = 1, -- Force first iteration
@intErrNo = 0,
@intLoops = 5 -- maximum loops to make (too prevent
running for too long)
SELECT @intRowsToDelete = COUNT(*) -- Number of rows to be deleted
FROM dbo.accounting_data_archive_0511_to_0512
WHERE timestamp < dateadd(mm,-9,getdate())
WHILE @intRowCount > 0 AND @intErrNo
= 0 AND @intLoops
> 0
BEGIN
SELECT @dtLoop = GetDate()
DELETE FROM dbo.accounting_data_archive_0511_to_0512
WHERE timestamp < dateadd(mm,-9,getdate()) -- needs index access !!
SELECT @intErrNo = @@ERROR, @intRowCount
= @@ROWCOUNT
-- implicit
commit
SELECT @intRowsToDelete
= @intRowsToDelete - @intRowCount,
@intLoops = @intLoops
- 1
--
Debugging usage only:
PRINT 'Deleted: ' + CONVERT(varchar(20),
@intRowCount)
+ ', Elapsed: ' + CONVERT(varchar(20),
DATEDIFF(Second, @dtLoop, GetDate())) +
' seconds,'
+ ' remaining to delete=' + CONVERT(varchar(20), @intRowsToDelete)
+ ', Loops left=' + CONVERT(varchar(20), @intLoops)
WAITFOR DELAY '000:00:05' -- 5 seconds for other users to gain access
END
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 11 seconds,
remaining to delete=2192287, Loops left=4
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 17 seconds,
remaining to delete=2092287, Loops left=3
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 14 seconds,
remaining to delete=1992287, Loops left=2
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 15 seconds,
remaining to delete=1892287, Loops left=1
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 23 seconds,
remaining to delete=1792287, Loops left=0
…
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 21 seconds,
remaining to delete=692385, Loops left=4
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 26 seconds,
remaining to delete=592385, Loops left=3
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 50 seconds,
remaining to delete=492385, Loops left=2
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 30 seconds,
remaining to delete=392385, Loops left=1
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 27 seconds,
remaining to delete=292385, Loops left=0
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 29 seconds,
remaining to delete=192415, Loops left=4
(100000 ligne(s) affectee(s))
Deleted: 100000, Elapsed: 34 seconds,
remaining to delete=92415, Loops left=3
(92425 ligne(s) affectee(s))
Deleted: 92425, Elapsed: 25 seconds,
remaining to delete=-10, Loops left=2
(0 ligne(s) affectee(s))
Deleted: 0, Elapsed: 0 seconds,
remaining to delete=-10, Loops left=1
base
|
db_size
|
unallocated_space
|
NPSXML
|
49 367.75 MB
|
1798.37 MB
|
Increase of
log space.
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounting_data_archive_0511_to_0512
|
60 350 712
|
44357312 KB
|
43 148 744 KB
|
1 137 560 KB
|
71008 KB
|
xxxSize
decreased : reservedSize down of 1 486 592 KB
SELECT o.name AS table_name,p.index_id, i.name AS
index_name , au.type_desc AS allocation_type, au.data_pages, partition_number
FROM sys.allocation_units AS au
JOIN sys.partitions
AS p ON
au.container_id
= p.partition_id
JOIN sys.objects
AS o ON
p.object_id
= o.object_id
JOIN sys.indexes
AS i ON
p.index_id
= i.index_id AND i.object_id = p.object_id
WHERE o.name = N'accounting_data_archive_0511_to_0512'
ORDER BY
o.name, p.index_id;
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
IN_ROW_DATA
|
5393593
|
1
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
ROW_OVERFLOW_DATA
|
0
|
1
|
accounting_data_archive_0511_to_0512
|
14
|
IX_accounting_data_archive_0511_to_0512
|
IN_ROW_DATA
|
141680
|
1
|
-- Using a
Dynamic Management View, let's see how much space our table is consuming.
--check the
size of the table
SELECT alloc_unit_type_desc,page_count,avg_page_space_used_in_percent,record_count
FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N'dbo.accounting_data_archive_0511_to_0512'),NULL,NULL,'Detailed') ;
alloc_unit_type_desc
|
page_count
|
avg_page_space_used_in_percent
|
record_count
|
IN_ROW_DATA
|
5393593
|
84,40
|
60350712
|
IN_ROW_DATA
|
141680
|
99,97
|
60350712
|
IN_ROW_DATA
|
452
|
96,79
|
141680
|
IN_ROW_DATA
|
9
|
15,49
|
452
|
IN_ROW_DATA
|
1
|
2,76
|
9
|
ANOTHER
DELETION : 36 214 Rows
(36214 ligne(s) affectee(s))
Deleted: 36214, Elapsed: 7 seconds,
remaining to delete=0, Loops left=4
(0 ligne(s) affectee(s))
Deleted: 0,
Elapsed: 0 seconds, remaining to delete=0, Loops left=3
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
IN_ROW_DATA
|
5390550
|
1
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
ROW_OVERFLOW_DATA
|
0
|
1
|
accounting_data_archive_0511_to_0512
|
14
|
IX_accounting_data_archive_0511_to_0512
|
IN_ROW_DATA
|
141595
|
1
|
Heap total
Pages goes down from 5393593 to 5390550
= 3043 pages
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounting_data_archive_0511_to_0512
|
60 314 498
|
44333952 KB
|
43 124 400 KB
|
1 136 880 KB
|
72672 KB
|
Pages
decrease, though I thought the « "holes" were
re-used by SQL Server »
See below
for another test on a smaller table.
4.2 Table Compression
4.2.0 Prerequisite
- Drop index created for massive Delete
drop index
IX_accounting_data_archive_0511_to_0512
on accounting_data_archive_0511_to_0512
- Is COMPRESSION enabled ?
--
compression setting
select object_name (object_id) as table_name, data_compression_desc
from sys.partitions where object_name (object_id) = 'accounting_data_archive_0511_to_0512'
accounting_data_archive_0511_to_0512 NONE
- Table Size
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounting_data_archive_0511_to_0512
|
60 314 498
|
43195608 KB
|
43 124 400 KB
|
88 KB
|
71120 KB
|
SELECT o.name AS
table_name,p.index_id, i.name AS
index_name , au.type_desc AS allocation_type, au.data_pages, partition_number
FROM sys.allocation_units AS au
JOIN
sys.partitions
AS p ON
au.container_id
= p.partition_id
JOIN
sys.objects
AS o ON
p.object_id
= o.object_id
JOIN
sys.indexes
AS i ON
p.index_id
= i.index_id AND i.object_id = p.object_id
WHERE o.name =
N'accounting_data_archive_0511_to_0512'
ORDER BY o.name,
p.index_id;
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
IN_ROW_DATA
|
5390550
|
1
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
ROW_OVERFLOW_DATA
|
0
|
1
|
- Row length … too long on 40 GB Table
-
Look at the current
row size
select max_record_size_in_bytes
from sys.dm_db_index_physical_stats (db_id('compression'),
object_id('compression.accounting_data_archive_0511_to_0512'),
null, null, 'DETAILED')
where object_name (object_id) = 'accounting_data_archive_0511_to_0512'
4.2.1 Estimate Gain
sp_estimate_data_compression_savings
[ @schema_name = ]
'schema_name'
, [ @object_name = ]
'object_name'
, [@index_id = ] index_id
, [@partition_number = ]
partition_number
, [@data_compression = ]
'data_compression'
[;]
An (IS) lock is acquired on
the table during this operation. If an (IS) lock cannot be obtained, the
procedure will be blocked. The table is scanned under the read committed
isolation level.
- What if we use ROW or PAGE Level TABLE COMPRESSION ?
USE NPSXML;
GO
EXEC sp_estimate_data_compression_savings 'dbo',
'accounting_data_archive_0511_to_0512', NULL, NULL, 'ROW'
;
object_name
|
schema
|
index_id
|
partition
number |
size_with_current
compression_setting (KB) |
size_with_requested
compression_setting (KB) |
accounting_data_archive_0511_to_0512
|
dbo
|
0
|
1
|
43 124 488
|
19 210 256
|
Size would
be divided by 2.
EXEC sp_estimate_data_compression_savings 'dbo',
'accounting_data_archive_0511_to_0512', NULL, NULL, 'PAGE'
;
object_name
|
schema
|
index_id
|
partition
number |
size_with_current
compression_setting (KB) |
size_with_requested
compression_setting (KB) |
accounting_data_archive_0511_to_0512
|
dbo
|
0
|
1
|
43 124 488
|
5 887 840
|
Size would
be divided by 7.
4.2.2 Compress Table : 1H04
- Switch to SIMPLE Mode if needed
USE NPSXML
GO
ALTER DATABASE NPSXML
SET RECOVERY SIMPLE;
GO
-- This command can also be executed
ONLINE
ALTER TABLE dbo.accounting_data_archive_0511_to_0512
REBUILD WITH (DATA_COMPRESSION
= PAGE);
GO
-- Reset the database recovery model.
ALTER DATABASE NPSXML
SET RECOVERY FULL;
GO
4.2.3 Gain
ü
Table downsize : 38713128 KB =
36.9 GB
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounting_data_archive_0511_to_0512
|
60 314 498
|
4482480 KB
|
4 481 816 KB
|
24 KB
|
640 KB
|
ü
Table Pages downsize : 4 830 325
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
IN_ROW_DATA
|
560225
|
1
|
accounting_data_archive_0511_to_0512
|
0
|
NULL
|
ROW_OVERFLOW_DATA
|
0
|
1
|
ü
DB Unallocated Space growth :
39.37 GB
base
|
db_size
|
unallocated_space
|
reserved
|
data
|
index_size
|
unused
|
NPSXML
|
49998.00 MB
|
42119.05 MB
|
4897736 KB
|
4895528 KB
|
744 KB
|
1464 KB
|
To give this
space back to the OS : 43.3 GB ( includes LOG )
EXEC master.sys.xp_fixeddrives --
T : 12 313 MB
-- 02H37
DBCC SHRINKDATABASE (NPSXML, 15);
GO
EXEC master.sys.xp_fixeddrives -- T : 56 682 MB
5] Delete on Table
5.1] Delete on Table :
Are the Pages deallocated ?
I wonder if
the freed space stays part of the table for future Insert like in Oracle.
- Initial metrics
use ReportServerTempDB
go
sp_spaceused
base
|
db_size
|
unallocated_space
|
reserved
|
data
|
index_size
|
unused
|
ReportServerTempDB
|
255.81 MB
|
12.82 MB
|
7608 KB
|
6512 KB
|
952 KB
|
144 KB
|
- Create Table / Load 250 000 rows
CREATE TABLE accounts ( fname VARCHAR(20), lname VARCHAR(20))
GO
INSERT accounts VALUES ('Fred', 'Flintstone') --
6min26
GO 250000
SELECT TOP 10 * FROM
accounts
GO
base
|
db_size
|
unallocated_space
|
reserved
|
data
|
index_size
|
unused
|
ReportServerTempDB
|
255.81 MB
|
5.44 MB
|
15168 KB
|
14032 KB
|
960 KB
|
176 KB
|
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounts
|
250000
|
7560 KB
|
7520 KB
|
8 KB
|
32 KB
|
- Non Clustered Index – HEAP Table
CREATE INDEX
IX_accounts ON accounts (lname);
base
|
db_size
|
unallocated_space
|
reserved
|
data
|
index_size
|
unused
|
ReportServerTempDB
|
258.81 MB
|
1.55 MB
|
22216 KB
|
14032 KB
|
7936 KB
|
248 KB
|
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounts
|
250000
|
14608 KB
|
7520 KB
|
6984 KB
|
104 KB
|
--check the
size of the table
SELECT alloc_unit_type_desc,page_count,avg_page_space_used_in_percent,record_count
FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(N'dbo.accounts'),NULL,NULL,'Detailed') ;
alloc_unit_type_desc
|
page_count
|
avg_page_space_used_in_percent
|
record_count
|
IN_ROW_DATA
|
940
|
95,27
|
250000
|
IN_ROW_DATA
|
866
|
99,84
|
250000
|
IN_ROW_DATA
|
4
|
90,92
|
866
|
IN_ROW_DATA
|
1
|
1,66
|
4
|
SELECT o.name AS table_name,p.index_id, i.name AS
index_name , au.type_desc AS allocation_type, au.data_pages, partition_number
FROM sys.allocation_units AS au
JOIN sys.partitions
AS p ON
au.container_id
= p.partition_id
JOIN sys.objects
AS o ON
p.object_id
= o.object_id
JOIN sys.indexes
AS i ON
p.index_id
= i.index_id AND i.object_id = p.object_id
WHERE o.name = N'accounts'
ORDER BY
o.name, p.index_id;
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounts
|
0
|
NULL
|
IN_ROW_DATA
|
940
|
1
|
accounts
|
2
|
IX_accounts
|
IN_ROW_DATA
|
866
|
1
|
- Delete all rows
-- delete
top(200000) from accounts
delete from accounts
(250000 ligne(s)
affectee(s))
base
|
db_size
|
unallocated_space
|
reserved
|
data
|
index_size
|
unused
|
ReportServerTempDB
|
258.81 MB
|
15.43 MB
|
8008 KB
|
6696 KB
|
992 KB
|
320 KB
|
table
|
num_rows
|
reservedSize
|
dataSize
|
indexSize
|
unusedSize
|
accounts
|
0
|
400 KB
|
184 KB
|
40 KB
|
176 KB
|
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounts
|
0
|
NULL
|
IN_ROW_DATA
|
23
|
1
|
accounts
|
2
|
IX_accounts
|
IN_ROW_DATA
|
1
|
1
|
- Clustered Index
CREATE clustered
INDEX IX_accounts ON accounts (lname);
alloc_unit_type_desc
|
page_count
|
avg_page_space_used_in_percent
|
record_count
|
IN_ROW_DATA
|
1083
|
99,79
|
250000
|
IN_ROW_DATA
|
5
|
85,59
|
1083
|
IN_ROW_DATA
|
1
|
1,88
|
5
|
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounts
|
1
|
IX_accounts
|
IN_ROW_DATA
|
1083
|
1
|
After Total
Delete
table
|
index_id
|
index
|
allocation_type
|
data_pages
|
partition_number
|
accounts
|
1
|
IX_accounts
|
IN_ROW_DATA
|
1
|
1
|
Conclusion
table type
|
Init Pages #
|
# Pages after Delete all rows
|
Desc
|
Heap
|
940 Tab
866 Idx |
23
1 |
Rebuild
index to get more pages deallocated
|
Clustered
|
1083
|
1
|
Every
pages are given back to the DB
|
5.2] Delete according to
dates
SELECT GETDATE() -- sysdate
select dateadd(hh,-1,getdate()) --
remove one hour
select dateadd(dd,1,getdate()) --
add one day
select dateadd(dd,-200,getdate()) --
remove 200 days
-- 104 tables creation_date older than 6 months
SELECT name
, type_desc , create_date
FROM sys.Tables where create_date <
dateadd(dd,-200,getdate()) order
by create_date desc
-- drop them
SELECT 'drop table
ODS.genesys.' +
name + ' ;'
FROM sys.Tables where create_date <
dateadd(dd,-200,getdate()) order
by create_date desc
-- 100 tables creation_date older than 6 months
SELECT name
, type_desc , create_date
FROM sys.Tables where create_date <
dateadd(dd,-200,getdate()) order
by create_date desc
-- drop them
SELECT 'drop table
ODS.genesys.' +
name + ' ;'
FROM sys.Tables where create_date <
dateadd(dd,-200,getdate()) order
by create_date desc
drop table
ODS.genesys.OL_DATA80 ;
drop table
ODS.genesys.OL_DATA79 ;
SET LANGUAGE
English
dbcc sqlperf('logspace')
use ODS
-- after drop tables
EXEC sp_spaceused
db sz unallocated
ODS 14606.25 MB 6807.34 MB
DBCC SHRINKDATABASE ( ODS
, 0 , TRUNCATEONLY
) -- same, need page movement
DBCC SHRINKDATABASE ( ODS
, 5 ) --
log full
ALTER DATABASE
ODS SET RECOVERY
SIMPLE; --
9 MB free
DBCC SHRINKDATABASE ( ODS
, 5 )
db fid cur_sz min_sz used_pages estim_pages
8 1 1050784 288 1050512 1050512
8 2 160 128 160 128
EXEC master.sys.xp_fixeddrives -- 6 GB Free