Optimization

Industrial strength vCenter database maintenance (for SQL Express too!)

Over time, vCenter does a huge number of reads and writes to it’s database. Most of these come from the performance stats, and depending on the level of stats you have turned on, the number of writes can be very substantial. After a while, even with a small-to-medium infrastructure, the database will need some love to keep it working like it should. VMware has some recommendations about maintenance on your database, specifically here if you are using SQL Server. However, their recommendations only do a little to help if you have a very badly fragmented database.

You see, dbcc indexdefrag only defragments the index. This means that it will reorganize the pages in the index so that they are near to each other, but if you have a lot of partially filled pages, it still won’t do a whole lot of good. Don’t misunderstand me, it will help as it means that an index scan will perform significantly better since the scan will not require as much I/O work, but there are usually very few pages freed, which means that there could still be a large number of (potentially unnecessary) pages in the index.

Here is the example output that VMware provides in the KB article linked above:

DBCC SHOWCONTIG scanning 'VPX_HIST_STAT1' table...
Table: 'VPX_HIST_STAT1' (805577908); index ID: 3, database ID: 6
LEAF level scan performed.
- Pages Scanned................................: 173933
- Extents Scanned..............................: 21904
- Extent Switches..............................: 79082
- Avg. Pages per Extent........................: 7.9
- Scan Density [Best Count:Actual Count].......: 27.49% [21742:79083]
- Logical Scan Fragmentation ..................: 38.79%
- Extent Scan Fragmentation ...................: 84.35%
- Avg. Bytes Free per Page.....................: 5174.1
- Avg. Page Density (full).....................: 36.07%
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Notice the “Avg. Page Density (full)” item…each page is only 36% full, this means that there is a huge amount of white space in each page, which under the right circumstances, can be ok, but in this case, we probably don’t want that. Generally speaking, if there is a high number of writes to the table (an consequentially the index) then you want a lower page density (a.k.a. fill factor), a higher number of reads would mean a higher fill factor is appropriate.

vCenter, by my estimation, does quite a few writes to the database, but it also does a fair amount of reads (every time you view the performance tab, every time those graphs refresh, it’s a series of reads). Additionally, the roll-up stats act as a bit of an equalizer, as they do a significant amount of deletions in the tables.

What all this means, to me anyway, is that a medium-high fill factor (70-80%) seems to fit the bill. So, 36% suddenly seems quite low, and that 36% is only marginally improved with the index defrag.

Well, there happens to be a command available that rebuilds the indexes: alter index rebuild. What this means is that the current indexes (and all associated pages on disk) are deleted, after which the database engine will read each row in the table and rebuild the index, making it contiguous on disk, and we can specify the fill factor to what we think is appropriate.

Fortunately, some kind soul over on MSDN posted a very nice script that will check the status of all indexes on all tables in a particular database. To use the script, open SQL Server Management Studio (SSMS), connect to your SQL Server instance and open a new query window. Enter a use statement for the database:

USE VIM_VCDB
GO

Then copy the SQL in the post made by N8WEI into the SSMS query window below the above USE statement. There are a couple of parameters that you can set: the fill factor, the index defrag threshold, the index rebuild threshold, and the “report only” value. Fill factor is just that, I set it to 70%. The index defrag threshold (“reorg_frag_thresh”) can stay relatively low (10% or less), the rebuild threshold (“rebuild_frag_thresh”) can stay at 30% (unless you want to force a rebuild on all indexes, in which case set reorg_frag_thresh to 1 and rebuild_frag_thresh to 2). The last option (“report_only”) determines if the script will actually take any action. Leave it set to 1 for the moment.

By leaving report_only to 1, it will only check the indexes, it will not perform any action upon them. So when you press the “Execute” button (or F5), it will scan through the indexes for the database and check their fragmentation level. The result window will have a list of the indexes and the action to be taken.

Before you proceed, be aware of a couple of things. Doing an index defrag is transparent to the users (e.g. vCenter). If the database is very busy, it may seem a little slow while the defrag is occurring, but the database will still be usable. When an index rebuild is performed, the table is locked so that no action can be taken during the operation. This means that for the duration of the rebuild the table will be unavailable for read/write. This probably isn’t a big deal…I run the operation about once a month on all tables and it takes less than 60 seconds to complete. This means each table is only locked for a few seconds, at most, which is probably ok. vCenter updates each host’s performance stats every 20 seconds, and it shouldn’t fail the insert operation if it has to wait a second or two. If you are concerned about it, simply shutdown the vCenter service on the server and it will stop performing queries.

With that said, change report_only to 0 (zero), and hit the button. It will do it’s thing (the first time may take a minute or two depending on your stats level), and when you’re done your indexes should be fresh and new.

If you want a warm and tingly, be sure to run the VMware recommended dbcc showcontig on the history tables before and after executing the index rebuild(s). You should see near 99.9%+ scan density and a page density within a few hundredths of a percent of the value specified.

The end result is that performance is significantly improved, even for operations that don’t involve the performance stats (though those are especially noticeable). I run the above script, with settings to rebuild indexes, once a month. I also run the script with settings to defrag the indexes once a day, which helps to prevent as many page splits and, consquentially, leads to less fragmentation. (Hint: Use the SQL Server Agent to schedule the operations.)

Oh, and this works with SQL Express, though you may have to turn on connecting via TCP before you can use SSMS to execute queries (and there’s no SQL Server Agent, so you’ll have to use scheduled tasks).

