<?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/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Brent Ozar PLF</title>
	
	<link>http://www.brentozar.com</link>
	<description>Your technology pain-relief experts.</description>
	<lastBuildDate>Wed, 23 May 2012 14:03:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/BrentOzar-SqlServerDba" /><feedburner:info uri="brentozar-sqlserverdba" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by-nc-nd/3.0/</creativeCommons:license><feedburner:emailServiceId>BrentOzar-SqlServerDba</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>The SQL Server Performance Checkup from a Consultant’s Perspective</title>
		<link>http://feedproxy.google.com/~r/BrentOzar-SqlServerDba/~3/tBN1m1Z8Czc/</link>
		<comments>http://www.brentozar.com/archive/2012/05/sql-server-performance-checkup-from-consultants-perspective/#comments</comments>
		<pubDate>Wed, 23 May 2012 14:00:13 +0000</pubDate>
		<dc:creator>Jes Schultz Borland</dc:creator>
				<category><![CDATA[Consulting]]></category>

		<guid isPermaLink="false">http://www.brentozar.com/?p=14663</guid>
		<description><![CDATA[Here at Brent Ozar PLF, we offer a server performance checkup to clients. As the newest member of the team, I wasn’t sure what to expect when running one. I found out that it’s pretty cool. I pretend we&#8217;re Special Forces operatives, strapped into our parachutes, doing a HALO opening over client servers. (This homemade parachute...<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
]]></description>
			<content:encoded><![CDATA[<p>Here at Brent Ozar PLF, we offer a <a href="http://www.brentozar.com/consulting-services/sql-server-performance-checkup/" target="_blank">server performance checkup</a> to clients. As the newest member of the team, I wasn’t sure what to expect when running one. I found out that it’s pretty cool. I pretend we&#8217;re Special Forces operatives, strapped into our parachutes, doing a HALO opening over client servers. (This homemade parachute gets caught on my chair a lot.)</p>
<div class="wp-caption alignright" style="width: 310px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; float: right;"><a href="http://www.flickr.com/photos/soldiersmediacenter/397708723/lightbox/" target="_blank"><img src="http://www.brentozar.com/wp-content/uploads/2012/05/parachuting-in-300x237.jpg" alt="" width="300" height="237" /></a><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">This isn&#39;t covered by worker&#39;s comp</p></div>
<p>This checkup is about learning as much as it is fixing servers. What have I learned? What is it like to be a consultant, to be deep-diving into a variety of environments?</p>
<div>
<h3>Variety is the Spice of Life</h3>
<p>Even though they all use the same software, every SQL Server environment is different. Each one has a few features installed. But have you worked in one company using clustering, replication, mirroring, and log shipping? How about full-text indexing and FileStream? How many different hardware configurations do you have? How many SAN vendors does one company use?</p>
<p>The checkups are enjoyable because I get to see a variety of configurations. There is always something new to learn. Seeing how something works in one environment can give me ideas for fixing or improving something in another.</p>
<h3>Teaching Best Practices</h3>
<p>Let me take you back a few years, to when I was handed the DBA title for the first time because the DBA left the company. At that time, I could write T-SQL and knew SSRS fairly well. However, I didn&#8217;t know auto-shrink and xp_cmdshell were bad. This isn&#8217;t knowledge we&#8217;re born with, it isn&#8217;t covered in most college textbooks, and a programmer won&#8217;t know. But I learned. Now, I get to pass on that knowledge.</p>
<p>Our <a href="http://www.BrentOzar.com/blitz/ " target="_blank">sp_Blitz script</a> will check for things like databases in Full recovery without log backups being run, users with sysadmin rights, user databases on the C: drive, and auto-shrink enabled. When I see things that aren&#8217;t best practices, I can point them out and teach the users why. I can encourage them to change the settings, if applicable, or discuss why they have it set that way. They learn something new, and I get to impart my knowledge. We all win.</p>
<h3>Community Contributions</h3>
<p>Our very own Brent Ozar wrote the sp_Blitz script. But there are a lot of other people&#8217;s queries we&#8217;ve built on. Adam Machanic, Amit Banerjee, and Dave Levy have provided inspiration. We use scripts from SQLServerPedia.com. We recommend <a href="http://BrentOzar.com/go/active" target="_blank">Adam Machanic’s sp_WhoIsActive</a>, and <a href="http://www.brentozar.com/go/FreeMaintenance/" target="_blank">Ola Hallengren’s maintenance scripts</a>.</p>
<p>There are many SQL Server resources available to you, whether they are blogs, videos, books, or scripts. We don’t reinvent the wheel each time we come to a problem, and you don’t need to either. As Brent has blogged before, <a href="http://www.brentozar.com/archive/2010/10/im-sending-my-clients-your-blog/" target="_blank">we send our clients to other people’s blogs</a> for resources.</p>
<h3>Ready the Parachutes!</h3>
<p>Running a performance checkup is a great experience for me and the client. Solving problems and teaching people at the same time is the most rewarding job I’ve had! I think a huge factor to being successful as a consultant is having the desire to constantly learn. If that sounds like you, there may be a career path for you to explore.</p>
</div>
<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=tBN1m1Z8Czc:9uEH2CTmtyI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?i=tBN1m1Z8Czc:9uEH2CTmtyI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=tBN1m1Z8Czc:9uEH2CTmtyI:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BrentOzar-SqlServerDba/~4/tBN1m1Z8Czc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.brentozar.com/archive/2012/05/sql-server-performance-checkup-from-consultants-perspective/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.brentozar.com/archive/2012/05/sql-server-performance-checkup-from-consultants-perspective/</feedburner:origLink></item>
		<item>
		<title>Storage Protocol Basics: iSCSI, NFS, Fibre Channel, and FCoE</title>
		<link>http://feedproxy.google.com/~r/BrentOzar-SqlServerDba/~3/lSrRNLThbW4/</link>
		<comments>http://www.brentozar.com/archive/2012/05/storage-protocol-basics-iscsi-nfs-fibre-channel-fcoe/#comments</comments>
		<pubDate>Tue, 22 May 2012 13:30:44 +0000</pubDate>
		<dc:creator>Brent Ozar</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Virtualization]]></category>
		<category><![CDATA[FC]]></category>
		<category><![CDATA[fcoe]]></category>
		<category><![CDATA[iscsi]]></category>
		<category><![CDATA[nfs]]></category>
		<category><![CDATA[storage]]></category>
		<category><![CDATA[vmware]]></category>

		<guid isPermaLink="false">http://www.brentozar.com/?p=14400</guid>
		<description><![CDATA[Wanna get your storage learn on?  VMware has a well-laid-out explanation of the pros and cons of different ways to connect to shared storage.  The guide covers the four storage protocols, but let&#8217;s get you a quick background primer first. iSCSI, NFS, FC, and FCoE Basics iSCSI means you map your storage over TCPIP.  You...<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
]]></description>
			<content:encoded><![CDATA[<p>Wanna get your storage learn on?  VMware has a well-laid-out explanation of the pros and cons of different ways to connect to shared storage.  The guide covers the four storage protocols, but let&#8217;s get you a quick background primer first.</p>
<h3>iSCSI, NFS, FC, and FCoE Basics</h3>
<p>iSCSI means you map your storage over TCPIP.  You typically put in dedicated Ethernet network cards and a separate network switch.  Each server and each storage device has its own IP address(es), and you connect by specifying an IP address where your drive lives.  In Windows, each drive shows up in Computer Manager as a hard drive, and you format it.  This is called block storage.</p>
<p>NFS means you access a file share like \\MyFileServerName\MyShareName, and you put files on it.  In Windows, this is a mapped network drive.  You access folders and files there, but you don&#8217;t see the network mapped drive in Computer Manager as a local drive letter.  You don&#8217;t get exclusive access to NFS drives.  You don&#8217;t need a separate network cable for NFS &#8211; you just access your file shares over whatever network you want.</p>
<p>Fibre Channel is a lot like iSCSI, except it uses fiberoptic cables instead of Ethernet cables.  It&#8217;s a separate dedicated network just for storage, so you don&#8217;t have to worry as much about performance contention &#8211; although you do still have to worry.</p>
<p>Fibre Channel Over Ethernet runs the FC protocol over Ethernet cables, specifically 10Gb Ethernet.  This gained niche popularity because you can use just one network (10Gb Ethernet) for both regular network traffic and storage network traffic rather than having one set of switches for fiber and one set for Ethernet.</p>
<p>Now that you&#8217;re armed with the basics, <a href="http://www.vmware.com/files/pdf/techpaper/Storage_Protocol_Comparison.pdf">check out VMware&#8217;s PDF guide</a>, then read on for my thoughts.</p>
<h3>What I See in the Wild</h3>
<p>1Gb iSCSI is cheap as all get out, and just as slow.  It&#8217;s a great way to get started with virtualization because you don&#8217;t usually need much storage throughput anyway &#8211; your storage is constrained by multiple VMs sharing the same spindles, so you&#8217;re getting random access, and it&#8217;s slow anyway.  It&#8217;s really easy to configure 1Gb iSCSI because you&#8217;ve already got a 1Gb network switch infrastructure.  SQL Server on 1Gb iSCSI sucks, though &#8211; you&#8217;re constrained big time during backups, index rebuilds, table scans, etc.  These large sequential operations that can easily saturate a 1Gb pipe, and storage becomes your bottleneck in no time.</p>
<p>NFS is the easiest way to manage virtualization, and I see a lot of success with it.  It&#8217;s probably an easy way to manage SQL clusters, too, but I&#8217;m not about to go there yet.  It&#8217;s just too risky if you&#8217;re using the same network for both data traffic and storage traffic &#8211; a big stream of sudden network traffic (like backups) over the same network pipes is a real danger for SQL Server&#8217;s infamous 15 second IO errors.  Using 10Gb Ethernet mitigates this risk, though.</p>
<p>Fibre Channel is the easiest way to maximize performance because you rule out the possibility of data traffic interfering with storage traffic.  It&#8217;s really hard to troubleshoot, and requires a dedicated full time SAN admin, but once it&#8217;s in and configured correctly, it&#8217;s happy days for the DBA.</p>
<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=lSrRNLThbW4:WjHDcuCfluI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?i=lSrRNLThbW4:WjHDcuCfluI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=lSrRNLThbW4:WjHDcuCfluI:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BrentOzar-SqlServerDba/~4/lSrRNLThbW4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.brentozar.com/archive/2012/05/storage-protocol-basics-iscsi-nfs-fibre-channel-fcoe/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.brentozar.com/archive/2012/05/storage-protocol-basics-iscsi-nfs-fibre-channel-fcoe/</feedburner:origLink></item>
		<item>
		<title>SQL Server Tricks: How Can I Restore a Subset of My Tables to A Prior Point in Time?</title>
		<link>http://feedproxy.google.com/~r/BrentOzar-SqlServerDba/~3/Tw6OS6dXLvo/</link>
		<comments>http://www.brentozar.com/archive/2012/05/sql-server-tricks-how-can-i-restore-subset-of-my-tables-prior-point-time/#comments</comments>
		<pubDate>Thu, 17 May 2012 13:00:58 +0000</pubDate>
		<dc:creator>Kendra Little</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[filegroups]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[Synonyms]]></category>
		<category><![CDATA[Tricks]]></category>

		<guid isPermaLink="false">http://www.brentozar.com/?p=14351</guid>
		<description><![CDATA[This question came up when working with a client last week. The team mentioned they were planning to move some tables into a new filegroup. The new filegroup is intended to help quickly restore data in cases when a monthly process goes off the rails and leaves the data in some tables in a bad...<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
]]></description>
			<content:encoded><![CDATA[<p>This question came up when working with a client last week. The team mentioned they were planning to move some tables into a new filegroup. The new filegroup is intended to help quickly restore data in cases when a monthly process goes off the rails and leaves the data in some tables in a bad state.</p>
<p>Over the years I’ve worked on a lot of backup and restore plans with SQL Server, and I learned the hard way that filegroup level restores don’t do exactly what you might think.</p>
<div id="attachment_14566" class="wp-caption alignright" style="width: 291px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; float: right;"><img class="size-medium wp-image-14566" title="ImportantDB" src="http://www.brentozar.com/wp-content/uploads/2012/05/ImportantDB-281x300.png" alt="DBZilla Attacks!" width="281" height="300" /><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">What if he only eats a FEW tables?</p></div>
<p>In this post, we’ll talk through a sample problem. I’ll explain while filegroup level backups don’t fit the bill to solve this problem, and then talk through a couple of alternatives that may make life easier.</p>
<h3 id="our_problem_we_need_to_restore_the_data_for_some_of_the_tables_in_a_database">Our Problem: We Need to Restore the Data for Some of the Tables in a Database</h3>
<p>Let’s say you manage a database named ImportantDB. Some tables are updated daily in ImportantDB, and other tables are only updated once per month. The tables updated once per month are updated by a legacy application and you don’t have access to the source code.</p>
<p>Periodically, the monthly load will fail due to issues outside of SQL Server. When this occurs, the recommended procedure is to reset the monthly tables to the state they were in prior to the monthly load job beginning, and restart the process. (Essentially, you start over.)</p>
<p>Restoring the entire database takes a long time, and might remove changes to the “daily” tables as well.</p>
<h3 id="attempt_1_filegroup_level_backups">Attempt 1: Filegroup Level Backups</h3>
<p>In SQL Server we have the ability to back up and restore individual filegroups. In Enterprise Edition, SQL Server also has the ability to have the Primary and select other filegroups online and responding to queries while you are restoring individual filegroups.</p>
<p>For situations like this, it <em>seems</em> like filegroup level backups and restores will be the answer to our problem. The plan we make looks like this:</p>
<ul>
<li>Move the monthly tables into a filegroup named MONTHLYTABLES</li>
<li>Set the filegroup as READ_ONLY</li>
</ul>
<p>Whenever we need to load data into the filegroup, we plan to:</p>
<ul>
<li>Take a filegroup level backup of MONTHLYTABLES</li>
<li>Set the MONTHLYTABLES filegroup as READ_WRITE</li>
<li>Start the process to change data</li>
<li>If there are any issues with the data load, restore over the filegroup from the READ_ONLY backup</li>
</ul>
<h3 id="why_filegroup_level_restores_don8217t_solve_this_problem">Why Filegroup Level Restores Don’t Solve This Problem</h3>
<p>The restore sequence described above in SQL Server won’t work, by design. SQL Server’s mission with filegroup level restores is described in Books Online <a href="http://msdn.microsoft.com/en-us/library/ms177425.aspx">here</a>:</p>
<blockquote><p>Each filegroup-restore sequence restores and recovers one or more offline filegroups to a point consistent with the database.</p></blockquote>
<p>As soon as the MONTHLYTABLES filegroup is made READ_WRITE, we can no longer restore over it with a backup made from a prior point in time and bring it online. We can perform the filegroup level RESTORE if we’re in the appropriate recovery model, but in order to bring it online we also have to restore additional log backups to bring it to a point in time that is consistent with the rest of the database. (Don’t believe me? Check out Tibor Karaszi’s fine <a href="http://sqlblog.com/blogs/tibor_karaszi/archive/2009/06/25/table-restore-and-filegroups.aspx">blog</a> on the topic with sample code. Tibor’s examples are for the full recovery model— play around with things and you’ll see that you can&#8217;t make it work in the simple recovery model, either.)</p>
<p>Why does it have to be this way? It’s because SQL Server doesn’t track transaction status by filegroups, and its mission is to ensure transactional consistency within a database. If we could restore individual filegroups to different points in time and bring everything online, we wouldn’t have a way to ensure consistency.</p>
<h3 id="alternative_1_database_snapshots">Alternative 1: Database Snapshots</h3>
<p>If we’re running SQL Server Enterprise Edition, we can automate a solution to our process by using a database snapshot. Our monthly load procedure would look like this:</p>
<ul>
<li>Create a database snapshot</li>
<li>Start the process to change data</li>
<li>If there are any issues with the data load, either:
<ul>
<li>Revert to the snapshot (this will impact the whole database)</li>
<li>Truncate and reload the monthly tables using the snapshot as a data source</li>
</ul>
</li>
</ul>
<p>This solution will work, but depending on the size of the monthly tables, it may have some performance problems. The database snapshot will use IO for all the data changed in the monthly tables. If the monthly tables are very large, we will end up spending a lot of writes against our snapshot file as well as the database we are repairing.</p>
<p>If it’s OK to lose any other data that has changed since the snapshot was taken, the revert option may work for us— provided that <a href="http://msdn.microsoft.com/en-us/library/ms179557(v=sql.105).aspx">we don’t mind dropping any full text catalogs and rebuilding the transaction log</a>.</p>
<p>The only time I really like a database snapshot option is when I’m 100% sure that other processes have not been updating data. That just isn’t the case for a lot of databases, so we may need to seek other options.</p>
<h3 id="alternative_2_views">Alternative 2: Views</h3>
<p>We could also solve this problem by moving the monthly tables into a new database named ImportantMonthly. Then, we would replace the original tables in ImportantDB with views. A simple view of “SELECT [columnnames] from ImportantMonthly.schema.table” would be put in place for each table.</p>
<div id="attachment_14569" class="wp-caption alignright" style="width: 276px;  border: 1px solid #dddddd; background-color: #f3f3f3; padding-top: 4px; margin: 10px; text-align:center; float: right;"><img class=" wp-image-14569 " title="DatabaseHero" src="http://www.brentozar.com/wp-content/uploads/2012/05/DatabaseHero-295x300.png" alt="ImportantDB is safe... and possibly has a friend." width="266" height="270" /><p style=' padding: 0 4px 5px; margin: 0;'  class="wp-caption-text">Important DB is safe... and possibly has a friend.</p></div>
<p>With the views defined in this way, they would function just like tables and allow insert, update, delete, and select statements to be run against the base tables.</p>
<p>This would allow the process to become:</p>
<ul>
<li>Take a full database backup of ImportantMonthly</li>
<li>Start the process to change data</li>
<li>If there are any issues with the data load, restore over the ImportantMonthly database</li>
</ul>
<p>The main gotcha to be aware with using views in this manner is that if the definition of the tables in ImportantMonthly changes, you may be required to refresh the metadata for the views with the procedure <a href="http://msdn.microsoft.com/en-us/library/ms187821.aspx">sp_refreshview</a>.</p>
<h3 id="alternative_3_synonyms">Alternative 3: Synonyms</h3>
<p>Similar to the view solution, we could move the tables into ImportantMonthly, and then replace the original tables in ImportantDB with synonyms.</p>
<p>Synonyms in SQL Server don’t have the same metadata issue as views, but there is one important thing to know: <a href="http://msdn.microsoft.com/en-us/library/ms187552.aspx">you cannot reference a synonym that is on the other side of a linked server</a>.</p>
<h3 id="the_devil_is_in_the_details">The Devil is in the Details</h3>
<p>This example highlights one thing to me: when you try to solve a problem with just one kind of tool, you have to make compromises. To build a strong, reliable solution and mitigate the risks, database administrators need the collaboration of whomever controls the application code for the database, whether that be a vendor or an in-house development team.</p>
<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=Tw6OS6dXLvo:kdimUDobNhM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?i=Tw6OS6dXLvo:kdimUDobNhM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=Tw6OS6dXLvo:kdimUDobNhM:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BrentOzar-SqlServerDba/~4/Tw6OS6dXLvo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.brentozar.com/archive/2012/05/sql-server-tricks-how-can-i-restore-subset-of-my-tables-prior-point-time/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.brentozar.com/archive/2012/05/sql-server-tricks-how-can-i-restore-subset-of-my-tables-prior-point-time/</feedburner:origLink></item>
		<item>
		<title>Video: Heaps in SQL Server: Performance, Maintenance, and Your Sanity</title>
		<link>http://feedproxy.google.com/~r/BrentOzar-SqlServerDba/~3/VOto9doIz7I/</link>
		<comments>http://www.brentozar.com/archive/2012/05/video-heaps/#comments</comments>
		<pubDate>Wed, 16 May 2012 13:00:58 +0000</pubDate>
		<dc:creator>Kendra Little</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Videos]]></category>
		<category><![CDATA[heaps]]></category>
		<category><![CDATA[Internals]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[Schema]]></category>

		<guid isPermaLink="false">http://www.brentozar.com/?p=14546</guid>
		<description><![CDATA[Do you use heaps in SQL Server? How can heaps impact your query performance and database maintenance? In this 30 minute webcast I will show you how heaps behave differently than than tables with clustered indexes in SQL Server. You&#8217;ll learn how to identify heaps, how to measure their size, and how to plan a...<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
]]></description>
			<content:encoded><![CDATA[<p>Do you use heaps in SQL Server? How can heaps impact your query performance and database maintenance? In this 30 minute webcast I will show you how heaps behave differently than than tables with clustered indexes in SQL Server. You&#8217;ll learn how to identify heaps, how to measure their size, and how to plan a change to convert your heaps to clustered indexes.</p>
<p>This talk is aimed toward DBAs and developers who have worked with SQL Server &gt;= 1 year. I cover LOTS of dynamic management views and tools to view table structures&#8211; it&#8217;s OK if you haven&#8217;t used them all before, you&#8217;ll still be able to get the concepts.</p>
<p>Want the scripts used in the talk? Scroll on down&#8211; scripts are included in this post below the video.</p>
<p><iframe width="600" height="338" src="http://www.youtube.com/embed/IenCauHymlo?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p><span id="more-14546"></span></p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">--Author: Brent Ozar PLF, LLC</span>
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">--Purpose: Demo some of the peculiarities of heaps in SQL Server.</span>
<span style="color: #808080; font-style: italic;">--This script is for use on TEST servers (not production). It creates</span>
<span style="color: #808080; font-style: italic;">--and drops a database and uses undocumented stored procedures.</span>
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">--References: We run this script in our video demo on heaps. Check out the</span>
<span style="color: #808080; font-style: italic;">--video for intepretation of the script results and more.</span>
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">--Usage notes: This demo uses both undocumented and documented procedures</span>
<span style="color: #808080; font-style: italic;">--in SQL Server.</span>
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">--The undocumented procedures are NOT meant to be run against</span>
<span style="color: #808080; font-style: italic;">--production-- they are widely used, but be careful with all undocumented procedures</span>
<span style="color: #808080; font-style: italic;">--and use at your own risk. (&quot;Undocumented&quot; means Microsoft doesn't officially</span>
<span style="color: #808080; font-style: italic;">--support them.)</span>
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">--This demo also uses sys.dm_db_database_page_allocations, which is a new undocumented</span>
<span style="color: #808080; font-style: italic;">--DMV in  SQL Server 2012. If you're testing these scripts against an earlier version of</span>
<span style="color: #808080; font-style: italic;">--SQL Server, you can use DBCC IND (also undocumented) to see the same information.</span>
<span style="color: #808080; font-style: italic;">--We include an example of DBCC IND with the syntax in the demo.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS IO OFF;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS <span style="color: #993333; font-weight: bold;">TIME</span> OFF;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Recreate the HeapsOfHeaps database for testing.</span>
<span style="color: #808080; font-style: italic;">--This drops the database-- use with care.  (Hopefully you</span>
<span style="color: #808080; font-style: italic;">--don't have production databases with that name.)</span>
&nbsp;
WHILE @@TRANCOUNT <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span>
    <span style="color: #993333; font-weight: bold;">BEGIN</span>
        <span style="color: #993333; font-weight: bold;">ROLLBACK</span>
    <span style="color: #993333; font-weight: bold;">END</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">IF</span> DB_ID<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'HeapsOfHeaps'</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span>
    <span style="color: #993333; font-weight: bold;">BEGIN</span>
        <span style="color: #993333; font-weight: bold;">USE</span> master;
        <span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">DATABASE</span> HeapsOfHeaps <span style="color: #993333; font-weight: bold;">SET</span> SINGLE_USER <span style="color: #993333; font-weight: bold;">WITH</span> <span style="color: #993333; font-weight: bold;">ROLLBACK</span> IMMEDIATE;
        <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">DATABASE</span> HeapsOfHeaps;
    <span style="color: #993333; font-weight: bold;">END</span>
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Create and use the database.</span>
<span style="color: #808080; font-style: italic;">--This creates it in the default location with default sizes-- change if you wish.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">DATABASE</span> HeapsOfHeaps;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">USE</span> HeapsOfHeaps;
<span style="color: #993333; font-weight: bold;">SET</span> NOCOUNT <span style="color: #993333; font-weight: bold;">ON</span>;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS IO OFF;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS <span style="color: #993333; font-weight: bold;">TIME</span> OFF;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's create a heap!</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> dbo<span style="color: #66cc66;">.</span>DataPile
    <span style="color: #66cc66;">&#40;</span>
      datapileid <span style="color: #993333; font-weight: bold;">BIGINT</span> <span style="color: #993333; font-weight: bold;">IDENTITY</span>  <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
      col1 <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1024</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span>
    <span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Insert 1000 rows.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">DECLARE</span> @i <span style="color: #993333; font-weight: bold;">INT</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span>;
<span style="color: #993333; font-weight: bold;">BEGIN</span> TRAN
WHILE @i <span style="color: #66cc66;">&lt;=</span> <span style="color: #cc66cc;">1000</span>
    <span style="color: #993333; font-weight: bold;">BEGIN</span>
        <span style="color: #993333; font-weight: bold;">INSERT</span>  dbo<span style="color: #66cc66;">.</span>dataPile <span style="color: #66cc66;">&#40;</span>col1<span style="color: #66cc66;">&#41;</span>
                <span style="color: #993333; font-weight: bold;">SELECT</span>  REPLICATE<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'A'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">200</span><span style="color: #66cc66;">&#41;</span> ;
        <span style="color: #993333; font-weight: bold;">SELECT</span>  @i <span style="color: #66cc66;">=</span> @i <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #993333; font-weight: bold;">END</span>
COMMIT;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Here's a query that will show if you have heaps.</span>
<span style="color: #808080; font-style: italic;">--You want to look for Index_Id = 0.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span>  sc<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span>Schema Name<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">,</span>
        so<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #66cc66;">&#91;</span><span style="color: #993333; font-weight: bold;">TABLE_NAME</span><span style="color: #66cc66;">&#93;</span>
<span style="color: #993333; font-weight: bold;">FROM</span>    sys<span style="color: #66cc66;">.</span>indexes si
        <span style="color: #993333; font-weight: bold;">JOIN</span> sys<span style="color: #66cc66;">.</span>objects so <span style="color: #993333; font-weight: bold;">ON</span> si<span style="color: #66cc66;">.</span>object_id <span style="color: #66cc66;">=</span> so<span style="color: #66cc66;">.</span>object_id
        <span style="color: #993333; font-weight: bold;">JOIN</span> sys<span style="color: #66cc66;">.</span>schemas sc <span style="color: #993333; font-weight: bold;">ON</span> so<span style="color: #66cc66;">.</span>schema_id <span style="color: #66cc66;">=</span> sc<span style="color: #66cc66;">.</span>schema_id
<span style="color: #993333; font-weight: bold;">WHERE</span>   so<span style="color: #66cc66;">.</span>is_ms_shipped <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>  <span style="color: #808080; font-style: italic;">/* Not shipped by Microsoft */</span>
        <span style="color: #993333; font-weight: bold;">AND</span> si<span style="color: #66cc66;">.</span>index_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span> <span style="color: #808080; font-style: italic;">/* Index Id 0 = A Heap */</span>
        <span style="color: #993333; font-weight: bold;">AND</span> so<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">TYPE</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'U'</span>; <span style="color: #808080; font-style: italic;">/* User table */</span>
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--You can also look at the table and TRY to find indexes</span>
<span style="color: #993333; font-weight: bold;">EXEC</span> sp_helpindex <span style="color: #ff0000;">'DataPile'</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's look at the structure of our heap with DBCC IND.</span>
<span style="color: #808080; font-style: italic;">--This is a special system command (undocumented!).</span>
<span style="color: #808080; font-style: italic;">--PageType 10= an IAM page (Index Allocation Map).</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Parameters: DatabaseName, TableName, IndexID</span>
&nbsp;
DBCC IND<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'HeapsOfHeaps'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--In SQL 2012 we can also query a new DMV to see allocations!</span>
<span style="color: #808080; font-style: italic;">--This DMV is also undocumented.</span>
<span style="color: #808080; font-style: italic;">--Parameters: DatabaseId, ObjectId, IndexId, PartitionId, mode</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_database_page_allocations<span style="color: #66cc66;">&#40;</span>db_id<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>object_id<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'DETAILED'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--We can also get information about the table's fragmentation.</span>
<span style="color: #808080; font-style: italic;">--This is a documented procedure, but I'm running it in detailed mode so it's going to look</span>
<span style="color: #808080; font-style: italic;">--at all the pages in the active table. Be very careful if you run this in detailed mode</span>
<span style="color: #808080; font-style: italic;">--against a production database.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> alloc_unit_type_desc<span style="color: #66cc66;">,</span>
	index_depth<span style="color: #66cc66;">,</span> page_count<span style="color: #66cc66;">,</span> avg_page_space_used_in_percent<span style="color: #66cc66;">,</span>
	record_count<span style="color: #66cc66;">,</span> forwarded_record_count
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_index_physical_stats<span style="color: #66cc66;">&#40;</span>DB_ID<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> OBJECT_ID<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'detailed'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--sys.dm_db_partition_stats looks at the metadata.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> used_page_count<span style="color: #66cc66;">,</span> in_row_used_page_count<span style="color: #66cc66;">,</span> reserved_page_count<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">ROW_COUNT</span>
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_partition_stats
<span style="color: #993333; font-weight: bold;">WHERE</span> object_name<span style="color: #66cc66;">&#40;</span>object_id<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'DataPile'</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's count how many reads we have to do to scan the table.</span>
<span style="color: #808080; font-style: italic;">--Run the select, then go to the Messages tab.</span>
<span style="color: #808080; font-style: italic;">--Look at the number of &quot;logical reads&quot; we did.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS IO <span style="color: #993333; font-weight: bold;">ON</span>;
<span style="color: #993333; font-weight: bold;">SET</span> STATISTICS <span style="color: #993333; font-weight: bold;">TIME</span> <span style="color: #993333; font-weight: bold;">ON</span>;
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>dataPile;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's make half of the rows have larger values in them.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">UPDATE</span> dbo<span style="color: #66cc66;">.</span>DataPile
<span style="color: #993333; font-weight: bold;">SET</span> col1<span style="color: #66cc66;">=</span>REPLICATE<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'B'</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">WHERE</span> dataPileid % <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--How many reads does it take to scan the table now?</span>
<span style="color: #808080; font-style: italic;">--Run the select, then go to the Messages tab.</span>
<span style="color: #808080; font-style: italic;">--Look at the number of &quot;logical reads&quot; we did.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>dataPile;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Why did we do so many more logical reads????</span>
<span style="color: #808080; font-style: italic;">--Let's find some information by looking at the table's fragmentation now.</span>
<span style="color: #808080; font-style: italic;">--Note: look at the record_count column-- we didn't insert any records!</span>
<span style="color: #808080; font-style: italic;">--It's counting wrong by the number of forwarded records.</span>
<span style="color: #808080; font-style: italic;">--(That's documented in Books Online, by the way.)</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> alloc_unit_type_desc<span style="color: #66cc66;">,</span>
	index_depth<span style="color: #66cc66;">,</span> page_count<span style="color: #66cc66;">,</span> avg_page_space_used_in_percent<span style="color: #66cc66;">,</span>
	record_count<span style="color: #66cc66;">,</span> forwarded_record_count
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_index_physical_stats<span style="color: #66cc66;">&#40;</span>DB_ID<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> OBJECT_ID<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'detailed'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--We can see something special happened reading, as well.</span>
<span style="color: #808080; font-style: italic;">--Check out forwarded_fetch_count.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> leaf_insert_count<span style="color: #66cc66;">,</span> leaf_update_count<span style="color: #66cc66;">,</span> forwarded_fetch_count
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_index_operational_stats<span style="color: #66cc66;">&#40;</span>db_id<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>object_id<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--What about deletes?</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's delete all of the rows from the table, except for five.</span>
<span style="color: #993333; font-weight: bold;">DELETE</span> <span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>datapile
<span style="color: #993333; font-weight: bold;">WHERE</span> datapileid <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">5</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--OK, we only have FIVE rows in this table now. We started with 1000.</span>
<span style="color: #808080; font-style: italic;">--How many reads does it take to read now?</span>
<span style="color: #808080; font-style: italic;">--Run the select, go to the messages tab, and look at logical reads.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> dbo<span style="color: #66cc66;">.</span>dataPile;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--What changed?</span>
<span style="color: #808080; font-style: italic;">--We got rid of MOST of the forwarded record pointers.</span>
<span style="color: #808080; font-style: italic;">--But we still have 80+ pages allocated! For only five rows!</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> alloc_unit_type_desc<span style="color: #66cc66;">,</span>
	index_depth<span style="color: #66cc66;">,</span> page_count<span style="color: #66cc66;">,</span> avg_page_space_used_in_percent<span style="color: #66cc66;">,</span>
	record_count<span style="color: #66cc66;">,</span> forwarded_record_count
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_index_physical_stats<span style="color: #66cc66;">&#40;</span>DB_ID<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> OBJECT_ID<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'detailed'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--sys.dm_db_partition_stats agrees that we still have LOTS of pages.</span>
<span style="color: #808080; font-style: italic;">--It gets the row count right, by the way.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> used_page_count<span style="color: #66cc66;">,</span> in_row_used_page_count<span style="color: #66cc66;">,</span> reserved_page_count<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">ROW_COUNT</span>
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_partition_stats
<span style="color: #993333; font-weight: bold;">WHERE</span> object_name<span style="color: #66cc66;">&#40;</span>object_id<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'DataPile'</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's create a nonclustered index on our heap.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">UNIQUE</span> NONCLUSTERED <span style="color: #993333; font-weight: bold;">INDEX</span> ix_datapile_nc_datapileid <span style="color: #993333; font-weight: bold;">ON</span> dbo<span style="color: #66cc66;">.</span>DataPile <span style="color: #66cc66;">&#40;</span>datapileid<span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's look at what pages are being used for the nonclustered index.</span>
<span style="color: #808080; font-style: italic;">--We're using the undocumented new DMV again.</span>
<span style="color: #808080; font-style: italic;">--We have an INDEX page type instead of a DATA page type. */</span>
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_database_page_allocations<span style="color: #66cc66;">&#40;</span>db_id<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>object_id<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'DETAILED'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Now, let's take the index page ID:</span>
<span style="color: #808080; font-style: italic;">--This is the allocated_page_page_id for the row where page_type_desc=INDEX_PAGE</span>
<span style="color: #808080; font-style: italic;">--We'll plug it into DBCC PAGE.</span>
<span style="color: #808080; font-style: italic;">--This is another undocumented procedure that lets us look at page data.</span>
<span style="color: #808080; font-style: italic;">--Check out the values in the HEAP RID Column and record them.</span>
&nbsp;
DBCC TRACEON <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3604</span><span style="color: #66cc66;">&#41;</span>;
DBCC PAGE <span style="color: #66cc66;">&#40;</span>HeapsOfHeaps<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">284</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Now let's rebuild the heap.</span>
<span style="color: #808080; font-style: italic;">--We can do that-- we can rebuild a heap! (On SQL Server 2008 and above.)</span>
<span style="color: #808080; font-style: italic;">--Prior to SQL Server 2008, the most popular way to de-fragment a heap is to</span>
<span style="color: #808080; font-style: italic;">--add and remove a clustered index--- but it has the same impact we'll see here.</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> dbo<span style="color: #66cc66;">.</span>DataPile REBUILD;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Let's check out our nonclustered index...</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">SELECT</span> allocated_page_page_id<span style="color: #66cc66;">,</span> page_type_desc
<span style="color: #993333; font-weight: bold;">FROM</span> sys<span style="color: #66cc66;">.</span>dm_db_database_page_allocations<span style="color: #66cc66;">&#40;</span>db_id<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>object_id<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'DataPile'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">,</span><span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">'DETAILED'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Hey, wait a second, the PAGE IDs are different for the Non-Clustered index.</span>
<span style="color: #808080; font-style: italic;">--And we didn't rebuild the non-clustered index--- we just asked for a rebuild of the heap!</span>
<span style="color: #808080; font-style: italic;">--But yet our non-clustered index shows us that it is on totally new pages now.</span>
<span style="color: #808080; font-style: italic;">--What's up with that????</span>
&nbsp;
DBCC TRACEON <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3604</span><span style="color: #66cc66;">&#41;</span>;
DBCC PAGE <span style="color: #66cc66;">&#40;</span>HeapsOfHeaps<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">370</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">GO</span>
&nbsp;
<span style="color: #808080; font-style: italic;">-- Compare those HEAP RIDS to what you recorded before.</span>
<span style="color: #808080; font-style: italic;">--We explain why this is and what this means in the video.</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--Wow, rebuilding a big heap with nonclustered indexes could</span>
<span style="color: #808080; font-style: italic;">--cause LOTS and LOTS of unexpected IO.</span>
<span style="color: #808080; font-style: italic;">--Really, the times when we want to have a heap in SQL Server are the exception rather than the rule.</span>
<span style="color: #808080; font-style: italic;">--We like to default to clustered indexes in SQL Server---</span>
<span style="color: #808080; font-style: italic;">--unless we have performance tests showing that heaps are better for that use case!</span></pre></div></div>

<p>...<br /><i>You should <a href="https://brentozarevents.webex.com/brentozarevents/onstage/g.php?p=L8FEedipisA0NL4Sx6LCRIr0GCEjWxetdMub8XyE7SDiiipisI2rL&t=m">sign up for our free upcoming webcasts now</a>.</i></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=VOto9doIz7I:jHXcOAu7k-w:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?i=VOto9doIz7I:jHXcOAu7k-w:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?a=VOto9doIz7I:jHXcOAu7k-w:YwkR-u9nhCs"><img src="http://feeds.feedburner.com/~ff/BrentOzar-SqlServerDba?d=YwkR-u9nhCs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/BrentOzar-SqlServerDba/~4/VOto9doIz7I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.brentozar.com/archive/2012/05/video-heaps/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.brentozar.com/archive/2012/05/video-heaps/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced
Object Caching 1236/1291 objects using disk: basic

Served from: www.brentozar.com @ 2012-05-23 22:42:02 -->

