SQL Server下实现利用SQL Server Agent Job对索引重建实现Balance Load
昨天工作中遇到这样一个场景,有个项目需要把某台服务器下所有的表和索引都启用数据压缩(data_compression=page),已经启用了的表和索引就不需要再压缩一次了。统计一下后发现要运行的REBUILD INDEX代码多达上万条,而整个服务器上的所有需要压缩的数据库对象大小加起来估计接近1TB。这种情况下如果把所有工作都交给一条脚本来完成,估计整个周末都跑不完。那么我们的想法就是用多个SQL Server Agent Job来做完成这个任务,分配单位是表(也就是说把同一张表的所有索引重建任务都分配给Job 1,这样避免出现不同Job间对同时间对同一张表的索引重建导致死锁问题),分配原则是按数据页面总大小依次分配,就像这样:
No Index_Name Pages Assign_To
1 Index1 10000 Job1
1 Index2 9000 Job2
1 Index3 8000 Job3
1 Index4 7000 Job1
.....
下面是实现代码:
/*
this script works to compress pages of tables of all database of the server,
skipping those which were compressed and system databases like master, msdb, tempdb, model
*/ /*first of all, get the datbase list to construct the sql**/ IF object_id('tempdb..#t') IS NOT NULL
BEGIN
DROP TABLE #t
END
GO CREATE TABLE #t(db SYSNAME, object_id INT, index_id INT)
GO IF object_id('tempdb..#t2') IS NOT NULL
BEGIN
DROP TABLE #t2
END
GO CREATE TABLE #t2(ID INT IDENTITY(1,1), db SYSNAME, stm VARCHAR(MAX), dpages INT, object_id INT, index_id INT)
GO DECLARE @db SYSNAME,
@sql VARCHAR(MAX) = '',
@sql2 VARCHAR(MAX) = '' DECLARE cur CURSOR FOR
SELECT name FROM sys.databases WHERE name not in ('master', 'msdb', 'tempdb', 'model') OPEN cur FETCH NEXT FROM cur INTO @db WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = @sql + 'UNION ALL select distinct '''+@db+''' db, object_id, index_id from [' + @db + '].sys.partitions(nolock) where data_compression_desc <> ''PAGE''' + CHAR(13);
SET @sql2 = @sql2 + 'UNION ALL SELECT '''+@db+''' as db, CASE id.type_desc WHEN ''HEAP'' THEN ''ALTER TABLE '+QUOTENAME(@db)+'.'' + QUOTENAME(sch.name) + ''.'' + QUOTENAME(ob.name) + '' REBUILD PARTITION = ALL WITH (DATA_COMPRESSION = PAGE);''
ELSE ''ALTER INDEX '' + QUOTENAME(id.name) + '' ON '+QUOTENAME(@db)+'.'' + QUOTENAME(sch.name) + ''.'' + QUOTENAME(ob.name) + '' REBUILD WITH (DATA_COMPRESSION = PAGE);'' END AS stm, syid.dpages, id.object_id, id.index_id
FROM ['+@db+'].sys.indexes id join
['+@db+'].sys.sysindexes syid(nolock) ON syid.id = id.object_id AND syid.indid = id.index_id join
['+@db+'].sys.objects ob(nolock) ON ob.object_id = id.object_id join
['+@db+'].sys.schemas sch(nolock) ON sch.schema_id = ob.schema_id join
#t non_compr on non_compr.object_id = id.object_id and non_compr.index_id = id.index_id
WHERE ob.type_desc = ''USER_TABLE'' ' + CHAR(13); FETCH NEXT FROM cur INTO @db
END CLOSE cur
DEALLOCATE cur SET @sql = RIGHT(@sql, LEN(@sql)-10) SET @sql2 = RIGHT(@sql2, LEN(@sql2)-10) --INSERT #t EXEC(@sql) /*table #t stores temp data queried from sys.partitions because I found that this DMV runs
slowly when joining other tables in some databases like DW. To avoid it, I store data in a temporary table.**/
INSERT #t EXEC(@sql) /*table #t2 works to output statements to rebuild indexes**/
INSERT #t2(db, stm, dpages, object_id, index_id) EXEC (@sql2) --SELECT * FROM #t2 IF OBJECT_ID('Stage.dbo.table1') IS NOT NULL
DROP TABLE Stage.dbo.table1
GO DECLARE @nbr_of_workers AS SMALLINT
SET @nbr_of_workers = 6; --actually @nbr_of_workers should be the number plus 1 ;WITH bal_load AS (
SELECT db, object_id, dpages as obj_dpages, ROW_NUMBER() OVER (PARTITION BY groupfactor ORDER BY dpages DESC) AS group_nbr FROM (
SELECT db, object_id, dpages, NTILE((SELECT COUNT(DISTINCT db+CAST(object_id AS VARCHAR)) FROM #t2)/@nbr_of_workers) OVER (ORDER BY dpages DESC) AS groupfactor FROM (
SELECT db, object_id, SUM(dpages) dpages FROM #t2 GROUP BY db, object_id) T) T) SELECT t.id, t.db, t.stm, t.dpages, t.object_id, t.index_id , bal_load.obj_dpages, bal_load.group_nbr, 0 AS compressed
INTO Stage.dbo.table1
FROM #t2 t JOIN bal_load ON bal_load.db = t.db AND bal_load.object_id = t.object_id
ORDER BY bal_load.group_nbr, bal_load.db, bal_load.obj_dpages DESC, bal_load.object_id CREATE UNIQUE CLUSTERED INDEX CLST_IX_table1 ON Stage.dbo.table1(ID);
GO
Stage.dbo.table1这张表存储了所有要run的命令,然后group_nbr这个栏位表明哪些命令属哪个job
然后在各个job的T-SQL代码里面就这样写:
IF EXISTS(SELECT * FROM Stage.dbo.table1(NOLOCK) WHERE compressed = 0 AND group_nbr=1)
BEGIN
IF OBJECT_ID('tempdb..#t') IS NOT NULL DROP TABLE #t
CREATE TABLE #t(row_nbr INT IDENTITY(1,1) PRIMARY KEY CLUSTERED, ID INT, stm VARCHAR(MAX)) DECLARE @cmd VARCHAR(MAX), @ID INT, @stm VARCHAR(MAX), @curr_row_nbr INT = 1, @max_row_nbr INT INSERT #t(ID, stm)
SELECT ID, stm
FROM Stage.dbo.table1(NOLOCK)
WHERE compressed = 0 AND group_nbr=1; SET @max_row_nbr = SCOPE_IDENTITY(); WHILE @curr_row_nbr <= @max_row_nbr
BEGIN
BEGIN TRY
SELECT @ID = ID, @stm = stm FROM #t WHERE row_nbr = @curr_row_nbr;
EXEC(@stm);
UPDATE Stage.dbo.table1 SET compressed = 1 WHERE ID = @ID;
SET @curr_row_nbr = @curr_row_nbr + 1;
END TRY
BEGIN CATCH
--SELECT ERROR_MESSAGE()
SET @curr_row_nbr = @curr_row_nbr + 1;
CONTINUE
END CATCH
END
END
搞定
SQL Server下实现利用SQL Server Agent Job对索引重建实现Balance Load的更多相关文章
- SQL Server中是否可以准确获取最后一次索引重建的时间?
在SQL Server中,我们能否找到索引的创建时间?最后一次索引重建(Index Rebuild)的时间? 最后一次索引重组(INDEX REORGANIZE)的时间呢? 答案是我们无法准确的找到 ...
- ORACLE11g下如何利用SQL DEVELOPER连接上数据库
最近在学习数据库的相关内容,在sqlplus敲了几天命令行窗口后,想尝试一下用sql developer 连接上数据库但一直没有实现.在网上查询了相关资料后现在终于弄好了,就来写下此篇博文与大家分享! ...
- PL/SQL Developer下设置“长SQL自己主动换行”
***********************************************声明*************************************************** ...
- mybatis的sql中使用$会出现sql注入示例
mybatis的sql中使用$会出现sql注入示例: 模拟简单登录场景: 页面代码: function login(){ //sql注入 var user = { username : "' ...
- SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变
前提 本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...
- 利用sql server直接创建日历
看到网上有高手直接用sql查询创建日历,也想自己动手实践一遍.笔者这里的实现和网上的都没有什么区别,思路也没有什么新意.觉得好玩,就把它记下来吧. 一.准备知识1.sql的with关键字关于with和 ...
- 利用本地SQL Server维护计划来维护SQL Database
On-Premise的SQL Server提供了维护计划来定期.定时的维护SQL Server.一般的做法是:定义SQL Server Agent Jobs,而后维护计划帮助我们定期.定时执行SQL ...
- 利用SQL Server 2008 R2创建自动备份计划
本文主要利用SQL Server 2008 R2自带的"维护计划"创建一个自动备份数据的任务. 首先,启动 Sql Management studio,确保"SQL Se ...
- Windows Server 2003 Sp2 下无法安装SQL Server 2008 Management Studio Express问题
Windows Server 2003 Sp2 下无法安装SQL Server 2008 Management Studio Express问题钉子 发表于 2010-5-22 1:42:51问题描述 ...
随机推荐
- 水王ID查找
一. 题目 1 三人行设计了一个灌水论坛.信息学院的学生都喜欢在上面交流灌水,传说在论坛上有一个“水王”,他不但喜欢发帖,还会回复其他ID发的每个帖子.坊间风闻该“水王”发帖数目超过了帖子数目的一半. ...
- Shell遍历文件的每一行[转载]
#!/bin/sh while read line do echo $line done < /home/jms/lab/input.txt
- 或许你不知道:ArrayList
ArrayList 底层以一个transient 线性数组来存储数据,它提供了无参构造方法,和有参构造方法,用户可以通过有参构造方法来初始化长度.如果不传参数,则默认调用无参构造器,数组默认长度为10 ...
- 三张图看遍Linux 性能监控、测试、优化工具
Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 ...
- 单点登录的原理与CAS技术的研究
1.什么是单点登录? 关于单点登录技术的说明参考文章:http://www.cnblogs.com/yupeng/archive/2012/05/24/2517317.html 一般来说,整个原理大家 ...
- LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面
// test20.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include< ...
- iNode for linux install
http://wenku.baidu.com/link?url=953T6GZCnaBzwr4YqPFUT4oOyYr4wyOnXlCLO1OUYZkaJWh2fTs634SM7ZpYiTKkpmYX ...
- A trip through the graphics pipeline 2011 Part 10(翻译)
之前的几篇翻译都烂尾了,这篇希望....能好些,恩,还有往昔呢. ------------------------------------------------------------- primi ...
- oom日志查看
这通常会触发 Linux 内核里的 Out of Memory (OOM) killer,OOM killer 会杀掉某个进程以腾出内存留给系统用,不致于让系统立刻崩溃.如果检查相关的日志文件(/va ...
- SEO优化的黑帽手法是否值得使用?
PR劫持 可能很多人也会听到说,什么网站权重越高越好,这也就是后面越来越多人都对谷歌的PR的宣传看的很重,自建站的都追求PR值,权重越高代表这个网站越受信任. 比如一个新站PR值为0,一个老站PR为6 ...