And, if you are using SQL Express, you can also use SSMS Express (even if you are using the full SQL Server you can use SSMS Express). The SQL Server Management Stuido 2008 Express is a very nice (and very functional) application, and it’s freely available from Microsoft (::watches for sky to begin falling::).

Optimization
vCenter

Comments (0)

Permalink

PowerCLI: Update VMX Configuration Parameters (in mass)

My Virtual Infrastructure was recently audited.  As part of my preparation for said audit I needed to verify that several extra configuration Parameters were set on every VM. Nothing ground breaking, this has all been covered here, and here. So why the repost, well I’m obsessed with scaling! I don’t like doing anything that I can’t use to the nth degree. Having said that I found two simple tweaks that dramatically increased the performance of these scripts.

If you ever find yourself using where-object move back up the pipeline… can you use a filter instead? Here I dramatically improved performance by leveraging the built-in filter capabilities of Get-View. I was also able to crank it up by simply switching from the ReconfigVM method to the ReconfigVM_Task method. Unless your performing some serial action, always, always use the task method. Offloading the babysitting to vCenter just makes sense! Finally, I loath text files, especially when they create a needless dependencies. Here I use a simple hashtable to embed my configuration in the script it self.

I successfully used this script to update over 500 vm’s in less than 4min!  Now that is what I call scale!  I know the security experts our there would argue that this is meaningless, b/c of this or that… all I know is I passes my audit with flying colors (didn’t have one ding on a VM’s configuration).

$ExtraOptions = @{
    "isolation.tools.copy.disable"="true";
    "isolation.tools.paste.disable"="true";
    "isolation.tools.diskShrink.disable"="true";
    "isolation.tools.diskWiper.disable"="true";
    "isolation.tools.connectable.disable"="true";
    "isolation.tools.setGUIOptions.Enable"="false";
    "log.keepOld"="10";
    "log.rotateSize"="100000"
}
 
# build our configspec using the hashtable from above.  I prefer this
# method over the use of files b/c it has one less needless dependency.
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
# note we have to call the GetEnumerator before we can iterate through
Foreach ($Option in $ExtraOptions.GetEnumerator()) {
    $OptionValue = New-Object VMware.Vim.optionvalue
    $OptionValue.Key = $Option.Key
    $OptionValue.Value = $Option.Value
    $vmConfigSpec.extraconfig += $OptionValue
}
# Get all vm's not including templates
$VMs = Get-View -ViewType VirtualMachine -Property Name -Filter @{"Config.Template"="false"}
 
# Do it!
foreach($vm in $vms){
    $vm.ReconfigVM_Task($vmConfigSpec)
}

~Glenn

Optimization
PowerCLI
Powershell
Scripting
VMware
Virtulization

Comments (2)

Permalink

Bash script to apply NFS snapshot fix

After learning about the whole NFS fiasco I decided to create a quick bash script that would be part of my post kickstart process to apply the recommendations from NetApp as well as the fix required by VMware.

mmmmm, BASHy goodness….

Continue Reading »

ESX
NetApp
Optimization
VMware

Comments (0)

Permalink

Where-object vs WQL

No matter what you’re doing in PowerShell there are guaranteed to be at least 5 different ways to accomplish your goal.  Early on I would suggest focusing on the functionality, but after your script is working as intended.  A little time spent tuning and optimizing your various functions and loops will go a long way.   Sometimes an IF statement is faster than a switch. Likewise while vs. until vs. foreach… Take the time and try the various options.  Performance varies greatly depending on what type of object you’re working with, and what you’re doing with that object.   So far in my quest for posh speed I have found two things to be globally true:

1. The less data you pass down the pipe line the faster your script will run.
2. 99% of the time filtering at the source is 25%-50% faster then using select-object/where-object.

Along those lines I FINALY figured out how to do a “where not” WQL query!  Low and behold Glenn’s global laws of performance held true again…

If execution times are keeping you in the dark ages of automation.  Look no further than your own code.  I am yet to find a task where PowerShell doesn’t crush VBscript/WSH/BAT.

~Glenn

Optimization
Powershell
Scripting

Comments (0)

Permalink

XML vs CSV

Okay, so I know what .Net is, but how was I supposed to know it was this powerful.  For anyone who has every worked with xml in VBScript… I feel your pain.  With that knowledge of the headache, that was the “Msxml2.DOMDocument” com object.  I have avoided XML like the plague.   Problem is I was completely oblivious to what “.Net support” really meant!  I have several projects at work where I use PowerShell to “interact” with REST based web services.  Not wanting to take that XML dive, I requested “PowerShell hooks”, and was obliged.

When our programmers asked me, what I wanted returned?  I told them to give me a CSV in the format of a custom PS Object.  At the time, this seemed a no brainier.  Not only do I not have to worry about WSDL/ADO/XML, but also the data would stay objectized.

It worked GREAT that was until I started to manipulate large data sets.  Then my simple system fell apart. Downloading and saving that CSV file, before I could import that data.  Was simply too much, and was drastically degrading performance.  Therefore, I asked the question on the PowerShell community forums about optimizing such a task. The response I got lead me to crack open Bruce’s PowerShell in Action.  Low and behold, where has .Net been all my life!

Posted By bsonposh on 07/06/2008 10:51 AM
Actually… the *-clixml are meant for serializing and deserializing objects. Import-cliXML expects a VERY specific format.

If you want to “import” XML you can just type it
[XML]$myxml = < some data >

That is it… Just by type casting your object with [xml] the .net framework does the rest.  Not only is it easier then my custom CSV’s but its twice as fast!

~Glenn Sizemore

Optimization

Comments (0)

Permalink