<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Robert&amp;#39;s SQL Blog</title><subtitle type="html">My thoughts on SQL Server, PowerShell and Microsoft products in general</subtitle><id>http://blogs.technet.com/b/rhartskeerl/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/" /><link rel="self" type="application/atom+xml" href="http://blogs.technet.com/b/rhartskeerl/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2011-10-31T22:29:00Z</updated><entry><title>Remember to vote for your AlwaysOn Availability Groups</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2013/04/24/remember-to-vote-for-your-alwayson-availability-groups.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2013/04/24/remember-to-vote-for-your-alwayson-availability-groups.aspx</id><published>2013-04-24T08:37:34Z</published><updated>2013-04-24T08:37:34Z</updated><content type="html">&lt;p&gt;While visiting a customer and helping them set up AlwaysOn Availability Groups we came across a surprising "feature". On my laptop I had build a demo lab consisting of one domain controller, three Windows 2008R2 Core member servers with SQL 2012 SP1 installed and a full Windows 2008 R2 installation with SQL Server management studio installed. I had setup the cluster, enabled AlwaysOn and created an empty database to create an availability group. I tested the availability group by manually failing over using management studio and this worked fine.&lt;/p&gt;
&lt;p&gt;But that's in the demo world. Usually we have all kind of conditions that cause our demo's not to work with our customers. In this case the customer had set up an availability group as well and the failover was working when initiated from management studio. But stopping the SQL Server service caused the Availability Group to stay in a resolving state and never failover. I tried this on my machine and it failed over perfectly. The only difference between my setup and the customer was that I was using a three node cluster and they were using a two node + file share cluster. To match the customers setup I removed the third replica from the availability group and evicted this node from the cluster. This left me with a two node cluster. What is important to remember is that this is not a recommended setup. In this setup you will never have majority and the cluster will go offline when one of the nodes goes offline. This basically defeats the purpose of a cluster. But to satisfy my curiosity I stopped the SQL Server service. To my surprise the availability group failed over to the other node.&lt;/p&gt;
&lt;p&gt;A quick recap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Three node cluster with an availability group: Stopping the service fails over the availability group&lt;/li&gt;
&lt;li&gt;Two node cluster (&lt;span style="color: #ff0000; text-decoration: underline; background-color: #ffffff;"&gt;&lt;strong&gt;not recommended&lt;/strong&gt;&lt;/span&gt;) with an availability group: Stopping the service fails over the availability group&lt;/li&gt;
&lt;li&gt;Two node with file share witness: Stopping the service leaves the secondary in a resolving state and the listener remains offline&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a known issue and if you read the signs along the road you would have noticed this. The reason I missed it at first is that in the earlier builds the link in the warning did not work. Below is a screenshot of the warning you will get when you perform a&amp;nbsp;failover in the third scenario.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29/2450.ClusterQuorum.png"&gt;&lt;img src="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29/2450.ClusterQuorum.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There is a KB article that describes this behavior (&lt;a href="http://support.microsoft.com/kb/2761129"&gt;http://support.microsoft.com/kb/2761129&lt;/a&gt;) and this references the same KB article (&lt;a href="http://support.microsoft.com/kb/2494036"&gt;http://support.microsoft.com/kb/2494036&lt;/a&gt;) that is mentioned in the link in the warning message. In short it turns out that the nodes do not have a vote. You can see this by querying &lt;strong&gt;sys.dm_hadr_cluster_members&lt;/strong&gt; or clicking the &lt;strong&gt;View Cluster Quorum Information&lt;/strong&gt; link in the AlwaysOn dashboard. This will show NULL or Not Available. This means the nodes do not have a vote and we need the vote to determine if there is quorum.&lt;/p&gt;
&lt;p&gt;After applying the hotfix we get the desired behavior and the dmv and dashboard show 1 indicating each node has a vote. Stopping the service results in a failover leaving the new primary in a Not Synchronizing state. This is the expected state but leaves the availability group at risk. Another replica must come online as soon as possible to start synchronizing.&amp;nbsp;In this state the transaction log will not be able to truncate and reuse the space within the log file.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3568719" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="SQL Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server+2012/" /><category term="AlwaysOn" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/AlwaysOn/" /></entry><entry><title>From 0 to SQL Demo lab in a few easy steps – Part 4</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2013/03/08/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-4.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2013/03/08/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-4.aspx</id><published>2013-03-08T17:30:16Z</published><updated>2013-03-08T17:30:16Z</updated><content type="html">&lt;p&gt;I have not been able to follow up my post for a long time. Work has to be done as well. The good thing is that it gives me a lot of new ideas for blog posts and as a (late) resolution for the new year I will write more blog posts
&lt;/p&gt;&lt;p&gt;But back to part 4 of building a SQL Demo lab. There are a few things you have to consider building an entire lab. Some are easy and some require creativity. First let me list the steps you would take to create an AlwaysOn demo manually.
&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Build a Domain Controller
&lt;/li&gt;&lt;li&gt;Provision some users to the domain
&lt;/li&gt;&lt;li&gt;Install 2 or more member servers
&lt;/li&gt;&lt;li&gt;Install SQL Server 2012
&lt;/li&gt;&lt;li&gt;Configure SQL Server
&lt;/li&gt;&lt;li&gt;Build a cluster on top of the member servers
&lt;/li&gt;&lt;li&gt;Enable AlwaysOn
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And that should leave you with a ready-to-go demo machine.
&lt;/p&gt;&lt;p&gt;In the previous part we have done all the individual steps but the complexity lies in the sequence. We cannot add a member server if there is no domain controller and we cannot enable AlwaysOn if there is no Windows Cluster build on top of the member servers. And what would be the use of automating things if we have to execute three or four scripts manually. 
&lt;/p&gt;&lt;h3&gt;Key Value Pairs to the rescue
&lt;/h3&gt;&lt;p&gt;Hyper-V virtual machines have this concept of exchanging data through a dedicated registry portion. There is some good information out there but the best I found so far was this blog post by Taylor Brown; &lt;a href="http://blogs.msdn.com/b/taylorb/archive/2012/12/05/customizing-the-key-value-pair-kvp-integration-component.aspx"&gt;http://blogs.msdn.com/b/taylorb/archive/2012/12/05/customizing-the-key-value-pair-kvp-integration-component.aspx&lt;/a&gt;. By leveraging this concept I can write some PowerShell code that will read this data in a loop and exit when a certain value has been saved to the registry key. This will enable me to create one script that will call different scripts to install the various servers but in the proper sequence. In my VM I will set a status. Using a function on the host I read the value and depending on the status I will proceed to the next step. 
&lt;/p&gt;&lt;h3&gt;There had to be challenges
&lt;/h3&gt;&lt;p&gt;Of course there had to be. What I wanted was to alter the unattend.xml files. I could have taken the easy road and use placeholders like @computernamehere@ and just do a textual replace. But I choose to use XML to navigate through the unattend.xml and change the proper value. To give you an example of some funny PowerShell behavior. Imagine this piece of XML:
&lt;/p&gt;&lt;p&gt;&amp;lt;root&amp;gt;&lt;br/&gt;    &amp;lt;data type="database"&amp;gt;&lt;br/&gt;        &amp;lt;name&amp;gt;master&amp;lt;/name&amp;gt;&lt;br/&gt;    &amp;lt;/data&amp;gt;&lt;br/&gt;    &amp;lt;data type="job"&amp;gt;&lt;br/&gt;        &amp;lt;id&amp;gt;1&amp;lt;/id&amp;gt;&lt;br/&gt;    &amp;lt;/data&amp;gt;&lt;br/&gt;&amp;lt;/root&amp;gt;
&lt;/p&gt;&lt;p&gt;If you navigate through this piece of XML in PowerShell, for example $xml.root.data.name it will return master. Great! A new world of possibilities arises. Things get ugly if you want to change the value. You get an error telling you the value cannot be set. It took some time but it turns out to be related to the fact the data element is there twice but the name element only once. When you navigate through the XML PowerShell uses late binding to figure this out but when you write to it, it wants to know exact. I solved this in my script by using Xpath queries to get to the correct element.
&lt;/p&gt;&lt;p&gt;On my SkyDrive you can find the scripts I used: &lt;a href="http://sdrv.ms/Y0oUfv"&gt;http://sdrv.ms/Y0oUfv&lt;/a&gt;
	&lt;/p&gt;&lt;p&gt;The main script I used is Create-Lab which will create a Domain Controller and configure it. Installs 1 management member server and 3 SQL Servers. When the installation of the third server is finished a cluster is build and Availability Groups are enabled. The instances are restarted using WMI. This proved to be the most reliable method. If you want a shorter example of what the script does check out Create-Lab-Demo. This creates a lab with SQL 2008 R2 and SQL 2012 installed on it.
&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Important!&lt;/strong&gt; In the Create… scripts there are names and paths I used on my machine. Evaluate each one and set this to your environment. Also in my script I refer to two *.wim files for the base installation. Due to legal and other reasons I cannot provide you these files but you can use a *.wim file from the Windows setup media or create your one using the method I described in one of my earlier posts. Also the iso files I used for SQL Server are of course not included and you need to provide your one. Finally, the keys included are setup keys the installer uses when you would choose Skip Installation during the Windows Setup process. Check one of my earlier posts to see where to retrieve these keys.
&lt;/p&gt;&lt;p&gt;Feel free to contact me for any further information or improvements. And remember, do not use these scripts in production environments. They were built to create quick demo labs.
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3557497" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>From 0 to SQL Demo lab in a few easy steps – Part 3</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/09/07/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-3.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/09/07/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-3.aspx</id><published>2012-09-07T13:55:00Z</published><updated>2012-09-07T13:55:00Z</updated><content type="html">&lt;p&gt;In part 1 showed how you could install Windows on a virtual disk and use that disk to create a new virtual machine. We improved on part 2 to show how to set the administrator password or the computer name during installation to minimize user input.&lt;/p&gt;
&lt;p&gt;In part 3 we will take another step. It's nice to have a clean Windows installation with the desired network configuration or computer name but what if I need a domain controller setup with some default settings or have a SQL server joined to an existing domain.&lt;/p&gt;
&lt;p&gt;The magic is in the unattend file as well. Besides setting the computer name or network we can also autologon for a specified number of times. We can also specify commands we want to run when the logon takes place.&lt;/p&gt;
&lt;p&gt;First the autologon. To get this going add the following XML right before the UserAccounts segment but after the OOBE.&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="html"&gt;&amp;lt;AutoLogon&amp;gt;&lt;br /&gt; &amp;lt;Password&amp;gt;&lt;br /&gt; &amp;lt;Value&amp;gt;p@ssw0rd&amp;lt;/Value&amp;gt;&lt;br /&gt; &amp;lt;PlainText&amp;gt;true&amp;lt;/PlainText&amp;gt;&lt;br /&gt; &amp;lt;/Password&amp;gt;&lt;br /&gt; &amp;lt;Username&amp;gt;Administrator&amp;lt;/Username&amp;gt;&lt;br /&gt; &amp;lt;LogonCount&amp;gt;1&amp;lt;/LogonCount&amp;gt;&lt;br /&gt; &amp;lt;Enabled&amp;gt;true&amp;lt;/Enabled&amp;gt;&lt;br /&gt; &amp;lt;Domain&amp;gt;CONTOSO&amp;lt;/Domain&amp;gt;&lt;br /&gt; &amp;lt;/AutoLogon&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, not the best method for a production environment but it fits my purpose. If you use WAIK to generate the XML file the password will be encrypted.&lt;/p&gt;
&lt;p&gt;We can now specify some commands we want to execute during the logon process. It is important to know how to install what you want using commands only. For active directory this is easy. You run DCPROMO and specify an unattend file. In this file you specify the domain name, level and dns settings. Some examples of the unattend file are on technet.&lt;/p&gt;
&lt;p&gt;To copy it over I add another Copy-Item to my PowerShell script to copy my ad installation file to the destination system. Finally you must add the command to execute:&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="html"&gt;&amp;lt;FirstLogonCommands&amp;gt;&lt;br /&gt; &amp;lt;SynchronousCommand wcm:action="add"&amp;gt;&lt;br /&gt; &amp;lt;CommandLine&amp;gt;dcpromo.exe /unattend:c:\ad.txt&amp;lt;/CommandLine&amp;gt;&lt;br /&gt; &amp;lt;Description&amp;gt;Installation of AD&amp;lt;/Description&amp;gt;&lt;br /&gt; &amp;lt;Order&amp;gt;1&amp;lt;/Order&amp;gt;&lt;br /&gt; &amp;lt;/SynchronousCommand&amp;gt;&lt;br /&gt; &amp;lt;/FirstLogonCommands&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If all goes well you will have a shiny new domain controller. Now for step two. Adding a member server to the domain. There are several ways to add a machine to the domain. I have tried a few but my knowledge of active directory is not at the same level as SQL so I ran in some issues using the autojoin. Eventually what worked for me was just specifying the user to join the domain. Again, using the autojoin is much safer than putting passwords in text files. This is what I added after the network settings in the unattend file.&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="html"&gt;&amp;lt;component name="Microsoft-Windows-UnattendedJoin" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;Identification&amp;gt;&lt;br /&gt; &amp;lt;UnsecureJoin&amp;gt;false&amp;lt;/UnsecureJoin&amp;gt;&lt;br /&gt; &amp;lt;Credentials&amp;gt;&lt;br /&gt; &amp;lt;Domain&amp;gt;CONTOSO&amp;lt;/Domain&amp;gt;&lt;br /&gt; &amp;lt;Username&amp;gt;bob&amp;lt;/Username&amp;gt;&lt;br /&gt; &amp;lt;Password&amp;gt;p@ssw0rd&amp;lt;/Password&amp;gt;&lt;br /&gt; &amp;lt;/Credentials&amp;gt;&lt;br /&gt; &amp;lt;JoinDomain&amp;gt;contoso.com&amp;lt;/JoinDomain&amp;gt;&lt;br /&gt; &amp;lt;MachineObjectOU&amp;gt;OU=Servers,DC=contoso,DC=com&amp;lt;/MachineObjectOU&amp;gt;&lt;br /&gt; &amp;lt;DebugJoin&amp;gt;true&amp;lt;/DebugJoin&amp;gt;&lt;br /&gt; &amp;lt;/Identification&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next thing was installing SQL server. There are several ways to do this. One is to use the sysprep feature and include SQL in your base image and then finalize the installation. This proved to be limited for me. This only works for some components of SQL and also not for all versions of SQL. I wanted a solution that would work regardless of the version. My solution was to add the DVD during the VM creation and run a cmdline setup of SQL Server. This gives me much more control and flexibility. To install SQL server I created a cmd file with a very basic setup:&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="html"&gt;d:\Setup.exe /q /ACTION=Install /FEATURES=SQLEngine,ADV_SSMS /INSTANCEID=SQL2012 /SQLSVCACCOUNT="NT Service\MSSQL$SQL2012" /ADDCURRENTUSERASSQLADMIN="True" /AGTSVCACCOUNT="NT Service\SQLAgent$SQL2012" /AGTSVCSTARTUPTYPE=Automatic /BROWSERSVCSTARTUPTYPE=Automatic /TCPENABLED=1 /IACCEPTSQLSERVERLICENSETERMS /INDICATEPROGRESS /UPDATEENABLED=0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And using the logon command I showed earlier I started this installation after the first logon. I also added a LOGOFF command to the cmd file just to return to the logon screen.&lt;/p&gt;
&lt;p&gt;This works perfectly. I did notice the installation of SQL took a long time because of some .NET requirements. I have included these in my base image and things got a lot faster afterwards. Check your installation logs to see where most time is spend and see if you can speed things up by including these in the base image.&lt;/p&gt;
&lt;p&gt;In the final part I will provide you with the definite PowerShell scripts and command files to recreate what I showed here.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3518752" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="PowerShell" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/PowerShell/" /><category term="Windows Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+Server+2012/" /><category term="Windows 8" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+8/" /></entry><entry><title>From 0 to SQL Demo lab in a few easy steps – Part 2</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/08/22/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-2.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/08/22/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-2.aspx</id><published>2012-08-22T15:09:00Z</published><updated>2012-08-22T15:09:00Z</updated><content type="html">&lt;p&gt;This post is part of a series of posts about buidling a lab environment using some of the new PowerShell cmdlets and features in Windows 8.&lt;/p&gt;
&lt;p&gt;In the &lt;a href="http://blogs.technet.com/b/rhartskeerl/archive/2012/08/15/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-1.aspx"&gt;previous post&lt;/a&gt; I explained how to create a virtual disk, apply a standard Windows Server 2008 image to it and attach the disk to a new VM. If you followed my steps you should have noticed that it was not a fully automated experience. During the installation I was asked to provide the regional settings, set or skip a license key, accept the EULA and provide an administrator password. And when I finally was logged in I still had to do a lot of configuration like setting an ip-address and renaming the machine. In this post we will get these steps out of the way as well.&lt;/p&gt;
&lt;p&gt;The first step is to do some primary settings. In my case I enable PowerShell and Remote Desktop. This is also a good time to download updates and .NET frameworks you might need later. Try to keep things as basic as possible. Only set the ip-address if that's needed. We will change it later on.&lt;/p&gt;
&lt;p&gt;Once the machine is to your liking it's time to &lt;strong&gt;sysprep &lt;/strong&gt;it. Sysprep is located in the sysprep folder inside the system32 folder. Sysprep removes all personal information from the machines and makes it possible to create an image for redeployment. Start sysprep and choose OOBE Experience, Shutdown and make sure the box at Generalize is checked or better run it from the commandline: &lt;strong&gt;sysprep /generalize /oobe /shutdown&lt;/strong&gt;. Make sure you specify the generalize option. This will create a new machine identifier for every machine. If you miss that one you could get into weird problems.&lt;/p&gt;
&lt;p&gt;After sysprep is done it shuts down the machine. Now it's time to create an image that we can use as a base for deployement. You only have to do this once for every base image you want to create. I'm using a Windows 2008 and Windows 2008 Core template. Using DISM you can create an image (WIM) file. First you need to mount the image using Mount-VHD &amp;lt;pathtovhd&amp;gt;. Now capture the image with: &lt;strong&gt;DISM.exe /Capture-Image /ImageFile:D:\vm\base.wim /CaptureDir:G:\ /name:Base-Image&lt;/strong&gt;. Replace the paths and name with your own. After some time a file is created. Make sure to dismount the vhd using &lt;strong&gt;Dismount-VHD&lt;/strong&gt;. This concludes step 1 of this task. Next up is to automate the installation. There is an easy way and a hard way. The easy way is to use the Windows Automation Installation Kit. This tool has an editor to create unattended files. Another option is to create one with notepad. Of course you can also copy from others. Here is an example of the unattend.xml I'm using to create a domain controller. Read through it, I will explain the values in a moment.&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="html"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;br /&gt; &amp;lt;unattend xmlns="urn:schemas-microsoft-com:unattend"&amp;gt;&lt;br /&gt; &amp;lt;settings pass="specialize"&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;\&lt;br /&gt; &amp;lt;ComputerName&amp;gt;DC-01&amp;lt;/ComputerName&amp;gt;&lt;br /&gt; &amp;lt;TimeZone&amp;gt;UTC&amp;lt;/TimeZone&amp;gt;&lt;br /&gt; &amp;lt;RegisteredOrganization&amp;gt;Contoso Corp.&amp;lt;/RegisteredOrganization&amp;gt;&lt;br /&gt; &amp;lt;RegisteredOwner&amp;gt;Contoso Corp.&amp;lt;/RegisteredOwner&amp;gt;&lt;br /&gt; &amp;lt;ProductKey&amp;gt;7P8GH-FV2FF-8FDCR-YK49D-D7P97&amp;lt;/ProductKey&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-DNS-Client" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="NonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;Interfaces&amp;gt;&lt;br /&gt; &amp;lt;Interface wcm:action="add"&amp;gt;&lt;br /&gt; &amp;lt;DNSServerSearchOrder&amp;gt;&lt;br /&gt; &amp;lt;IpAddress wcm:action="add" wcm:keyValue="1"&amp;gt;127.0.0.1&amp;lt;/IpAddress&amp;gt;&lt;br /&gt; &amp;lt;/DNSServerSearchOrder&amp;gt;&lt;br /&gt; &amp;lt;Identifier&amp;gt;Local Area Connection&amp;lt;/Identifier&amp;gt;&lt;br /&gt; &amp;lt;/Interface&amp;gt;&lt;br /&gt; &amp;lt;/Interfaces&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-TCPIP" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;Interfaces&amp;gt;&lt;br /&gt; &amp;lt;Interface wcm:action="add"&amp;gt;&lt;br /&gt; &amp;lt;Ipv4Settings&amp;gt;&lt;br /&gt; &amp;lt;DhcpEnabled&amp;gt;false&amp;lt;/DhcpEnabled&amp;gt;&lt;br /&gt; &amp;lt;Metric&amp;gt;10&amp;lt;/Metric&amp;gt;&lt;br /&gt; &amp;lt;RouterDiscoveryEnabled&amp;gt;false&amp;lt;/RouterDiscoveryEnabled&amp;gt;&lt;br /&gt; &amp;lt;/Ipv4Settings&amp;gt;&lt;br /&gt; &amp;lt;Identifier&amp;gt;Local Area Connection&amp;lt;/Identifier&amp;gt;&lt;br /&gt; &amp;lt;UnicastIpAddresses&amp;gt;&lt;br /&gt; &amp;lt;IpAddress wcm:action="add" wcm:keyValue="1"&amp;gt;192.168.200.1/24&amp;lt;/IpAddress&amp;gt;&lt;br /&gt; &amp;lt;/UnicastIpAddresses&amp;gt;&lt;br /&gt; &amp;lt;Routes&amp;gt;&lt;br /&gt; &amp;lt;Route wcm:action="add"&amp;gt;&lt;br /&gt; &amp;lt;Identifier&amp;gt;1&amp;lt;/Identifier&amp;gt;&lt;br /&gt; &amp;lt;Metric&amp;gt;10&amp;lt;/Metric&amp;gt;&lt;br /&gt; &amp;lt;NextHopAddress&amp;gt;192.168.200.1&amp;lt;/NextHopAddress&amp;gt;&lt;br /&gt; &amp;lt;Prefix&amp;gt;0.0.0.0/0&amp;lt;/Prefix&amp;gt;&lt;br /&gt; &amp;lt;/Route&amp;gt;&lt;br /&gt; &amp;lt;/Routes&amp;gt;&lt;br /&gt; &amp;lt;/Interface&amp;gt;&lt;br /&gt; &amp;lt;/Interfaces&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;/settings&amp;gt;&lt;br /&gt; &amp;lt;settings pass="oobeSystem"&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;InputLocale&amp;gt;132105&amp;lt;/InputLocale&amp;gt;&lt;br /&gt; &amp;lt;SystemLocale&amp;gt;en-US&amp;lt;/SystemLocale&amp;gt;&lt;br /&gt; &amp;lt;UILanguage&amp;gt;en-US&amp;lt;/UILanguage&amp;gt;&lt;br /&gt; &amp;lt;UserLocale&amp;gt;en-US&amp;lt;/UserLocale&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;OOBE&amp;gt;&lt;br /&gt; &amp;lt;HideEULAPage&amp;gt;true&amp;lt;/HideEULAPage&amp;gt;&lt;br /&gt; &amp;lt;/OOBE&amp;gt;&lt;br /&gt; &amp;lt;UserAccounts&amp;gt;&lt;br /&gt; &amp;lt;AdministratorPassword&amp;gt;&lt;br /&gt; &amp;lt;Value&amp;gt;p@ssw0rd&amp;lt;/Value&amp;gt;&lt;br /&gt; &amp;lt;PlainText&amp;gt;true&amp;lt;/PlainText&amp;gt;&lt;br /&gt; &amp;lt;/AdministratorPassword&amp;gt;&lt;br /&gt; &amp;lt;/UserAccounts&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;/settings&amp;gt;&lt;br /&gt; &amp;lt;settings pass="windowsPE"&amp;gt;&lt;br /&gt; &amp;lt;component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;&lt;br /&gt; &amp;lt;UserData&amp;gt;&lt;br /&gt; &amp;lt;AcceptEula&amp;gt;true&amp;lt;/AcceptEula&amp;gt;&lt;br /&gt; &amp;lt;/UserData&amp;gt;&lt;br /&gt; &amp;lt;/component&amp;gt;&lt;br /&gt; &amp;lt;/settings&amp;gt;&lt;br /&gt; &amp;lt;/unattend&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are several sections in the xml. One section is the pass phase. This tells the setup routing at what point to use the settings. Some settings are only valid in one phase while other can be in multiple. The Windows Automation Kit knows and will only choose the right ones.&lt;/p&gt;
&lt;p&gt;In the first part of the file the computer name is set along with the time zone and other details. The product key is not a real key but a temporary one. It's actually the same key that's entered when you click skip during the setup process. You can find this key inside a file in the Windows installation dvd. So, it's not a real key, just one that will get the setup process automated.&lt;/p&gt;
&lt;p&gt;In the second part the network is set. In this example the ip 192.168.200.1 is used with netmask 255.255.255.0. The DNS is set to 127.0.0.1 because this machine will take the role of domain controller with DNS installed. The gateway is set to the 192.168.200.1 as well.&lt;/p&gt;
&lt;p&gt;The last part is where the locale settings are set. The values can be retrieved from this table. Also the EULA is accepted and the administrator password is set. If you use the Windows Automation Kit the password will be encrypted. As a best practice you should not include the password in plain text.&lt;/p&gt;
&lt;p&gt;So far for preparation, now it's show time. The trick is to get the unattend.xml we created located at the rootdrive of the machine. Using PowerShell and the commands from the previous post this task is easy. As you might recall I mounted the disk to apply the image and set the bootrecords. Run through the steps from the first post up until the point where the drive is dismounted. With the disk still mounted you can copy whatever file you want to the drive, including an unattend. If you add this PowerShell one-liner before you dismount the disk the file will be copied: &lt;strong&gt;Copy-Item source destination &amp;ndash;force&lt;/strong&gt;. This will copy the file from A to B. Now dismount the disk and you are done.&lt;/p&gt;
&lt;p&gt;Once the autounattend is copied you can start the VM. After a few minutes and with no user interaction you should be able to log into the machine.&lt;/p&gt;
&lt;p&gt;This brings us one step closer to a complete unattended installation of a lab environment. In the next post I will explain how to perform post install actions like installing and configuring AD and setting up SQL Server.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3515653" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="Windows Server 2008 R2" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+Server+2008+R2/" /><category term="PowerShell" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/PowerShell/" /><category term="Windows 8" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+8/" /></entry><entry><title>From 0 to SQL Demo lab in a few easy steps – Part 1</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/08/15/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-1.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/08/15/from-0-to-sql-demo-lab-in-a-few-easy-steps-part-1.aspx</id><published>2012-08-15T11:16:00Z</published><updated>2012-08-15T11:16:00Z</updated><content type="html">&lt;p&gt;As a Premier Field Engineer I get into a different challenge every week. These challenges can be anything; performance issues, architecture review or migration scenarios. If I'm at a customer site it is not always possible (or recommended) to test my solution on the production systems. And if it's a possible bug I want to reproduce it so it can be investigated. For this you will need a lab environment. But building a lab environment can be a time consuming task. Most of the times I need different SQL versions, clustering, AlwaysOn or another Microsoft product relying on SQL server. And when I'm ready to present and prove my solution I don't want any data from other customers to be visible. For these reasons I always build new and fresh environments. If it's a performance issue I can get away with just a single VM but if it is a more complex scenario I might have to install a domain controller and a series of other machines as well.&lt;/p&gt;
&lt;p&gt;I used to run Windows Server 2008 R2 on my laptop as my primary OS. Basically because I needed Hyper-V. But with Windows 8 I can run Hyper-V on a client OS and as a bonus I get a lot more PowerShell cmdlets to automate recurring tasks. Do you see where I'm going? There is some great software available to automate the deployment of VM's. You can use Windows Deployment Services or System Center Virtual Machine Manager. But I wanted an out-of-the-box solution that didn't require any additional tooling other than Windows 8 with Hyper-V enabled. And there is.&lt;/p&gt;
&lt;p&gt;This post will be part of a series of posts because getting a complete AlwaysOn cluster running is a lot of preparation and understanding all the steps will make it easier to customize this to your purpose. Basically I will break it down in a few steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Part 1:&lt;/strong&gt; Installing Windows on a virtual disk and boot it in Hyper-V&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 2:&lt;/strong&gt; Automating and customizing the installation using sysprep and unattend&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 3:&lt;/strong&gt; Running post deployment tasks like AD configuration or SQL Server installation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Part 4:&lt;/strong&gt; Putting it together&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Installing Windows on a virtual disk and boot it in Hyper-V&lt;/p&gt;
&lt;p&gt;Before you can start to automate anything with PowerShell you will need the steps to do it. Imagine you would create a new VM? What steps do you need to take?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create the VM&lt;/li&gt;
&lt;li&gt;Insert the DVD&lt;/li&gt;
&lt;li&gt;Install Windows&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we are going to do this in PowerShell you will need to reorder some of the items. In PowerShell we will create the disk first, install Windows on it and create the VM in the final step.&lt;/p&gt;
&lt;h2&gt;Create a vhd(x) with PowerShell&lt;/h2&gt;
&lt;p&gt;There are several ways to create a virtual disk. You can use DISKPART but that can be a bit of a drag and is harder to automate, or you can use PowerShell. In Windows 8 you can use some new and cool cmdlets to create a virtual disk. The next script will create a vhd and format it. I will explain them after the script.&lt;/p&gt;
&lt;p style="background: white;"&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: darkred;"&gt;"D:\vm\dc-01.vhdx"&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$vhd&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: blue;"&gt;New-VHD&lt;/span&gt; &lt;span style="color: navy;"&gt;-Path&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;span style="color: navy;"&gt;-SizeBytes&lt;/span&gt; &lt;span style="color: purple;"&gt;30GB&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Mount-DiskImage&lt;/span&gt; &lt;span style="color: navy;"&gt;-ImagePath&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$disk&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: blue;"&gt;Get-DiskImage&lt;/span&gt; &lt;span style="color: navy;"&gt;-ImagePath&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;span style="color: darkgray;"&gt;|&lt;/span&gt; &lt;span style="color: blue;"&gt;Get-Disk&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Initialize-Disk&lt;/span&gt; &lt;span style="color: navy;"&gt;-Number&lt;/span&gt; &lt;span style="color: orangered;"&gt;$disk&lt;span style="color: darkgray;"&gt;.&lt;/span&gt;Number &lt;span style="color: navy;"&gt;-PartitionStyle&lt;/span&gt; &lt;span style="color: blueviolet;"&gt;MBR&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$volume&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: blue;"&gt;New-Partition&lt;/span&gt; &lt;span style="color: navy;"&gt;-DiskNumber&lt;/span&gt; &lt;span style="color: orangered;"&gt;$disk&lt;span style="color: darkgray;"&gt;.&lt;/span&gt;Number &lt;span style="color: navy;"&gt;-UseMaximumSize&lt;/span&gt; &lt;span style="color: navy;"&gt;-AssignDriveLetter&lt;/span&gt; &lt;span style="color: navy;"&gt;-IsActive&lt;/span&gt; &lt;span style="color: darkgray;"&gt;|&lt;/span&gt; &lt;span style="color: blue;"&gt;Format-Volume&lt;/span&gt; &lt;span style="color: navy;"&gt;-Confirm:&lt;span style="color: orangered;"&gt;$false&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$drive&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: darkgray;"&gt;[&lt;span style="color: teal;"&gt;string&lt;span style="color: darkgray;"&gt;]&lt;span style="color: orangered;"&gt;$volume&lt;span style="color: darkgray;"&gt;.&lt;/span&gt;DriveLetter &lt;span style="color: darkgray;"&gt;+&lt;/span&gt; &lt;span style="color: darkred;"&gt;":\" &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We start with setting a variable to make things easier later on. The variable &lt;strong&gt;$vhdpath&lt;/strong&gt; hold the path to our virtual disk. The first step is to create the disk using &lt;strong&gt;New-VHD&lt;/strong&gt; with the specified size, in my case 30GB is enough. The disk will be dynamically by default but you can create a fixed or differencing disk as well. Refer to the documentation for more options: &lt;a href="http://technet.microsoft.com/en-us/library/hh848503"&gt;http://technet.microsoft.com/en-us/library/hh848503&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following step is to mount the image using &lt;strong&gt;Mount-DiskImage&lt;/strong&gt; specifying the path. When the disk is mounted you can format it using PowerShell instead of DISKPART. Formatting is a three-step action; first initialize the disk, partition it and finally format it. This is not different from DISKPART. Once it's formatted we can get a handle to the drive which we will need later on.&lt;/p&gt;
&lt;p&gt;With a freshly formatted drive we are ready to install Windows. For those of you that are not familiar with deployment or images; we can deploy Windows directly to a disk. No need to boot into a DVD. When you install Windows an image file (*.wim) is applied to the destination. The proper boot records are written and you are off to go. Prior to Windows 8 you would need a tool called ImageX to capture and apply images to a destination. Being part of the Windows Automation Deployment Toolkit this was another download and dependency and does not fit in my &lt;em&gt;'only use what's default'&lt;/em&gt; policy. But with Windows 8 this is not a problem. The command line tool &lt;strong&gt;DISM&lt;/strong&gt; is extended to capture and apply images as well. Being part of the operating system it can be used for my purpose. Check out the next piece of PowerShell.&lt;/p&gt;
&lt;h2&gt;Install the DVD&lt;/h2&gt;
&lt;p style="background: white;"&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$image&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: darkred;"&gt;"F:\sources\install.wim"&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$dismArgs&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; @(&lt;span style="color: darkred;"&gt;"/Apply-Image"&lt;span style="color: darkgray;"&gt;,&lt;/span&gt; "/ImageFile:&lt;span style="color: orangered;"&gt;$image&lt;span style="color: darkred;"&gt;"&lt;span style="color: darkgray;"&gt;,&lt;/span&gt; "/index:4"&lt;span style="color: darkgray;"&gt;,&lt;/span&gt; "/ApplyDir:&lt;span style="color: orangered;"&gt;$drive&lt;span style="color: darkred;"&gt;"&lt;/span&gt;) &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Start-Process&lt;/span&gt; &lt;span style="color: navy;"&gt;-FilePath&lt;/span&gt; &lt;span style="color: darkred;"&gt;"DISM.exe"&lt;/span&gt; &lt;span style="color: navy;"&gt;-ArgumentList&lt;/span&gt; &lt;span style="color: orangered;"&gt;$dismArgs&lt;/span&gt; &lt;span style="color: navy;"&gt;-NoNewWindow&lt;/span&gt; &lt;span style="color: navy;"&gt;-Wait&lt;/span&gt; &lt;span style="color: navy;"&gt;-PassThru &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;There is no DISM cmdlet so we will resort to invoking the process. The source is set to my DVD drive with the Windows Server 2008 R2 DVD loaded. The index is set to 4 because I'm installing the Enterprise Core edition. You need to supply an index if the image contains multiple installations. I will not elaborate much on this because in the next post I will show another method. If you want to find out the index number of the installation use &lt;strong&gt;DISM /Get-WimInfo /wimfile:&amp;lt;pathtowimfile&amp;gt;&lt;/strong&gt;. Finally we apply this to the drive we obtained after the formatting.&lt;/p&gt;
&lt;p&gt;When that's finished the proper boot records need to be written to the disk. The tool is &lt;strong&gt;bcdboot&lt;/strong&gt; and we pass the drive and boot type as parameter.&lt;/p&gt;
&lt;p style="background: white;"&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$bcdargs&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; @((&lt;span style="color: blue;"&gt;Join-Path&lt;/span&gt; &lt;span style="color: orangered;"&gt;$drive&lt;/span&gt; &lt;span style="color: darkred;"&gt;"Windows"&lt;/span&gt;)&lt;span style="color: darkgray;"&gt;,&lt;/span&gt; &lt;span style="color: darkred;"&gt;"/s &lt;span style="color: orangered;"&gt;$drive&lt;span style="color: darkred;"&gt;"&lt;span style="color: darkgray;"&gt;,&lt;/span&gt; "/f BIOS"&lt;/span&gt;) &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Start-Process&lt;/span&gt; &lt;span style="color: navy;"&gt;-FilePath&lt;/span&gt; &lt;span style="color: darkred;"&gt;"bcdboot.exe"&lt;/span&gt; &lt;span style="color: navy;"&gt;-ArgumentList&lt;/span&gt; &lt;span style="color: orangered;"&gt;$bcdargs&lt;/span&gt; &lt;span style="color: navy;"&gt;-NoNewWindow&lt;/span&gt; &lt;span style="color: navy;"&gt;-Wait&lt;/span&gt; &lt;span style="color: navy;"&gt;-PassThru &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Create the VM&lt;/h2&gt;
&lt;p&gt;And basically that's it. All that is left is to create the VM, start it and open it. And as you might have guessed, Windows 8 comes loaded with all you need cmdlets.&lt;/p&gt;
&lt;p style="background: white;"&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$vmname&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: darkred;"&gt;"DEMO-01"&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Dismount-DiskImage&lt;/span&gt; &lt;span style="color: navy;"&gt;-ImagePath&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: orangered;"&gt;$vm&lt;/span&gt; &lt;span style="color: darkgray;"&gt;=&lt;/span&gt; &lt;span style="color: blue;"&gt;New-VM&lt;/span&gt; &lt;span style="color: navy;"&gt;-name&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vmname&lt;/span&gt; &lt;span style="color: navy;"&gt;-MemoryStartupBytes&lt;/span&gt; &lt;span style="color: purple;"&gt;512MB&lt;/span&gt; &lt;span style="color: navy;"&gt;-SwitchName&lt;/span&gt; &lt;span style="color: darkred;"&gt;"Hyper-V Internal Network"&lt;/span&gt; &lt;span style="color: navy;"&gt;-VHDPath&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vhdpath&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Set-VMMemory&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vm&lt;/span&gt; &lt;span style="color: navy;"&gt;-DynamicMemoryEnabled&lt;/span&gt; &lt;span style="color: orangered;"&gt;$true&lt;/span&gt; &lt;span style="color: navy;"&gt;-MinimumBytes&lt;/span&gt; &lt;span style="color: purple;"&gt;512MB&lt;/span&gt; &lt;span style="color: navy;"&gt;-MaximumBytes&lt;/span&gt; &lt;span style="color: purple;"&gt;1GB&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;Start-VM&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vm&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Lucida Console; font-size: 9pt;"&gt;&lt;span style="color: blue;"&gt;vmconnect&lt;/span&gt; &lt;span style="color: blueviolet;"&gt;localhost&lt;/span&gt; &lt;span style="color: navy;"&gt;-G&lt;/span&gt; &lt;span style="color: orangered;"&gt;$vm&lt;span style="color: darkgray;"&gt;.&lt;/span&gt;VMId &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;First another variable is loaded with the name of the VM. Then the disk is dismounted and a new VM is created. It's connected to my Hyper-V switch named "Hyper-V Internal Network". You will need to adjust this to your environment. In the second step dynamic memory is configured. I use this a lot. Using dynamic memory enables me to have 6 VM's running with 8GB internal memory and still not run into any issues. The final two steps are starting the vm and connecting to it using &lt;strong&gt;vmconnect&lt;/strong&gt;. The latter can be discarded of course. Also notice I'm using the identifier to connect to the VM. During my testing I found out it is possible to create multiple VM's with the same name. Connecting to the identifier makes sure you connect to the right one.&lt;/p&gt;
&lt;p&gt;After a few minutes you should have a shiny Windows installation awaiting you to create a new administrator password. In the next post I will go into customizing the installation, sysprepping it and automating the installation process.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3514481" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="PowerShell" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/PowerShell/" /><category term="Windows Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+Server+2012/" /><category term="Windows 8" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+8/" /></entry><entry><title>Using table variables (or temp tables) to speed up… or slow down</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/07/21/using-table-variables-or-temp-tables-to-speed-up-or-slow-down.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/07/21/using-table-variables-or-temp-tables-to-speed-up-or-slow-down.aspx</id><published>2012-07-21T14:04:40Z</published><updated>2012-07-21T14:04:40Z</updated><content type="html">&lt;p&gt;In SQL Server you can use temporary tables to store intermediate results. This is a common used technique to speed up query processing. Recently I came across a problem where the temporary tables were causing the performance degradation. I'm not going into the different temporary tables types, there are good posts on these. I'm going to walk you through a real-life example and show that the most given answer in the SQL Server world holds true; "It Depends".
&lt;/p&gt;&lt;p&gt;In this case the desired result was a single stored procedure that would return multiple results based on some or no search criteria. If a user navigated to the page the complete set was returned and only one filter was applied. In the result set there was a row count, a paged result and some distinct fields from the total results to provide additional filtering. Think of these as slicers and dicers you use in Excel. I will demonstrate the general idea using the AdventureWorks database. I'm using the 2008 version here.
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;DECLARE&lt;/span&gt;
			&lt;span style="color:teal"&gt;@t&lt;/span&gt;
			&lt;span style="color:blue"&gt;table &lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;id&lt;/span&gt;
					&lt;span style="color:blue"&gt;int&lt;/span&gt;
					&lt;span style="color:blue"&gt;IDENTITY&lt;span style="color:gray"&gt;,&lt;/span&gt;
						&lt;span style="color:teal"&gt;salesorderid&lt;/span&gt; int&lt;span style="color:gray"&gt;)&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;INSERT&lt;/span&gt;
			&lt;span style="color:blue"&gt;INTO&lt;/span&gt;
			&lt;span style="color:teal"&gt;@t&lt;span style="color:blue"&gt;
					&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;salesorderid&lt;span style="color:gray"&gt;)&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderID&lt;/span&gt;
					&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
					&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;/span&gt;
							&lt;span style="color:teal"&gt;soh&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Purchasing&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethod&lt;/span&gt;
					&lt;span style="color:teal"&gt;sm&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethodID&lt;/span&gt; =&lt;/span&gt; sm&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethodID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;sm&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt; =&lt;/span&gt;
				&lt;span style="color:red"&gt;'CARGO TRANSPORT 5'&lt;/span&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;/span&gt;
					&lt;span style="color:blue"&gt;DESC&lt;span style="color:gray"&gt;;&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 1 Get Rowcount&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:fuchsia"&gt;COUNT&lt;span style="color:gray"&gt;(*)&lt;/span&gt;
				&lt;span style="color:blue"&gt;AS&lt;/span&gt;
				&lt;span style="color:teal"&gt;TotalRecords&lt;/span&gt;
				&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
				&lt;span style="color:teal"&gt;@t&lt;span style="color:gray"&gt;;&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 2 Get Current page&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SubTotal&lt;span style="color:gray"&gt;,&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;span style="color:gray"&gt;,&lt;/span&gt; p&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;LastName&lt;span style="color:gray"&gt;,&lt;/span&gt; c&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;AccountNumber&lt;/span&gt;
													&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
													&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;/span&gt;
															&lt;span style="color:teal"&gt;soh&lt;/span&gt;
														&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;@t&lt;/span&gt;
			&lt;span style="color:teal"&gt;t&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderID&lt;/span&gt; =&lt;/span&gt; t&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;salesorderid&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesTerritory&lt;/span&gt;
					&lt;span style="color:teal"&gt;st&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt; =&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesPerson&lt;/span&gt;
					&lt;span style="color:teal"&gt;sp&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesPersonID&lt;/span&gt; =&lt;/span&gt; sp&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;BusinessEntityID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Customer&lt;/span&gt;
					&lt;span style="color:teal"&gt;c&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;CustomerID&lt;/span&gt; =&lt;/span&gt; c&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;CustomerID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Person&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Person&lt;/span&gt;
					&lt;span style="color:teal"&gt;p&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;sp&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;BusinessEntityID&lt;/span&gt; =&lt;/span&gt; p&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;BusinessEntityID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;t&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;id&lt;/span&gt; BETWEEN&lt;/span&gt; 1 &lt;span style="color:gray"&gt;AND&lt;/span&gt; 20
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;/span&gt;
					&lt;span style="color:blue"&gt;DESC&lt;span style="color:gray"&gt;;&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 3 Get SalesTerritory values&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:blue"&gt;DISTINCT&lt;/span&gt;
			&lt;span style="color:teal"&gt;st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt;
							&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
							&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesTerritory&lt;/span&gt;
									&lt;span style="color:teal"&gt;st&lt;/span&gt;
								&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt; =&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;@t&lt;/span&gt;
			&lt;span style="color:teal"&gt;t&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderID&lt;/span&gt; =&lt;/span&gt; t&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;salesorderid&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORdER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;span style="color:gray"&gt;;&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 4 Get OrderDate Year values&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:blue"&gt;DISTINCT&lt;/span&gt;
			&lt;span style="color:fuchsia"&gt;YEAR&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;)&lt;/span&gt;
								&lt;span style="color:blue"&gt;as&lt;/span&gt; OrderDateYear&lt;/span&gt;
							&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
							&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;/span&gt;
									&lt;span style="color:teal"&gt;soh&lt;/span&gt;
								&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;@t&lt;/span&gt;
			&lt;span style="color:teal"&gt;t&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderID&lt;/span&gt; =&lt;/span&gt; t&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;salesorderid&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;OrderDateYear&lt;span style="color:gray"&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;In preparation a table variable is filled with the filtered set of ID's and is sorted in the desired order. In the first query we retrieve the row count for the set. The second set is the actual result set the user will see in the application. In this case it's the first page with 20 results. In step 3 and 4 additional results are returned that are used in the application to provide quick filters for the user. When I run this query on my database I get 4 sets with a total of 35 rows. For this I used 25628 reads. That seemed a lot to me. The execution plan for this one showed some missing indexes and some clustered index scans here and there. I added a few indexes. If you are running along, here they are:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_SALESORDERHEADER_ShipMethodId&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;ShipMethodId&lt;span style="color:gray"&gt;)&lt;/span&gt;
								&lt;span style="color:blue"&gt;INCLUDE&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;SalesOrderID&lt;span style="color:gray"&gt;,&lt;/span&gt; OrderDate&lt;span style="color:gray"&gt;);&lt;/span&gt;
										&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_SALESORDERHEADER_Select&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;SalesOrderId&lt;span style="color:gray"&gt;,&lt;/span&gt; OrderDate&lt;span style="color:gray"&gt;)&lt;/span&gt;
								&lt;span style="color:blue"&gt;INCLUDE&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;CustomerID&lt;span style="color:gray"&gt;,&lt;/span&gt; SalesPersonID&lt;span style="color:gray"&gt;,&lt;/span&gt; TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; SubTotal&lt;span style="color:gray"&gt;);&lt;/span&gt;
										&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_SALESORDERHEADER_Territory&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;SalesOrderID&lt;span style="color:gray"&gt;,&lt;/span&gt; TerritoryID&lt;span style="color:gray"&gt;)&lt;/span&gt;
							&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_TERRITORY_Name&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesTerritory&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; Name&lt;span style="color:gray"&gt;);&lt;/span&gt;
							&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_PERSON_Lastname&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Person&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Person&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;LastName&lt;span style="color:gray"&gt;)&lt;/span&gt;
							&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;This got my reads down to 900. That's to show you will need a proper indexing strategy. But still, more work could be done. One of the things I tried first was use a temporary table instead of a table variable. But this increased my reads. Although I could add indexes the index creation itself would cause even more reads. And in this example the set is not that big but when I was working with the real set things got ugly pretty quickly.
