-
-
Notifications
You must be signed in to change notification settings - Fork 98
/
Copy pathОбслуживание статистик для всех баз данных (пример).sql
137 lines (121 loc) · 4.64 KB
/
Обслуживание статистик для всех баз данных (пример).sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
DECLARE @DB_Name varchar(100)
DECLARE @Command nvarchar(max)
DECLARE database_cursor CURSOR FOR
SELECT db.[name]
FROM MASTER.sys.sysdatabases db
-- Исключаем системные базы данных, а также те базы данных,
-- для которых имются собственные планы обслуживания
WHERE NOT db.[name] IN (
-- Системные базы данных
'master',
'model',
'msdb',
'tempdb'
)
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO @DB_Name
WHILE @@FETCH_STATUS = 0
BEGIN
-- Скрипт обслуживания индекса взят из "Обслуживание статистики (расширенный).sql"
SELECT @Command = 'USE ' + @DB_Name + '; '
+ '
SET NOCOUNT ON;
DECLARE -- Настройки
-- Текущее время
@timeNow TIME = CAST(GETDATE() AS TIME),
-- Начало доступного интервала времени обслуживания
@timeFrom TIME = CAST(''22:00:00'' AS TIME),
-- Окончание доступного интервала времени обслуживания
@timeTo TIME = CAST(''07:00:00'' AS TIME);
-- Проверка доступен ли запуск обслуживания в текущее время
IF (@timeTo >= @timeFrom) BEGIN
IF(NOT (@timeFrom <= @timeNow AND @timeTo >= @timeNow))
RETURN;
END ELSE BEGIN
IF(NOT ((@timeFrom <= @timeNow AND ''23:59:59'' >= @timeNow)
OR (@timeTo >= @timeNow AND ''00:00:00'' <= @timeNow)))
RETURN;
END
DECLARE -- Служебные переменные
@TableName SYSNAME
,@IndexName SYSNAME
,@Operation NVARCHAR(128) = ''UPDATE STATISTICS''
,@RunDate DATETIME
,@StartDate DATETIME
,@FinishDate DATETIME
,@SQL NVARCHAR(500);
DECLARE todo CURSOR FOR
SELECT
''
UPDATE STATISTICS ['' + SCHEMA_NAME([o].[schema_id]) + ''].['' + [o].[name] + ''] ['' + [s].[name] + '']
WITH FULLSCAN'' + CASE WHEN [s].[no_recompute] = 1 THEN '', NORECOMPUTE'' ELSE '''' END + '';''
, [o].[name]
, [s].[name] AS [stat_name]
FROM (
SELECT
[object_id]
,[name]
,[stats_id]
,[no_recompute]
,[last_update] = STATS_DATE([object_id], [stats_id])
,[auto_created]
FROM sys.stats WITH(NOLOCK)
WHERE [is_temporary] = 0) s
LEFT JOIN sys.objects o WITH(NOLOCK)
ON [s].[object_id] = [o].[object_id]
LEFT JOIN (
SELECT
[p].[object_id]
,[p].[index_id]
,[total_pages] = SUM([a].[total_pages])
FROM sys.partitions p WITH(NOLOCK)
JOIN sys.allocation_units a WITH(NOLOCK) ON [p].[partition_id] = [a].[container_id]
GROUP BY
[p].[object_id]
,[p].[index_id]) p
ON [o].[object_id] = [p].[object_id] AND [p].[index_id] = [s].[stats_id]
LEFT JOIN sys.sysindexes si
ON [si].[id] = [s].[object_id] AND [si].[indid] = [s].[stats_id]
WHERE [o].[type] IN (''U'', ''V'')
AND [o].[is_ms_shipped] = 0
AND [rowmodctr] > 0
ORDER BY [rowmodctr] DESC;
OPEN todo;
WHILE 1=1
BEGIN
FETCH NEXT FROM todo INTO @SQL, @TableName, @IndexName;
IF @@FETCH_STATUS != 0
BREAK;
-- Проверка доступен ли запуск обслуживания в текущее время
IF (@timeTo >= @timeFrom) BEGIN
IF(NOT (@timeFrom <= @timeNow AND @timeTo >= @timeNow))
RETURN;
END ELSE BEGIN
IF(NOT ((@timeFrom <= @timeNow AND ''23:59:59'' >= @timeNow)
OR (@timeTo >= @timeNow AND ''00:00:00'' <= @timeNow)))
RETURN;
END
SET @StartDate = GetDate();
BEGIN TRY
EXEC sp_executesql @SQL;
SET @FinishDate = GetDate();
-- Здесь можно сохранить информацию о проведенной операции обслуживания
-- @TableName - имя таблицы
-- @IndexName - имя индекса
-- @Operation - вид операции (перестроение или реорганизация)
-- @RunDate - дата запуска операции обслуживания (начало запуска всего скрипта)
-- @StartDate - начало конкретно этой операции
-- @FinishDate - завершение конкретно этой операции
END TRY
BEGIN CATCH
PRINT CAST(Error_message() AS NVARCHAR(250)) + '' '' + CAST(Error_Number() AS NVARCHAR(250)) + '' '' + CAST(Error_Line() AS NVARCHAR(250));
END CATCH
END
CLOSE todo;
DEALLOCATE todo;
'
EXEC sp_executesql @Command
FETCH NEXT FROM database_cursor INTO @DB_Name
END
CLOSE database_cursor
DEALLOCATE database_cursor