Monday, October 8, 2018

Powershell One Liners: Get current cpu utilization on all your SQL Servers

# Assuming you have list of servers in servers.txt, each server name in its own line

$ComputerNames = get-content servers.txt


# Method 1 - Using the Get-Counter cmdlet
# Notice that here you can also easily add the interval and max sample sizes


Get-Counter -Counter "\Processor(_Total)\% Processor Time" -SampleInterval 10 -MaxSamples 5 -ComputerName $ComputerNames | Export-Counter -path PercentageProcessorTime.csv -fileformat csv -force

# Method 2 - Using WMI Object
Get-WmiObject -Query "Select * from Win32_PerfFormattedData_PerfOS_Processor where name = '_Total'" -ComputerName $ComputerNames | sort PercentProcessorTime -descending | ft -Property PSComputerName, name, PercentProcessorTime -autosize







Powershell One Liners: Get status of SQL Instances on All SQL Servers


# Assuming you have list of servers in servers.txt, each sever name in its own line

$ComputerNames = get-content servers.txt

Get-WmiObject -Query "select * from win32_service where PathName like '%%sqlservr.exe%%'"  -ComputerName $ComputerNames | ft -Property PSComputerName, @{Name = "ServiceName"; Expression = 'Name'}, PathName, ExitCode, ProcessID, StartMode, State, Status




# To export the output into an excel/csv, just add "export-csv <filename.csv>" at the end..

Get-WmiObject -Query "select * from win32_service where PathName like '%%sqlservr.exe%%'"  -ComputerName $ComputerNames | ft -Property PSComputerName, @{Name = "ServiceName"; Expression = 'Name'}, PathName, ExitCode, ProcessID, StartMode, State, Status | export-csv SQLInstancesStatus.csv






PS: Or, to make this a true one-liner, embed the get-content cmdlet inside rounded brackets


Get-WmiObject -Query "select * from win32_service where PathName like '%%sqlservr.exe%%'"  -ComputerName (get-content servers.txt) | ft -Property PSComputerName, @{Name = "ServiceName"; Expression = 'Name'}, PathName, ExitCode, ProcessID, StartMode, State, Status


Sunday, October 7, 2018

SQL Server monitoring with built-in features

Do you think you need to use commercial tools like SQL Diagnostic Manager, SQL Sentry, Spotlight etc.. ?  Or do you think the built-in features are enough? There are complelling arguments in favor of each.

In this blog I hope to touch on every built-in feature to gather the performance information, some give real-time overviews of your databases whereas others provide detailed, on-demand data on SQL Server health and performance. I hope you learn something new.


There are several ways to use T-SQL queries to monitor SQL Server, using dynamic management views, built-in functions, stored procedures, or system data collections…


DMVs are virtual tables that you can query on adhoc or as part of your custom, automated monitoring.  Some shows sql server state at a particular instant whereas others, especially those that deal with performance counters, measures values on a regular internal and show you the difference between two samples.

sys.dm_os_performance_counters DMV is of particular interest to view every performance object and counter of interest.

For example, to view the buffer manager performance object values:

SELECT object_name,
       counter_name,
       cntr_value
FROM   sys.dm_os_performance_counters
WHERE  object_name = 'SQLServer:Buffer Manager'
       AND cntr_value != 0;

go

You’ll get a result similar to this:



My goal here is not to teach you each dmv, rather teach you to teach yourself!  You can find all such views in a system view sys.system_objects. 


select top 10000 * from sys.system_objects where type_desc = 'view'  order by name






For example, Filter the results on specific terms lie hadr for the always on views.

select top 10000 * from sys.system_objects
where type_desc = 'view' 
and name like '%hadr%'
order by name



HA Clusters:

select top 10000 * from sys.system_objects where type_desc = 'view' 
and name like '%cluster%'
order by name



To get a better understanding or each dmv, you should check out the specific documentation.

Built-in functions


Unlike dynamic management views, which return data in the form of virtual tables, built-in functions return system data as single numerical values, calculated since the server was last started. You can call each built-in function as the argument of a SELECT statement. For example, you can use the built-in function @@connections to return the sum of successful and unsuccessful connections over time:

SELECT @@connections AS "Total Connections";
GO

Total Connections
-----------------
             121

Note: @@connections increments every time a user attempts to log in (even if the attempt is unsuccessful).

The only built-in system statistics function that doesn’t return a single numerical value is sys.fn_virtualfilestats.

System stored procedures

Most stored procedures help with administrative tasks such as attaching a database or adding a login, but some stored procedures report metrics. But there are plenty that return stored meta data/configuration information.

EXEC sp_spaceused;


Management Data Warehouse


Simply put, MDW is SQL Server databases to store the state and performance data are stored from one or more SQL Servers. From there reports are generated and you can also create your own custom reports.

This feature actually brings it much closer to the way the compercial monitoring tools work and someday might make the paid tools completely redundent.

It uses the SQL Server Integration Services to automate the task of querying the database and writing the results to the Management Data Warehouse.

To read more on it:



SQL Server Management Studio


Activity Monitor

The Activity Monitor makes it possible to view SQL Server metrics in real time. To use the Activity Monitor, type “Ctrl-Alt-A” or click the icon within the SSMS toolbar.



To view execution plan for an expensive query, right click on the query and select Show Execution Plan:




Note: You can’t adjust the sizes of the graphs or the metrics they show. Nor can you change the way the Activity Monitor calculates the statistics for query performance

Dashboard Reports

There are about 20 standard dashboards reports in SSMS.



You can create a custom report.  And if you are keen to develop more reports, check out the Power BI , SQL Server Reporting Services (SSRS) etc. that provides more features PDF-ready reports, reports for the mobile devices etc..