&lt;/p&gt;&lt;p&gt;The last thing I tried was to remove the temporary tables altogether and use a view. My thought was to create a view with the search criteria in the view and maybe index that view. This view could easily be reused by the other sets. The definition of the view and the adjusted queries are below:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;VIEW&lt;/span&gt;
			&lt;span style="color:teal"&gt;vSearch&lt;/span&gt;
			&lt;span style="color:blue"&gt;AS&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderID&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesPersonID&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;CustomerID&lt;span style="color:gray"&gt;,&lt;/span&gt; soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SubTotal&lt;span style="color:gray"&gt;,&lt;/span&gt; sm&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt;
																&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Purchasing&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethod&lt;/span&gt;
					&lt;span style="color:teal"&gt;sm&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;soh&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethodID&lt;/span&gt; =&lt;/span&gt; sm&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;ShipMethodID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;GO&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 1 Get Rowcount&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:fuchsia"&gt;COUNT&lt;span style="color:gray"&gt;(*)&lt;/span&gt;
				&lt;span style="color:blue"&gt;AS&lt;/span&gt;
				&lt;span style="color:teal"&gt;TotalRecords&lt;/span&gt;
				&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
				&lt;span style="color:teal"&gt;vSearch&lt;/span&gt;
				&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
				&lt;span style="color:teal"&gt;Name&lt;/span&gt;
				&lt;span style="color:gray"&gt;=&lt;/span&gt;
				&lt;span style="color:red"&gt;'CARGO TRANSPORT 5'&lt;/span&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 2 Get Current page&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;,&lt;/span&gt; v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SubTotal&lt;span style="color:gray"&gt;,&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;span style="color:gray"&gt;,&lt;/span&gt; p&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;LastName&lt;span style="color:gray"&gt;,&lt;/span&gt; c&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;AccountNumber&lt;/span&gt;
													&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
												&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:gray; font-family:Consolas; font-size:9pt"&gt;(&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:fuchsia"&gt;ROW_NUMBER&lt;span style="color:gray"&gt;()&lt;/span&gt;
				&lt;span style="color:blue"&gt;OVER &lt;span style="color:gray"&gt;(&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
						&lt;span style="color:blue"&gt;BY&lt;/span&gt;
						&lt;span style="color:teal"&gt;OrderDate&lt;/span&gt;
						&lt;span style="color:blue"&gt;DESC&lt;span style="color:gray"&gt;)&lt;/span&gt; AS&lt;/span&gt;
						&lt;span style="color:teal"&gt;row_id&lt;span style="color:gray"&gt;,&lt;/span&gt; SalesOrderID&lt;span style="color:gray"&gt;,&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; SalesPersonID&lt;span style="color:gray"&gt;,&lt;/span&gt; CustomerID&lt;span style="color:gray"&gt;,&lt;/span&gt; OrderDate&lt;span style="color:gray"&gt;,&lt;/span&gt; SubTotal&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
			&lt;span style="color:teal"&gt;vSearch&lt;/span&gt;
			&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;Name&lt;/span&gt;
			&lt;span style="color:gray"&gt;=&lt;/span&gt;
			&lt;span style="color:red"&gt;'CARGO TRANSPORT 5'&lt;span style="color:gray"&gt;)&lt;/span&gt;
				&lt;span style="color:teal"&gt;v&lt;/span&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesTerritory&lt;/span&gt;
					&lt;span style="color:teal"&gt;st&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt; =&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Customer&lt;/span&gt;
					&lt;span style="color:teal"&gt;c&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;CustomerID&lt;/span&gt; =&lt;/span&gt; c&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;CustomerID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;Person&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Person&lt;/span&gt;
					&lt;span style="color:teal"&gt;p&lt;/span&gt;
					&lt;span style="color:blue"&gt;ON&lt;/span&gt;
					&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesPersonID&lt;/span&gt; =&lt;/span&gt; p&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;BusinessEntityID&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;row_id&lt;/span&gt; BETWEEN&lt;/span&gt; 1 &lt;span style="color:gray"&gt;AND&lt;/span&gt; 20
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;/span&gt;
					&lt;span style="color:blue"&gt;DESC&lt;span style="color:gray"&gt;;&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 3 Get SalesTerritory values&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:blue"&gt;DISTINCT&lt;/span&gt;
			&lt;span style="color:teal"&gt;st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt;
							&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
							&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesTerritory&lt;/span&gt;
									&lt;span style="color:teal"&gt;st&lt;/span&gt;
								&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:gray"&gt;INNER&lt;/span&gt;
			&lt;span style="color:gray"&gt;JOIN&lt;/span&gt;
			&lt;span style="color:teal"&gt;vSearch&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt; =&lt;/span&gt; st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;TerritoryID&lt;/span&gt;
				&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt; =&lt;/span&gt;
				&lt;span style="color:red"&gt;'CARGO TRANSPORT 5'&lt;/span&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORdER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;st&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;span style="color:gray"&gt;;&lt;/span&gt;
					&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:green"&gt;-- 4 Get OrderDate Year values&lt;/span&gt;
		&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;SELECT&lt;/span&gt;
			&lt;span style="color:blue"&gt;DISTINCT&lt;/span&gt;
			&lt;span style="color:fuchsia"&gt;YEAR&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;)&lt;/span&gt;
								&lt;span style="color:blue"&gt;as&lt;/span&gt; OrderDateYear&lt;/span&gt;
							&lt;span style="color:blue"&gt;FROM&lt;/span&gt;
							&lt;span style="color:teal"&gt;vSearch&lt;/span&gt;
							&lt;span style="color:teal"&gt;v&lt;/span&gt;
						&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;WHERE&lt;/span&gt;
			&lt;span style="color:teal"&gt;v&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;Name&lt;/span&gt; =&lt;/span&gt;
				&lt;span style="color:red"&gt;'CARGO TRANSPORT 5'&lt;/span&gt;
			&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;ORDER&lt;/span&gt;
			&lt;span style="color:blue"&gt;BY&lt;/span&gt;
			&lt;span style="color:teal"&gt;OrderDateYear&lt;span style="color:gray"&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;An additional index was needed:
