Advertisement
Guest User

Untitled

a guest
Apr 24th, 2017
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.71 KB | None | 0 0
  1. USE [msdb]
  2. GO
  3.  
  4. /****** Object: Job [RCSCareSysLive Reindex] Script Date: 04/24/2017 16:04:18 ******/
  5. BEGIN TRANSACTION
  6. DECLARE @ReturnCode INT
  7. SELECT @ReturnCode = 0
  8. /****** Object: JobCategory [Database Maintenance] Script Date: 04/24/2017 16:04:18 ******/
  9. IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'Database Maintenance' AND category_class=1)
  10. BEGIN
  11. EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'Database Maintenance'
  12. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  13.  
  14. END
  15.  
  16. DECLARE @jobId BINARY(16)
  17. EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'RCSCareSysLive Reindex',
  18. @enabled=1,
  19. @notify_level_eventlog=0,
  20. @notify_level_email=0,
  21. @notify_level_netsend=0,
  22. @notify_level_page=0,
  23. @delete_level=0,
  24. @description=N'Reindex RCSCAreSysLive database, Created By: David Fowler, Advanced on 13 Oct 2016',
  25. @category_name=N'Database Maintenance',
  26. @owner_login_name=N'sa', @job_id = @jobId OUTPUT
  27. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  28. /****** Object: Step [Reindex] Script Date: 04/24/2017 16:04:18 ******/
  29. EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Reindex',
  30. @step_id=1,
  31. @cmdexec_success_code=0,
  32. @on_success_action=3,
  33. @on_success_step_id=0,
  34. @on_fail_action=2,
  35. @on_fail_step_id=0,
  36. @retry_attempts=0,
  37. @retry_interval=0,
  38. @os_run_priority=0, @subsystem=N'TSQL',
  39. @command=N'--Database Reindex
  40. --Written By: David Fowler
  41. --Date: 10/02/2016
  42. --Updated 13/03/2017 - Reorganise indexes that can''t be rebuilt online
  43. DECLARE @MaxRunTime INT = 50
  44. DECLARE @AllowOnlineRebuild BIT = 0
  45. DECLARE @AllowReorg BIT = 1
  46. DECLARE @ReorgOnFail BIT = 0 --reorganise an index if online rebuild not possible
  47.  
  48. --size of index and fragmentation. Set ReindexGroupOrder = to the SizeRating
  49. IF OBJECT_ID(''tempdb..#indexstats'') IS NOT NULL DROP TABLE #indexstats
  50. IF OBJECT_ID(''tempdb..#indexpriority'') IS NOT NULL DROP TABLE #indexpriority
  51. IF OBJECT_ID(''tempdb..#TotalUsage'') IS NOT NULL DROP TABLE #TotalUsage
  52. TRUNCATE TABLE ADVANCED_utility..ReindexWork
  53.  
  54. DECLARE @RetryFlag BIT = 0
  55. DECLARE @StartTime AS DateTime
  56. SET @StartTime = GETDATE()
  57.  
  58.  
  59. SELECT SUM(user_seeks + user_scans + user_lookups) AS TotalUsage
  60. INTO #TotalUsage
  61. FROM sys.dm_db_index_usage_stats
  62.  
  63. --Get frgamentation statistics, this is running a SIMPLE scan. We''re only worried about the leaf nodes for the priority calculations
  64. SELECT objects.name AS TableName,
  65. objects.object_id AS object_id,
  66. indexes.index_id AS index_id,
  67. indexstats.page_count AS page_count,
  68. indexstats.index_level AS index_level,
  69. COUNT(indexes.name) AS IndexCount,
  70. AVG(indexstats.avg_fragmentation_in_percent) AS avg_fragmentation_in_percent,
  71. SUM(page_count) AS TotalPageCount,
  72. usage.user_seeks + usage.user_scans + usage.user_lookups AS usage,
  73. TotalUsage.TotalUsage,
  74. CAST((usage.user_seeks + usage.user_scans + usage.user_lookups) AS NUMERIC) / CAST(TotalUsage.TotalUsage AS NUMERIC) * 100 as usage_percentage
  75.  
  76. INTO #indexstats
  77. FROM sys.dm_db_index_physical_stats (DB_ID(), NULL,NULL,NULL,''sampled'') indexstats
  78. JOIN sys.objects objects ON objects.object_id = indexstats.object_id
  79. JOIN sys.indexes indexes ON indexes.index_id = indexstats.index_id
  80. AND indexes.object_id = indexstats.object_id
  81. JOIN sys.dm_db_index_usage_stats usage ON usage.object_id = objects.object_id
  82. AND usage.index_id = indexes.index_id,
  83.  
  84. #TotalUsage TotalUsage
  85. WHERE indexes.index_id != 0 --exclude any heaps
  86. AND indexes.is_disabled = 0 --exclude disabled indexes
  87. AND usage.database_id = DB_ID()
  88. GROUP BY objects.name, objects.object_id, indexes.index_id, indexstats.page_count, indexstats.index_level,usage.user_seeks,usage.user_scans,usage.user_lookups, TotalUsage
  89. ORDER BY avg_fragmentation_in_percent DESC
  90.  
  91. --Calculate priority ranking based on index size, we''re only interested in indexes with fragmentation over 20%
  92. SELECT
  93. CASE
  94. WHEN page_count < 1000 THEN 1
  95. WHEN page_count < 10000 THEN 2
  96. WHEN page_count < 50000 THEN 3
  97. WHEN page_count < 100000 THEN 4
  98. WHEN page_count >= 100000 THEN 5
  99. END AS SizeRating,
  100. CASE
  101. WHEN avg_fragmentation_in_percent < 10 THEN 1
  102. WHEN avg_fragmentation_in_percent < 30 THEN 2
  103. WHEN avg_fragmentation_in_percent < 60 THEN 3
  104. WHEN avg_fragmentation_in_percent < 80 THEN 4
  105. WHEN avg_fragmentation_in_percent >= 80 THEN 5
  106. END AS FragRating,
  107. NTILE(5) OVER (ORDER BY usage) AS UsageRating,
  108. page_count,
  109. (CAST(page_count AS NUMERIC) * 8)/1024/1024 AS sizeGB,
  110. avg_fragmentation_in_percent,
  111. usage,
  112. tables.name AS TableName,
  113. tables.object_id,
  114. indexes.index_id,
  115. indexes.name AS IndexName
  116. INTO #indexpriority
  117. FROM #indexstats
  118. JOIN sys.tables tables ON #indexstats.object_id = tables.object_id
  119. JOIN sys.indexes indexes ON indexes.index_id = #indexstats.index_id AND indexes.object_id = #indexstats.object_id
  120. WHERE avg_fragmentation_in_percent > 10
  121. AND #indexstats.index_level = 0
  122.  
  123.  
  124. --load into index work table
  125.  
  126. INSERT INTO ADVANCED_utility..ReindexWork
  127. SELECT *, SizeRating + FragRating + UsageRating AS OverallRating,
  128. CASE
  129. WHEN FragRating = 2 THEN ''ALTER INDEX ['' + indexname + ''] ON ['' + TableName + ''] REORGANIZE;'' --reorg any indexes with fragmentation < 30%
  130. ELSE ''ALTER INDEX ['' + indexname + ''] ON ['' + TableName + ''] REBUILD WITH (ONLINE = ON);''
  131. END AS ReIndexStatement,
  132. 0 AS complete,
  133. NULL,NULL,NULL
  134. FROM #indexpriority
  135. WHERE SizeRating != 1
  136. AND FragRating != 1
  137. AND UsageRating != 1
  138.  
  139.  
  140. --loop through each reindex in order of overallrating
  141.  
  142. DECLARE @object_id INT
  143. DECLARE @index_id INT
  144. DECLARE @IndexStmt VARCHAR(500)
  145. DECLARE @SizeGB INT
  146.  
  147. DECLARE reindex_cursor CURSOR FOR
  148. SELECT [object_id], index_id, ReindexStatement, SizeGB
  149. FROM ADVANCED_utility..ReindexWork
  150. ORDER BY OverallRating DESC
  151.  
  152. OPEN reindex_cursor
  153. FETCH NEXT FROM reindex_cursor INTO @object_id, @index_id, @IndexStmt, @SizeGB
  154.  
  155. WHILE @@FETCH_STATUS = 0
  156. AND DATEDIFF(MINUTE, @StartTime, GETDATE()) < @MaxRunTime --stop if job has run for longer than 4 hours
  157. BEGIN
  158.  
  159. --check available disk space
  160.  
  161. IF ((SELECT DISTINCT (volumestats.available_bytes/1024/1024/1024) + ((size*8/1024/1024) - (FILEPROPERTY(masterfiles.name, ''SpaceUsed'')*8/1024/1024))
  162. FROM sys.master_files masterfiles
  163. CROSS APPLY sys.dm_os_volume_stats(masterfiles.database_id, file_id) volumestats
  164. WHERE masterfiles.type = 0
  165. AND masterfiles.database_id = DB_ID()) > @SizeGB * 2)
  166.  
  167. BEGIN --if disk space ok, run reindex and log O code in work table
  168.  
  169. BEGIN TRY
  170. --set start time
  171. UPDATE ADVANCED_utility..ReindexWork
  172. SET starttime = GETDATE()
  173. WHERE @object_id = OBJECT_ID
  174. AND @index_id = index_id
  175.  
  176. --execute statement
  177. EXEC (@IndexStmt)
  178.  
  179. --PRINT @IndexStmt
  180. UPDATE ADVANCED_utility..ReindexWork
  181. SET complete = 1,
  182. stoptime = GETDATE()
  183. WHERE @object_id = OBJECT_ID
  184. AND @index_id = index_id
  185. END TRY
  186. BEGIN CATCH --log error in work table
  187.  
  188. --if error becase it can''t run an online index, run a reord instead
  189. IF ERROR_MESSAGE() LIKE ''An online operation cannot be performed for index%''
  190. BEGIN
  191. UPDATE ADVANCED_utility..ReindexWork
  192. SET complete = 4,
  193. ReIndexStatement = REPLACE(ReIndexStatement, ''REBUILD WITH (ONLINE = ON)'',''REORGANIZE'')
  194. WHERE @object_id = OBJECT_ID
  195. AND @index_id = index_id
  196.  
  197. SET @RetryFlag = 1
  198. END
  199. ELSE --for other errors, log error code 3 and error message
  200. BEGIN
  201. UPDATE ADVANCED_utility..ReindexWork
  202. SET complete = 3,
  203. error = ERROR_MESSAGE(),
  204. stoptime = GETDATE()
  205. WHERE @object_id = OBJECT_ID
  206. AND @index_id = index_id
  207. END
  208. END CATCH
  209.  
  210. --for indexes that couldn''t be rebuilt online, run a reorganise
  211.  
  212. IF @RetryFlag = 1 --if retry flag set, rerun reindex as reorg
  213. BEGIN
  214. SET @RetryFlag = 0
  215.  
  216. BEGIN TRY
  217. SELECT @IndexStmt = ReIndexStatement
  218. FROM ADVANCED_utility..ReindexWork
  219. WHERE @object_id = OBJECT_ID
  220. AND @index_id = index_id
  221.  
  222. --execute statement
  223. EXEC (@IndexStmt)
  224.  
  225. --PRINT @IndexStmt
  226. UPDATE ADVANCED_utility..ReindexWork
  227. SET complete = 1,
  228. stoptime = GETDATE()
  229. WHERE @object_id = OBJECT_ID
  230. AND @index_id = index_id
  231.  
  232. END TRY
  233.  
  234. BEGIN CATCH
  235. UPDATE ADVANCED_utility..ReindexWork
  236. SET complete = 3,
  237. error = ERROR_MESSAGE(),
  238. stoptime = GETDATE()
  239. WHERE @object_id = OBJECT_ID
  240. AND @index_id = index_id
  241. END CATCH
  242. END
  243. END
  244. ELSE BEGIN --if disk space low, log skip code in work table
  245.  
  246. UPDATE ADVANCED_utility..ReindexWork
  247. SET complete = 2,
  248. error = ''Skipped Due To Low Disk Space'',
  249. stoptime = GETDATE()
  250. WHERE @object_id = OBJECT_ID
  251. AND @index_id = index_id
  252.  
  253. END
  254.  
  255. FETCH NEXT FROM reindex_cursor INTO @object_id, @index_id, @IndexStmt,@SizeGB
  256.  
  257. END
  258.  
  259. CLOSE reindex_cursor
  260. DEALLOCATE reindex_cursor
  261.  
  262.  
  263.  
  264. ----retry indexes that couldn''t be rebuilt offline
  265. --IF (@AllowOnlineRebuild = 1)
  266. --BEGIN
  267.  
  268. -- UPDATE ADVANCED_utility..ReindexWork
  269. -- SET ReIndexStatement = REPLACE(ReIndexStatement, ''REBUILD WITH (ONLINE = ON)'',''REBUILD WITH (ONLINE = OFF)'')
  270. -- WHERE error LIKE ''%The operation must be performed offline.''
  271.  
  272. -- DECLARE reindex_cursor CURSOR FOR
  273. -- SELECT [object_id], index_id, ReindexStatement, SizeGB
  274. -- FROM ADVANCED_utility..ReindexWork
  275. -- WHERE error LIKE ''%The operation must be performed offline.''
  276. -- ORDER BY OverallRating DESC
  277.  
  278. -- OPEN reindex_cursor
  279. -- FETCH NEXT FROM reindex_cursor INTO @object_id, @index_id, @IndexStmt, @SizeGB
  280.  
  281. -- WHILE @@FETCH_STATUS = 0
  282. -- AND DATEDIFF(hh, @StartTime, GETDATE()) < @MaxRunTime --stop if job has run for longer than 4 hours
  283. -- BEGIN
  284.  
  285. -- --check available disk space
  286.  
  287. -- IF ((SELECT DISTINCT (volumestats.available_bytes/1024/1024/1024) + ((size*8/1024/1024) - (FILEPROPERTY(masterfiles.name, ''SpaceUsed'')*8/1024/1024))
  288. -- FROM sys.master_files masterfiles
  289. -- CROSS APPLY sys.dm_os_volume_stats(masterfiles.database_id, file_id) volumestats
  290. -- WHERE masterfiles.type = 0
  291. -- AND masterfiles.database_id = DB_ID()) > @SizeGB * 2)
  292.  
  293. -- BEGIN --if disk space ok, run reindex and log O code in work table
  294.  
  295. -- BEGIN TRY
  296. -- --set start time
  297. -- UPDATE ADVANCED_utility..ReindexWork
  298. -- SET starttime = GETDATE()
  299. -- WHERE @object_id = OBJECT_ID
  300. -- AND @index_id = index_id
  301.  
  302. -- --execute statement
  303. -- EXEC (@IndexStmt)
  304.  
  305. -- --PRINT @IndexStmt
  306. -- UPDATE ADVANCED_utility..ReindexWork
  307. -- SET complete = 1,
  308. -- stoptime = GETDATE()
  309. -- WHERE @object_id = OBJECT_ID
  310. -- AND @index_id = index_id
  311. -- END TRY
  312. -- BEGIN CATCH --log error in work table
  313. -- UPDATE ADVANCED_utility..ReindexWork
  314. -- SET complete = 3,
  315. -- error = ERROR_MESSAGE(),
  316. -- stoptime = GETDATE()
  317. -- WHERE @object_id = OBJECT_ID
  318. -- AND @index_id = index_id
  319. -- END CATCH
  320. -- END
  321. -- ELSE BEGIN --if disk space low, log skip code in work table
  322.  
  323. -- UPDATE ADVANCED_utility..ReindexWork
  324. -- SET complete = 2,
  325. -- error = ''Skipped Due To Low Disk Space'',
  326. -- stoptime = GETDATE()
  327. -- WHERE @object_id = OBJECT_ID
  328. -- AND @index_id = index_id
  329.  
  330. -- END
  331.  
  332. -- FETCH NEXT FROM reindex_cursor INTO @object_id, @index_id, @IndexStmt,@SizeGB
  333.  
  334. -- END
  335.  
  336. -- CLOSE reindex_cursor
  337. -- DEALLOCATE reindex_cursor
  338. --END
  339.  
  340.  
  341. --update history table
  342.  
  343. INSERT INTO ADVANCED_utility..ReindexHistory
  344. SELECT page_count, avg_fragmentation_in_percent, tableName, indexName, OverallRating, ReindexStatement, complete, error, starttime, stoptime
  345. FROM ADVANCED_utility..[ReindexWork]
  346. WHERE complete != 0',
  347. @database_name=N'RCSCareSysLive',
  348. @flags=0
  349. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  350. /****** Object: Step [Update Stats] Script Date: 04/24/2017 16:04:18 ******/
  351. EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Update Stats',
  352. @step_id=2,
  353. @cmdexec_success_code=0,
  354. @on_success_action=1,
  355. @on_success_step_id=0,
  356. @on_fail_action=2,
  357. @on_fail_step_id=0,
  358. @retry_attempts=0,
  359. @retry_interval=0,
  360. @os_run_priority=0, @subsystem=N'TSQL',
  361. @command=N'DECLARE @stmt VARCHAR(256)
  362. DECLARE @rowmod INT
  363.  
  364. DECLARE UpdateStatsCurr CURSOR FOR
  365. SELECT DISTINCT ''UPDATE STATISTICS '' + QUOTENAME(OBJECT_NAME(sysindexes.id)) AS STMT
  366. FROM sys.sysindexes sysindexes
  367. JOIN sys.indexes indexes ON sysindexes.id = indexes.object_id AND
  368. sysindexes.indid = indexes.index_id
  369. JOIN sys.tables tables ON indexes.object_id = tables.object_id
  370. WHERE indexes.index_id > 0
  371. AND rowmodctr > 10000
  372.  
  373. OPEN UpdateStatsCurr
  374. FETCH NEXT FROM UpdateStatsCurr INTO @stmt
  375.  
  376. WHILE @@FETCH_STATUS = 0
  377. BEGIN
  378. EXEC(@stmt)
  379. PRINT @stmt
  380. FETCH NEXT FROM UpdateStatsCurr INTO @stmt
  381. END
  382.  
  383. CLOSE UpdateStatsCurr
  384. DEALLOCATE UpdateStatsCurr
  385. ',
  386. @database_name=N'RCSCareSysLive',
  387. @flags=0
  388. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  389. EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
  390. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  391. EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'nightly @ 2am',
  392. @enabled=1,
  393. @freq_type=4,
  394. @freq_interval=1,
  395. @freq_subday_type=1,
  396. @freq_subday_interval=0,
  397. @freq_relative_interval=0,
  398. @freq_recurrence_factor=0,
  399. @active_start_date=20161013,
  400. @active_end_date=99991231,
  401. @active_start_time=20000,
  402. @active_end_time=235959,
  403. @schedule_uid=N'5a95157d-1cb0-468c-9e72-a94318e07b1a'
  404. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  405. EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
  406. IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
  407. COMMIT TRANSACTION
  408. GOTO EndSave
  409. QuitWithRollback:
  410. IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
  411. EndSave:
  412.  
  413. GO
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement