【发布时间】:2016-01-05 22:21:12
【问题描述】:
使用 SQL Server 2012。
使用为每个数据库存储的系统视图,我想保留整个实例中所有索引的索引行为摘要。下面的代码收集了一些统计数据并将它们放在一个表中以供以后使用。问题是,我不得不使用游标来遍历实例中的数据库。任何人都可以提出一个更好的方法来做到这一点而不必使用光标?
USE Master
GO
-- If the procedure already exists then update it.
IF OBJECT_ID('sp_index_stats') IS NOT NULL
DROP PROCEDURE sp_index_stats
GO
CREATE PROCEDURE sp_index_stats AS
DECLARE @dbname NVARCHAR(128)
DECLARE @finalSQL NVARCHAR(1024)
-- Results of the query are put into a table in Demo_DB.
-- So empty it now for the new results.
TRUNCATE TABLE Demo_DB.dbo.index_stats
-- Use a cursor to get a list of all the tables in the instance.
DECLARE database_cursor CURSOR LOCAL FOR
SELECT name
FROM Master.dbo.sysdatabases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO @dbname
WHILE @@FETCH_STATUS = 0
BEGIN
-- Each database will contain the same structue, so I need
-- to create a standard query just changing the database name.
SET @finalSQL = 'INSERT INTO Demo_DB.dbo.index_stats '
-- Sort out the select statement.
SET @finalSQL = @finalSQL + 'SELECT sdb.name, st.name, si.name, si.type_desc, '
SET @finalSQL = @finalSQL + 'si.is_primary_key, si.fill_factor, '
SET @finalSQL = @finalSQL + 'sd.user_scans, sd.last_user_scan, '
SET @finalSQL = @finalSQL + 'sd.user_updates, sd.last_user_update '
-- The 'from' and 'joins' need to be adjusted slightly for each databse.
SET @finalSQL = @finalSQL + 'FROM ' + @dbname + '.sys.tables st '
SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.indexes si ON (si.object_id = st.object_id) '
SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.dm_db_index_usage_stats sd ON (si.object_id = sd.object_id) '
SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.databases sdb ON (sdb.database_id = sd.database_id) ;'
-- Ok, let's run that...
EXEC (@finalSQL)
-- Get the next database in the instance..,
FETCH NEXT FROM database_cursor INTO @dbname
END
CLOSE database_cursor
DEALLOCATE database_cursor
GO
问候,
JC.
【问题讨论】:
-
这是一个名为 sp_MSforeachdb 的未记录过程。然而,似乎其他 T-SQL 程序员认为不应该使用它:stackoverflow.com/questions/20131930/… 游标的替代方法是使用
While,如下所述:stackoverflow.com/questions/61967/… -
光标有什么问题?你认为另一种方法会更快吗?为什么?此过程在运行时的主要成本将是从每个数据库中单独提取所有统计信息/元数据,而不是围绕生成这些单独查询的脚手架。
-
@AaronBertrand:我不认为循环比游标更好。我也不相信相反的情况。但据我所知,网络上关于这个话题的讨论有些争议:一些支持游标,一些支持循环with table variables and PK,还有一些说这取决于具体情况(服务器版本、设置、音量等)。 James 要求提供一个光标的替代方案,我让他知道了一个替代方案(同时没有评估它)。我希望没关系。
-
@Ralph 这只是一个常见的误解,即 while 循环比游标快。是的,它是一种替代品,就像红色法拉利是黄色法拉利的替代品一样。
标签: sql-server tsql