Mar*_*lli 3 sql-server statistics index-statistics
嗨,我一直在编写一个脚本来更新我所有数据库上所有表的统计信息。这个想法是稍后对其进行参数化,但作为一个快速解决方案,今天不想实施Ola 的脚本,请按照下面的脚本进行操作。
我已经在几台服务器上对其进行了测试,但在我安排它在周日早上在实时服务器上运行之前,想获得一些想法并与您分享。
SET NOCOUNT ON
DECLARE @DBS TABLE (I INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
DBNAME SYSNAME NOT NULL )
DECLARE @I INT
,@Z INT
,@SQL VARCHAR(1008)
,@j INT
,@Y INT
,@MYDB SYSNAME
INSERT INTO @DBS
SELECT s.name
FROM sys.databases s
INNER JOIN SYS.master_files F ON S.DATABASE_ID = F.database_id AND F.data_space_id = 1
WHERE S.STATE = 0 -- online
AND S.database_id > 3 -- exclude master, tempdb and model -- I left msdb
AND S.is_read_only = 0 -- read/write
AND S.user_access = 0 -- multi_user
AND S.NAME NOT IN ('TableBackups',
'Troubleshooting')
ORDER BY F.SIZE DESC
SELECT @Z = @@ROWCOUNT
SELECT @I = 1
WHILE @I <= @z BEGIN
BEGIN TRY DROP TABLE #T END TRY BEGIN CATCH END CATCH
CREATE TABLE #T( I INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED, MYSQL VARCHAR(1008) NOT NULL )
SELECT @MYDB = QUOTENAME (S.DBNAME )
,@SQL = 'USE ' + QUOTENAME (S.DBNAME ) + ';' + CHAR(13) + '
' + CHAR(13) +
'INSERT INTO #T(MYSQL) SELECT ''UPDATE STATISTICS '' + QUOTENAME(NAME) FROM SYS.TABLES WHERE TYPE = ''U'' ' + CHAR(13)
FROM @DBS s
WHERE s.I = @I
PRINT CAST (@SQL AS NTEXT)
BEGIN TRY
EXEC (@SQL)
SELECT @Y = @@ROWCOUNT
END TRY
BEGIN CATCH
SELECT @Y = 0
END CATCH
SELECT @J = 1
WHILE @J <= @y BEGIN
SELECT @SQL = 'USE ' + @MYDB + ';' + CHAR(13) + MYSQL
FROM #T
WHERE I= @J
BEGIN TRY
EXEC (@SQL)
END TRY
BEGIN CATCH
END CATCH
PRINT CAST (@SQL AS NTEXT)
SELECT @J = @J + 1
END
SELECT @I = @I +1
END /*WHILE*/
Run Code Online (Sandbox Code Playgroud)
马上,您的脚本将完全忽略架构,因此它会失败,除非您的所有生产服务器仅dbo显式用作所有表的命名空间(并且没有人拥有除 之外的默认架构dbo)。您NTEXT似乎也无缘无故地使用了已弃用的数据类型 ( )。此外,我不认为WHERE针对 sys.tables的条款是必要的(我不知道除了 a 之外U还有什么)。不知道你为什么要按文件大小排序;如果您首先处理最大的数据库,则该作业不会完成得更快(如果data_space_id = 1.
最后,我想知道盲目更新整个实例中每个数据库中每个表的统计信息是否真的明智,无论大小如何......以及为什么您不费心检查索引视图,这也需要维护。如果添加一些逻辑来排除任何不需要的表,则可以节省大量工作。
我的部分解决方案
这段代码会稍微难以维护,没有TRY/CATCH你的包装器,也没有添加任何关于实际追求哪些表的额外逻辑,但是因为我从动态 SQL 中获得自动化任务(和真的很喜欢在这个网站上没有水平或垂直滚动条的解决方案),给你。当您对输出感到满意时,请注释打印并取消注释 exec。
DECLARE @sql NVARCHAR(MAX) = N'', @stats NVARCHAR(MAX) = N'';
SELECT @sql += N'EXEC ' + QUOTENAME(name) + '.sys.sp_executesql @stats;'
FROM sys.databases
WHERE [state] = 0 AND user_access = 0; -- and your other filters
SET @stats = N'DECLARE @inner NVARCHAR(MAX) = N'''';
SELECT @inner += CHAR(10) + N''UPDATE STATISTICS ''
+ QUOTENAME(s.name) + ''.'' + QUOTENAME(t.name) + '';''
FROM sys.tables AS t
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id];
PRINT CHAR(10) + DB_NAME() + CHAR(10) + @inner;
--EXEC sys.sp_executesql @inner;'
EXEC [master].sys.sp_executesql @sql, N'@stats NVARCHAR(MAX)', @stats;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6733 次 |
| 最近记录: |