&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas; font-size:9pt"&gt;&lt;span style="color:blue"&gt;CREATE&lt;/span&gt;
			&lt;span style="color:blue"&gt;NONCLUSTERED&lt;/span&gt;
			&lt;span style="color:blue"&gt;INDEX&lt;/span&gt;
			&lt;span style="color:teal"&gt;temp_IX_SALESORDERHEADER_ShipMethodID&lt;/span&gt;
			&lt;span style="color:blue"&gt;ON&lt;/span&gt;
			&lt;span style="color:teal"&gt;Sales&lt;span style="color:gray"&gt;.&lt;span style="color:teal"&gt;SalesOrderHeader&lt;span style="color:blue"&gt;
							&lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;ShipMethodID&lt;span style="color:gray"&gt;)&lt;/span&gt;
									&lt;span style="color:blue"&gt;INCLUDE &lt;span style="color:gray"&gt;(&lt;span style="color:teal"&gt;OrderDate&lt;span style="color:gray"&gt;,&lt;span style="color:teal"&gt;CustomerID&lt;span style="color:gray"&gt;,&lt;span style="color:teal"&gt;SalesPersonID&lt;span style="color:gray"&gt;,&lt;span style="color:teal"&gt;TerritoryID&lt;span style="color:gray"&gt;,&lt;span style="color:teal"&gt;SubTotal&lt;span style="color:gray"&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;
 &lt;/p&gt;&lt;p&gt;This resulted in 466 reads. More optimizations can be done bit a big win was gained by using a view and just retrieving the data directly instead of using temporary sets.
&lt;/p&gt;&lt;p&gt;A big lesson lies in the creation of the temporary objects. If you create a simple table with two columns and just 10 records and you select the table you will only get a few reads. If you create a table variable, insert the real table into the variable and select it again you get a couple of hundred reads. On small sets you won't notice a big difference but on larger sets the difference on cpu, reads, writes and duration is really noticeable.
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3510114" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="Performance" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Performance/" /></entry><entry><title>I got my MCM Lab result.... And I failed!</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/07/06/i-got-my-mcm-lab-result-and-i-failed.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/07/06/i-got-my-mcm-lab-result-and-i-failed.aspx</id><published>2012-07-06T16:51:48Z</published><updated>2012-07-06T16:51:48Z</updated><content type="html">&lt;p&gt;A couple of weeks ago I got the result from my SQL 2008 MCM Lab exam and I failed.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I have been working with SQL Server for almost 12 years. I have been a developer, &lt;span&gt;dba&lt;/span&gt; and architect and last year I joined Microsoft to become a Premier Field Engineer on SQL Server. This means I have a broad experience with several aspects of SQL Server and since joining Microsoft I learned something new every week, if not every day.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So how did I prepare for the MCM Lab exam? Well I did not. And I choose to. I wanted to know where I stood. Talking to other people who were thinking of doing the MCM and reading through the materials I was not sure what to expect. And for me that makes it hard to prepare myself. Although one could argue this is exactly what you would do in real life, it just doesn't feel the same. Failing the MCM Lab exam made me more experienced. Every day I waited for the result I knew more and more what I did wrong and how it should have been done. So even though I failed I have learned a lot. I think you can prepare yourself perfectly by going through the material listed on the MCM site. I just didn't have to time to go through it although I did went through some video's. So in a sense I did prepare myself, but for me, everyday is preparation for the MCM. I get challenged every week by different customers, with different SQL Server setups and different challenges. Some are hard, some are easy, some bring up a lot of discussion and some are just a lot of fun but every engagement has made me more knowledgeable on SQL.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Of course I am retaking the exam. And the fact that I did not pass but did well, strengthens me in my believe that I can achieve this. But this time I come prepared. I know my weak points.This means I can develop a proper &lt;span&gt;battleplan&lt;/span&gt;. I will watch a few of the MCM videos, especially those in my weak areas (&lt;/span&gt;&lt;a href="http://technet.microsoft.com/en-us/sqlserver/ff977043.aspx"&gt;&lt;span&gt;http://technet.microsoft.com/en-us/&lt;span&gt;sqlserver&lt;/span&gt;/ff977043.&lt;span&gt;aspx&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;). I will setup a lab myself an try out some scenarios I think are common or hard to setup. Being able to apply knowledge from experience will help you getting the job done.&lt;/p&gt;
&lt;p&gt;I love the exam. It is so much more testing your skills then the "regular" exams. But then again, this is the master exam. If you are pursuing the exam yourself challenge yourself with peers, get a group of people together trying to achieve the same goal. And if you think you are ready, go for it. Worst thing that could happen is that you fail. But that wouldn't be the end of the world. You can always retry.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3507833" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="MCM" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/MCM/" /></entry><entry><title>Kerberos and AvailabilityGroups - What you need to know</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2012/03/04/kerberos-and-availabilitygroups-what-you-need-to-know.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2012/03/04/kerberos-and-availabilitygroups-what-you-need-to-know.aspx</id><published>2012-03-04T17:47:00Z</published><updated>2012-03-04T17:47:00Z</updated><content type="html">&lt;p&gt;With the freshly released SQL Server 2012 we can put availability groups to live. You have seen all the demo's and now you are ready to get things going in your own datacenter. At this point you might get to a few surprises. One of these might be to get Kerberos going for your availability groups. If we recap the theory behind availability groups we get a more clearer picture.&lt;/p&gt;
&lt;p&gt;In SQL Server 2012 we use availability groups as a unit of failover. We have up to five single SQL instances. The underlying nodes participate in the same Windows Failover Cluster. In the cluster configuration you will notice a few resources shared amongst these independent SQL instances:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Availability Group Resource&lt;/li&gt;
&lt;li&gt;IP-Address&lt;/li&gt;
&lt;li&gt;Virtual Network Name&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now if you want to use Kerberos you must make sure all prerequirements are met. The most important thing being a service principal name, or SPN. We set a SPN using the SETSPN command that's included in the Windows. A good start on more information is Books Online: &lt;a href="http://msdn.microsoft.com/en-us/library/ms191153(v=sql.110).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms191153(v=sql.110).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Getting Kerberos to work on just SQL should not be hard. So now we introduce availability groups. This is where it gets harder. To get Kerberos working on availability groups you must also set a SPN on the virtual network name.&lt;/p&gt;
&lt;p&gt;So if you have an availability group named AG-SQL-1 in the CONTOSO.COM domain you must set a SPN on ag-sql-1.contoso.com with the correct port and the domain account running the SQL Server process. So here is a catch. What if the availability group fails over to another node. It needs to be registered again unless that node is running with the same domain credentials.&lt;/p&gt;
&lt;p&gt;Bottom line: if you want to use Kerberos with availability groups you need to run all nodes with the same domain account. This will save you a lot of headaches.&lt;/p&gt;
&lt;p&gt;You can read&amp;nbsp;up on it in Books Online: &lt;a href="http://msdn.microsoft.com/en-us/library/ff878487(v=sql.110).aspx#PrerequisitesSI"&gt;http://msdn.microsoft.com/en-us/library/ff878487(v=sql.110).aspx#PrerequisitesSI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3484502" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="SQL Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server+2012/" /><category term="AlwaysOn" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/AlwaysOn/" /></entry><entry><title>SQL Server 2012 RC0, A New AlwaysOn Experience</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2011/11/20/sql-server-2012-rc0-a-new-alwayson-experience.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2011/11/20/sql-server-2012-rc0-a-new-alwayson-experience.aspx</id><published>2011-11-20T09:01:27Z</published><updated>2011-11-20T09:01:27Z</updated><content type="html">&lt;p&gt;Last week RC0 for SQL Server 2012 was released. If you missed it you can find it here: &lt;a title="http://www.microsoft.com/download/en/details.aspx?id=28145" href="http://www.microsoft.com/download/en/details.aspx?id=28145"&gt;http://www.microsoft.com/download/en/details.aspx?id=28145&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;One area where you will find improvements or changes is AlwaysOn Availability Groups. In this post I will step through the wizard to show you the improvements that were made. The basis is a 4 node Windows Server 2008 R2 cluster with a stand alone SQL Server 2012 RC0 installation on each of them. All instances use the same domain account. On my first instance, SQL-02, I have two databases; AlwaysOnDb1 and AlwaysOnDb2. I will create an availability group for these databases and sync these to three replica’s.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;In Management Studio connect to the first instance, SQL-02 and navigate to the new &lt;strong&gt;AlwaysOn High Availability&lt;/strong&gt; tree item. Right click it and choose &lt;strong&gt;New Availability Group Wizard&lt;/strong&gt;.&lt;/li&gt;    &lt;li&gt;Skip the Welcome Screen by clicking &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;    &lt;li&gt;First specify the name for the availability group. I’m using AG-AlwaysOn-1. Click &lt;strong&gt;Next&lt;/strong&gt; to proceed.&lt;/li&gt;    &lt;li&gt;In the next screen you can specify the databases you can use in your availability group. Choose all that apply and click &lt;strong&gt;Next&lt;/strong&gt; to proceed. If for some reason the database cannot be chosen check the status column.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/6153.image_5F00_4E8303B1.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/2843.image_5F00_thumb_5F00_7E7D2F65.png" width="244" height="226" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;The next screen is where the real magic happens. This screen has changed a lot since CTP3. Let’s go through each tab. The first tab is &lt;strong&gt;Replicas&lt;/strong&gt;. This is where you will specify the replicas. Add an replica by clicking &lt;strong&gt;Add Replica&lt;/strong&gt; and choose your favorite option. I’m using all four instances.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/5305.image_5F00_2F303711.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/1185.image_5F00_thumb_5F00_54B9B472.png" width="244" height="227" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;The second tab is &lt;strong&gt;Endpoints&lt;/strong&gt;. This is where you will specify the endpoints used by the mirroring sessions. By default these are encrypted.&lt;/li&gt;    &lt;li&gt;The third tab is &lt;strong&gt;Backup Preferences&lt;/strong&gt;. This is where you specify where the backups are taken. But remember, this is not forced. You have to create the logic yourself. Read more about backups on replicas here: &lt;a title="http://msdn.microsoft.com/en-us/library/hh245119(v=sql.110).aspx" href="http://msdn.microsoft.com/en-us/library/hh245119(v=sql.110).aspx"&gt;http://msdn.microsoft.com/en-us/library/hh245119(v=sql.110).aspx&lt;/a&gt;. To demonstrate this later on I will set the top priority on SQL-04, then SQL-03 and last SQL-02. I will configure SQL-05 as a machine where no backups are allowed.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/8032.image_5F00_7A4331D3.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/1108.image_5F00_thumb_5F00_0ADB2CC2.png" width="244" height="226" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;The final tab on this screen is the &lt;strong&gt;Listener&lt;/strong&gt; tab. The listener is the connection between the availability group and the application. The name specified in this tab, is the name you use for your connection. Provide a name and a port and set the network mode to Static or DHCP according to your network setup.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/3264.image_5F00_1768D9DE.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/8055.image_5F00_thumb_5F00_0F050487.png" width="244" height="226" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Click &lt;strong&gt;Next&lt;/strong&gt; to continue and specify how you want the data to be initialized. There are three options here:       &lt;br /&gt;1. &lt;strong&gt;Full&lt;/strong&gt; – If you want the wizard to take care of the synchronization.       &lt;br /&gt;2. &lt;strong&gt;Join Only&lt;/strong&gt; – If you have already placed the databases on the replica’s.       &lt;br /&gt;3. &lt;strong&gt;Skip&lt;/strong&gt; – If you plan to place the databases on another time.&lt;/li&gt;    &lt;li&gt;Clicking &lt;strong&gt;Next&lt;/strong&gt; will validate your configuration and the greener the better.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/4338.image_5F00_58B3DC77.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/4846.image_5F00_thumb_5F00_04F0635C.png" width="244" height="226" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Next&lt;/strong&gt; followed by &lt;strong&gt;Finish&lt;/strong&gt; will create the availability group.       &lt;br /&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/6318.image_5F00_7C8C8E04.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/5824.image_5F00_thumb_5F00_1A8A9BF9.png" width="244" height="225" /&gt;&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;The warning is related to the Windows Server cluster configuration. In my case this is not the most desired configuration. The warning provides a link to the KB article that describes the quorum models and what the preferred one is.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Now that the availability group is created we can open up the dashboard to view the health. You can open the dashboard by right clicking the &lt;strong&gt;AlwaysOn High Availability&lt;/strong&gt; item in management studio and choose &lt;strong&gt;Show Dashboard&lt;/strong&gt;. This is what it looks like.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/2781.image_5F00_6D95391D.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/7180.image_5F00_thumb_5F00_0B934712.png" width="244" height="175" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To quickly check if I can perform backups on a replica I connect to SQL-05 using management studio, open a new query window and create a COPY_ONLY backup. This will work, although I specified during the wizard that this replica was not available for backups. So remember, you can always create a COPY_ONLY full or a log backup on the replicas. For log backups remember that these will also be part of the log chain. You &lt;strong&gt;&lt;u&gt;&lt;font color="#ff0000"&gt;WILL&lt;/font&gt;&lt;/u&gt; &lt;/strong&gt;need these to restore your database to a point in time. You can create backup logic with the new &lt;strong&gt;sys.fn_hadr_backup_is_preferred_replica&lt;/strong&gt; function. Here is an example.&lt;/p&gt;  &lt;div style="margin: 0px; padding: 0px; float: none; display: inline;" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6f19087e-daff-46b2-a369-c2ff16f62adc" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #ddd; max-height: 300px; overflow: auto"&gt; &lt;ol start="1" style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;if&lt;/span&gt; &lt;span style="color:#008000"&gt;sys&lt;/span&gt;&lt;span style="color:#808080"&gt;.&lt;/span&gt;&lt;span style="color:#008080"&gt;fn_hadr_backup_is_preferred_replica&lt;/span&gt;&lt;span style="color:#808080"&gt;(&lt;/span&gt;&lt;span style="color:#ff0000"&gt;&amp;#39;AlwaysOnDb1&amp;#39;&lt;/span&gt;&lt;span style="color:#808080"&gt;)&lt;/span&gt; &lt;span style="color:#808080"&gt;=&lt;/span&gt; 0&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;begin&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#008000"&gt;-- This is not the preferred replica&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;raiserror&lt;/span&gt;&lt;span style="color:#808080"&gt;(&lt;/span&gt; &lt;span style="color:#ff0000"&gt;&amp;#39;Backup is not preferred on this replica&amp;#39;&lt;/span&gt;&lt;span style="color:#808080"&gt;,&lt;/span&gt;10&lt;span style="color:#808080"&gt;,&lt;/span&gt;1&lt;span style="color:#808080"&gt;)&lt;/span&gt; &lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;end&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;else&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;begin&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#008000"&gt;-- Backup this database&lt;/span&gt;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;backup&lt;/span&gt; &lt;span style="color:#0000ff"&gt;database&lt;/span&gt; &lt;span style="color:#008080"&gt;AlwaysOnDb1&lt;/span&gt; &lt;span style="color:#0000ff"&gt;to&lt;/span&gt; &lt;span style="color:#0000ff"&gt;disk&lt;/span&gt; &lt;span style="color:#808080"&gt;=&lt;/span&gt; &lt;span style="color:#ff0000"&gt;&amp;#39;&amp;#92;&amp;#92;dc-01&amp;#92;temp&amp;#92;AlwaysOnDb1_FULL.bak&amp;#39;&lt;/span&gt; &lt;span style="color:#0000ff"&gt;WITH&lt;/span&gt; &lt;span style="color:#0000ff"&gt;COPY_ONLY&lt;/span&gt;&lt;/li&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;end&lt;/span&gt;&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;p&gt;SQL Server 2012 RC0 provides an even better experience for the availability groups but you still have to be in control. Know what you are doing. Where you want backups to happen. If log backups are made on replicas. With greater powers come greater responsibilities.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3466272" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="SQL Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server+2012/" /><category term="AlwaysOn" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/AlwaysOn/" /></entry><entry><title>Getting HadronCore on SQL Server 2012</title><link rel="alternate" type="text/html" href="http://blogs.technet.com/b/rhartskeerl/archive/2011/10/31/getting-hadroncore-on-sql-server-2012.aspx" /><id>http://blogs.technet.com/b/rhartskeerl/archive/2011/10/31/getting-hadroncore-on-sql-server-2012.aspx</id><published>2011-10-31T21:29:00Z</published><updated>2011-10-31T21:29:00Z</updated><content type="html">&lt;p&gt;One of the new features of SQL Server 2012 is AlwaysOn Availability Groups. You can think of Availability Groups as Database Mirroring on steroids. Database mirroring is only limited to one database, one secondary and if you wanted to read off it you had to create a snapshot. And in the case of a failover the application has to reconnect to another machine.&lt;/p&gt;
&lt;p&gt;AlwaysOn Availability Groups provide much more flexibility for high availability and disaster recovery. With AlwaysOn you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use multiple databases within an availability group. The group becomes the unit of failover and not a single database.&lt;/li&gt;
&lt;li&gt;Use up to four secondary's.&lt;/li&gt;
&lt;li&gt;Secondary&amp;rsquo;s can be readable without using a snapshot.&lt;/li&gt;
&lt;li&gt;Backups can be taken off secondary&amp;rsquo;s.&lt;/li&gt;
&lt;li&gt;A Virtual Network Name can be used to redirect clients.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another great feature is the support for Windows server core editions and the growing adaption of PowerShell. In this post I will guide you through a gui-less installation of AlwaysOn availability groups. Let&amp;rsquo;s get started.&lt;/p&gt;
&lt;p&gt;If you want to use availability groups you will need a Windows Failover Cluster. No need to run off. This is not the cluster you are used too. Besides, cluster installations have become much easier with Windows Server 2008 and SQL Server 2008. You can still cluster a SQL instance with SQL Server 2012, in fact it has much improved as well. What would you say about SMB support, local storage support for TempDB, multi-subnet clustering and better diagnostics and failover policy. But let&amp;rsquo;s not get sidetracked, we are doing availability groups.&lt;/p&gt;
&lt;p&gt;To prove that SQL isn&amp;rsquo;t clustered I will install SQL first on all machines and configure Windows Failover Clustering later. All machines are Windows Server 2008 R2 Sp1 Core editions with all updates installed including .NET 4.0. Every machine has one disk, the OS disk. No shared cluster disks or iSCSI drives here. The machines have one NIC and are all bound to a local Contoso domain. I&amp;rsquo;m using one domain account for all installations and I also added the account to the SYSADMIN server role afterwards. Installation is easy, pop in the disk or whatever you are using and fire away: &lt;br /&gt;&lt;strong&gt;setup.exe /q /ACTION=Install /FEATURES=SQLENGINE /INSTANCENAME=MSSQLSERVER &lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;/SQLSVCACCOUNT=CONTOSO\sqlsvc &lt;a&gt;/SQLSVCPASSWORD=p@ssw0rd&lt;/a&gt; &lt;br /&gt;/AGTSVCACCOUNT=CONTOSO\sqlsvc &lt;a&gt;/AGTSVCPASSWORD=p@ssw0rd&lt;/a&gt; &lt;br /&gt;/IACCEPTSQLSERVERLICENSETERMS /INDICATEPROGRESS &lt;br /&gt;/AGTSVCSTARTUPTYPE=Automatic /SQLSYSADMINACCOUNTS=CONTOSO\SqlAdmins &lt;br /&gt;/TCPENABLED=1 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This will install the SQL Server engine on the box, and just SQL Server. That&amp;rsquo;s all I need, but you are not limited to only installing the engine on core. Second thing is to open up the firewall; &lt;strong&gt;netsh advfirewall firewall add rule name="SQL Server Default TCP Port" dir=in action=allow protocol=tcp localport=1433 profile=domain&lt;/strong&gt;. To prepare thing for the Availability Groups I will open port 5022 as well. This is the port I will use for the mirroring endpoint. I&amp;rsquo;m using this command; &lt;strong&gt;netsh advfirewall firewall add rule name="SQL Server HADR Endpoint" dir=in action=allow protocol=tcp localport=5022 profile=domain&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all. I repeated this on all my four machines and checked the connection between all of them. Next step is getting Windows Failover Clustering working.&lt;/p&gt;
&lt;p&gt;For all machines we need to enable Failover Clustering. For this we use the trusty DISM command line tool; &lt;strong&gt;DISM /online /enable-feature /featurename:FailoverCluster-Core&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now we got everything setup to get the cluster going. Installing a cluster on core couldn&amp;rsquo;t be easier. On the shell type: &lt;strong&gt;cluster /cluster:cls-sql-01 /create /nodes:"SQL-02 SQL-03 SQL-04 SQL-05" /ipaddr:192.168.200.8/24&lt;/strong&gt; and you&amp;rsquo;re done. Wait for it to finish and you&amp;rsquo;ve got yourself a nice cluster, a very basic cluster, but it&amp;rsquo;s enough to get AlwaysOn going. And you can use the cluster.exe to make it as complicated as you like.&lt;/p&gt;
&lt;p&gt;The next step is to enable AlwaysOn. Remember that if you destroy a cluster and rebuild it you also have to disable and enable AlwaysOn. Enabling AlwaysOn has to be done with PowerShell or the SQL Configuration Manager. In my case it will be PowerShell because I don&amp;rsquo;t have a GUI. There are two ways to do this, start SQLPS, the SQL Server PowerShell host or import the SQLPS module in PowerShell. I prefer the second method. So I first start PowerShell, then import SQLPS using Import-Module SqlPS. This will give a warning which you can ignore. To enable AlwaysOn we use one of the new SQL Server cmdlets, Enable-SqlHadrService. This function accepts a parameter to tell which instance you want to enable and optionally you can force it to restart the instance. I&amp;rsquo;m using &lt;strong&gt;Enable-SqlHadrService &amp;ndash;serverinstance SQL-02 &amp;ndash;force&lt;/strong&gt; to enable AlwaysOn and force a restart. If you don&amp;rsquo;t supply &amp;ndash;force you will be prompted to restart the instance. This is repeated for all instances.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Now we have to make a sidestep. In CTP3 we have to enable a traceflag to get all the functionality I wanted in my little demonstration. For this I once again restorted to PowerShell and used &lt;strong&gt;New-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQLServer\Parameters" -Name "SQLArg3" -Value "-T9532" -PropertyType "String"&lt;/strong&gt;. Now this it limited to my setup and machine. The general idea is to add an extra value to the startup arguments. If this will work in your environment depends on your configuration. So, it is the registry you are dealing with, if you are not comfortable or don&amp;rsquo;t know what&amp;rsquo;s going on in this statement don&amp;rsquo;t do it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now the big moment has arrived. The following long line of PowerShell will setup the availability groups for me, and again for me. Tweak and alter it to satisfy your needs. This script is based on the one provided in Books Online (&lt;a title="http://msdn.microsoft.com/en-us/library/gg492181(v=SQL.110).aspx" href="http://msdn.microsoft.com/en-us/library/gg492181(v=SQL.110).aspx"&gt;http://msdn.microsoft.com/en-us/library/gg492181(v=SQL.110).aspx&lt;/a&gt;).&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="csharp"&gt; $Primary = "SQL-02" &lt;br /&gt; $SecondaryList = "SQL-03","SQL-04","SQL-05" &lt;br /&gt; $AgName = "AG_PS_DEMO" &lt;br /&gt; $Database = "SAMPLE" &lt;br /&gt; $BackupDirectory = "\\DC-01\temp\" &lt;br /&gt; $ENDPOINTPORT = 5022 &lt;br /&gt; pushd&lt;br /&gt; &lt;br /&gt; # Backup databases and logs &lt;br /&gt; foreach($db in $Database) &lt;br /&gt; { &lt;br /&gt; Write-Host -ForegroundColor Green "Backup $db (and log) on $Primary" &lt;br /&gt; $fullBackupFile = Join-Path $BackupDirectory "$db.bak" &lt;br /&gt; $logBackupFile = Join-Path $BackupDirectory "$db.trn" &lt;br /&gt; &lt;br /&gt; Backup-SqlDatabase $db $fullbackupFile -ServerInstance $Primary &lt;br /&gt; Backup-SqlDatabase $db $logBackupFile -ServerInstance $Primary -BackupAction "Log" &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; New-SqlHadrEndpoint -Path SQLSERVER:\SQL\$Primary\Default -Name HadrEndpoint -Port $ENDPOINTPORT &lt;br /&gt; Set-SqlHadrEndpoint -Path SQLSERVER:\SQL\$Primary\Default\Endpoints\HadrEndpoint -State Started &lt;br /&gt; New-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-03\Default -Name HadrEndpoint -Port $ENDPOINTPORT &lt;br /&gt; Set-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-03\Default\Endpoints\HadrEndpoint -State Started &lt;br /&gt; New-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-04\Default -Name HadrEndpoint -Port $ENDPOINTPORT &lt;br /&gt; Set-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-04\Default\Endpoints\HadrEndpoint -State Started &lt;br /&gt; New-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-05\Default -Name HadrEndpoint -Port $ENDPOINTPORT &lt;br /&gt; Set-SqlHadrEndpoint -Path SQLSERVER:\SQL\SQL-05\Default\Endpoints\HadrEndpoint -State Started&lt;br /&gt; &lt;br /&gt; # Create availability replicas as templates &lt;br /&gt; $replica1 = New-SqlAvailabilityReplica -Name $Primary -EndpointURL "TCP://SQL-02:$ENDPOINTPORT" -AsTemplate -FailOverMode 'Automatic' -AvailabilityMode 'SynchronousCommit' -Version 11 &lt;br /&gt; $replica2 = New-SqlAvailabilityReplica -Name $SecondaryList[0] -EndpointURL "TCP://SQL-03:$ENDPOINTPORT" -AsTemplate -FailOverMode 'Automatic' -AvailabilityMode 'SynchronousCommit' -Version 11 &lt;br /&gt; $replica3 = New-SqlAvailabilityReplica -Name $SecondaryList[1] -EndpointURL "TCP://SQL-04:$ENDPOINTPORT" -AsTemplate -FailOverMode 'Manual' -AvailabilityMode 'AsynchronousCommit' -Version 11 &lt;br /&gt; $replica4 = New-SqlAvailabilityReplica -Name $SecondaryList[2] -EndpointURL "TCP://SQL-05:$ENDPOINTPORT" -AsTemplate -FailOverMode 'Manual' -AvailabilityMode 'AsynchronousCommit' -ConnectionModeInSecondaryRole 'AllowAllConnections' -Version 11&lt;br /&gt; &lt;br /&gt; # Create AG on primary &lt;br /&gt; cd SQLSERVER:\SQL\$Primary\default &lt;br /&gt; Write-Host -ForegroundColor Green "Create availability group $AgName on $Primary" &lt;br /&gt; New-SqlAvailabilityGroup $AgName -AvailabilityReplica ($replica1,$replica2,$replica3,$replica4) -Database $Database&lt;br /&gt; &lt;br /&gt; foreach($Secondary in $SecondaryList) &lt;br /&gt; { &lt;br /&gt; # Join AG on secondary &lt;br /&gt; Write-Host -ForegroundColor Green "Join $Secondary to availability group $AgName" &lt;br /&gt; cd SQLSERVER:\SQL\$Secondary\default &lt;br /&gt; Join-SqlAvailabilityGroup -Name $AgName&lt;br /&gt; &lt;br /&gt; # Restore databases and logs &lt;br /&gt; foreach($db in $Database) &lt;br /&gt; { &lt;br /&gt; Write-Host -ForegroundColor Green "Restore $db (and log) on $Secondary" &lt;br /&gt; $fullBackupFile = Join-Path $BackupDirectory "$db.bak" &lt;br /&gt; $logBackupFile = Join-Path $BackupDirectory "$db.trn"&lt;br /&gt; &lt;br /&gt; Restore-SqlDatabase $db $fullbackupFile -ServerInstance $Secondary -NoRecovery &lt;br /&gt; Restore-SqlDatabase $db $logBackupFile -ServerInstance $Secondary -RestoreAction "Log" -NoRecovery&lt;br /&gt; &lt;br /&gt; trap { Write-Warning "Error while restoring, but continuing." ; continue } &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; # Join databases on secondary &lt;br /&gt; Write-Host -ForegroundColor Green "Join databases to availability group $AgName" &lt;br /&gt; $availabilityGroup = get-item SQLSERVER:\SQL\$Secondary\DEFAULT\AvailabilityGroups\$AgName&lt;br /&gt; &lt;br /&gt; foreach($db in $Database) &lt;br /&gt; { &lt;br /&gt; Add-SqlAvailabilityDatabase -InputObject $availabilityGroup -Database $db &lt;br /&gt; } &lt;br /&gt; } &lt;br /&gt; popd &lt;br /&gt; &lt;br /&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To finish it off a fancy screenshot of the hard work.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/8662.image_5F00_6C82FAF1.png"&gt;&lt;img style="margin: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-90-29-metablogapi/0333.image_5F00_thumb_5F00_1D81E9F8.png" width="244" height="161" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To get things going on Windows Server 2008 Core is not hard. Up to point where you setup the availability groups it&amp;rsquo;s much faster, easier and repeatable. Setting up the availability groups can be done from a remote machine using the wizard if you like. The script I demonstrated here worked on my setup, you have to change it to get things going on your side.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3462504" width="1" height="1"&gt;</content><author><name>Robert Hartskeerl</name><uri>http://blogs.technet.com/rhartskeerl_4000_msn.com/ProfileUrlRedirect.ashx</uri></author><category term="SQL Server" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server/" /><category term="Windows Server 2008 R2" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/Windows+Server+2008+R2/" /><category term="SQL Server 2012" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/SQL+Server+2012/" /><category term="AlwaysOn" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/AlwaysOn/" /><category term="PowerShell" scheme="http://blogs.technet.com/b/rhartskeerl/archive/tags/PowerShell/" /></entry></feed>