我正在尝试创建一个存储过程来重建所有数据库的所有索引,碎片大于> 30%
DECLARE @SQL nvarchar(max)
DECLARE @dbname VARCHAR(50)
DECLARE @dbid VARCHAR(50)
DECLARE @SQL2 nvarchar(max)
--Cursor for database names
DECLARE db_cursor CURSOR READ_ONLY FOR
SELECT name, database_id FROM sys.databases
WHERE name NOT IN ('master','model','msdb','tempdb')
--opening the cursor and go to first row
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname, @dbid
WHILE @@FETCH_STATUS = 0
BEGIN
-- Dynamic query to fill @MyIndexFragmented with data
SET @SQL= 'USE ' + @dbname + CHAR(13) +
'
DECLARE @IndexName varchar(150)
DECLARE @TableName varchar(150)
DECLARE @Filas INTEGER
--Declare Table Variable
DECLARE @MyIndexFragmented TABLE
(Databasename varchar(50),
TableName varchar(200),
IndexName varchar(200),
Avg_Fragmentation Decimal,
Page_Count INT )
INSERT INTO @MyIndexFragmented
SELECT DB_NAME(database_id) AS DatabaseName,
OBJECT_NAME(ips.object_id) AS TableName,
i.name AS IndexName,
avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, ''LIMITED'') ips
INNER JOIN sys.indexes i
ON i.object_id = ips.object_id
AND i.index_id = ips.index_id
INNER JOIN sys.partitions p
ON p.object_id = i.object_id
AND p.index_id = i.index_id
WHERE avg_fragmentation_in_percent >= 30
AND ips.index_id > 0
AND page_count > 1000
ORDER BY avg_fragmentation_in_percent DESC
set @filas= (select count (*) from @MyIndexFragmented)
IF @filas>0
BEGIN
-- nested cursor
DECLARE index_cursor CURSOR FOR
SELECT IndexName, TableName FROM @MyIndexFragmented
OPEN index_cursor
-- Nos vamos a la primera fila
FETCH NEXT FROM index_cursor INTO @Indexname, @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
ALTER INDEX @IndexName ON @TableName REBUILD
--Next Row
FETCH NEXT FROM index_cursor INTO @Indexname, @TableName
END
CLOSE index_cursor
DEALLOCATE index_cursor
END -- FOR FILAS >0'
EXECUTE SP_EXECUTESQL @SQL
FETCH NEXT FROM db_cursor INTO @dbname, @dbid
end
CLOSE db_cursor
DEALLOCATE db_cursor
我收到了这个错误:
'@IndexName'附近的语法不正确。
所以我找不到动态制作的方法:
ALTER INDEX @IndexName ON @TableName REBUILD
有什么建议吗?
全部谢谢
答案 0 :(得分:1)
这是我的最终代码,正在运作。如果有人试图重建/重新组织所有数据库上的所有碎片索引(> 5< 30 - 重新组织) (> 30重建) 这是代码
{{1}}
答案 1 :(得分:0)
如果碎片超过30%,这个动态代码将帮助您重新构建索引,此代码可能会帮助您(尝试避免将光标应用于表上的锁定)
DECLARE @command nvarchar(max),@Satetement nvarchar(max)
IF OBJECT_ID('tempdb..##TableList') IS NOT NULL
DROP TABLE ##TableList
CREATE TABLE ##TableList
(
ID INT IDENTITY
,DbName varchar(100)
,TableList nvarchar(100)
,IndexName nvarchar(500)
,SchemaName nvarchar(500)
)
SET @Satetement ='
INSERT INTO ##TableList(DbName,TableList,IndexName,SchemaName)
SELECT
DB_NAME(DB_ID()),
dbtables.[name],
dbindexes.[name],
dbschemas.[name]
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id WHERE indexstats.database_id = DB_ID()
AND indexstats.avg_fragmentation_in_percent >=30
AND indexstats.index_id > 0
AND page_count > 1000
'
SELECT @command = 'IF ''?'' IN (''SqlClass'',''AdventureWorks2012'') BEGIN USE ? EXEC ('''+ @Satetement+''') END ' +CHAR(13)+CHAR(10)
PRINT @command
EXEC sp_MSforeachdb @command
SET @command=''
DECLARE @fillfactor INT =85
,@MinID INT
,@MaxID INT
,@Table VARCHAR(100)
,@Database VARCHAR(100)
,@GetIndex VARCHAR(500)
,@GetSchema VARCHAR(500)
,@SQl nvarchar(max)
SELECT @MinID=MIN(Id) ,@MaxID=MAX(Id) from ##TableList where IndexName IS NOT NULL
WHILE (@MinID<=@MaxID)
Begin
SELECT DISTINCT @Table=TableList,
@Database=DbName,
@GetIndex=IndexName,
@GetSchema=SchemaName
FROM ##TableList where id=@MinID AND IndexName IS NOT NULL
SET @command = ' ALTER INDEX '+@GetIndex+' ON [' + @Database+']'+'.['+@GetSchema+ ']'+'.['+@Table +']'+ ' REBUILD WITH (FILLFACTOR = ' + CONVERT(VARCHAR(3),@fillfactor) + ')'
EXEC ( @command)
PRINT @GetIndex +' index was Rebuild'
--PRINT (@command)
SET @MinID=@MinID+1
END
执行上述脚本后,检查索引的更改填充因子值运行以下查询
SELECT
DB_NAME() AS Database_Name
, sc.name AS Schema_Name
, o.name AS Table_Name
, o.type_desc
, i.name AS Index_Name
, i.type_desc AS Index_Type
, i.fill_factor
FROM sys.indexes i
INNER JOIN sys.objects o ON i.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE i.name IS NOT NULL
AND o.type = 'U'
AND i.fill_factor not in (0, 100)
ORDER BY i.fill_factor DESC, o.name
答案 2 :(得分:0)
非常感谢您的早期回复。 Sreenu131,你的建议对我来说非常好。
我只是改变了一行,以便整理所有数据库(系统数据库除外)
SELECT @command = 'IF ''?'' NOT IN (''msdb'', ''master'',''model'',''tempdb'' ) BEGIN USE ? EXEC ('''+ @Satetement+''') END ' +CHAR(13)+CHAR(10)
非常感谢!!!