Performance Monitor

Windows Performance Monitor helps you visualize system-level resource usage from your Windows hosts, and enables you to correlate these metrics with SQL Server performance counters in time series graphs.
You can launch it from the Administrative Tools menu group or run the following from the Run window:

%windir%\system32\perfmon.msc /s



Once in there, click on the Performance Monitor on the left and it will automatically start showing the percentage processor time. Click on the + to add more performance counters, including SQL Server counters.

 

Now, do you still think you need to use commercial tools like SQL Diagnostic Manager, SQL Sentry, Spotlight etc.. ?  

Even though the gap between the two has decreased significantly, I think they still have a place in enterprise database monitoring and tuning. If for nothing else then for the ease of setup and use (in some cases, out of the box) and if you have already made significant investments in them in the past.

I also think that they are supplementary vs complementary to each other and you should use them both.

Tuesday, September 18, 2018

Check if any database has auditing configured


Here is a DMV script to check whether a or any database has the auditing configured and running, along with few other useful attributes if it does.


Few things to keep in mind:

  • Auditing is available from SQL version 2008 and up....
  • Until very recently (SQL version 2016 and up), granual (object level) auditing at the database level is available only on Enterprise edition. 
  • Although you could still use server level auditing to setup auditing at the database level


So keeping that in mind, I wrote this in a way to be able to execute as a multi-server query either using CMS or just a bunch of locally registered servers.

If you are running this as a multi-server script, you should turn on the "Merge Results" setting in the SSMS.

Finally, if you feel that this script is unncessarily complicated, its because it is written in a way so that it can be executed against any version and editon of sql server, whether it supports auditing or not!

Hope you find this use and please feel free to customize it anyway you would like...



SET nocount ON

USE [master]

go


IF Object_id('tempdb..##t1_db_audit_specs') IS NOT NULL
  DROP TABLE ##t1_db_audit_specs

go

DECLARE @sql_version_number NVARCHAR(100)
DECLARE @edition NVARCHAR(100)
DECLARE @SQL NVARCHAR(2000)

create table ##t1_db_audit_specs
(
             comment nvarchar(4000),
             dbname nvarchar(256),
             audit__target_name  nvarchar(256),
             db_audit_name nvarchar(256),
             is_server_audit_enabled   BIT,
             is_db_audit_enabled   BIT,


             on_failure_desc    NVARCHAR(256),
             max_file_size      BIGINT,
             max_rollover_files INT,
             queue_delay        INT,
             log_file_path      NVARCHAR(520),
             log_file_name      NVARCHAR(520),

             create_date  datetime,
             modify_date  datetime,
             sql_version_number NVARCHAR(256),
             edition            NVARCHAR(100)

)


SET @sql_version_number = Cast(Serverproperty('ProductVersion') AS NVARCHAR(100))
SET @edition = Cast(Serverproperty('Edition') AS NVARCHAR(100))

SET @SQL =
'

if ''?'' not in  (''master'', ''model'', ''msdb'', ''tempdb'')
and CAST(DATABASEPROPERTYEX(''?'', ''status'') as varchar(50)) = ''ONLINE''
and CAST(DATABASEPROPERTYEX(''?'', ''Updateability'') as varchar(50)) IN (''READ_WRITE'', ''READ_ONLY'')
      INSERT INTO ##t1_db_audit_specs
      SELECT
                    null,
                    ''?'' dbname,
                sa.name audit_name,
                     das.name db_audit_name,
             sa.is_state_enabled,
             das.is_state_enabled,

             sa.on_failure_desc,
             sa.max_file_size,
             sa.queue_delay,
             sa.max_rollover_files,
             sa.log_file_path,
             sa.log_file_name,

             das.create_date,
             das.modify_date,
             ''' + @sql_version_number + ''' sql_version_number,
             ''' + @edition + ''' sql_edition

      FROM   [?].sys.database_audit_specifications das
         inner join sys.server_file_audits sa on sa.audit_id = das.database_specification_id
  '
print @sql

IF LEFT(@sql_version_number, Charindex('.', @sql_version_number) - 1) < 10              -- SQL version check
               INSERT INTO ##t1_db_audit_specs (sql_version_number, edition, comment)
               VALUES     (@sql_version_number, @edition, '<<Auditing is not supported due to Older version>>')
ELSE
  BEGIN
  IF not exists (select * from sys.server_file_audits)                                  -- Is Auditing supported?
               INSERT INTO ##t1_db_audit_specs (sql_version_number, edition, comment)
               VALUES     (@sql_version_number, @edition, '<<There is no audit target is configured and therefore database audit could not have been created.>>')

  ELSE IF (CAST(SERVERPROPERTY('Edition') AS VARCHAR(100)) NOT LIKE 'Enterprise%')      -- Is database level auditing supported?
               INSERT INTO ##t1_db_audit_specs (sql_version_number, edition, comment)
               VALUES     (@sql_version_number, @edition, '<<Granular auditing is not available in non-Enterprise editions of SQL Server.>>')

  ELSE
                    EXEC master..sp_MSforeachdb @sql
  END

if not exists (SELECT * FROM   ##t1_db_audit_specs)
               INSERT INTO ##t1_db_audit_specs (sql_version_number, edition, comment)
               VALUES     (@sql_version_number, @edition, '<<No database has auditing configured.')

SELECT * FROM   ##t1_db_audit_specs

--
IF Object_id('tempdb..##t1_db_audit_specs') IS NOT NULL
  DROP TABLE ##t1_db_audit_specs


go

Truncating very large transaction log in full recovery mode

While I always configure transaction log backups for every database in non-simple recovery model, and to compliment it I also have monitorin...