Summary: SQL MVP, Sean McCown, talks about using Windows PowerShell to examine Dirty and Expensive SQL Server properties.

Microsoft Scripting Guy, Ed Wilson, is here. Here is blog two of three in a series from guest blogger, Sean McCown. Yesterday, we published Use PowerShell to Work with SQL Server Instance-Level Properties. You can read more about Sean and his previous guest blogs on the Hey, Scripting Guy! Blog site.

Here’s Sean…

In the last post, we talked about getting server properties and saving them to a table so you can get a good inventory of your environment. This time we’re going to talk about a couple of the columns in the property list that we didn’t get to before: Dirty and Expensive. I’ll quickly give you the line of code, but you can refer to the last post for a full explanation:

$a = dir | ?{$_.name –eq “SDLSEANM”} 

$a.properties | FT Name, Value, Expensive –auto

Let’s explore the Dirty column first. As it turns out, Windows PowerShell works with the same concept of caching that SQL Server does. So whenever you have a Windows PowerShell session open, and you make changes to objects, you’re quite often only making changes to the in-session copy of the objects, and not to the objects on the server.

Those of you who follow my videos have heard me say many times that if an object has an Alter() method, it’s usually meant to be used. A simple example is when you change the recovery model of your databases. If you go to the database level in Windows PowerShell, you can run the following code to change your recovery model from Full to Simple.

Dir | %{$_.RecoveryModel = 3}

There are three recovery models in SQL, and in SMO you work with the numbers—even though the numbers are translated when you query them. A good way to remember it is that they go from the most protective to the least. So Full is 1 and Simple is 3.

So if you look at the recovery models of the databases again, you’ll see that they’ve all been changed to Simple.

Dir | FT Name, RecoveryModel –auto

But if you look at the recovery model for any of the databases in SSMS, you’ll see that it’s still Full. So why is that? Well, that’s because you’ve only changed the in-session version of the property and it hasn’t been pushed to the server. To push it to the server, you’ll need to call the Alter() method like this:

Dir | %{$_.RecoveryModel = 3; $_.Alter()}

And now if you go to SSMS, you’ll see the values have been changed. This is what the Dirty column in the properties collection tells you. It tells you whether the value has been pushed to the server. It’s a lot like how writing to pages works. When you write data to a page, it gets written in memory, and it’s not until a checkpoint comes around that it actually writes the page to disk. In fact, we say that the checkpoint writes “dirty” pages to disk—dirty pages being those that have been changed, but not hardened to disk yet.

It’s the same thing here. The in-session page is dirty. That is, it hasn’t been written to the server yet. You can prove this very easily. After the first line where you made the change previously, but you didn’t call the Alter() method, view the properties and see what you find in the Dirty column. Do it exactly like this:

Dir | %{$_.RecoveryModel = 3}

$a = dir | select -first 1 ## just return the 1st one to avoid the loop. 

$a.properties | FT Name, Dirty -auto

You will see that RecoveryModel is set to True, which is dirty. The change has not been pushed to the server. Now run it again and call the Alter() method afterward, then inspect the properties again.

Dir | %{$_.RecoveryModel = 3; $_.Alter()} 

$a = dir | select -first 1 ## just return the 1st one to avoid the loop. 

$a.properties | FT Name, Dirty -auto

You can see that Dirty has been set back to False because the change has now been pushed to the server. You can verify this in SSMS now. Be very careful with this concept though. A common mistake beginners make is that they confuse properties with methods, and they often think that methods work the same way. They don’t.

So to change a property, you have to call the Alter() method to save the change, but when you call a method—for example, Drop()—you don’t need to call the Alter() method. The change is made on the server when the object is in the pipeline. So don’t confuse changing properties with calling methods or you’ll be very sorry one day.

You can use this method of looking at your dirty properties anywhere you see an object with properties and a property collection. I know I started this post talking about instance-level properties, but I wanted to show you that it’s the same at all levels so I gave you the example working with databases.

Now we can go back and do the exact same thing at the instance level and change something there.

$a = dir | ?{$_.name –eq “SDLSEANM”} 

$a.BackupDirectory = “F:\MyBackups” 

$a.properties | FT Name, Dirty -auto 

So you see, nothing has really changed. We can still inspect the Dirty column like we did at the database level. And of course, that means that we still have to call the Alter() method when making the change to begin with. Only here we have it set to a variable, so it may be best to separate it into two calls. Here’s what the final version looks like:

$a = dir | ?{$_.name –eq “SDLSEANM”} 

$a.BackupDirectory = “F:\MyBackups” 

$a.Alter()

$a.properties | FT Name, Dirty –auto

Alright, that’s it for the Dirty column. Now let’s talk briefly about the Expensive column. There’s not a lot of advice I can give you about it, but I want you to know what it means. Expensive means that the particular property is more expensive to gather. Now, there’s nothing like a good tautological definition—but what do you want from me? That’s really what it means. But logically, what does “expensive” mean? Well unfortunately, it doesn’t mean anything tangible in this case—nothing that is documented anyway. If you look up Property.Expensive Property on MSDN it says:

“The boundary between expensive properties and inexpensive properties is an arbitrary value.”

Frankly, I was hoping for a little more than that, but it pretty much jives with what I’ve seen in my testing and in my experience. I haven’t had any trouble pulling back any of the properties marked as expensive, so the value really must be completely arbitrary.

However, that’s not to say that if you were pulling back a lot of values, that you wouldn’t see some performance issues. I’ve only ever tested this on jobs and pulling back an expensive property (say Category) hasn’t proven to be any more expensive than anything else. But maybe if I had 10,000 jobs, I might start seeing some lag. If you notice these properties being slower on your system, you know how to investigate it now. You can query on whether it’s marked as Expensive, and then exclude it from your collection and see if the time improves. If it does, that one really is expensive for you.

Alright, that’s it for this time.

~Sean

Thank you, Sean. Come back tomorrow for another guest blog by Sean.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy