Wednesday, January 18, 2012

Check Statistics


This script helps to check when was the last time the statistics were updated for all tables/indexes in all the databases, also provides a table modification rate value (percentage) so then you can perform update stats with fullscan for tables/indexes based on a defined rule (ex. stats for tables/indexes not updated in the last 30 days and/or the modification rate is over 30%) 


select @@ServerName, getdate()
/* **************************************************************** */
use master
go
DECLARE @db sysname,
            @cmd varchar(4000)
SET NOCOUNT ON

IF (object_id( 'tempdb..#DBA_STATISTICS_STATUS' ) IS NOT NULL) DROP TABLE #DBA_STATISTICS_STATUS ;

CREATE TABLE #DBA_STATISTICS_STATUS(
id int identity primary key,
database_name sysname,
table_schema sysname,
table_name sysname,
index_name sysname,
table_id int,
index_id int,
modifiedRows int,
rowcnt int,
ModifiedPercent DECIMAL(18,8),
lastStatsUpdate datetime
)

DECLARE Cursor_Statistics CURSOR FOR
SELECT name FROM sys.databases (NOLOCK)
WHERE NAME not in ('tempdb') and Is_Read_only = 0
order by name

OPEN Cursor_Statistics

FETCH NEXT FROM Cursor_Statistics
INTO @db

WHILE @@FETCH_STATUS = 0
BEGIN
      SELECT @cmd = 'USE ['+@db+'];
Insert into #DBA_STATISTICS_STATUS
select
db_name() as database_name,
schemas.name as table_schema,
tbls.name as table_name,
i.name as index_name,
i.id as table_id,
i.indid as index_id,
i.rowmodctr as modifiedRows,
(select max(rowcnt) from sysindexes i2 where i.id = i2.id and i2.indid < 2) as rowcnt,
convert(DECIMAL(18,8), convert(DECIMAL(18,8),i.rowmodctr) / convert(DECIMAL(18,8),(select max(rowcnt) from sysindexes i2 where i.id = i2.id and i2.indid < 2))) as ModifiedPercent,
stats_date( i.id, i.indid ) as lastStatsUpdate
from sysindexes i
inner join sysobjects tbls on i.id = tbls.id
inner join sysusers schemas on tbls.uid = schemas.uid
inner join information_schema.tables tl
on tbls.name = tl.table_name
and schemas.name = tl.table_schema
--and tl.table_type=''BASE TABLE''
where 0 < i.indid and i.indid < 255
and table_schema <> ''sys''
and i.rowmodctr <> 0
and i.status not in (8388704,8388672)
and (select max(rowcnt) from sysindexes i2 where i.id = i2.id and i2.indid < 2) > 0
'
    
    
      --PRINT @cmd
      EXEC (@cmd)

      FETCH NEXT FROM Cursor_Statistics
INTO @db
END

CLOSE Cursor_Statistics
DEALLOCATE Cursor_Statistics

SELECT * from #DBA_STATISTICS_STATUS WHERE ModifiedPercent >= 20 or datediff(DD,lastStatsUpdate,getdate()) >= 30
ORDER BY database_name,rowcnt desc

DECLARE @table sysname,
            @schema sysname,
            @index sysname        

DECLARE Cursor_Statistics CURSOR FOR
SELECT database_name,table_schema,table_name,index_name from #DBA_STATISTICS_STATUS WHERE ModifiedPercent >= 20 or datediff(DD,lastStatsUpdate,getdate()) >= 30
ORDER BY database_name,rowcnt desc

OPEN Cursor_Statistics

FETCH NEXT FROM Cursor_Statistics
INTO @db,@schema,@table,@index


WHILE @@FETCH_STATUS = 0
BEGIN
      SELECT @cmd = 'USE ['+@db+'];
      UPDATE STATISTICS '+@schema+'.'+@table+' '+@index+' WITH FULLSCAN;
      '
    
      PRINT @cmd
      EXEC (@cmd)
      PRINT '--'+cast(getdate() as varchar(20))


      FETCH NEXT FROM Cursor_Statistics
      INTO @db,@schema,@table,@index
END

CLOSE Cursor_Statistics
DEALLOCATE Cursor_Statistics
GO

select @@ServerName, getdate()
/* **************************************************************** */
IF (object_id( 'tempdb..#DBA_STATISTICS_STATUS' ) IS NOT NULL) DROP TABLE #DBA_STATISTICS_STATUS ;

No comments:

Post a Comment