<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" 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/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Bob Pusateri - The Outer Join</title>
	
	<link>http://www.bobpusateri.com</link>
	<description>Bob Pusateri's thoughts on SQL Server and kindred subjects</description>
	<lastBuildDate>Thu, 26 Jan 2012 15:25:23 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/TheOuterJoin" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="theouterjoin" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Collecting Index Usage Statistics</title>
		<link>http://www.bobpusateri.com/archive/2012/01/collecting-index-usage-statistics/</link>
		<comments>http://www.bobpusateri.com/archive/2012/01/collecting-index-usage-statistics/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 15:25:23 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=712</guid>
		<description><![CDATA[<p>Knowing when and how often your indexes are used can really come in handy. Indexes that are never utilized aren&#8217;t worth keeping around, and knowing their usage patterns can be a big help when making decisions regarding things such as filegroup placement and compression settings. SQL Server 2005 brought some great advancements in the form [...]]]></description>
			<content:encoded><![CDATA[<p>Knowing when and how often your indexes are used can really come in handy. Indexes that are never utilized aren&#8217;t worth keeping around, and knowing their usage patterns can be a big help when making decisions regarding things such as filegroup placement and compression settings. SQL Server 2005 brought some great advancements in the form of the <a href="http://msdn.microsoft.com/en-us/library/ms188755.aspx" target="_blank">sys.dm_db_index_usage_stats</a> DMV, which returns statistics on index usage that are automatically being kept by the server. While it&#8217;s a step forward, I feel it still leaves a few things to be desired: </p>
<ul>
<li>The values are cumulative since the server was last restarted</li>
<li>Once the server is shut down or restarted, there&#8217;s no way to get the previous values back</li>
</ul>
<p><a href="http://commons.wikimedia.org/wiki/File%3AUSA_inverted_Jenny_siegal_nov_07_%24977%2C500_.jpg" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Collectable" src="http://img.bobpusateri.com/bc/2012/01/InvertedJenny.jpg" class="alignright" width="300" height="260" /></a>With this in mind, I came up with my own system for archiving <em>non-cumulative</em> index usage stats on a daily basis.  Microsoft introduced <a href="http://msdn.microsoft.com/en-us/library/dd939169(SQL.100).aspx" target="_blank">Management Data Warehouse</a> in SQL Server 2008 which provides a way to keep track of these statistics over time (along with many others), but I&#8217;ve been using my own method longer than that. This will also work in SQL Server Express Edition, which <a href="http://msdn.microsoft.com/en-us/library/cc645993.aspx#RDBMS_mgmt" target="_blank">doesn&#8217;t support MDW</a>. I&#8217;ll give descriptions of each part below, but if you just want the code right now <a href="http://img.bobpusateri.com/bc/2012/01/CollectUsageStats.zip" target="_blank">download it here</a>.</p>
<h4>Tables</h4>
<p><strong>IndexUsageStats_LastCumulative</strong><br />
As I mentioned before, the output from sys.dm_db_index_usage_stats is cumulative since the last time the server was restarted, and I was looking for a way to find daily values that weren&#8217;t cumulative. Restarting the server immediately after collecting the values would have accomplished this, but users probably wouldn&#8217;t be very happy :). Instead I just keep track of the previous cumulative values and subtract them from the current ones. If the output shows an index was used 7 times on Tuesday at Midnight, and the same number was 12 on Wednesday at Midnight, then it must have been used 5 times in that 24 hour period. IndexUsageStats_LastCumulative holds the previous cumulative values for all indexes to make this calculation possible.</p>
<p><strong>Names</strong><br />
The only true way to identify an object in SQL Server is by its name, but DMVs typically return object IDs instead of names. It&#8217;s easy to translate between names and IDs, but over time names and IDs can change:<br />
- If an object is dropped and re-created with the same name, chances of it having the same ID are virtually zero.<br />
- If an object is renamed, its ID will not change, but of course its name will.<br />
Using either IDs or Names exclusively can make historical values become useless over time &#8211; you might have an ID that&#8217;s no longer valid or a name that changed a while back. To give myself more options for tracking changes over time, I store both. Since storing each object&#8217;s name in a character data type would consume a lot of space and be repetitive, I prefer to map object names to numeric values, and this table facilitates that.</p>
<p><strong>IndexUsageStats</strong><br />
This table does the heavy <strike>lifting</strike> storing for our system &#8211; it contains all the historical index usage statistics by both object ID and name. I&#8217;ve found it to be a great candidate for compression if you&#8217;re running enterprise edition, but it&#8217;s still pretty compact even when uncompressed thanks to the Names table.</p>
<h4>Stored Procedures</h4>
<p><strong>CollectIndexUsageStats</strong><br />
The stored procedure that drives statistics collection. You&#8217;ll want to set up a job to run this &#8211; mine runs at midnight. Basically it iterates through each online database in the instance collecting usage stats and then compares them to the previous cumulative values and writes the differences to the IndexUsageStats table. You&#8217;ll find comments in-line.</p>
<h4>Views</h4>
<p><strong>vw_IndexUsageStats</strong><br />
Since the data contained in the IndexUsageStats table is all numeric, it&#8217;s not the easiest to browse. This view makes some joins back to the Names table so things are a little more user-friendly. Most of the queries I write are against this view. Object IDs aren&#8217;t returned here as they&#8217;re typically not needed. When they are necessary, I&#8217;ll write more detailed queries against IndexUsageStats.</p>
<p>A few notes before the code:</p>
<ul>
<li>As always, this code is offered <strong>as-is</strong> with <strong>no warranty whatsoever</strong>. Do not deploy this in a production environment before you have tested it and understand exactly what it does.</li>
<li>I recommend putting all these objects in their own database. If you already have a DBA database for management information that should work fine too. My database is called &#8220;iDBA&#8221; because I inherited it with that name.</li>
<li>This was written and tested on SQL Server 2008 and 2008R2. It can probably be tweaked to run in 2005 by removing the datetime2 datatype and writing substitute queries for the MERGE statement.</li>
</ul>
<pre class="brush: sql; title: ; notranslate">
-----------------------------------------------------------
-- Name: CollectIndexUsageStats.sql
--
-- Description: Collects index usage statistics over time.
--
-- Author: Bob Pusateri, http://www.bobpusateri.com
--
-- THIS SCRIPT IS PROVIDED &quot;AS-IS&quot; WITHOUT ANY WARRANTY.
-- DO NOT RUN THIS ON A PRODUCTION SYSTEM UNTIL YOU HAVE
--   COMPLETE UNDERSTANDING OF THE TASKS IT PERFORMS AND
--   HAVE TESTED IT ON A DEVELOPMENT SYSTEM.
-----------------------------------------------------------

-- I recommend putting these objects in a separate database
-- (or your existing DBA database if you have one)
--
-- If your DBA database is not named 'iDBA', you'll want to replace it with your DB name
--     It is referenced several times in the script below
USE [iDBA];
GO

-- stores cumulative data from sys.dm_db_index_usage_stats DMV
CREATE TABLE [dbo].[IndexUsageStats_LastCumulative] (
	[ServerNameID] [int] NOT NULL,
	[DatabaseID] [smallint] NOT NULL,
	[ObjectID] [int] NOT NULL,
	[IndexID] [int] NOT NULL,
	[LoadTime] [datetime2](0) NOT NULL,
	[User_Seeks] [bigint] NOT NULL,
	[User_Scans] [bigint] NOT NULL,
	[User_Lookups] [bigint] NOT NULL,
	[User_Updates] [bigint] NOT NULL,
	[System_Seeks] [bigint] NOT NULL,
	[System_Scans] [bigint] NOT NULL,
	[System_Lookups] [bigint] NOT NULL,
	[System_Updates] [bigint] NOT NULL,
	CONSTRAINT [PK_IUS_C] PRIMARY KEY CLUSTERED ([ServerNameID],[DatabaseID],[ObjectID],[IndexID])
);
GO

-- used for Server/DB/Schema/Table/Index name mapping
CREATE TABLE [dbo].[Names] (
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[Value] [nvarchar](260) NOT NULL,
	CONSTRAINT [PK_Names] PRIMARY KEY CLUSTERED ([ID])
);
GO

-- stores historical usage statistics
CREATE TABLE [dbo].[IndexUsageStats] (
	[StatsDate] [datetime2](0) NOT NULL,
	[ServerNameID] [int] NOT NULL,
	[DatabaseID] [smallint] NOT NULL,
	[ObjectID] [int] NOT NULL,
	[IndexID] [int] NOT NULL,
	[DatabaseNameID] [int] NOT NULL,
	[SchemaNameID] [int] NOT NULL,
	[TableNameID] [int] NOT NULL,
	[IndexNameID] [int] NULL,
	[User_Seeks] [bigint] NOT NULL,
	[User_Scans] [bigint] NOT NULL,
	[User_Lookups] [bigint] NOT NULL,
	[User_Updates] [bigint] NOT NULL,
	[System_Seeks] [bigint] NOT NULL,
	[System_Scans] [bigint] NOT NULL,
	[System_Lookups] [bigint] NOT NULL,
	[System_Updates] [bigint] NOT NULL,
	CONSTRAINT [PK_IUS] PRIMARY KEY CLUSTERED ([StatsDate],[ServerNameID],[DatabaseID],[ObjectID],[IndexID]),
	CONSTRAINT [FK_IUS_Names_DB] FOREIGN KEY([DatabaseNameID]) REFERENCES [dbo].[Names] ([ID]),
	CONSTRAINT [FK_IUS_Names_Index] FOREIGN KEY([IndexNameID]) REFERENCES [dbo].[Names] ([ID]),
	CONSTRAINT [FK_IUS_Names_Schema] FOREIGN KEY([SchemaNameID]) REFERENCES [dbo].[Names] ([ID]),
	CONSTRAINT [FK_IUS_Names_Table] FOREIGN KEY([TableNameID]) REFERENCES [dbo].[Names] ([ID]),
	CONSTRAINT [CK_IUS_PositiveValues] CHECK ([User_Seeks]&gt;=(0) AND [User_Scans]&gt;=(0) AND [user_Lookups]&gt;=(0)
		AND [user_updates]&gt;=(0) AND [system_seeks]&gt;=(0) AND [system_scans]&gt;=(0) AND [system_lookups]&gt;=(0)
		AND [system_updates]&gt;=(0))
);
GO

-- collects usage statistics
-- I run this once daily (can be run more often if you like)
CREATE PROCEDURE [dbo].[CollectIndexUsageStats]
AS
BEGIN
	BEGIN TRY
		SET NOCOUNT ON;

		-- get current stats for all online databases

		SELECT database_id, name
		INTO #dblist
		FROM sys.databases
		WHERE [state] = 0
			AND database_id != 2; -- skip TempDB

		CREATE TABLE #t (
			StatsDate DATETIME2(0),
			ServerName SYSNAME,
			DatabaseID SMALLINT,
			ObjectID INT,
			IndexID INT,
			DatabaseName SYSNAME,
			SchemaName SYSNAME,
			TableName SYSNAME,
			IndexName SYSNAME NULL,
			User_Seeks BIGINT,
			User_Scans BIGINT,
			User_Lookups BIGINT,
			User_Updates BIGINT,
			System_Seeks BIGINT,
			System_Scans BIGINT,
			System_Lookups BIGINT,
			System_Updates BIGINT
		);

		DECLARE @DBID INT;
		DECLARE @DBNAME SYSNAME;
		DECLARE @Qry NVARCHAR(2000);

		-- iterate through each DB, generate &amp; run query
		WHILE (SELECT COUNT(*) FROM #dblist) &gt; 0
		BEGIN
			SELECT TOP (1) @DBID=database_id, @DBNAME=[name]
			FROM #dblist ORDER BY database_id;

			SET @Qry = '
				INSERT INTO #t
				SELECT
					SYSDATETIME() AS StatsDate,
					@@SERVERNAME AS ServerName,
					s.database_id AS DatabaseID,
					s.object_id AS ObjectID,
					s.index_id AS IndexID,
					''' + @DBNAME + ''' AS DatabaseName,
					c.name AS SchemaName,
					o.name AS TableName,
					i.name AS IndexName,
					s.user_seeks,
					s.user_scans,
					s.user_lookups,
					s.user_updates,
					s.system_seeks,
					s.system_scans,
					s.system_lookups,
					s.system_updates
				FROM sys.dm_db_index_usage_stats s
				INNER JOIN ' + @DBNAME + '.sys.objects o ON s.object_id = o.object_id
				INNER JOIN ' + @DBNAME + '.sys.schemas c ON o.schema_id = c.schema_id
				INNER JOIN ' + @DBNAME + '.sys.indexes i ON s.object_id = i.object_id and s.index_id = i.index_id
				WHERE s.database_id = ' + CONVERT(NVARCHAR,@DBID) + ';
				';

			EXEC sp_executesql @Qry;

			DELETE FROM #dblist WHERE database_id = @DBID;
		END -- db while loop

		DROP TABLE #DBList;

		BEGIN TRAN;

		-- create ids for Server Name by inserting new ones into dbo.Names
		INSERT INTO iDBA.dbo.Names (Value)
		SELECT DISTINCT RTRIM(LTRIM(t.ServerName)) AS ServerName
		FROM #t t
		LEFT JOIN iDBA.dbo.Names n ON t.ServerName = n.Value
		WHERE n.ID IS NULL AND t.ServerName IS NOT NULL
		ORDER BY RTRIM(LTRIM(t.ServerName));

		-- same as above for DatabaseName
		INSERT INTO iDBA.dbo.Names (Value)
		SELECT DISTINCT RTRIM(LTRIM(t.DatabaseName)) AS DatabaseName
		FROM #t t
		LEFT JOIN iDBA.dbo.Names n ON t.DatabaseName = n.Value
		WHERE n.ID IS NULL AND t.DatabaseName IS NOT NULL
		ORDER BY RTRIM(LTRIM(t.DatabaseName));

		-- SchemaName
		INSERT INTO iDBA.dbo.Names (Value)
		SELECT DISTINCT RTRIM(LTRIM(t.SchemaName)) AS SchemaName
		FROM #t t
		LEFT JOIN iDBA.dbo.Names n ON t.SchemaName = n.Value
		WHERE n.ID IS NULL AND t.SchemaName IS NOT NULL
		ORDER BY RTRIM(LTRIM(t.SchemaName));

		-- TableName
		INSERT INTO iDBA.dbo.Names (Value)
		SELECT DISTINCT RTRIM(LTRIM(t.TableName)) AS TableName
		FROM #t t
		LEFT JOIN iDBA.dbo.Names n ON t.TableName = n.Value
		WHERE n.ID IS NULL AND t.TableName IS NOT NULL
		ORDER BY RTRIM(LTRIM(t.TableName));

		-- IndexName
		INSERT INTO iDBA.dbo.Names (Value)
		SELECT DISTINCT RTRIM(LTRIM(t.IndexName)) AS IndexName
		FROM #t t
		LEFT JOIN iDBA.dbo.Names n ON t.IndexName = n.Value
		WHERE n.ID IS NULL AND t.IndexName IS NOT NULL
		ORDER BY RTRIM(LTRIM(t.IndexName));

		-- Calculate Deltas
		INSERT INTO iDBA.dbo.IndexUsageStats (StatsDate, ServerNameID, DatabaseID, ObjectID,
			IndexID, DatabaseNameID, SchemaNameID, TableNameID, IndexNameID, User_Seeks, User_Scans,
			User_Lookups, User_Updates, System_Seeks, System_Scans, System_Lookups, System_Updates)
		SELECT
			t.StatsDate,
			s.ID AS ServerNameID,
			t.DatabaseID,
			t.ObjectID,
			t.IndexID,
			d.ID AS DatabaseNameID,
			c.ID AS SchemaNameID,
			b.ID AS TableNameID,
			i.ID AS IndexNameID,
			CASE
				-- if the previous cumulative value is greater than the current one, the server has been reset
				-- just use the current value
				WHEN t.User_Seeks - ISNULL(lc.User_Seeks,0) &lt; 0 THEN t.User_Seeks
				-- if the prev value is less than the current one, then subtract to get the delta
				ELSE t.User_Seeks - ISNULL(lc.User_Seeks,0)
			END AS User_Seeks,
			CASE
				WHEN t.User_Scans - ISNULL(lc.User_Scans,0) &lt; 0 THEN t.User_Scans
				ELSE t.User_Scans - ISNULL(lc.User_Scans,0)
			END AS User_Scans,
			CASE
				WHEN t.User_Lookups - ISNULL(lc.User_Lookups,0) &lt; 0 THEN t.User_Lookups
				ELSE t.User_Lookups - ISNULL(lc.User_Lookups,0)
			END AS User_Lookups,
			CASE
				WHEN t.User_Updates - ISNULL(lc.User_Updates,0) &lt; 0 THEN t.User_Updates
				ELSE t.User_Updates - ISNULL(lc.User_Updates,0)
			END AS User_Updates,
			CASE
				WHEN t.System_Seeks - ISNULL(lc.System_Seeks,0) &lt; 0 THEN t.System_Seeks
				ELSE t.System_Seeks - ISNULL(lc.System_Seeks,0)
			END AS System_Seeks,
			CASE
				WHEN t.System_Scans - ISNULL(lc.System_Scans,0) &lt; 0 THEN t.System_Scans
				ELSE t.System_Scans - ISNULL(lc.System_Scans,0)
			END AS System_Scans,
			CASE
				WHEN t.System_Lookups - ISNULL(lc.System_Lookups,0) &lt; 0 THEN t.System_Lookups
				ELSE t.System_Lookups - ISNULL(lc.System_Lookups,0)
			END AS System_Lookups,
			CASE
				WHEN t.System_Updates - ISNULL(lc.System_Updates,0) &lt; 0 THEN t.System_Updates
				ELSE t.System_Updates - ISNULL(lc.System_Updates,0)
			END AS System_Updates
		FROM #t t
		INNER JOIN iDBA.dbo.Names s ON t.ServerName = s.Value
		INNER JOIN iDBA.dbo.Names d ON t.DatabaseName = d.Value
		INNER JOIN iDBA.dbo.Names c ON t.SchemaName = c.Value
		INNER JOIN iDBA.dbo.Names b ON t.TableName = b.Value
		LEFT JOIN iDBA.dbo.Names i ON t.IndexName = i.Value
		LEFT JOIN iDBA.dbo.IndexUsageStats_LastCumulative lc
			ON s.ID = lc.ServerNameID
			AND t.DatabaseID = lc.DatabaseID
			AND t.ObjectID = lc.ObjectID
			AND t.IndexID = lc.IndexID
		ORDER BY StatsDate, ServerName, DatabaseID, ObjectID, IndexID;

		-- Update last cumulative values with the current ones
		MERGE INTO iDBA.dbo.IndexUsageStats_LastCumulative lc
		USING #t t
		INNER JOIN iDBA.dbo.Names s ON t.ServerName = s.Value
		ON s.ID = lc.ServerNameID
			AND t.DatabaseID = lc.DatabaseID
			AND t.ObjectID = lc.ObjectID
			AND t.IndexID = lc.IndexID
		WHEN MATCHED THEN
			UPDATE SET
				lc.LoadTime = t.StatsDate,
				lc.User_Seeks = t.User_Seeks,
				lc.User_Scans = t.User_Scans,
				lc.User_Lookups = t.User_Lookups,
				lc.User_Updates = t.User_Updates,
				lc.System_Seeks = t.System_Seeks,
				lc.System_Scans = t.System_Scans,
				lc.System_Lookups = t.System_Lookups,
				lc.System_Updates = t.System_Updates
		WHEN NOT MATCHED BY TARGET THEN
			INSERT (ServerNameID, DatabaseID, ObjectID, IndexID, LoadTime, User_Seeks, User_Scans,
				User_Lookups, User_Updates, System_Seeks, System_Scans,
				System_Lookups, System_Updates)
			VALUES (s.ID, t.DatabaseID, t.ObjectID, t.IndexID, t.StatsDate, t.User_Seeks, t.User_Scans,
				t.User_Lookups, t.User_Updates, t.System_Seeks, t.System_Scans,
				t.System_Lookups, t.System_Updates)
		WHEN NOT MATCHED BY SOURCE
			THEN DELETE;

		COMMIT TRAN;

	END TRY
	BEGIN CATCH

		IF @@TRANCOUNT &gt; 0
			ROLLBACK TRAN;

		DECLARE @ErrorNumber INT;
		DECLARE @ErrorSeverity INT;
		DECLARE @ErrorState INT;
		DECLARE @ErrorProcedure NVARCHAR(126);
		DECLARE @ErrorLine INT;
		DECLARE @ErrorMessage NVARCHAR(2048);

		SELECT @ErrorNumber = ERROR_NUMBER(),
			   @ErrorSeverity = ERROR_SEVERITY(),
			   @ErrorState = ERROR_STATE(),
			   @ErrorProcedure = ERROR_PROCEDURE(),
			   @ErrorLine = ERROR_LINE(),
			   @ErrorMessage = ERROR_MESSAGE();

		RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);

	END CATCH
END
GO

-- displays usage statistics
CREATE VIEW [dbo].[vw_IndexUsageStats]
AS
SELECT
	s.StatsDate,
	vn.Value AS ServerName,
	dbn.Value AS DatabaseName,
	sn.Value AS SchemaName,
	tn.Value AS TableName,
	dn.Value AS IndexName,
	s.IndexID,
	s.User_Seeks,
	s.User_Scans,
	s.User_Lookups,
	s.User_Updates,
	s.System_Seeks,
	s.System_Scans,
	s.System_Lookups,
	s.System_Updates
FROM dbo.IndexUsageStats s
INNER JOIN dbo.Names vn ON s.ServerNameID = vn.ID
INNER JOIN dbo.Names dbn ON s.DatabaseNameID = dbn.ID
INNER JOIN dbo.Names sn ON s.SchemaNameID = sn.ID
INNER JOIN dbo.Names tn ON s.TableNameID = tn.ID
LEFT JOIN dbo.Names dn ON s.IndexNameID = dn.ID;
GO
</pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=LXdhOESxUNs:VcwX0D6B5mI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=LXdhOESxUNs:VcwX0D6B5mI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=LXdhOESxUNs:VcwX0D6B5mI:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/LXdhOESxUNs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2012/01/collecting-index-usage-statistics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2012: New Year, New Goals</title>
		<link>http://www.bobpusateri.com/archive/2012/01/2012-new-year-new-goals/</link>
		<comments>http://www.bobpusateri.com/archive/2012/01/2012-new-year-new-goals/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 13:42:55 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=710</guid>
		<description><![CDATA[<p>Happy New Year to all! At the start of 2011, I laid out some goals for the year and did an update on them back in July. Now that it&#8217;s 2012 it&#8217;s a great time to take a look at what I accomplished (and fell short on) last year and also set some new targets. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.flickr.com/photos/sally_12/339912423/" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Happy New Year" src="http://img.bobpusateri.com/bc/2012/01/HappyNewYear.jpg" class="alignright" width="350" height="377" /></a>Happy New Year to all! At the start of 2011, I <a href="http://www.bobpusateri.com/archive/2011/01/t-sql-tuesday-14-my-techie-resolutions/" target="_blank">laid out some goals</a> for the year and did an update on them <a href="http://www.bobpusateri.com/archive/2011/07/2011-goals-update-midyear-edition/" target="_blank">back in July</a>. Now that it&#8217;s 2012 it&#8217;s a great time to take a look at what I accomplished (and fell short on) last year and also set some new targets.  My 2011 goals were as follows:</p>
<p><strong>Speak More</strong> &#8211; I spoke at two SQL Saturdays this year, <a href="http://www.bobpusateri.com/archive/2011/03/sql-saturday-67-wrap-up/" target="_blank">#67 in Chicago</a> and <a href="http://www.bobpusateri.com/archive/2011/11/sql-saturday-101-wrap-up/" target="_blank">#101 in Kansas City</a>. I had hoped to make it to more than 2, but I still met my goal for the year and am hoping to continue the trend.</p>
<p><strong>Travel More</strong> &#8211; I flew to Kansas City when I spoke there, so I&#8217;ll consider this goal completed as well.</p>
<p><strong>Become eligible to take the MCM exam</strong> &#8211; I achieved this when I <a href="http://www.bobpusateri.com/archive/2011/04/microsoft-exam-70-451-wrap-up/" target="_blank">passed 70-451</a> back in April. Check!</p>
<p><strong>Attend training</strong> &#8211; I considered this done when I attended the <a href="http://www.bobpusateri.com/archive/2011/05/my-sqlskills-immersion-experience/" target="_blank">SQLskills Immersion Event in Chicago</a> in May.</p>
<p><strong>Keep up the blogging</strong> &#8211; I had kind of a mid-year lull in blog posts, but I like to think I finished off strong. I had 39 posts in 2011, but 45 in 2010. Worse yet, I didn&#8217;t even blog the entire year in 2010. Definitely a fail here.</p>
<p><strong>Learn IO</strong> &#8211; As I mentioned in July, the plan was for my team to get a new SAN this year. We now have the SAN, actually it was delivered just last week. Unfortunately with the holidays apparently nobody from the vendor was available to install it, so as far as I know it is currently in our datacenter but still in boxes. Hopefully it gets set up soon so I can start working with it, but in the meantime this is a fail as well.</p>
<p><strong>Help out more</strong> &#8211; I&#8217;m still around on twitter and chip in on #sqlhelp when I can, but more things going on at work keep me from being as active as I would like. I&#8217;m going to have to find a way to increase my activity. Fail.</p>
<p>All in all I consider myself to be 4 for 7. I did some great things in 2011, but not quite as much as I had hoped. That being said, I think it&#8217;s ok that I didn&#8217;t do everything I wanted to as those things will automatically roll over into next year. Here&#8217;s what I hope to accomplish in 2012:</p>
<p><strong>Continue all the above</strong> &#8211; While I listed the above as goals, many of them are more of a journey than a destination. For example, training is a process that should have no end because there will always be something else out there to learn. The same goes for speaking, traveling, blogging and helping out. As for my goal of learning more about IO (and SAN management in particular) I should get that opportunity very soon once our new hardware is installed.</p>
<p><strong>More MCM Progress</strong> &#8211; Becoming eligible to take the Microsoft Certified Master exam was great, but that&#8217;s no stopping point. I need to keep up studying, practicing, and working towards passing things! I don&#8217;t feel comfortable saying I want to become an MCM in 2012, so instead my goal is to continue progressing toward it.</p>
<p><strong>Attend the PASS Summit</strong> &#8211; I should have done this long ago but never got the opportunity, so one of my goals for this year is to attend the PASS Summit. Perhaps this year I can be on the other side of all the tweets coming from the keynote! An added bonus would be if I could speak there, and I will definitely be submitting a few abstracts once the call for speakers opens.</p>
<p><strong>Blog smarter, not harder</strong> &#8211; While my previous goal of keeping up my blogging is all well and good, I don&#8217;t just want to focus on the number of posts I write &#8211; anyone can write a lot of short and useless things and call it a victory in terms of quantity. I&#8217;m generally happy with what I put up here &#8211; if I don&#8217;t like a post then it doesn&#8217;t go live, and I&#8217;ve left a few on the cutting room floor or delayed them so they can be improved. In 2012 I plan to continue this trend and ensure that when you come here you will find informational, helpful, and thought-provoking material. As always, I welcome your comments and do my best to respond to them in short order. If you, my readers, aren&#8217;t happy, then there&#8217;s really no point in me having a blog to begin with!</p>
<p>So that&#8217;s my goals for the year. May you all have a happy, healthy, and prosperous 2012!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=gjVkz_qW1bs:sF-DvJbTNbQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=gjVkz_qW1bs:sF-DvJbTNbQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=gjVkz_qW1bs:sF-DvJbTNbQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/gjVkz_qW1bs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2012/01/2012-new-year-new-goals/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>T-SQL Tuesday #025: Trick or …?</title>
		<link>http://www.bobpusateri.com/archive/2011/12/t-sql-tuesday-025-trick-or/</link>
		<comments>http://www.bobpusateri.com/archive/2011/12/t-sql-tuesday-025-trick-or/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 13:45:15 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>
		<category><![CDATA[TSQL Tuesday]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=707</guid>
		<description><![CDATA[<p>This month&#8217;s T-SQL Tuesday is hosted by Allen White (blog &#124; @SQLRunr) and is an invitation to show off a nifty T-SQL trick you use to make your job easier.  Here&#8217;s one of my favorites as of late:</p>
<p>Some of the source systems we copy from shard their data across multiple similar tables.  For [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sqlblog.com/blogs/allen_white/archive/2011/12/05/t-sql-tuesday-025-invitation-to-share-your-tricks.aspx" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="T-SQL Tuesday Logo" src="http://img.bobpusateri.com/bc/2010/06/TSQL2sDay150x150.jpg" title="T-SQL Tuesday!" class="alignright" width="150" height="150" /></a>This month&#8217;s <a href="http://sqlblog.com/blogs/allen_white/archive/2011/12/05/t-sql-tuesday-025-invitation-to-share-your-tricks.aspx" target="_blank">T-SQL Tuesday</a> is hosted by Allen White (<a href="http://sqlblog.com/blogs/allen_white/default.aspx" target="_blank">blog</a> | <a href="http://twitter.com/sqlrunr" target="_blank">@SQLRunr</a>) and is an invitation to show off a nifty T-SQL trick you use to make your job easier.  Here&#8217;s one of my favorites as of late:</p>
<p>Some of the source systems we copy from shard their data across multiple similar tables.  For example, instead of having 1 table named dbo.Sales, they might have 30 of them named <code>dbo.Sales_001</code> to <code>dbo.Sales_030</code>. If there were a rhyme or reason to this sharding it might be seen as an advantage, but unfortunately neither myself nor others on the team have ever found a method to this madness, and the vendor will not divulge the way they do this.  As if that&#8217;s not bad enough, additional tables can pop up out of nowhere, and not all these tables are guaranteed to contain the same columns.  Table <code>dbo.Sales_031</code> may pop up tomorrow and have only a subset of the columns from the previous 30 tables, or may contain new columns not present in any of the others.</p>
<p>To keep this all straight, I have a process that compares the columns in all applicable tables and generates a view that combines their contents using UNION ALL.  I&#8217;ve actually <a href="http://www.bobpusateri.com/archive/2011/10/creating-views-in-another-database/" target="_blank">blogged</a> about an aspect of this before, but today I have a function containing a nice little trick that&#8217;s proven very helpful for me.  Since the tables I&#8217;m generating a view of aren&#8217;t guaranteed to have the same columns in them, a simple &#8220;<code>SELECT *</code>&#8221; from each of them won&#8217;t work because unioning tables together requires identical datatypes in the same order. Instead I have to generate a select statement that explicitly lists all columns for every table.  T-SQL can easily accomplish this with cursors and loops, but then I found <a href="http://msdn.microsoft.com/en-us/library/ms189885.aspx" target="_blank">FOR XML PATH</a>, which made life a lot simpler.</p>
<p>FOR XML PATH has many features which are outside the scope of this post, but the one behavior we&#8217;re going to exploit today is that you can pass a row tag name that&#8217;s blank.  When you do this, instead of sandwiching each row between tags, it simply concatenates all the row values together into one string. If you add commas, you&#8217;ve got a great way to list out all the columns of a table which you can then form into a SELECT statement.  Without any further ado, here&#8217;s the demo code:</p>
<pre class="brush: sql; title: ; notranslate">
-- create our demo table with a few columns
CREATE TABLE dbo.MyTable (
   ID INT NOT NULL,
   Value VARCHAR(20),
   Notes NVARCHAR(MAX)
);

-- select the table's columns from system tables
SELECT c.name
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name = 'MyTable'
ORDER BY c.column_id;

-- now let's format it as XML
SELECT c.name
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name = 'MyTable'
ORDER BY c.column_id
FOR XML PATH;

-- now pass a blank string argument to PATH
-- note how the &lt;row&gt; tags are now removed but column tags remain
SELECT c.name
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name = 'MyTable'
ORDER BY c.column_id
FOR XML PATH('');

-- casting it to NVARCHAR removes the tags for each column
DECLARE @s NVARCHAR(MAX);

-- now let's add a blank string argument to PATH
SET @s = (
      SELECT ',' + QUOTENAME(c.name) -- comma to separate names
      FROM sys.columns c
      INNER JOIN sys.tables t ON c.object_id = t.object_id
      WHERE t.name = 'MyTable'
      ORDER BY c.column_id
      FOR XML PATH('') -- XML that really isn't
   );

-- remove the leading comma
SELECT SUBSTRING(@s, 2, LEN(@s));
</pre>
<p>Wrap the final output with a SELECT and a table name and you&#8217;re good to go.  There&#8217;s tons more uses for this than creating lists of columns &#8211; basically anytime you want to turn column values into a delimited list you can make it happen using this method. Happy coding!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=35SS93GDYt4:B82mixGbdVs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=35SS93GDYt4:B82mixGbdVs:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=35SS93GDYt4:B82mixGbdVs:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/35SS93GDYt4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/12/t-sql-tuesday-025-trick-or/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL Saturday #119 Open for Registration!</title>
		<link>http://www.bobpusateri.com/archive/2011/12/sql-saturday-119-open-for-registration/</link>
		<comments>http://www.bobpusateri.com/archive/2011/12/sql-saturday-119-open-for-registration/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 14:47:07 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=706</guid>
		<description><![CDATA[<p>The third time&#8217;s a charm! SQL Saturday #119 (Chicago 2012) has been posted on the SQL Saturday website!  It will once again be held at the DeVry University campus in Addison, IL and will be on May 19, 2012.</p>
<p>SQL Saturday in Chicago has a special place in my heart for a few reasons.  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://sqlsaturday.com/119/eventhome.aspx" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="SQL Saturday 119 Logo" src="http://img.bobpusateri.com/bc/2011/12/sqlsat119_web.png" class="alignright" width="236" height="115" /></a>The third time&#8217;s a charm! SQL Saturday #119 (Chicago 2012) has been posted on the <a href="http://sqlsaturday.com/119/eventhome.aspx" target="_blank">SQL Saturday website</a>!  It will once again be held at the <a href="http://www.devry.edu/" target="_blank">DeVry University</a> campus in <a href="http://www.devry.edu/locations/campuses/loc_addisoncampus.jsp" target="_blank">Addison, IL</a> and will be on May 19, 2012.</p>
<p>SQL Saturday in Chicago has a special place in my heart for a few reasons.  The first SQL Saturday I ever attended was SQL Saturday #31 back in 2009, the very first one held in Chicago.  I didn&#8217;t have this blog back then, but had an excellent time.  Last year was SQL Saturday #67, which <a href="http://www.bobpusateri.com/archive/2011/03/sql-saturday-67-this-week/" target="_blank">I did</a> <a href="http://www.bobpusateri.com/archive/2011/03/sql-saturday-67-wrap-up/" target="_blank">blog about</a>.  I was also very fortunate to be part of a great group of people who help put it together, and am back for more this time around.  The rest of our team consists of:</p>
<p>- Ted Krueger (<a href="http://blogs.lessthandot.com/index.php/All/?disp=authdir&#038;author=68" target="_blank">blog</a> | <a href="http://twitter.com/onpnt" target="_blank">@onpnt</a>)<br />
- Aaron Lowe (<a href="http://www.aaronlowe.net/" target="_blank">blog</a> | <a href="http://twitter.com/vendoran" target="_blank">@vendoran</a>)<br />
- Bill Lescher (<a href="http://twitter.com/blescher" target="_blank">@blescher</a>)<br />
- Rich Rousseau (<a href="http://twitter.com/zigzag219" target="_blank">@zigzag219</a>)<br />
- Wendy Pastrick (<a href="http://wendyverse.blogspot.com/" target="_blank">blog</a> | <a href="http://twitter.com/wendy_dance" target="_blank">@wendy_dance</a>)</p>
<h4>Register Today!</h4>
<p>Registration is open, so <a href="http://sqlsaturday.com/119/register.aspx" target="_blank">sign up today</a>!  We had a great turn out last year and we&#8217;re hoping to fill up again!  The event itself is free, but there is a $10.00 charge for lunch (it won&#8217;t be pizza!)  </p>
<h4>Why You Need To Be There</h4>
<ul>
<li><strong>It&#8217;s free knowledge!</strong>  Yes there is a charge for lunch, but that&#8217;s optional.  The training itself costs nothing. </li>
<li><strong>Meet other awesome DBAs!</strong>  Most companies have very few DBAs, sometimes only one.  This can lead to feelings of isolation and that the whole world of developers is against you.  You&#8217;re not alone though &#8211; there&#8217;s tons of us out there!  Community events are by far the best way to meet people in this field &#8211; where else can you hang out all day with a bunch of people as passionate about databases as you are?</li>
<li><strong>Did I mention it&#8217;s free?</strong></li>
</ul>
<h4>Call for Speakers</h4>
<p>Have you spoken at work, a user group, or a SQL Saturday before?  Have you never tried but are looking to take the plunge?  The call for speakers is open until April 19, 2012, so please <a href="http://sqlsaturday.com/119/callforspeakers.aspx" target="_blank">submit an abstract</a> (or two or three) if you&#8217;re at all interested!</p>
<p>I can&#8217;t wait to see you there in May!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=DZ_DvLVt5pM:jLmIturmdDo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=DZ_DvLVt5pM:jLmIturmdDo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=DZ_DvLVt5pM:jLmIturmdDo:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/DZ_DvLVt5pM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/12/sql-saturday-119-open-for-registration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Christmas Gifts I’d Like to See</title>
		<link>http://www.bobpusateri.com/archive/2011/12/christmas-gifts-id-like-to-see/</link>
		<comments>http://www.bobpusateri.com/archive/2011/12/christmas-gifts-id-like-to-see/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 13:45:38 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=704</guid>
		<description><![CDATA[<p>Well, we&#8217;re back at the top of the month again, and this time around for Meme Monday we&#8217;re to talk about what we&#8217;d love to see under the tree from Microsoft.  This got my creative juices flowing, and I came up three wishes:</p>
<p>First and foremost, if I had one wish that I could wish [...]]]></description>
			<content:encoded><![CDATA[<p>Well, we&#8217;re back at the top of the month again, and this time around for Meme Monday we&#8217;re to talk about <a href="http://thomaslarock.com/2011/11/meme-monday-for-december/" target="_blank">what we&#8217;d love to see under the tree from Microsoft</a>.  This got my creative juices flowing, and I came up three wishes:</p>
<p>First and foremost, if I had one wish that I could wish this holiday season, it would be that <a href="http://www.hulu.com/watch/115715/saturday-night-live-steve-martins-holiday-wish" target="_blank">all the children of the world would join hands and sing together in the spirit of harmony and peace</a>.</p>
<p>If I had two wishes that I could wish for this holiday season, it would be for all of the children of the world to join hands and sing, and for SQL Server to natively support <strong>object-level restores</strong>.  </p>
<p><a href="http://www.flickr.com/photos/wolfsavard/3327749796" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Christmas Presents" src="http://img.bobpusateri.com/bc/2011/12/ChristmasPresents.jpg" class="alignright" width="300" height="448" /></a>When working with a large database, native backups take a good deal of time to create and restore.  For this reason, VLDBs are likely to be backed up using non-native methods such as SAN snapshots, but let&#8217;s forget about those and stick with what Microsoft includes in the box.  If a single table needs to be restored from a backup, the only native way to accomplish this at the moment is to restore the entire database somewhere else and then copy the desired table back to the production server.  This takes a great amount of disk space (the entire size of the database) as well as the time necessary to restore all that data.  If available, filegroup backups can make it possible to restore only the specific filegroup(s) necessary for said table(s), but even that would be restoring more data than is necessary, since filegroups typically contain more than one table.</p>
<p>The best solution is to be able to restore an individual table or other object directly from a backup.  Since only the necessary data would be read out of the backup this would keep the required time and disk space to a minimum.  This feature is already offered by several third party vendors, but having it be built-in would be a huge help as you wouldn&#8217;t have to sit down with your boss and make the case for purchasing yet another tool.</p>
<p>If I had three wishes that I could wish for this holiday season, it would be again for the children, for object-level restores, and for the ability to <strong>run integrity checks on a backup</strong>.</p>
<p>The time it takes for DBCC CHECKDB to complete increases along with the size of the database being checked, and as databases get larger the general recommendation for integrity checks shifts towards running them on another server instead of the production machine.  Once again limiting ourselves to options provided natively by Microsoft, we would have to restore a full backup of our very large database on another machine and run DBCC CHECKDB on it.  As before, this will be expensive both in terms of time and disk space.</p>
<p>A few years ago Paul Randal mentioned in one of this <a href="http://sqlskills.com/blogs/paul/post/CHECKDB-From-Every-Angle-Consistency-Checking-Options-for-a-VLDB.aspx" target="_blank">blog posts</a> that during his time at Microsoft he developed and <a href="http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&#038;Sect2=HITOFF&#038;d=PALL&#038;p=1&#038;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&#038;r=1&#038;f=G&#038;l=50&#038;s1=7277905.PN.&#038;OS=PN/7277905&#038;RS=PN/7277905" target="_blank">patented</a> a way to run DBCC CHECKDB on a backup without restoring it.  I can&#8217;t imagine why Microsoft would sit on this technology, as I know it would be a huge help to me and I&#8217;m sure many others could benefit from it as well.  Hopefully sometime it can be included as a feature.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=E5ravdy7Z1s:M14WT9DCaV4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=E5ravdy7Z1s:M14WT9DCaV4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=E5ravdy7Z1s:M14WT9DCaV4:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/E5ravdy7Z1s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/12/christmas-gifts-id-like-to-see/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The 1433rd Psalm</title>
		<link>http://www.bobpusateri.com/archive/2011/11/the-1433rd-psalm/</link>
		<comments>http://www.bobpusateri.com/archive/2011/11/the-1433rd-psalm/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 13:45:44 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=699</guid>
		<description><![CDATA[<p></p>
<p style="text-align: center;">The DBA is my shepherd; I shall not want.</p>
<p style="text-align: center;">He maketh me to lie down in green Integration Services tasks:
he leadeth me beside the still SSDs.</p>
<p style="text-align: center;">He restoreth my filegroups:
he leadeth me in the paths of MS best practices for his sanity&#8217;s sake.</p>
<p style="text-align: center;">Yea, though I walk through the valley [...]]]></description>
			<content:encoded><![CDATA[<p><em></p>
<p style="text-align: center;">The DBA is my shepherd; I shall not want.</p>
<p style="text-align: center;">He maketh me to lie down in green Integration Services tasks:<br />
he leadeth me beside the still SSDs.</p>
<p style="text-align: center;">He restoreth my filegroups:<br />
he leadeth me in the paths of MS best practices for his sanity&#8217;s sake.</p>
<p style="text-align: center;">Yea, though I walk through the valley of the shadow of joins, I will fear no scans:<br />
for thou art the optimizer; Thy indexes and statistics they comfort me.</p>
<p style="text-align: center;">Thou preparest a table before me in the presence of mine schemas:<br />
thou anointest my database with DBCC CHECKDB;<br />
my plan cache runneth over.</p>
<p style="text-align: center;">Surely consistency and integrity shall follow me all the days of my life:<br />
and I will dwell in the house of the DBA for ever.</p>
<p></em></p>
<p><code><br /></code><br />
<code><br /></code></p>
<p>I can&#8217;t take full credit for this, as I was inspired by some remarks on twitter quite a while ago (&#8220;Yea, though I walk through the valley&#8230;&#8221;) A little detective work showed it probably originated on the <a href="http://www.sqlservercentral.com/Forums/Topic604325-61-2136.aspx#bm1019302" target="_blank">SQL Server Central Forum</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=ill9QywqdoE:yVFfvZntHlU:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=ill9QywqdoE:yVFfvZntHlU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=ill9QywqdoE:yVFfvZntHlU:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/ill9QywqdoE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/11/the-1433rd-psalm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Tale of Training</title>
		<link>http://www.bobpusateri.com/archive/2011/11/a-tale-of-training/</link>
		<comments>http://www.bobpusateri.com/archive/2011/11/a-tale-of-training/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 13:45:20 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[Thoughts]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=701</guid>
		<description><![CDATA[<p>As a follow-up to my previous post about the steps you may have to go through to attend training if your employer can&#8217;t or won&#8217;t offer assistance in the form of either money or time off, I have a story of my own to tell.  I was unhappy at my previous place of work [...]]]></description>
			<content:encoded><![CDATA[<p>As a follow-up to <a href="http://www.bobpusateri.com/archive/2011/11/negotiating-your-way-to-training/">my previous post</a> about the steps you may have to go through to attend training if your employer can&#8217;t or won&#8217;t offer assistance in the form of either money or time off, I have a story of my own to tell.  I was unhappy at my previous place of work for several reasons, a few of which I&#8217;ve blogged about already and a few more I&#8217;m sure will come in the future.</p>
<p>Back in March <a href="http://sqlskills.com/BLOGS/PAUL/post/Internals-Design-and-Performance-class-in-Chicago-in-May.aspx" target="_blank">it was announced</a> that SQLskills was coming to Chicago in May for one of their <a href="http://www.sqlskills.com/T_sqlskillsimmersionevents.asp" target="_blank">immersion events</a>, and I immediately knew I had to find a way to get there for several reasons.  First, they hadn&#8217;t ever held such an event in Chicago before, at least that I had known of.  Second, it was actually in the suburb of Oak Brook, which is no more than 20 minutes from my house, meaning I could save significant money by not having to pay for hotel accommodations.  I realize there are some good reasons others have blogged about for staying at the hotel for such an event as opposed to commuting home every night, but for me the money savings was key.  Finally (and perhaps most importantly), I felt I was ready for such training.  Had this occurred a year earlier I don&#8217;t think I would have been prepared, but at this point I believed I had the solid understanding of concepts that would allow me to benefit from this level of instruction.</p>
<p><a href="http://www.flickr.com/photos/beleaveme/4965799533/" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Lemonade" src="http://img.bobpusateri.com/bc/2011/11/Lemonade.jpg" class="alignright" width="350" height="522" /></a>When I took my previous job, I was told they had a budget for training and professional development and that I would be able to make use of it if an appropriate event came up.  Had I been told otherwise, I never would have accepted the position to begin with.  Feeling the immersion event was a great opportunity, I brought it up to my manager.  He said he would think about it and get back to me.  A month passed and I heard nothing, so I asked again.  At that point he told me no, he wouldn&#8217;t be able to help me pay for it, because he didn&#8217;t feel I needed any training.  You see, I had this habit of getting my work done correctly, on time, and never really had to ask anyone to help me in the process.  To me that would mean that I&#8217;m a good worker, but apparently to him it meant that I was as good as he needed me to be and thus didn&#8217;t need any form of training.  I guess to be worthy of training, I would need to screw things up or asked to have my hand held while doing my job.  What an excellent work ethic to instill in your employees!</p>
<p>After a few more attempts of explaining that such opportunities don&#8217;t come around often, I got a final answer of no, they would not pay for it.  Ok fine, I thought.  I told them I would pay for it myself and asked if I could have the time off to attend without taking away from my vacation.  I got a firm &#8220;no&#8221; for that as well.  I was also told that taking the time off without pay wasn&#8217;t an option, so the only way I was getting the time off to attend the class would be if I requested the vacation time and they decided to approve it.  Realizing again that the chance for such training wouldn&#8217;t come around again for a while, I decided to go ahead and take the week off to attend.  I felt the benefits of the immersion event would far outweigh the cost in terms of both money and vacation time.  Besides, I might not always have the money to front for such experiences.</p>
<p>I went to the class and it was amazing.  Everything I had hoped it would be.  I&#8217;ve <a href="http://www.bobpusateri.com/archive/2011/05/my-sqlskills-immersion-experience/">already blogged</a> about my experience, so if you&#8217;re interested and haven&#8217;t read about it already, feel free to check out that post.</p>
<p>When I got back to work after my week of vacation, recharged from my week of being immersed, the funniest thing happened.  My manager had the gall to ask me if I could copy my notes and materials from the class so the other DBAs could benefit.  My answer literally was &#8220;not just no, HELL NO!&#8221;.  I attended that class on my own dime and my own time.  Work had no interest in it, and besides I was on vacation.  Whether I spent the week doing consulting work, lying on a beach, or being an axe murderer it really shouldn&#8217;t matter to them.  He wasn&#8217;t pleased, but I had another ace up my sleeve:</p>
<p>The benefits of our SQL Server community never cease to amaze me.  It&#8217;s an amazing way to meet other people, and those people will put you in touch with others, some of which might be looking to hire a new DBA.  A few weeks prior to the immersion event I got an email from Brent Ozar (<a href="http://www.brentozar.com/" target="_blank">blog</a> | <a href="http://twitter.com/#!/brento" target="_blank">@BrentO</a>) saying that one of his clients was looking to hire a new DBA and he thought I would be a great fit.  He put me in touch with them, I interviewed, and I was offered the job while I was away at training for the week.  Upon my return I was planning on giving my two weeks&#8217; notice anyway, but it was an extra convenient time to do so when I was asked to hand over my notes.  It made the moment all the sweeter.</p>
<p>So what&#8217;s the lesson from all of this?  I like to think that &#8220;if there&#8217;s a will, there&#8217;s a way.&#8221;  I was able to achieve my goal and learn a ton even though it cost me money and vacation time.  Perhaps the bigger lesson here is that nothing has to be permanent if you don&#8217;t want it to be.  Never be afraid to ping your network when you&#8217;re looking for work, even if you&#8217;re just passively exploring your options.  You never know what might pop up.</p>
<p><em>A very Happy Thanksgiving to all my readers who celebrate it!  While it&#8217;s an American holiday, I like to think that the concept of gathering with family and loved ones to share a meal and reflect on our many blessings can be appreciated in any corner of the world.  All the best to you and yours!</em></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=WcSpA2sPGqU:8Tln1_xWDj4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=WcSpA2sPGqU:8Tln1_xWDj4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=WcSpA2sPGqU:8Tln1_xWDj4:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/WcSpA2sPGqU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/11/a-tale-of-training/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Negotiating Your Way to Training</title>
		<link>http://www.bobpusateri.com/archive/2011/11/negotiating-your-way-to-training/</link>
		<comments>http://www.bobpusateri.com/archive/2011/11/negotiating-your-way-to-training/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 13:45:19 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[Professional Development]]></category>
		<category><![CDATA[SQLServerPedia Syndication]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=697</guid>
		<description><![CDATA[<p>In honor of today being the last day to get the special preview rate for the 2012 PASS Summit, I thought I&#8217;d offer some tips on negotiating with your boss for money to attend such a conference or training event.  For more info about registration, click here.</p>
<p>Keeping up to date in the technology world [...]]]></description>
			<content:encoded><![CDATA[<p><em>In honor of today being the last day to get the special preview rate for the <a href="http://www.sqlpass.org/summit/2012/" target="_blank">2012 PASS Summit</a>, I thought I&#8217;d offer some tips on negotiating with your boss for money to attend such a conference or training event.  For more info about registration, <a href="http://www.sqlpass.org/summit/2012/Registration.aspx" target="_blank">click here</a>.</em></p>
<p><a href="http://www.flickr.com/photos/aidanmorgan/5589184944/" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Money" src="http://img.bobpusateri.com/bc/2011/11/Money.jpg" title="You&#039;re already showing it when it&#039;s in the banker&#039;s tray, right?" class="alignright" width="300" height="450" /></a>Keeping up to date in the technology world is a journey, not a destination.  I&#8217;m at peace with the fact that I&#8217;ll never know everything about SQL Server, but that doesn&#8217;t make me want to stop learning more.  If you&#8217;re not putting in the extra time to keep your skills and knowledge up to date, rest assured that someone else is.</p>
<p>Because of this, I&#8217;ve made sure to bring up questions about professional development in my last two job searches.  Employers should value employees who strive to progress in their field, and lack of willingness to allow me to do this is a total deal-breaker for me in a job search.  Of course it&#8217;s very easy to lie about it as well &#8211; I could make myself sound totally ambitious and energetic just to get my foot in the door somewhere, knowing that if I do a decent job they probably won&#8217;t get rid of me for lack of seeking out training.  Similarly it&#8217;s very easy for an employer to mislead an interviewee and tell them they have a budget for employee education and support such initiatives.  It&#8217;s also quite possible that an employer <em>had</em> a training budget when you were hired and those funds have since dried up or were reduced due to budget cuts or the like.  Unfortunately things like this can happen from time to time.  The question, then, is what to do about it.</p>
<p>So you&#8217;ve pitched a class or conference to your boss and they&#8217;ve come back to you saying that they&#8217;d like to send you because it seems like a great opportunity, but there just isn&#8217;t room in the budget.  Many will just give up at this point, but we&#8217;re more persistent than that, so some bargaining is now in order.</p>
<h4>Offer to pay part</h4>
<p>The first step is to ask if they can cover only part of the expense.  Offer to pay for the travel and hotel expenses yourself if the company can cover your registration fee.  Not only do you get to attend the training you wanted, but you also show your employer that you&#8217;re really serious about it and willing to contribute to the expense.  Be sure to stress that you&#8217;ll be happy to share the knowledge you gain with the rest of the team upon your return.  Another great point to bring up is that the company spends big money on SQL Server licenses, and a few thousand dollars extra to ensure you are well-trained to maintain such software is paltry by comparison.  </p>
<h4>Pay for it all in exchange for time</h4>
<p><a href="http://www.flickr.com/photos/fabrico/4420939363/" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="Bank" src="http://img.bobpusateri.com/bc/2011/11/Bank.jpg" title="This is actually a bank that shoots the coins upwards into the rocket.  My dad has one just like it - I can remember playing with it as a kid." class="alignright" width="300" height="448" /></a>If the above doesn&#8217;t work either because your boss won&#8217;t budge or perhaps there&#8217;s really no training budget at all, the next step is to offer to cover the costs yourself, provided you are given the time off to attend said training outside of your vacation time.  Both sides benefit from this &#8211; you get the training you want, and your employer gets the benefit of a more educated employee at no real expense to them.  Even though you&#8217;re paying, it&#8217;s still a win-win in my book.</p>
<p>This most common rebuttal to this will probably be along the lines of &#8220;we really can&#8217;t have you out of the office like that&#8221;.  Assure them you&#8217;ll be available by cel phone and email, just like when you&#8217;re at home on evenings and weekends.  Also mention that if there&#8217;s really an emergency, you&#8217;ll have your laptop with you and will be available to login remotely and work with the rest of the team back at the office to resolve any issues.  Point out that this is even a better deal for them than when you take vacation time, because you&#8217;ll be able to guarantee your availability this time around.</p>
<h4>Go completely on your own</h4>
<p>Finally, if your employer can&#8217;t stomach the cost of having you out of the office for free to attend training that will make you better at your job, my first thought is that you should think long and hard about if you want to remain working at that company.  Switching jobs is a pain, but I&#8217;d say chances are quite good you can do better somewhere else.  At this point, if you&#8217;re really serious about attending and you have PTO to burn, take the time off and go.  You&#8217;ll be glad you did.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=Ip_ompHt26Q:Mr6cplHS5gQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=Ip_ompHt26Q:Mr6cplHS5gQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=Ip_ompHt26Q:Mr6cplHS5gQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/Ip_ompHt26Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/11/negotiating-your-way-to-training/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>T-SQL Tuesday #24: Functions v. Procedures</title>
		<link>http://www.bobpusateri.com/archive/2011/11/t-sql-tuesday-24-functions-v-procedures/</link>
		<comments>http://www.bobpusateri.com/archive/2011/11/t-sql-tuesday-24-functions-v-procedures/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 14:45:20 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[TSQL Tuesday]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=696</guid>
		<description><![CDATA[<p>This month bring us the 24th edition of T-SQL Tuesday (24 already?  wow&#8230;.).  This time around our topic comes from Brad Schulz (blog) and has to do with stored procedures and functions.  Brad&#8217;s asking us to write whatever we&#8217;d like about either of them.</p>
<p>While from the bird&#8217;s-eye view both functions (the table-valued [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bradsruminations.blogspot.com/2011/10/invitation-for-t-sql-tuesday-024-prox-n.html" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="T-SQL Tuesday Logo" src="http://img.bobpusateri.com/bc/2010/06/TSQL2sDay150x150.jpg" title="T-SQL Tuesday!" class="alignright" width="150" height="150" /></a>This month bring us the 24th edition of T-SQL Tuesday (24 already?  wow&#8230;.).  This time around our topic comes from Brad Schulz (<a href="http://bradsruminations.blogspot.com/" target="_blank">blog</a>) and has to do with <a href="http://bradsruminations.blogspot.com/2011/10/invitation-for-t-sql-tuesday-024-prox-n.html" target="_blank">stored procedures and functions</a>.  Brad&#8217;s asking us to write whatever we&#8217;d like about either of them.</p>
<p>While from the bird&#8217;s-eye view both functions (the table-valued variety) and stored procedures appear as packages of code that can be encapsulated, they&#8217;re completely different and much thought should be given before making the decision to deploy code as either a stored procedure or function.  While they are totally different animals, I feel there&#8217;s a few basic pros and cons of each that should be known:</p>
<h4>Stored Procedures</h4>
<p><strong>Pros</strong></p>
<ul>
<li>The concept of a stored procedure is pretty well-known and similar across most platforms (you can find stored procedures in Oracle, MySQL, PostgreSQL, etc.)</li>
<li>Can perform pretty much any task, queries, administrative, etc.</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>It&#8217;s a huge pain to incorporate the result sets from a stored procedure into another query &#8211; Table-Valued Functions are much better for this purpose.</li>
</ul>
<h4>Table-Valued Functions</h4>
<p><strong>Pros</strong></p>
<ul>
<li>Can be used in a query just like any other table or view, and are very handy for this purpose.</li>
<li>Can be thought of as a view that accepts parameters.  An excellent choice if you want to expose views to people and shelter them from having to write additional SQL such as WHERE clauses.</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>Functions can&#8217;t make changes to the database state, such as changing the recovery model.  You can&#8217;t even create a function that does this &#8211; attempting to do so will return error 443.</li>
<li>You must list out ALL parameters, even those you just want to use the default value for (and assign them a value of DEFAULT).  This behavior is different from a stored procedure, where you can simply omit the parameters that you wish to use a default value for.</li>
</ul>
<p>I should add that this listing is only the tip of the iceberg.  There are many more differences between stored procedures and table-valued functions, and other types of functions (eg. Scalar) exist as well.  This is just a quick set of things I keep in my head for general design considerations.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=bQSqtCMKD5w:AiMChCnXUWc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=bQSqtCMKD5w:AiMChCnXUWc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=bQSqtCMKD5w:AiMChCnXUWc:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/bQSqtCMKD5w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/11/t-sql-tuesday-24-functions-v-procedures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts on #SQLFamily</title>
		<link>http://www.bobpusateri.com/archive/2011/11/thoughts-on-sqlfamily/</link>
		<comments>http://www.bobpusateri.com/archive/2011/11/thoughts-on-sqlfamily/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 14:36:29 +0000</pubDate>
		<dc:creator>Bob Pusateri</dc:creator>
				<category><![CDATA[Thoughts]]></category>

		<guid isPermaLink="false">http://www.bobpusateri.com/?p=694</guid>
		<description><![CDATA[<p>This is the second time I&#8217;ve participated in the &#8220;Meme Monday&#8221; blog events that have been brought to us by Tom LaRock (blog &#124; @SQLRockstar).  The topic is on what &#8220;SQL Family&#8221; means to us.  A few things popped into my head as soon as I read it, and I&#8217;m happy to share [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second time I&#8217;ve participated in the &#8220;Meme Monday&#8221; blog events that have been brought to us by Tom LaRock (<a href="http://thomaslarock.com/" target="_blank">blog</a> | <a href="http://twitter.com/#!/sqlrockstar" target="_blank">@SQLRockstar</a>).  The topic is on <a href="http://thomaslarock.com/2011/11/meme-monday-for-november/" target="_blank">what &#8220;SQL Family&#8221; means to us</a>.  A few things popped into my head as soon as I read it, and I&#8217;m happy to share them:</p>
<p><a href="http://www.flickr.com/photos/bananawacky/288256914/" target="_blank"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  alt="SQLFamily photo" src="http://img.bobpusateri.com/bc/2011/11/Family.jpg" class="alignright" width="300" height="410" /></a>First and foremost SQLFamily means there&#8217;s <strong>people you can count on</strong> for help, no matter what time it is.  Twitter definitely makes this possible, because there&#8217;s always people in our family awake in some part of the world, online and chattering about something.  The <a href="http://twitter.com/#!/search/%23sqlhelp" target="_blank">#sqlhelp</a> hash tag makes it even easier to accomplish this.</p>
<p>Another thing that&#8217;s made me feel special about our SQLFamily since the very beginning was the sense of <strong>equality</strong> between members.  There&#8217;s a very wide range of skills between all of us, from those who are just getting started in the database world all the way up to the experts that write books, documentation, and exams for everyone.  I&#8217;m very proud to say that I&#8217;ve never witnessed any form of elitist behavior, and it&#8217;s really nice to know that those at the top of the food chain haven&#8217;t forgotten that they started off at the bottom at one point too.</p>
<p>Finally, like any other type of family, there&#8217;s plenty of <strong>encouragement</strong> going around in our SQLFamily.  It&#8217;s an incredibly supportive and accepting environment.  When someone does something awesome like pass a certification exam, give a presentation or publish an excellent blog post, there&#8217;s always plenty of hi-fives and love to go around.  To me it&#8217;s a lot like the &#8220;cool kids club&#8221; in grade school, except membership is really and truly open to everyone.  That&#8217;s why I love it so much.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=WSX0e2zk9LY:qyoMKYD8mNk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/TheOuterJoin?a=WSX0e2zk9LY:qyoMKYD8mNk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/TheOuterJoin?i=WSX0e2zk9LY:qyoMKYD8mNk:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/TheOuterJoin/~4/WSX0e2zk9LY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.bobpusateri.com/archive/2011/11/thoughts-on-sqlfamily/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: www.bobpusateri.com @ 2012-02-03 15:23:05 -->

