In a previous post I talked about Relogging Perfmon binary log files to SQL. The next obvious step is to query the data from the database.
There are two ways to do this:
1. Using Performance Monitor
Once you open Performance Monitor, press the View Log Data button (Ctrl-L):
Then on the Source tab, if you have the ODBC System DSN configured to connect to your performance database, it will show up.
This allows you to view the log files directly from SQL, just as if you had loaded the binary log files.
2. Querying SQL directly
At first glance, the schema doesn’t seem very intuitive. But with a little digging, it’s not too bad.
Whenever you use PerfMon or relog to log to a database, it automatically sets up this schema for you. There are three tables:
Here are some queries that I’ve found useful:
Get all computers that have counter data logged:
SELECT DISTINCT MachineName FROM CounterDetails ORDER BY MachineName
Get available object names for a particular computer:
SELECT DISTINCT ObjectName FROM CounterDetails WHERE MachineName = ‘\\MYSERVER’ ORDER BY ObjectName
Get counter names for a particular computer and object:
SELECT DISTINCT CounterName FROM CounterDetails WHERE MachineName = ‘\\MYSERVER’ AND ObjectName = ‘Processor’ ORDER BY CounterName
Get instance names for a particular computer, object and counter:
SELECT DISTINCT InstanceName FROM CounterDetails WHERE MachineName = ‘\\MYSERVER’ AND ObjectName = ‘Processor’ AND CounterName = ‘% Processor Time’ ORDER BY InstanceName
Get counter values for a particular computer, object, counter and instance. Name the column appropriately:
SELECT CAST(LEFT(CounterDateTime, 16) as smalldatetime) AS CounterDateTime, REPLACE(CounterDetails.MachineName,'\\','') AS ComputerName, CounterDetails.ObjectName + ISNULL('(' + CounterDetails.InstanceName + ')','') + '\' + CounterDetails.CounterName AS [Counter], CounterData.CounterValue FROM CounterData INNER JOIN CounterDetails ON CounterData.CounterID = CounterDetails.CounterID INNER JOIN DisplayToID ON CounterData.GUID = DisplayToID.GUID WHERE CounterDetails.ObjectName = 'Processor' AND CounterDetails.CounterName = '% Processor Time' AND CounterDetails.MachineName = '\\MYSERVER’ AND CounterDetails.InstanceName = '_Total' ORDER BY CounterData.CounterDateTime
There’s a few nuances in the schema which creates complexity in this query. Let me try and explain:
Great stuff, Grant! I would be interested in learning more about how you used the Interval report parameter in your example.
Hi JeffR,
I used a MOD (%) function with the @Interval parameter to filter the number of data points.
AND DATEPART(MINUTE, CAST(LEFT(CounterDateTime, 16) as smalldatetime)) % @Interval = 0
So if you set the @Interval to '60', it will only return every 60th value. And since we know that the data is logged once per minute, that is equivalent to one data point an hour. 15 = every 15 minutes, etc.
I've made some modifications to the sprocs + reports lately as well which I'll share soon.
This will work to convert 'CounterDateTime' to a datetime:
CONVERT(datetime, LEFT(CounterDateTime, 23), 121)
For some reason, the right-most character is the null character.