<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments for SQL Fool</title>
	<atom:link href="http://sqlfool.com/comments/feed/" rel="self" type="application/rss+xml" />
	<link>http://sqlfool.com</link>
	<description>Adventures in SQL Tuning - a blog for the rest of us</description>
	<lastBuildDate>Thu, 04 Feb 2010 08:21:02 -0700</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>Comment on Filtered Indexes Work-Around by Jerry</title>
		<link>http://sqlfool.com/2010/02/filtered-indexes-work-around/comment-page-1/#comment-5061</link>
		<dc:creator>Jerry</dc:creator>
		<pubDate>Thu, 04 Feb 2010 08:21:02 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1307#comment-5061</guid>
		<description>Ok, that makes sense.  But just for the record, I received the error today using a join hint in the OPTION statement.</description>
		<content:encoded><![CDATA[<p>Ok, that makes sense.  But just for the record, I received the error today using a join hint in the OPTION statement.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Filtered Indexes Work-Around by Michelle Ufford</title>
		<link>http://sqlfool.com/2010/02/filtered-indexes-work-around/comment-page-1/#comment-5059</link>
		<dc:creator>Michelle Ufford</dc:creator>
		<pubDate>Wed, 03 Feb 2010 22:44:45 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1307#comment-5059</guid>
		<description>Hi Alex,

Yes, that works too!  I&#039;ll edit my post with your suggestion too.  Thank you.  :)

Michelle</description>
		<content:encoded><![CDATA[<p>Hi Alex,</p>
<p>Yes, that works too!  I&#8217;ll edit my post with your suggestion too.  Thank you.  <img src='http://sqlfool.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Michelle</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Filtered Indexes Work-Around by Michelle Ufford</title>
		<link>http://sqlfool.com/2010/02/filtered-indexes-work-around/comment-page-1/#comment-5058</link>
		<dc:creator>Michelle Ufford</dc:creator>
		<pubDate>Wed, 03 Feb 2010 22:43:34 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1307#comment-5058</guid>
		<description>Hi Jerry,

I actually mispoke (mistyped?) a little.  I thought the error message was returned that way because it was called via stored proc, but really you would get the same error message if you just try to force the hint in an ad-hoc query, too.  

You receive the error message because Query Optimizer, sometimes correctly and sometimes incorrectly, perceives that it will be unable to fulfill the request using the index you specify.  The only case I&#039;ve ever seen this in (so far) has been a filtered index.  Hopefully that helps, and good luck!  :)

Michelle</description>
		<content:encoded><![CDATA[<p>Hi Jerry,</p>
<p>I actually mispoke (mistyped?) a little.  I thought the error message was returned that way because it was called via stored proc, but really you would get the same error message if you just try to force the hint in an ad-hoc query, too.  </p>
<p>You receive the error message because Query Optimizer, sometimes correctly and sometimes incorrectly, perceives that it will be unable to fulfill the request using the index you specify.  The only case I&#8217;ve ever seen this in (so far) has been a filtered index.  Hopefully that helps, and good luck!  <img src='http://sqlfool.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Michelle</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Filtered Indexes Work-Around by Alex Kuznetsov</title>
		<link>http://sqlfool.com/2010/02/filtered-indexes-work-around/comment-page-1/#comment-5057</link>
		<dc:creator>Alex Kuznetsov</dc:creator>
		<pubDate>Wed, 03 Feb 2010 22:22:24 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1307#comment-5057</guid>
		<description>Hi Michelle,

I think that if you explicitly tell the optimizer that your parameter fits into the filter. Instead of:

SELECT DISTINCT myData
FROM dbo.filteredIndexTest
WHERE myDate &gt;= @myDate1;

let us try this:

SELECT DISTINCT myData
FROM dbo.filteredIndexTest
WHERE myDate &gt;= @myDate1
AND myDate&gt;&#039;theThresholdInMyFilteredIndex&#039;

What do you think, Michelle?</description>
		<content:encoded><![CDATA[<p>Hi Michelle,</p>
<p>I think that if you explicitly tell the optimizer that your parameter fits into the filter. Instead of:</p>
<p>SELECT DISTINCT myData<br />
FROM dbo.filteredIndexTest<br />
WHERE myDate &gt;= @myDate1;</p>
<p>let us try this:</p>
<p>SELECT DISTINCT myData<br />
FROM dbo.filteredIndexTest<br />
WHERE myDate &gt;= @myDate1<br />
AND myDate&gt;&#8217;theThresholdInMyFilteredIndex&#8217;</p>
<p>What do you think, Michelle?</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Filtered Indexes Work-Around by Jerry</title>
		<link>http://sqlfool.com/2010/02/filtered-indexes-work-around/comment-page-1/#comment-5056</link>
		<dc:creator>Jerry</dc:creator>
		<pubDate>Wed, 03 Feb 2010 21:53:02 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1307#comment-5056</guid>
		<description>Ok, in a freakish coincidence, I got the same error today for the very first time.  Wow.  Your post concentrated on why the sproc was not using the filtered index, and how to get it to use the index, which, of course, is valuable information.

However, I am much more interested in what causes this error in the first place. You state, &quot;...since this was a stored procedure, I was receiving the following error message...&quot;  implying this is due to sprocs.  However, we&#039;ve been using index hints in sprocs for years, and have never received this error. I am curious why I am getting it now all of a sudden on one specific sproc.  Do you or any of your readers have insight on that?

Thanks!</description>
		<content:encoded><![CDATA[<p>Ok, in a freakish coincidence, I got the same error today for the very first time.  Wow.  Your post concentrated on why the sproc was not using the filtered index, and how to get it to use the index, which, of course, is valuable information.</p>
<p>However, I am much more interested in what causes this error in the first place. You state, &#8220;&#8230;since this was a stored procedure, I was receiving the following error message&#8230;&#8221;  implying this is due to sprocs.  However, we&#8217;ve been using index hints in sprocs for years, and have never received this error. I am curious why I am getting it now all of a sudden on one specific sproc.  Do you or any of your readers have insight on that?</p>
<p>Thanks!</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Index Defrag Script, v3.0 by Dale Langham</title>
		<link>http://sqlfool.com/2009/06/index-defrag-script-v30/comment-page-2/#comment-5055</link>
		<dc:creator>Dale Langham</dc:creator>
		<pubDate>Tue, 02 Feb 2010 16:22:15 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1072#comment-5055</guid>
		<description>After running the script, you should run the following command to analyze and re-index the entire database:
EXEC dbo.p_maint_ExecuteMaintTasks @PeriodLength = 1
By passing @PeriodLength = 1, the procedure will perform all maintenance tasks in a single execution rather than dividing them up across multiple executions.
To set up recurring maintenance, you need a SQL Agent job that runs p_maint_ExecuteMaintTasks on a regular basis (if using the default settings, daily).  No parameters are necessary to run this stored procedure with default settings.  Using default settings, the procedure will divide all index maintenance tasks over a 7-day period with a near equal as possible load each day.
The stored procedure breaks the maintenance into two main steps: scheduling and execution.  The scheduling phase runs DBCC SHOWCONTIG WITH FAST to determine which indexes need to be defragmented and approximately how much work this will be.  It applies several layers of logic including a fragmentation threshold (default 10% logical fragmentation) and eliminating duplicate defrag operations due to non-clustered/clustered indexes on the same table.  For indexes where defragmentation isn’t needed, it schedules an update statistics operation.
The scheduling phase also estimates the approximate relative cost of each operation and attempts to assign each operation to a specific interval within the maintenance period.  By default, the maintenance period is 7 days long, and each period is one day.  The scheduling phase runs once per period while the execution phase runs once per interval.  (So by default, scheduling occurs weekly while maintenance execution occurs daily.)  The results of the scheduling phase are stored in the DBMaint_Task table.</description>
		<content:encoded><![CDATA[<p>After running the script, you should run the following command to analyze and re-index the entire database:<br />
EXEC dbo.p_maint_ExecuteMaintTasks @PeriodLength = 1<br />
By passing @PeriodLength = 1, the procedure will perform all maintenance tasks in a single execution rather than dividing them up across multiple executions.<br />
To set up recurring maintenance, you need a SQL Agent job that runs p_maint_ExecuteMaintTasks on a regular basis (if using the default settings, daily).  No parameters are necessary to run this stored procedure with default settings.  Using default settings, the procedure will divide all index maintenance tasks over a 7-day period with a near equal as possible load each day.<br />
The stored procedure breaks the maintenance into two main steps: scheduling and execution.  The scheduling phase runs DBCC SHOWCONTIG WITH FAST to determine which indexes need to be defragmented and approximately how much work this will be.  It applies several layers of logic including a fragmentation threshold (default 10% logical fragmentation) and eliminating duplicate defrag operations due to non-clustered/clustered indexes on the same table.  For indexes where defragmentation isn’t needed, it schedules an update statistics operation.<br />
The scheduling phase also estimates the approximate relative cost of each operation and attempts to assign each operation to a specific interval within the maintenance period.  By default, the maintenance period is 7 days long, and each period is one day.  The scheduling phase runs once per period while the execution phase runs once per interval.  (So by default, scheduling occurs weekly while maintenance execution occurs daily.)  The results of the scheduling phase are stored in the DBMaint_Task table.</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Index Defrag Script, v3.0 by Dale Langham</title>
		<link>http://sqlfool.com/2009/06/index-defrag-script-v30/comment-page-2/#comment-5054</link>
		<dc:creator>Dale Langham</dc:creator>
		<pubDate>Tue, 02 Feb 2010 16:20:11 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1072#comment-5054</guid>
		<description>Hi,
Not sure where I had this script from, but I have been using it for ages now, basically it defrags indexes over a period of 7 days to spread the load, but for some reason it doesn&#039;t like multiple schemas, as it adds dbo to all tables found etc... any ideas to make this work for all schemas would be great:

IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#039;dbo.DBMaint_Task&#039;) AND xtype = &#039;U&#039;)
BEGIN
	DROP TABLE dbo.DBMaint_Task
END
GO

CREATE TABLE dbo.DBMaint_Task(
	MaintTaskId		int		NOT NULL	IDENTITY(1, 1),
	Interval		int		NOT NULL,
	Command			nvarchar(4000)	NOT NULL,
	ItemWork		numeric(10,2)	NOT NULL,
	CompletedDatetime	datetime	NULL
	CONSTRAINT PK_DBMaint_Task PRIMARY KEY CLUSTERED(MaintTaskID)
)
GO

IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#039;dbo.p_maint_ScheduleMaintTasks&#039;) AND xtype = &#039;P&#039;)
BEGIN
	DROP PROCEDURE dbo.p_maint_ScheduleMaintTasks
END
GO

CREATE PROCEDURE dbo.p_maint_ScheduleMaintTasks
	@PeriodLength		int,		-- Number of intervals in a period
	@IndexRebuildThreshold	int	= 10	-- Maximum LogicalFragmentation value allowed before an index is rebuilt
AS

DECLARE @WorkPerIntervalGoal 	numeric(10,2)
DECLARE @CurrentInterval	int
DECLARE @RowsUpdated		int
DECLARE @MainTaskId		int

SET NOCOUNT ON

IF @PeriodLength = @IndexRebuildThreshold
	AND
	ObjectId  OBJECT_ID(&#039;dbo.DBMaint_Task&#039;)


-- If we rebuild a clustered index, we don&#039;t need to rebuild 
-- any nonclustered indexes on the same table
DELETE FROM
	rc1
FROM
	#ReindexCandidate rc1
INNER JOIN
	#ReindexCandidate rc2
	ON(
		rc1.ObjectId = rc2.ObjectId
	)
WHERE
	rc2.IndexID = 1 -- IndexID = 1 means the clustered index
	AND
	rc1.IndexID  1


TRUNCATE TABLE dbo.DBMaint_Task

INSERT INTO dbo.DBMaint_Task(
	Interval,
	Command,
	ItemWork)
SELECT
	-1 AS Interval,
	N&#039;DBCC DBREINDEX(&#039;&#039;&#039; + USER_NAME(OBJECTPROPERTY(rc1.ObjectId, &#039;OwnerId&#039;)) + N&#039;.&#039; + rc1.ObjectName + N&#039;&#039;&#039;&#039; + 
		CASE IndexId WHEN 1 THEN N&#039;&#039; ELSE N&#039;, &#039;&#039;&#039; + IndexName + N&#039;&#039;&#039;&#039; END + N&#039;)&#039; AS Command,
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = rc1.ObjectId) AS ItemWork
FROM
	#ReindexCandidate rc1

-- Find all tables that we&#039;re not doing a clustered index rebuild on
INSERT INTO dbo.DBMaint_Task(
	Interval,
	Command,
	ItemWork)
SELECT
	-1 AS Interval,
	N&#039;UPDATE STATISTICS [&#039; + USER_NAME(uid) + N&#039;].[&#039; + so1.name + N&#039;] WITH FULLSCAN&#039; AS Command,
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = so1.id) * 0.40 AS ItemWork
FROM
	dbo.sysobjects so1
LEFT OUTER JOIN 
	#ReindexCandidate rc1
	ON 
		(
			rc1.ObjectId = so1.id
			AND
			rc1.IndexId = 1
		)
WHERE
	so1.xtype = &#039;U&#039;
	AND
	rc1.ObjectId IS NULL
	AND
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = so1.id)  0
	AND
	so1.id  OBJECT_ID(&#039;dbo.DBMaint_Task&#039;)

DELETE FROM
	dbo.DBMaint_Task
WHERE
	ItemWork = 0

-- Break all ties by ItemWork
-- This algorithm is arbitrary, but the amount of estimated work it adds is trival
SET @RowsUpdated = 1
WHILE @RowsUpdated  0
BEGIN
	UPDATE
		mt1
	SET
		ItemWork = ItemWork + 0.01
	FROM
		dbo.DBMaint_Task mt1
	INNER JOIN
		(
			SELECT
				MAX(MaintTaskId) AS MaintTaskId
			FROM
				dbo.DBMaint_Task
			GROUP BY
				ItemWork
			HAVING
				COUNT(*) &gt; 1
		) mt2
	ON
		(
			mt1.MaintTaskId = mt2.MaintTaskId
		)
	
	SET @RowsUpdated = @@ROWCOUNT
END		


SET @CurrentInterval = 1
WHILE @CurrentInterval = mt1.ItemWork 
				AND 
				mt2.Interval = -1
		) &lt;= @WorkPerIntervalGoal	
	
	SET @RowsUpdated = @@ROWCOUNT

	IF @RowsUpdated = 0
	BEGIN
		UPDATE
			mt1
		SET
			Interval = @CurrentInterval
		FROM
			dbo.DBMaint_Task mt1
		WHERE
		mt1.ItemWork = (
			SELECT 
				MAX(mt2.ItemWork) 
			FROM 
				dbo.DBMaint_Task mt2
			WHERE 
				mt2.Interval = -1
		)
	END

	SET @CurrentInterval = @CurrentInterval + 1
END

SET NOCOUNT OFF

GO


IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#039;dbo.p_maint_ExecuteMaintTasks&#039;) AND xtype = &#039;P&#039;)
BEGIN
	DROP PROCEDURE dbo.p_maint_ExecuteMaintTasks
END
GO

CREATE PROCEDURE dbo.p_maint_ExecuteMaintTasks
	@PeriodLength 			int = 7,	-- Number of intervals in a period
	@IndexRebuildThreshold		int = 10,	-- Maximum LogicalFragmentation value allowed before an index is rebuilt
	@ForceInterval			int = NULL,	-- Manually set the current interval rather than calculating it from the date
	@ForceRebuildTaskList 		int = 0,	-- If non-zero, force a rebuild of the task list
	@RebuildTaskListInterval	int = 1		-- The interval in which to automatically rebuild the task list
AS

DECLARE @CurrentInterval	 	int
DECLARE @TaskCount			int
DECLARE @Command			nvarchar(4000)
DECLARE @MaintTaskId			int

SET NOCOUNT ON

IF @PeriodLength &lt; 1
BEGIN
	RAISERROR(N&#039;@PeriodLength must be greater than zero.&#039;, 16, 1)
	RETURN
END

IF @ForceInterval IS NOT NULL
BEGIN
	IF @ForceInterval  @PeriodLength
	BEGIN
		RAISERROR(N&#039;If not null, @ForceInterval must be less than or equal to @PeriodLength.&#039;, 16, 1)
		RETURN
	END
END

IF @RebuildTaskListInterval &gt; @PeriodLength
BEGIN
	RAISERROR(N&#039;@RebuildTaskListInterval must be less than or equal to @PeriodLength.&#039;, 16, 1)
	RETURN
END

IF NOT @IndexRebuildThreshold BETWEEN 0 AND 100
BEGIN
	RAISERROR(N&#039;@IndexRebuildThreshold must be between 0 and 100.&#039;, 16, 1)
	RETURN
END

SELECT
	@TaskCount = COUNT(*)
FROM
	dbo.DBMaint_Task
WHERE
	CompletedDatetime IS NULL

IF @ForceInterval IS NULL
BEGIN
	SELECT 
		@CurrentInterval = ((YEAR(GETDATE() - 59) * 365 + DATEPART(dy, GETDATE() - 59)) % @PeriodLength) + 1
END
ELSE
BEGIN
	SELECT
		@CurrentInterval = @ForceInterval
END

IF @TaskCount = 0 OR @ForceRebuildTaskList  0 OR @CurrentInterval = @RebuildTaskListInterval
BEGIN
	EXEC dbo.p_maint_ScheduleMaintTasks 
		@PeriodLength = @PeriodLength,
		@IndexRebuildThreshold = @IndexRebuildThreshold
END

DECLARE csr_Task CURSOR FAST_FORWARD FOR
SELECT
	MaintTaskId,
	Command
FROM
	dbo.DBMaint_Task
WHERE
	Interval = @CurrentInterval
	AND
	CompletedDatetime IS NULL

OPEN csr_Task

FETCH NEXT FROM csr_Task INTO @MaintTaskId, @Command
WHILE @@FETCH_STATUS = 0
BEGIN
	PRINT CONVERT(nvarchar(30), GETDATE(), 121) + N&#039;: Executing &quot;&#039; + @Command + N&#039;&quot;&#039;
	EXEC(@Command)
	PRINT &#039;&#039;

	UPDATE
		dbo.DBMaint_Task
	SET
		CompletedDatetime = GETDATE()
	WHERE
		MaintTaskId = @MaintTaskId

	FETCH NEXT FROM csr_Task INTO @MaintTaskId, @Command
END

CLOSE csr_Task
DEALLOCATE csr_Task

SET NOCOUNT OFF
GO</description>
		<content:encoded><![CDATA[<p>Hi,<br />
Not sure where I had this script from, but I have been using it for ages now, basically it defrags indexes over a period of 7 days to spread the load, but for some reason it doesn&#8217;t like multiple schemas, as it adds dbo to all tables found etc&#8230; any ideas to make this work for all schemas would be great:</p>
<p>IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#8216;dbo.DBMaint_Task&#8217;) AND xtype = &#8216;U&#8217;)<br />
BEGIN<br />
	DROP TABLE dbo.DBMaint_Task<br />
END<br />
GO</p>
<p>CREATE TABLE dbo.DBMaint_Task(<br />
	MaintTaskId		int		NOT NULL	IDENTITY(1, 1),<br />
	Interval		int		NOT NULL,<br />
	Command			nvarchar(4000)	NOT NULL,<br />
	ItemWork		numeric(10,2)	NOT NULL,<br />
	CompletedDatetime	datetime	NULL<br />
	CONSTRAINT PK_DBMaint_Task PRIMARY KEY CLUSTERED(MaintTaskID)<br />
)<br />
GO</p>
<p>IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#8216;dbo.p_maint_ScheduleMaintTasks&#8217;) AND xtype = &#8216;P&#8217;)<br />
BEGIN<br />
	DROP PROCEDURE dbo.p_maint_ScheduleMaintTasks<br />
END<br />
GO</p>
<p>CREATE PROCEDURE dbo.p_maint_ScheduleMaintTasks<br />
	@PeriodLength		int,		&#8211; Number of intervals in a period<br />
	@IndexRebuildThreshold	int	= 10	&#8211; Maximum LogicalFragmentation value allowed before an index is rebuilt<br />
AS</p>
<p>DECLARE @WorkPerIntervalGoal 	numeric(10,2)<br />
DECLARE @CurrentInterval	int<br />
DECLARE @RowsUpdated		int<br />
DECLARE @MainTaskId		int</p>
<p>SET NOCOUNT ON</p>
<p>IF @PeriodLength = @IndexRebuildThreshold<br />
	AND<br />
	ObjectId  OBJECT_ID(&#8216;dbo.DBMaint_Task&#8217;)</p>
<p>&#8211; If we rebuild a clustered index, we don&#8217;t need to rebuild<br />
&#8211; any nonclustered indexes on the same table<br />
DELETE FROM<br />
	rc1<br />
FROM<br />
	#ReindexCandidate rc1<br />
INNER JOIN<br />
	#ReindexCandidate rc2<br />
	ON(<br />
		rc1.ObjectId = rc2.ObjectId<br />
	)<br />
WHERE<br />
	rc2.IndexID = 1 &#8212; IndexID = 1 means the clustered index<br />
	AND<br />
	rc1.IndexID  1</p>
<p>TRUNCATE TABLE dbo.DBMaint_Task</p>
<p>INSERT INTO dbo.DBMaint_Task(<br />
	Interval,<br />
	Command,<br />
	ItemWork)<br />
SELECT<br />
	-1 AS Interval,<br />
	N&#8217;DBCC DBREINDEX(&#8221;&#8217; + USER_NAME(OBJECTPROPERTY(rc1.ObjectId, &#8216;OwnerId&#8217;)) + N&#8217;.&#8217; + rc1.ObjectName + N&#8221;&#8221; +<br />
		CASE IndexId WHEN 1 THEN N&#8221; ELSE N&#8217;, &#8221;&#8217; + IndexName + N&#8221;&#8221; END + N&#8217;)&#8217; AS Command,<br />
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = rc1.ObjectId) AS ItemWork<br />
FROM<br />
	#ReindexCandidate rc1</p>
<p>&#8211; Find all tables that we&#8217;re not doing a clustered index rebuild on<br />
INSERT INTO dbo.DBMaint_Task(<br />
	Interval,<br />
	Command,<br />
	ItemWork)<br />
SELECT<br />
	-1 AS Interval,<br />
	N&#8217;UPDATE STATISTICS [' + USER_NAME(uid) + N'].[' + so1.name + N'] WITH FULLSCAN&#8217; AS Command,<br />
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = so1.id) * 0.40 AS ItemWork<br />
FROM<br />
	dbo.sysobjects so1<br />
LEFT OUTER JOIN<br />
	#ReindexCandidate rc1<br />
	ON<br />
		(<br />
			rc1.ObjectId = so1.id<br />
			AND<br />
			rc1.IndexId = 1<br />
		)<br />
WHERE<br />
	so1.xtype = &#8216;U&#8217;<br />
	AND<br />
	rc1.ObjectId IS NULL<br />
	AND<br />
	(SELECT SUM(dpages) FROM dbo.sysindexes si1 WHERE id = so1.id)  0<br />
	AND<br />
	so1.id  OBJECT_ID(&#8216;dbo.DBMaint_Task&#8217;)</p>
<p>DELETE FROM<br />
	dbo.DBMaint_Task<br />
WHERE<br />
	ItemWork = 0</p>
<p>&#8211; Break all ties by ItemWork<br />
&#8211; This algorithm is arbitrary, but the amount of estimated work it adds is trival<br />
SET @RowsUpdated = 1<br />
WHILE @RowsUpdated  0<br />
BEGIN<br />
	UPDATE<br />
		mt1<br />
	SET<br />
		ItemWork = ItemWork + 0.01<br />
	FROM<br />
		dbo.DBMaint_Task mt1<br />
	INNER JOIN<br />
		(<br />
			SELECT<br />
				MAX(MaintTaskId) AS MaintTaskId<br />
			FROM<br />
				dbo.DBMaint_Task<br />
			GROUP BY<br />
				ItemWork<br />
			HAVING<br />
				COUNT(*) &gt; 1<br />
		) mt2<br />
	ON<br />
		(<br />
			mt1.MaintTaskId = mt2.MaintTaskId<br />
		)</p>
<p>	SET @RowsUpdated = @@ROWCOUNT<br />
END		</p>
<p>SET @CurrentInterval = 1<br />
WHILE @CurrentInterval = mt1.ItemWork<br />
				AND<br />
				mt2.Interval = -1<br />
		) &lt;= @WorkPerIntervalGoal	</p>
<p>	SET @RowsUpdated = @@ROWCOUNT</p>
<p>	IF @RowsUpdated = 0<br />
	BEGIN<br />
		UPDATE<br />
			mt1<br />
		SET<br />
			Interval = @CurrentInterval<br />
		FROM<br />
			dbo.DBMaint_Task mt1<br />
		WHERE<br />
		mt1.ItemWork = (<br />
			SELECT<br />
				MAX(mt2.ItemWork)<br />
			FROM<br />
				dbo.DBMaint_Task mt2<br />
			WHERE<br />
				mt2.Interval = -1<br />
		)<br />
	END</p>
<p>	SET @CurrentInterval = @CurrentInterval + 1<br />
END</p>
<p>SET NOCOUNT OFF</p>
<p>GO</p>
<p>IF EXISTS(SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(&#039;dbo.p_maint_ExecuteMaintTasks&#039;) AND xtype = &#039;P&#039;)<br />
BEGIN<br />
	DROP PROCEDURE dbo.p_maint_ExecuteMaintTasks<br />
END<br />
GO</p>
<p>CREATE PROCEDURE dbo.p_maint_ExecuteMaintTasks<br />
	@PeriodLength 			int = 7,	&#8211; Number of intervals in a period<br />
	@IndexRebuildThreshold		int = 10,	&#8211; Maximum LogicalFragmentation value allowed before an index is rebuilt<br />
	@ForceInterval			int = NULL,	&#8211; Manually set the current interval rather than calculating it from the date<br />
	@ForceRebuildTaskList 		int = 0,	&#8211; If non-zero, force a rebuild of the task list<br />
	@RebuildTaskListInterval	int = 1		&#8211; The interval in which to automatically rebuild the task list<br />
AS</p>
<p>DECLARE @CurrentInterval	 	int<br />
DECLARE @TaskCount			int<br />
DECLARE @Command			nvarchar(4000)<br />
DECLARE @MaintTaskId			int</p>
<p>SET NOCOUNT ON</p>
<p>IF @PeriodLength &lt; 1<br />
BEGIN<br />
	RAISERROR(N&#039;@PeriodLength must be greater than zero.&#039;, 16, 1)<br />
	RETURN<br />
END</p>
<p>IF @ForceInterval IS NOT NULL<br />
BEGIN<br />
	IF @ForceInterval  @PeriodLength<br />
	BEGIN<br />
		RAISERROR(N&#8217;If not null, @ForceInterval must be less than or equal to @PeriodLength.&#8217;, 16, 1)<br />
		RETURN<br />
	END<br />
END</p>
<p>IF @RebuildTaskListInterval &gt; @PeriodLength<br />
BEGIN<br />
	RAISERROR(N&#8217;@RebuildTaskListInterval must be less than or equal to @PeriodLength.&#8217;, 16, 1)<br />
	RETURN<br />
END</p>
<p>IF NOT @IndexRebuildThreshold BETWEEN 0 AND 100<br />
BEGIN<br />
	RAISERROR(N&#8217;@IndexRebuildThreshold must be between 0 and 100.&#8217;, 16, 1)<br />
	RETURN<br />
END</p>
<p>SELECT<br />
	@TaskCount = COUNT(*)<br />
FROM<br />
	dbo.DBMaint_Task<br />
WHERE<br />
	CompletedDatetime IS NULL</p>
<p>IF @ForceInterval IS NULL<br />
BEGIN<br />
	SELECT<br />
		@CurrentInterval = ((YEAR(GETDATE() &#8211; 59) * 365 + DATEPART(dy, GETDATE() &#8211; 59)) % @PeriodLength) + 1<br />
END<br />
ELSE<br />
BEGIN<br />
	SELECT<br />
		@CurrentInterval = @ForceInterval<br />
END</p>
<p>IF @TaskCount = 0 OR @ForceRebuildTaskList  0 OR @CurrentInterval = @RebuildTaskListInterval<br />
BEGIN<br />
	EXEC dbo.p_maint_ScheduleMaintTasks<br />
		@PeriodLength = @PeriodLength,<br />
		@IndexRebuildThreshold = @IndexRebuildThreshold<br />
END</p>
<p>DECLARE csr_Task CURSOR FAST_FORWARD FOR<br />
SELECT<br />
	MaintTaskId,<br />
	Command<br />
FROM<br />
	dbo.DBMaint_Task<br />
WHERE<br />
	Interval = @CurrentInterval<br />
	AND<br />
	CompletedDatetime IS NULL</p>
<p>OPEN csr_Task</p>
<p>FETCH NEXT FROM csr_Task INTO @MaintTaskId, @Command<br />
WHILE @@FETCH_STATUS = 0<br />
BEGIN<br />
	PRINT CONVERT(nvarchar(30), GETDATE(), 121) + N&#8217;: Executing &#8220;&#8216; + @Command + N&#8217;&#8221;&#8216;<br />
	EXEC(@Command)<br />
	PRINT &#8221;</p>
<p>	UPDATE<br />
		dbo.DBMaint_Task<br />
	SET<br />
		CompletedDatetime = GETDATE()<br />
	WHERE<br />
		MaintTaskId = @MaintTaskId</p>
<p>	FETCH NEXT FROM csr_Task INTO @MaintTaskId, @Command<br />
END</p>
<p>CLOSE csr_Task<br />
DEALLOCATE csr_Task</p>
<p>SET NOCOUNT OFF<br />
GO</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Index Defrag Script, v3.0 by Gmamata</title>
		<link>http://sqlfool.com/2009/06/index-defrag-script-v30/comment-page-2/#comment-5051</link>
		<dc:creator>Gmamata</dc:creator>
		<pubDate>Sat, 30 Jan 2010 20:38:03 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1072#comment-5051</guid>
		<description>Hi Michelle,

Is this latest version of the script that has addressed some of the issues by users (like Derick and SuperCoolMoss pointed about the stats rebuild feature in your defrag script will only complete for one database.)?

Thank you</description>
		<content:encoded><![CDATA[<p>Hi Michelle,</p>
<p>Is this latest version of the script that has addressed some of the issues by users (like Derick and SuperCoolMoss pointed about the stats rebuild feature in your defrag script will only complete for one database.)?</p>
<p>Thank you</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Index Defrag Script Updates &#8211; Beta Testers Needed by Log Buffer #176: a Carnival of the Vanities for DBAs &#124; The Pythian Blog</title>
		<link>http://sqlfool.com/2010/01/index-defrag-script-updates-beta-testers-needed/comment-page-1/#comment-5050</link>
		<dc:creator>Log Buffer #176: a Carnival of the Vanities for DBAs &#124; The Pythian Blog</dc:creator>
		<pubDate>Fri, 29 Jan 2010 19:03:41 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=1298#comment-5050</guid>
		<description>[...] Michelle Ufford has updates on her index defrag script – beta testers are needed. [...]</description>
		<content:encoded><![CDATA[<p>[...] Michelle Ufford has updates on her index defrag script – beta testers are needed. [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Automated Index Defrag Script by Madhu.G</title>
		<link>http://sqlfool.com/2009/03/automated-index-defrag-script/comment-page-1/#comment-5049</link>
		<dc:creator>Madhu.G</dc:creator>
		<pubDate>Fri, 29 Jan 2010 18:23:13 +0000</pubDate>
		<guid isPermaLink="false">http://sqlfool.com/?p=689#comment-5049</guid>
		<description>Nice work, Thank you for the script.</description>
		<content:encoded><![CDATA[<p>Nice work, Thank you for the script.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
