Wednesday, December 29, 2021

Monitor Active SQL Server Connections and Sessions using T-SQL

Summary: Quickly audit your SQL Server environment with this T-SQL script that groups active connections by IP address, application name, and login to identify resource usage and connection leaks.

Monitoring Active SQL Server Connections and Sessions

Managing server load requires a clear understanding of who is connected to your database and what applications they are using. Here's a handy SQL query to get an overview of your active SQL Server connections and sessions. It helps you quickly see the source IP, the client hostname, and the total connection count per user. This is an essential tool for monitoring server activity or troubleshooting connection leaks.


SELECT 
    ec.client_net_address AS [IP Address],
    es.[program_name] AS [Application],
    es.[host_name] AS [Client Host],
    es.login_name AS [Login],
    COUNT(ec.session_id) AS [Connection Count]
FROM sys.dm_exec_sessions AS es WITH (NOLOCK)
INNER JOIN sys.dm_exec_connections AS ec WITH (NOLOCK) 
    ON es.session_id = ec.session_id
GROUP BY 
    ec.client_net_address,
    es.[program_name],
    es.[host_name],
    es.login_name
ORDER BY 
    ec.client_net_address,
    es.[program_name]
OPTION (RECOMPILE);
        

How the Query Works

This script performs an inner join between two critical Dynamic Management Views (DMVs):

  • sys.dm_exec_connections: Provides information about the physical transport layer and the client IP addresses.
  • sys.dm_exec_sessions: Contains high-level metadata about each session, such as the authenticated user and the application name.

By grouping the data, you can pinpoint exactly which application or user is consuming the most connection slots. The OPTION (RECOMPILE) hint ensures that SQL Server generates a fresh execution plan every time you run the script, which is ideal for querying volatile system views that change every second.

Conclusion

Regularly auditing your connections helps identify unauthorized access and application-level bugs where connections aren't being closed properly. For a deeper dive into SQL Server management, ensure your applications are utilizing connection pooling correctly to avoid hitting session limits.

Found this SQL monitoring script useful? Share it with your DBA team or subscribe for more T-SQL performance tuning guides!

How to Check TempDB Version Store Usage per Database in SQL Server

Summary: Use the sys.dm_tran_version_store_space_usage DMV to monitor how much TempDB space is consumed by version store records for Snapshot Isolation and RCSI.

Monitor Version Store Space Usage in TempDB

Looking to understand how much space the version store is using in your SQL Server tempdb? The sys.dm_tran_version_store_space_usage dynamic management view (DMV) is your primary tool for troubleshooting 1458 errors or general TempDB growth. It provides a summarized view of the total space consumed by version store records for each database on your instance.

This view is highly efficient and inexpensive to run because it does not traverse individual version store records. Instead, it provides an aggregated count of the pages used, making it an ideal choice for real-time monitoring and performance dashboards.

Retrieve Version Store Space Usage

Run the following T-SQL script to identify which database is responsible for the largest amount of version store data in TempDB:


SELECT 
    DB_NAME(database_id) AS [Database Name],
    reserved_page_count AS [Reserved Page Count],
    reserved_space_kb / 1024 AS [Version Store Space (MB)]
FROM sys.dm_tran_version_store_space_usage WITH (NOLOCK)
ORDER BY [Version Store Space (MB)] DESC
OPTION (RECOMPILE);
        

This query returns a clear breakdown of space usage, allowing you to quickly pinpoint which database has long-running transactions or high-volume updates under Snapshot Isolation or Read Committed Snapshot Isolation (RCSI).

Why Version Store Usage Matters

The version store is used to support row versioning features. If a transaction remains open for a long time, SQL Server cannot clean up the version store in tempdb, which can lead to disk space exhaustion. Monitoring this DMV helps DBAs proactively manage server health.


Related Reading:

Found this T-SQL monitoring tip helpful? Share it with your team or subscribe for more SQL Server performance tuning guides!

Sunday, December 26, 2021

Track SQL Server CPU Usage History for the Last 256 Minutes

Summary: Use this T-SQL script to extract historical CPU utilization from SQL Server ring buffers, providing a minute-by-minute breakdown of SQL usage vs. system idle time.

Track SQL Server CPU Usage for the Last 256 Minutes

Ever wonder how your SQL Server has been utilizing its CPU over time? This handy T-SQL script allows you to view the CPU utilization history for the last 256 minutes, broken down into one-minute intervals. It's a fantastic way to quickly pinpoint any performance bottlenecks or trends related to CPU usage without needing external monitoring tools.

The CPU History SQL Script


DECLARE @ts_now BIGINT = (
    SELECT cpu_ticks / (cpu_ticks / ms_ticks)
    FROM sys.dm_os_sys_info WITH (NOLOCK)
);

SELECT TOP (256) 
    SQLProcessUtilization AS [SQL Server CPU %],
    SystemIdle AS [System Idle %],
    100 - SystemIdle - SQLProcessUtilization AS [Other Process CPU %],
    DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS [Event Time]
FROM (
    SELECT 
        record.value('(./Record/@id)[1]', 'int') AS record_id,
        record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') AS [SystemIdle],
        record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS [SQLProcessUtilization],
        [timestamp]
    FROM (
        SELECT [timestamp], CONVERT(XML, record) AS [record]
        FROM sys.dm_os_ring_buffers WITH (NOLOCK)
        WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR'
          AND record LIKE N'%<SystemHealth>%'
    ) AS x
) AS y
ORDER BY record_id DESC
OPTION (RECOMPILE);
        

How It Works

This script queries sys.dm_os_ring_buffers, specifically targeting the RING_BUFFER_SCHEDULER_MONITOR. This internal ring buffer captures system health events, including CPU utilization, directly from the SQLOS scheduler.

By parsing the XML output, we extract:

  • SQLProcessUtilization: Percentage of CPU used by the SQL Server process.
  • SystemIdle: Percentage of CPU that is currently unused.
  • Other Process Utilization: Calculated as the remaining CPU used by Windows or other background applications.

For more in-depth information about how SQL Server manages internal tracking, check out the community resource: Inside sys.dm_os_ring_buffers.

Did this script help you find a bottleneck? Let us know in the comments below or check out our other performance tuning guides!

Sunday, December 19, 2021

How to Get SQL Server Hardware Information using sys.dm_os_sys_info

Summary: Use this T-SQL script to extract critical hardware metadata from SQL Server, including CPU core counts, physical memory, NUMA configuration, and virtualization type.

Retrieve SQL Server Hardware and System Information

This query provides valuable hardware information about your database server, which is essential for licensing audits, performance tuning, and capacity planning.

Pro Tip: A 'HYPERVISOR' value for 'virtual_machine_type_desc' doesn't automatically confirm SQL Server is running inside a virtual machine. This merely indicates that a hypervisor is present on the host machine (which could also mean the host has Hyper-V enabled).

Hardware Configuration Script


SELECT 
    cpu_count AS [Logical CPU Count], 
    scheduler_count, 
    (socket_count * cores_per_socket) AS [Physical Core Count], 
    socket_count AS [Socket Count], 
    cores_per_socket, 
    numa_node_count,
    physical_memory_kb / 1024 AS [Physical Memory (MB)], 
    max_workers_count AS [Max Workers Count], 
    affinity_type_desc AS [Affinity Type], 
    sqlserver_start_time AS [SQL Server Start Time],
    DATEDIFF(hour, sqlserver_start_time, GETDATE()) AS [Up Time (hrs)],
    virtual_machine_type_desc AS [Virtual Machine Type], 
    softnuma_configuration_desc AS [Soft-NUMA Config], -- SQL Server 2016+
    sql_memory_model_desc, -- SQL Server 2016 SP1+
    container_type_desc -- SQL Server 2019+
FROM sys.dm_os_sys_info WITH (NOLOCK) 
OPTION (RECOMPILE);
        

Understanding the Results

By querying sys.dm_os_sys_info, you get a snapshot of the resources SQL Server "sees." This is particularly useful for identifying:

  • Memory Model: Whether SQL Server is using conventional memory or "Locked Pages in Memory."
  • Core Density: The ratio of physical cores to sockets.
  • Soft-NUMA: Whether SQL Server is automatically managing NUMA nodes to improve performance on high-core-count machines.

Further Reading:

Need to tune your SQL Server performance? Check out our other scripts for monitoring CPU and memory usage!

Sunday, December 12, 2021

How to Check SQL Server Drive Free Space using T-SQL

Summary: Quickly audit available disk space on your SQL Server host using sys.dm_os_enumerate_fixed_drives and xp_fixeddrives to prevent disk fullness issues.

How to Check Available Disk Space in SQL Server

Ever need to quickly check the available space on your SQL Server drives without logging into the OS? Here are two handy methods to query disk space directly from a query window. We'll explore using a modern Dynamic Management View (DMV) and a classic system stored procedure.

Method 1: Using sys.dm_os_enumerate_fixed_drives

This DMV is the preferred modern method. It provides detailed information about fixed drives, including their path, type, and exact free space in bytes. It is highly precise and easy to format into Gigabytes (GB).


-- Querying disk space using a DMV
SELECT 
    fixed_drive_path AS [Drive],
    drive_type_desc AS [Type],
    CONVERT(DECIMAL(18, 2), free_space_in_bytes / 1073741824.0) AS [Available Space (GB)]
FROM sys.dm_os_enumerate_fixed_drives WITH (NOLOCK)
ORDER BY [Available Space (GB)] ASC
OPTION (RECOMPILE);
        

Method 2: Using xp_fixeddrives

For a simpler and quicker overview, the xp_fixeddrives extended stored procedure is a classic standby. While it provides less detail than the DMV, it is excellent for a fast snapshot of MB available on each drive.


-- Simple summary of drive free space (MB)
EXEC xp_fixeddrives;
        

For more technical details on how the engine enumerates these paths, refer to the official Microsoft documentation.


Is your TempDB growing too fast? Monitoring your disk space is the first step in maintaining a healthy SQL Server environment!

Saturday, December 11, 2021

How to Monitor SQL Server Resource Governor Pools using T-SQL

Summary: Use the sys.dm_resource_governor_resource_pools DMV to monitor memory utilization, IOPS limits, and target memory for your SQL Server resource pools.

Monitoring SQL Server Resource Governor Pools

Ever wondered about the current status of your SQL Server resource pools? When using Resource Governor to manage multi-tenant workloads or to limit internal background processes, it is critical to monitor how much memory and I/O each pool is actually consuming.

This quick query provides valuable insights into performance and memory utilization across all configured pools.

Resource Pool Utilization Script


SELECT
    pool_id,
    [Name],
    statistics_start_time,
    min_memory_percent,
    max_memory_percent,
    max_memory_kb / 1024 AS [max_memory_mb],
    used_memory_kb / 1024 AS [used_memory_mb],
    target_memory_kb / 1024 AS [target_memory_mb],
    min_iops_per_volume,
    max_iops_per_volume
FROM sys.dm_resource_governor_resource_pools WITH (NOLOCK)
OPTION (RECOMPILE);
        

Understanding the Metrics

This query leverages the sys.dm_resource_governor_resource_pools dynamic management view. Key columns to watch include:

  • used_memory_mb: The actual amount of memory currently held by the pool.
  • target_memory_mb: The amount of memory SQL Server is currently attempting to allocate to the pool based on workload demand and settings.
  • max_iops_per_volume: Helps you identify if I/O capping is actively restricting a specific resource pool's performance.

Optimizing your SQL Server resources? Check out our other guides on monitoring CPU trends and TempDB usage!

Sunday, December 5, 2021

How to View SQL Server Memory Dump History using T-SQL

Summary: Use the sys.dm_server_memory_dumps DMV to identify the location, creation time, and size of SQL Server memory dump files for crash analysis and troubleshooting.

Retrieve SQL Server Memory Dump Information

Understanding the status of memory dumps in your SQL Server instance is crucial for troubleshooting service crashes, unexpected restarts, and deep performance analysis. This method allows you to quickly identify if any dumps have been generated, where they are stored, and their total size.

Querying sys.dm_server_memory_dumps

You can use the following SQL query to access the sys.dm_server_memory_dumps dynamic management view. This view is highly useful because it prevents you from having to manually browse the SQL Server LOG folder in the file system.


-- Get details of all memory dumps generated by SQL Server
SELECT
    [filename] AS [Dump File Path],
    creation_time AS [Creation Time],
    size_in_bytes / 1048576.0 AS [Size (MB)]
FROM sys.dm_server_memory_dumps WITH (NOLOCK)
ORDER BY creation_time DESC
OPTION (RECOMPILE);
        

This query returns the full file path of the dump, the exact time it was triggered, and the size in MB. The results are ordered by creation time, putting the most recent events at the top of your list.

For more in-depth information about this DMV, refer to the official Microsoft Documentation.


Is your SQL Server generating frequent dumps? This usually indicates a serious underlying issue. Check your error logs or consult Microsoft Support for advanced analysis!

Monday, November 29, 2021

How to Identify System Manufacturer and Model via SQL Server Error Log

Summary: Use the xp_readerrorlog extended stored procedure to quickly retrieve hardware manufacturer and model details directly from the SQL Server startup sequences.

Identify System Manufacturer and Model from the SQL Server Error Log

Did you know you can quickly pinpoint your SQL Server's system manufacturer and model number directly from its error log? This is a highly efficient way to gather hardware details or verify server specifications without needing administrative access to the underlying Windows OS or BIOS.

Using a Simple SQL Query

When SQL Server starts, it logs several environmental details. You can use the following command to filter the current log for these specific entries:


-- Search the current error log for system hardware info
EXEC sys.xp_readerrorlog 0, 1, N'Manufacturer';
        

This command searches the current SQL Server error log (Log 0) for entries containing the word "Manufacturer." The output typically returns a line detailing the system's make (e.g., Dell, HP, VMware) and the specific model number.

Important Considerations

  • Log Recycling: This query only yields results if the error log hasn't been recycled (restarted) since the SQL Server instance last started. If the log has cycled, you may need to change the first parameter from 0 to 1, 2, etc., to search archived logs.
  • Virtualization: This method is excellent for confirming if your SQL Server is virtualized. Virtual environments like VMware or Azure will clearly state "VMware, Inc." or "Microsoft Corporation" with "Virtual Machine" in the model details.

Need to audit your hardware? Use this script as a quick win for your next server inventory report!

Saturday, November 13, 2021

How to Check Database Access Permissions in SQL Server using HAS_DBACCESS

Summary: Quickly identify which databases on a SQL Server instance you have permission to connect to using the HAS_DBACCESS function.

Check Which Databases You Can Access in SQL Server

Ever wonder which databases you actually have permission to enter on a shared instance? Instead of clicking through every database in Object Explorer and waiting for "Access Denied" errors, you can run a simple script to audit your permissions at a glance.

Using the HAS_DBACCESS Function

The HAS_DBACCESS function returns a 1 if the user has access to the database, a 0 if the user does not have access, and NULL if the database name is invalid.


-- List all databases and check current user access
SELECT 
    name AS [Database Name], 
    CASE 
        WHEN HAS_DBACCESS(name) = 1 THEN 'Yes' 
        ELSE 'No' 
    END AS [Has Access]
FROM sys.databases
ORDER BY name;
        

Why Use This?

This statement is particularly handy for a quick security check. It helps you verify:

  • If your login has been correctly mapped to a specific database.
  • Which databases are visible but restricted to your current credentials.
  • Connectivity status across a large instance with dozens of databases.

Working on security auditing? Combine this with our other scripts for a full view of your SQL Server environment!

Friday, October 29, 2021

Retrieve SQL Server Hardware and Registry Details via T-SQL

Summary: Learn how to use xp_instance_regread to query the Windows Registry for hardware details, including VMware PVSCSI parameters, BIOS release dates, and CPU specifications.

Querying Hardware and Registry Details from SQL Server

Ever wonder about the nitty-gritty details of your SQL Server's underlying hardware? While DMVs provide great data, sometimes peeking into the Windows Registry via T-SQL can give you specific environmental insights. Here is how to pull essential hardware information using xp_instance_regread.

1. VMware Storage Driver Parameters (PVSCSI)

For those running SQL Server on VMware, tuning your storage driver settings is critical for high-throughput I/O. You can check the current parameters for your PVSCSI adapter directly:


-- Check PVSCSI driver parameters
EXEC sys.xp_instance_regread 
    N'HKEY_LOCAL_MACHINE', 
    N'SYSTEM\CurrentControlSet\services\pvscsi\Parameters\Device', 
    N'DriverParameter';
        

Performance Note: For intensive workloads, VMware often recommends setting RequestRingPages=32 and MaxQueueDepth=254. For more details, see the official VMware KB article.


2. Discovering BIOS Release Date

Identifying the BIOS release date is a quick way to determine if a host needs a firmware update to patch stability or security issues. Run this command to pull it from the registry:


-- Retrieve BIOS release date
EXEC sys.xp_instance_regread 
    N'HKEY_LOCAL_MACHINE', 
    N'HARDWARE\DESCRIPTION\System\BIOS', 
    N'BiosReleaseDate';
        

3. Identifying Processor Details

Understanding exactly which CPU is powering your instance is fundamental for SQL Server licensing and performance tuning. This command grabs the full processor string:


-- Get CPU Model and Speed
EXEC sys.xp_instance_regread 
    N'HKEY_LOCAL_MACHINE', 
    N'HARDWARE\DESCRIPTION\System\CentralProcessor\0', 
    N'ProcessorNameString';
        

For deep dives into processor selection and its impact on SQL performance, I highly recommend checking out Glenn Berry's blog on Processor Selection.

Found this SQL monitoring script useful? Share it with your DBA team or subscribe for more T-SQL performance tuning guides!

Monday, October 25, 2021

How to Find Tables Without a Primary Key in SQL Server

Summary: Use this T-SQL script to audit your database schema and identify any tables lacking a primary key, a critical step for ensuring data integrity and performance.

Identify Tables Without a Primary Key

In SQL Server, primary keys play a crucial role in maintaining data integrity and optimizing query performance. However, during development or when working with legacy databases, you may come across tables that lack a primary key—either by design or oversight. Identifying these tables is an essential step in ensuring your database is well-structured and reliable.

📌 SQL Query to Find Missing Primary Keys

The query below leverages sys.tables and sys.key_constraints to retrieve a list of all user tables in your current database that do not have a primary key defined:


-- Find tables without a Primary Key
SELECT 
    s.[name] + N'.' + t.[name] AS [Table Name],
    t.create_date AS [Created Date]
FROM sys.tables AS t WITH (NOLOCK)
INNER JOIN sys.schemas AS s ON t.[schema_id] = s.[schema_id]
WHERE NOT EXISTS (
    SELECT 1
    FROM sys.key_constraints AS kc
    WHERE kc.[type] = N'PK'
      AND kc.parent_object_id = t.[object_id]
)
ORDER BY [Table Name]
OPTION (RECOMPILE);
        

🧩 Why This Matters

Tables without primary keys (often referred to as Heaps if they also lack a clustered index) can lead to significant architectural issues:

  • Data Duplication: Without a PK, there is no physical way for the engine to enforce row uniqueness at the schema level.
  • Performance Degradation: Heaps can lead to "RID Lookups" and inefficient data retrieval patterns.
  • Replication Failure: Many features, like Transactional Replication and certain ETL tools, require a primary key to function.
  • Join Complications: It becomes difficult to maintain reliable relationships between tables.

Optimizing your schema? Once you've identified these tables, consider adding an IDENTITY column or a natural key to improve your database's health!

Tuesday, September 28, 2021

How to Audit SQL Server Service Accounts and Status using T-SQL

Summary: Use the sys.dm_server_services DMV to quickly audit SQL Server service accounts, startup types, cluster status, and Instant File Initialization (IFI) settings.

Retrieve SQL Server Service Details and Configurations

Ever wondered about the nitty-gritty details of your SQL Server services? Instead of opening the Windows Services console (services.msc) or Configuration Manager, you can pull a comprehensive overview directly from a query window.

SQL Server Service Audit Script

This query provides a quick overview of essential information for each service associated with your current SQL Server instance.


-- Audit SQL Server services and configuration
SELECT 
    servicename AS [Service Name],
    process_id AS [PID],
    startup_type_desc AS [Startup Type],
    status_desc AS [Current Status],
    last_startup_time AS [Last Start Time],
    service_account AS [Account Name],
    is_clustered AS [Is Clustered?],
    cluster_nodename AS [Active Node],
    [filename] AS [Binary Path],
    instant_file_initialization_enabled AS [IFI Enabled]
FROM sys.dm_server_services WITH (NOLOCK)
OPTION (RECOMPILE);
        

Key Insights from this Query

  • Service Account: Quickly verify if your services are running under the correct least-privileged service accounts.
  • Instant File Initialization (IFI): Ensure IFI is enabled to speed up data file allocations and restores (SQL Server 2016+).
  • Startup Type: Identify services that might fail to start after a reboot because they are set to 'Manual'.
  • Cluster Details: Confirm which node in a Failover Cluster Instance (FCI) is currently hosting the service.

For more in-depth information regarding the columns in this DMV, refer to the official Microsoft documentation.


Performing a Health Check? Checking your service accounts and IFI status is a foundational step in any SQL Server performance audit!

Sunday, August 29, 2021

How to Analyze SQL Server Memory Usage by Clerk Type using T-SQL

Summary: Use the sys.dm_os_memory_clerks DMV to identify which components—such as the Buffer Pool, Plan Cache, or Columnstore—are consuming the most memory in your SQL Server instance.

Identify Top Memory Consumers via SQL Server Memory Clerks

If your SQL Server is experiencing high memory pressure, the first step is to identify which internal component is "hogging" the RAM. SQL Server uses Memory Clerks to manage allocations for different features like the Buffer Pool, Plan Cache, and CLR.

This query provides a clear breakdown of memory usage by various clerk types, ordered by the highest consumption, helping you pinpoint exactly where the memory is going.

Top 10 Memory Clerk Usage Script


-- Get top 10 memory consumers by Clerk Type
SELECT TOP (10) 
    mc.[type] AS [Memory Clerk Type],
    CAST((SUM(mc.pages_kb) / 1024.0) AS DECIMAL(15, 2)) AS [Memory Usage (MB)]
FROM sys.dm_os_memory_clerks AS mc WITH (NOLOCK)
GROUP BY mc.[type]
ORDER BY SUM(mc.pages_kb) DESC
OPTION (RECOMPILE);
        

Understanding Common Clerk Types

  • MEMORYCLERK_SQLBUFFERPOOL: This is usually the largest, representing the data cache.
  • CACHESTORE_SQLCP: The SQL Plan Cache (ad-hoc queries).
  • CACHESTORE_OBJCP: Object Plans (stored procedures, functions).
  • MEMORYCLERK_SQLOPTIMIZER: Memory used during the query optimization process.

This query leverages the sys.dm_os_memory_clerks DMV. For more in-depth exploration of performance tuning, check out these related articles:


Seeing unexpected memory usage? Large amounts of memory in CACHESTORE_SQLCP might indicate a need to enable "Optimize for Ad-hoc Workloads"!

How to Audit SQL Server NUMA Node Configuration and Scheduler Load

Summary: Use the sys.dm_os_nodes DMV to inspect NUMA node health, verify balanced CPU scheduler distribution, and monitor active worker loads across your hardware architecture.

Monitoring NUMA Node Configuration and Load Balance

This query provides valuable insights into your NUMA (Non-Uniform Memory Access) nodes, showing their composition and how much load they are currently handling. Understanding the distribution of resources and activity across your system's memory architecture is critical for high-performance database environments.

NUMA Node and Scheduler Audit Script


-- Check NUMA node health and scheduler distribution
SELECT 
    node_id,
    node_state_desc,
    memory_node_id,
    processor_group,
    cpu_count,
    online_scheduler_count,
    idle_scheduler_count,
    active_worker_count,
    avg_load_balance,
    resource_monitor_state
FROM sys.dm_os_nodes WITH (NOLOCK)
WHERE node_state_desc <> N'ONLINE DAC'
OPTION (RECOMPILE);
        

Why This Matters for Performance

After running this, you should verify that an equal number of online schedulers are assigned to each NUMA node. This is especially important for physical or virtual machines with more than four sockets or over 24 physical cores.

  • Balanced Load: An uneven distribution of schedulers can lead to "hot" NUMA nodes where specific CPUs are overworked while others remain idle.
  • License Alignment: On standard edition servers with core limits, ensure your limited cores are spread evenly across nodes to maximize memory bandwidth.
  • Resource Monitor State: This indicates if the internal thread responsible for memory management is healthy on that specific node.

For more detailed information on NUMA tuning and hardware alignment, explore these resources:

Troubleshooting performance bottlenecks? Proper NUMA alignment is often the "hidden" fix for scaling issues on large multi-processor servers!

Saturday, August 28, 2021

How to use SERVERPROPERTY to Retrieve SQL Server Instance Details

Summary: Use the SERVERPROPERTY function in T-SQL to extract essential metadata about your SQL Server instance, including versioning, edition, patch levels, and feature support.

Discovering SQL Server Instance Details with SERVERPROPERTY

Ever needed to quickly grab essential information about your SQL Server instance? The SERVERPROPERTY function is a powerful tool for DBAs and developers alike. It allows you to retrieve a wide range of details—from network names and versioning to specific engine configurations like collation and default file paths—all without needing access to the physical host.

The Comprehensive Instance Audit Script

Below is a comprehensive SQL query that leverages SERVERPROPERTY to pull numerous valuable insights about your SQL Server environment into a readable vertical list.


-- Retrieve a detailed snapshot of SQL Server instance properties
SELECT SERVERPROPERTY('MachineName') AS [Value], 'Machine Name' AS [Description]
UNION ALL SELECT SERVERPROPERTY('ServerName'), 'Server Name'
UNION ALL SELECT SERVERPROPERTY('InstanceName'), 'Instance'
UNION ALL SELECT SERVERPROPERTY('IsClustered'), 'IsClustered'
UNION ALL SELECT SERVERPROPERTY('ComputerNamePhysicalNetBIOS'), 'NetBIOS Physical Name'
UNION ALL SELECT SERVERPROPERTY('Edition'), 'Edition'
UNION ALL SELECT SERVERPROPERTY('ProductLevel'), 'Product Level (RTM/SP/CU)'
UNION ALL SELECT SERVERPROPERTY('ProductUpdateLevel'), 'CU Level'
UNION ALL SELECT SERVERPROPERTY('ProductVersion'), 'Full Product Version'
UNION ALL SELECT SERVERPROPERTY('ProductMajorVersion'), 'Major Version'
UNION ALL SELECT SERVERPROPERTY('ProductMinorVersion'), 'Minor Version'
UNION ALL SELECT SERVERPROPERTY('ProductBuild'), 'Build Number'
UNION ALL SELECT SERVERPROPERTY('ProductBuildType'), 'Build Type (GDR/OD/CU)'
UNION ALL SELECT SERVERPROPERTY('ProductUpdateReference'), 'KB Article Reference'
UNION ALL SELECT SERVERPROPERTY('ProcessID'), 'OS Process ID'
UNION ALL SELECT SERVERPROPERTY('Collation'), 'Server Collation'
UNION ALL SELECT SERVERPROPERTY('IsFullTextInstalled'), 'Full-Text Search Installed'
UNION ALL SELECT SERVERPROPERTY('IsIntegratedSecurityOnly'), 'Windows Auth Only Mode'
UNION ALL SELECT SERVERPROPERTY('FilestreamConfiguredLevel'), 'Filestream Level'
UNION ALL SELECT SERVERPROPERTY('IsHadrEnabled'), 'Always On (HADR) Enabled'
UNION ALL SELECT SERVERPROPERTY('HadrManagerStatus'), 'HADR Manager Status'
UNION ALL SELECT SERVERPROPERTY('InstanceDefaultDataPath'), 'Default Data Path'
UNION ALL SELECT SERVERPROPERTY('InstanceDefaultLogPath'), 'Default Log Path'
UNION ALL SELECT SERVERPROPERTY('BuildClrVersion'), 'CLR Version'
UNION ALL SELECT SERVERPROPERTY('IsXTPSupported'), 'In-Memory OLTP Supported'
UNION ALL SELECT SERVERPROPERTY('IsPolybaseInstalled'), 'Polybase Installed'
UNION ALL SELECT SERVERPROPERTY('IsAdvancedAnalyticsInstalled'), 'Machine Learning / R Services'
OPTION (RECOMPILE);
        

Why Use This?

This query provides a detailed overview of your SQL Server setup, making it incredibly useful for:

  • Inventory Audits: Quickly gathering version and edition details across multiple servers.
  • Troubleshooting: Verifying if a specific Cumulative Update (CU) or KB patch has been applied.
  • Configuration Checks: Ensuring default paths and security modes align with company standards.

Further Reading

For a complete and in-depth understanding of all properties available with this function, refer to the official Microsoft documentation.

Need to automate your environment discovery? This script is a perfect starting point for building a dynamic server inventory dashboard!

Wednesday, August 18, 2021

How to Check SQL Server Disk Space and Volume Stats via T-SQL

Summary: Use sys.dm_os_volume_stats to audit physical drive space, mount points, and file system attributes directly from SQL Server for all database files.

Monitoring Database Volume Stats and Disk Space

Ever wonder about the nitty-gritty details of where your SQL Server databases and files live? There's a powerful dynamic management function (DMF) that spills the beans on the operating system volume where your data resides. It's incredibly useful for auditing physical disk attributes or getting a live view of available free space without leaving SQL Server Management Studio.

Volume Stats and Free Space Query

This script uses a CROSS APPLY to join your master files with their respective volume statistics, providing a consolidated view of every drive currently hosting a SQL Server data or log file.


-- Detailed breakdown of volume stats for all database files
SELECT DISTINCT 
    vs.volume_mount_point AS [Mount Point],
    vs.file_system_type AS [File System],
    vs.logical_volume_name AS [Volume Name],
    CONVERT(DECIMAL(18, 2), vs.total_bytes / 1073741824.0) AS [Total Size (GB)],
    CONVERT(DECIMAL(18, 2), vs.available_bytes / 1073741824.0) AS [Available Size (GB)],
    CONVERT(DECIMAL(18, 2), vs.available_bytes * 1. / vs.total_bytes * 100.) AS [Space Free %],
    vs.supports_compression,
    vs.is_compressed,
    vs.supports_sparse_files,
    vs.supports_alternate_streams
FROM sys.master_files AS f WITH (NOLOCK)
CROSS APPLY sys.dm_os_volume_stats(f.database_id, f.[file_id]) AS vs
ORDER BY [Mount Point]
OPTION (RECOMPILE);
        

Why This Matters

Traditional methods like xp_fixeddrives only show drive letters. However, sys.dm_os_volume_stats is superior because:

  • Mount Point Support: It correctly identifies volumes mounted as folders (Mount Points), which are common in enterprise SAN environments.
  • Proactive Alerting: You can use the Space Free % logic to build automated alerts before a disk fills up and takes your database offline.
  • Feature Awareness: It identifies if a volume supports modern features like Sparse Files (used by Database Snapshots and CheckDB) or Compression.

For more in-depth documentation on this function, refer to the official Microsoft documentation.


Is your disk space running low? Identifying the exact volume and its percentage of free space is the first step in effective capacity planning!

Saturday, August 7, 2021

How to Find SQL Server Socket and Core Counts for Licensing

Summary: Use the xp_readerrorlog procedure to extract CPU socket, physical core, and logical core counts directly from the SQL Server startup logs for accurate licensing verification.

Find Socket and Core Counts in the SQL Server Error Log

This post will show you how to find out the socket, physical core, and logical core counts directly from your SQL Server Error log. This information is crucial for verifying your SQL Server licensing model, especially when moving between physical and virtual environments.

Querying the Error Log for CPU Metadata

During the SQL Server startup sequence, the engine detects and logs the available hardware topology. You can use the following command to filter the current log for these specific hardware entries:


-- Identify CPU hardware topology for licensing
EXEC sys.xp_readerrorlog 0, 1, N'detected', N'socket';
        

Why This Information is Vital

Running the command above helps you quickly confirm your SQL Server's hardware configuration and ensures it aligns with your licensing requirements:

  • Physical Core Count: Essential for Core-based licensing (Standard and Enterprise).
  • Socket Count: Useful for checking host-level hardware limits.
  • Hyperthreading: Confirming the ratio of logical vs. physical cores to ensure SQL Server is utilizing the available hardware efficiently.

Performing a Licensing Audit? This simple command is the fastest way to pull hardware stats without needing server-level permissions!

Wednesday, July 28, 2021

How to Check and Enable Global Trace Flags in SQL Server

Summary: Use DBCC TRACESTATUS to identify active global trace flags and learn how to enable performance-tuning flags like TF 3226, 6534, and 7745.

Managing Global Trace Flags in SQL Server

Ever wondered which global trace flags are active in your SQL Server environment? Trace flags are frequently used to temporarily set specific server characteristics or to switch off a particular behavior. You can easily discover which flags are currently active using the following command:


-- Check status of all global trace flags
DBCC TRACESTATUS (-1);
        

This command reveals all currently enabled global trace flags. For instance, you might encounter some common ones used in production environments:

  • TF 3226: Suppresses "backup successful" messages in the SQL Server Error Log. This is a must-have for servers with frequent log backups to keep the error log readable.
  • TF 6534: Enables native code execution for spatial data types, which can significantly boost performance for GIS-heavy workloads.
  • TF 7745: Prevents Query Store data from being written to disk during a failover or shutdown, prioritizing availability over the persistence of the latest runtime stats.

How to Enable a Trace Flag

To enable a specific trace flag globally (the -1 parameter is essential for global scope), use the DBCC TRACEON command:


-- Enable a trace flag globally (e.g., 3226)
DBCC TRACEON (3226, -1);
        

Note: While DBCC TRACEON enables a flag immediately, it will be lost upon restart. To make a trace flag persistent, you must add it as a Startup Parameter (e.g., -T3226) in the SQL Server Configuration Manager.


For a comprehensive list of all available trace flags, refer to the official Microsoft documentation.

Optimizing your instance? Always test trace flags in a development environment first, as some can significantly change the behavior of the Query Optimizer!

Monday, June 28, 2021

How to Audit and Optimize SQL Server Configurations using sys.configurations

Summary: Use the sys.configurations view to audit server-wide settings in SQL Server. Learn which critical performance options, such as Max Memory and Parallelism, require immediate attention.

Auditing SQL Server Instance Configurations

Understanding your SQL Server configuration settings is crucial for maintaining optimal performance and stability. The sys.configurations system catalog view provides a wealth of information about all server-wide options. Here is how to view them all at once:


-- Retrieve all server-wide configurations
SELECT 
    name,
    value,
    value_in_use,
    minimum,
    maximum,
    [description],
    is_dynamic,
    is_advanced
FROM sys.configurations WITH (NOLOCK)
ORDER BY name
OPTION (RECOMPILE);
        

This query gives you a comprehensive list, including the value_in_use (what is currently running) versus the value (what is saved in the metadata). It also flags is_dynamic settings—which take effect immediately—and is_advanced settings, which require sp_configure 'show advanced options', 1 to be modified.

Critical Settings for Performance Tuning

While reviewing all configurations is helpful, you should prioritize these specific settings during a health check. Below are common configurations and their typical best-practice starting points:


-- Check specific performance-critical settings
SELECT * FROM sys.configurations WITH (NOLOCK) 
WHERE name IN (
    'automatic soft-NUMA disabled',        -- Should be 0 in most modern cases
    'backup checksum default',             -- Should be 1 (Best practice)
    'backup compression default',          -- Should be 1 in most cases
    'clr enabled',                         -- Only enable if strictly required
    'cost threshold for parallelism',      -- Default of 5 is usually too low; try 50+
    'lightweight pooling',                 -- Should be 0
    'max degree of parallelism',           -- Should be set based on NUMA/Cores
    'max server memory (MB)',              -- Set a cap to leave room for the OS
    'optimize for ad hoc workloads',       -- Should be 1 to reduce plan cache bloat
    'priority boost',                      -- Should be 0
    'remote admin connections',            -- Should be 1 (Enables DAC)
    'tempdb metadata memory-optimized'     -- 0 by default; check for TempDB contention
)
ORDER BY name;
        

🧩 Important Considerations

  • Context Matters: Settings like cost threshold for parallelism and MAXDOP vary significantly depending on your specific hardware and workload (OLTP vs. DW).
  • Testing: Always test configuration changes in a non-production environment. Some changes can significantly alter query plan generation.
  • Persistence: For many of these settings, you must run RECONFIGURE after an sp_configure command for the change to take effect.

For more in-depth details on every available option, refer to the official Microsoft documentation for sys.configurations.

Is your server properly capped? Failing to set 'max server memory' is the #1 cause of OS instability on SQL Server hosts. Check your settings today!

SQL Server 2019 Build Versions, Release Dates, and KB Articles

Summary: Quickly identify your SQL Server build using @@VERSION and reference the comprehensive list of SQL Server 2019 release versions from CTP to RTM and GDR.

Determining Your SQL Server 2019 Build and Version

Ever wonder about the specific build and version of your SQL Server instance? Knowing your exact build number is essential for applying the correct security patches and cumulative updates. You can easily find this out using a simple T-SQL global variable:


-- Identify Server Name and Full Version Info
SELECT 
    @@SERVERNAME AS [Server Name], 
    @@VERSION AS [SQL Server and OS Version Info];
        

SQL Server 2019 Build History

Below is a detailed look at the various builds of SQL Server 2019 (Internal Version 15.0). This list includes the early Community Technology Previews (CTP), Release Candidates (RC), and General Distribution Releases (GDR).

Build Number Description / Milestone Release Date
15.0.1000.34 CTP 2.0 9/24/2018
15.0.1100.94 CTP 2.1 11/7/2018
15.0.1200.24 CTP 2.2 12/6/2018
15.0.1300.359 CTP 2.3 3/1/2019
15.0.1400.75 CTP 2.4 3/26/2019
15.0.1500.28 CTP 2.5 4/23/2019
15.0.1600.8 CTP 3.0 5/22/2019
15.0.1700.37 CTP 3.1 6/26/2019
15.0.1800.32 CTP 3.2 7/24/2019
15.0.1900.25 RC1 / Refresh 8/29/2019
15.0.2000.5 RTM (General Availability) 11/4/2019
15.0.2070.41 GDR1 11/4/2019

Official Microsoft Resources

Is your SQL Server out of date? Regularly checking your build number against official KB articles ensures you are protected against known vulnerabilities and performance bugs!

Saturday, June 19, 2021

Monitoring In-Memory OLTP Index Performance with sys.dm_db_xtp_index_stats

Summary: Audit Hekaton index efficiency using the sys.dm_db_xtp_index_stats DMV to track scans, retries, and row-level operations for In-Memory SQL Server tables.

Analyzing In-Memory OLTP Index Statistics

Understanding how your SQL Server indexes are performing is crucial for database optimization, especially when using In-Memory OLTP (Hekaton). Because memory-optimized tables utilize different data structures (like Hash and Range indexes), standard index DMVs often won't provide the full picture.

The following query leverages sys.dm_db_xtp_index_stats to provide deep insights into your in-memory index usage and health.

In-Memory Index Usage Query


-- Monitor In-Memory OLTP index activity
SELECT 
    OBJECT_NAME(i.[object_id]) AS [Object Name],
    i.index_id,
    i.[name] AS [Index Name],
    i.[type_desc] AS [Index Type],
    xis.scans_started,
    xis.scans_retries,
    xis.rows_touched,
    xis.rows_returned
FROM sys.dm_db_xtp_index_stats AS xis WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK) 
    ON i.[object_id] = xis.[object_id]
    AND i.index_id = xis.index_id
ORDER BY [Object Name], i.index_id
OPTION (RECOMPILE);
        

Key Metrics Explained

  • scans_retries: A high number here can indicate excessive transaction collisions or "interference" in the lock-free data structures, suggesting a need for better bucket counts in Hash indexes.
  • rows_touched vs. rows_returned: If rows_touched is significantly higher than rows_returned, your index may be scanning through many irrelevant rows (common in poorly tuned Hash indexes with high collision rates).
  • scans_started: Reflects the actual utilization frequency of the index by the query optimizer.

For further technical details, refer to the official Microsoft documentation for sys.dm_db_xtp_index_stats.


Related Performance Resources

Optimizing In-Memory performance? Ensure your Hash Index bucket counts are roughly 1x to 2x the number of unique values in your indexed column for maximum efficiency!

Saturday, June 5, 2021

How to Monitor SQL Server Query Store Settings and Health via T-SQL

Summary: Use the sys.database_query_store_options view to audit your Query Store configuration, monitor storage limits, and verify the current capture and cleanup modes.

Monitoring SQL Server Query Store Settings

The Query Store is often described as a "flight data recorder" for your database. To ensure it is functioning correctly and not hitting storage limits, you need to monitor the sys.database_query_store_options system view. This is essential for troubleshooting scenarios where the Query Store may have automatically switched to a Read-Only state.

Query Store Configuration Audit Script

The following query provides a quick breakdown of your current and desired Query Store states, storage consumption, and cleanup policies.


-- Audit Query Store health and configuration settings
SELECT
    actual_state_desc,               -- Current state (e.g., READ_WRITE or READ_ONLY)
    desired_state_desc,              -- The state you have requested
    interval_length_minutes,         -- Data aggregation interval
    current_storage_size_mb,         -- Current footprint on disk
    max_storage_size_mb,             -- Max allowed size before cleanup/read-only
    query_capture_mode_desc,         -- Capture policy (ALL, AUTO, or NONE)
    size_based_cleanup_mode_desc,    -- Automatic cleanup behavior
    readonly_reason                  -- Why the Query Store is currently read-only
FROM sys.database_query_store_options WITH (NOLOCK)
OPTION (RECOMPILE);
        

Key Metrics & Optimization Hints:

  • actual_state_desc vs desired_state_desc: If the actual state is READ_ONLY while the desired is READ_WRITE, check the readonly_reason. It is likely that the max_storage_size_mb has been reached.
  • WITH (NOLOCK): This hint performs a "dirty read." While it prevents locking contention on high-traffic systems, always use it carefully if precise consistency is required.
  • OPTION (RECOMPILE): This forces a fresh execution plan. For system views like this, it ensures you aren't looking at stale cached metadata from a previous run.

For a complete deep dive into Query Store maintenance and best practices, refer to the official Microsoft Query Store Documentation.

Is your Query Store filling up? Consider changing your QUERY_CAPTURE_MODE to AUTO to capture only the most relevant queries and save significant disk space!

Saturday, May 29, 2021

How to Check SQL Server Memory Pressure and Usage using DMVs

Summary: Use sys.dm_os_process_memory and sys.dm_os_sys_memory to monitor SQL Server memory health, detect low memory conditions, and audit physical vs. virtual memory usage.

Monitoring SQL Server Memory Health and Performance

When working with SQL Server, monitoring memory is crucial for optimal performance. These queries provide valuable insights into your system's memory state, helping you identify and address potential memory pressure issues before they impact your users.


1. Process Memory Low Conditions

The following query helps determine if your SQL Server process is experiencing low physical or virtual memory. Ideally, both values should be 0.


-- Check for low memory flags (0 = Normal, 1 = Low)
SELECT 
    m.process_physical_memory_low,
    m.process_virtual_memory_low
FROM sys.dm_os_process_memory m;
        

2. Current Instance Memory Usage

This query displays the amount of physical memory (RAM) currently consumed by your SQL Server instance.


-- Total memory currently used by the SQL process
SELECT 
    m.physical_memory_in_use_kb / 1024 AS [Mem Used in MB]
FROM sys.dm_os_process_memory m;
        

3. Overall System Memory Status

Gain a comprehensive overview of the host's memory health. The system_memory_state_desc is the most important field for a quick health check.


-- System-level memory overview
SELECT 
    m.total_physical_memory_kb / 1024 AS [Total Mem MB],
    m.available_physical_memory_kb / 1024 AS [Available Mem MB],
    m.system_memory_state_desc AS [Memory State]
FROM sys.dm_os_sys_memory m;
        

4. OS Memory & Page File Details

For deep troubleshooting, monitor the page file and system cache. For optimal performance, the state should be "Available physical memory is high."


-- Detailed OS memory audit
SELECT 
    total_physical_memory_kb/1024 AS [Total Memory (MB)],
    available_physical_memory_kb/1024 AS [Available Memory (MB)],
    total_page_file_kb/1024 AS [Total Page File (MB)],
    available_page_file_kb/1024 AS [Available Page File (MB)],
    system_cache_kb/1024 AS [System Cache (MB)],
    system_memory_state_desc AS [System Memory State]
FROM sys.dm_os_sys_memory WITH (NOLOCK) 
OPTION (RECOMPILE);
        

Understanding Memory State Descriptions:

  • Available physical memory is high: System health is excellent.
  • Physical memory usage is steady: Standard operational state.
  • Available physical memory is low: The OS is under pressure; check for other processes hogging RAM.
  • Available physical memory is running low: Critical state; SQL Server may start trimming its working set.

Further Reading and Resources:

Experiencing high Page Life Expectancy (PLE) drops? Use these scripts to verify if the OS is forcing SQL Server to release memory back to the system!

Saturday, May 8, 2021

How to Identify SQL Server Index Lock Contention and Wait Times

Summary: Use sys.dm_db_index_operational_stats to identify tables and indexes with high row and page lock contention, helping you pinpoint performance bottlenecks in your SQL Server databases.

Identifying Database Lock Contention and Index Wait Times

Hey there, fellow database enthusiasts! Ever wondered about those pesky database locks that can slow things down? Analyzing lock waits is a crucial step in maintaining a healthy and performant SQL Server environment.

Today, we're sharing a super useful SQL query to help you identify and analyze lock waits. This script is a fantastic tool for pinpointing specific tables and indexes experiencing contention, allowing you to focus your optimization efforts where they matter most.

SQL Query: Analyze Row and Page Lock Waits

This query calculates cumulative wait counts and durations for both row-level and page-level locks since the last SQL Server restart (or since the index was created).


-- Identify indexes with significant lock contention
SELECT 
    o.name AS [table_name],
    i.name AS [index_name],
    ios.index_id,
    ios.partition_number,
    SUM(ios.row_lock_wait_count) AS [total_row_lock_waits],
    SUM(ios.row_lock_wait_in_ms) AS [total_row_lock_wait_in_ms],
    SUM(ios.page_lock_wait_count) AS [total_page_lock_waits],
    SUM(ios.page_lock_wait_in_ms) AS [total_page_lock_wait_in_ms],
    SUM(ios.page_lock_wait_in_ms) + SUM(ios.row_lock_wait_in_ms) AS [total_lock_wait_in_ms]
FROM sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) AS ios
INNER JOIN sys.objects AS o WITH (NOLOCK) ON ios.[object_id] = o.[object_id]
INNER JOIN sys.indexes AS i WITH (NOLOCK) ON ios.[object_id] = i.[object_id]
    AND ios.index_id = i.index_id
WHERE o.[object_id] > 100 -- Filter out system objects
GROUP BY o.name, i.name, ios.index_id, ios.partition_number
HAVING SUM(ios.page_lock_wait_in_ms) + SUM(ios.row_lock_wait_in_ms) > 0
ORDER BY total_lock_wait_in_ms DESC
OPTION (RECOMPILE);
        

How to Interpret the Results

This query leverages sys.dm_db_index_operational_stats, a dynamic management function that provides detailed information about index activity.

  • Total Lock Wait (ms): The primary metric for identifying the biggest bottlenecks. Focus on the top rows first.
  • Row vs. Page Locks: High page lock waits often suggest that multiple rows on the same 8KB page are being contested, which might be mitigated by evaluating your index fill factor or page-locking settings.
  • Index Name: If you see high waits on a specific non-clustered index, consider if that index is strictly necessary or if query patterns are causing frequent updates that block reads.

Seeing high contention? Once you've identified the offending index, look at the underlying queries using sys.dm_exec_requests to see what is currently blocking your workload!

Saturday, May 1, 2021

How to Audit SQL Server Columnstore Index Physical Stats and Fragmentation

Summary: Use sys.dm_db_column_store_row_group_physical_stats to audit the health of your Columnstore indexes, monitor delta store growth, and calculate row-group fragmentation.

Analyzing Columnstore Index Physical Health

Ever wondered how to peek behind the curtains of your SQL Server's Columnstore indexes? Unlike traditional B-Tree indexes, Columnstore indexes are composed of row groups that can be in various states (Open, Closed, or Compressed).

This handy query gives you a detailed look at their physical stats, helping you understand their internal health and identify when it's time for an index reorganize or rebuild.

Columnstore Row Group Physical Stats Query


-- Audit Columnstore row group health and fragmentation
SELECT 
    OBJECT_NAME(ps.object_id) AS [TableName],
    i.[name] AS [IndexName],
    ps.index_id,
    ps.partition_number,
    ps.delta_store_hobt_id,
    ps.state_desc,
    ps.total_rows,
    ps.size_in_bytes,
    ps.trim_reason_desc,
    ps.generation,
    ps.transition_to_compressed_state_desc,
    ps.has_vertipaq_optimization,
    ps.deleted_rows,
    CAST(100.0 * (ISNULL(ps.deleted_rows, 0)) / NULLIF(ps.total_rows, 0) AS DECIMAL(5,2)) AS [Fragmentation %]
FROM sys.dm_db_column_store_row_group_physical_stats AS ps WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK) 
    ON ps.object_id = i.object_id
    AND ps.index_id = i.index_id
ORDER BY [TableName], ps.partition_number, ps.row_group_id
OPTION (RECOMPILE);
        

Key Metrics to Monitor

  • state_desc: Look for OPEN row groups. If you have too many small open row groups, it can indicate "trickle inserts" which hurt compression and performance.
  • Fragmentation %: In Columnstore, fragmentation is caused by deleted_rows. Since rows aren't physically removed from compressed segments immediately, high fragmentation means you are reading "dead" data into memory.
  • trim_reason_desc: This tells you why a row group was closed (e.g., BULKLOAD or MEMORY_LIMITATION). If you see MEMORY_LIMITATION frequently, your server may need more RAM to build optimal segments.

This SQL script dives into sys.dm_db_column_store_row_group_physical_stats to provide deep insights. It's an essential tool for any DBA managing large-scale data warehouses or real-time operational analytics.


Is your Fragmentation above 20%? Run ALTER INDEX ... REORGANIZE to physically remove deleted rows and merge smaller row groups for better compression!

Thursday, April 29, 2021

Comprehensive SQL Server Database Audit: Logs, Recovery Models, and Settings

Summary: Use this advanced T-SQL query to audit all databases on your instance. Track Transaction Log usage, Recovery Models, Compatibility Levels, and TDE Encryption status in a single view.

Deep Dive: Auditing SQL Server Database Health and Configuration

Monitoring the health of your databases requires more than just checking if they are "online." A proactive DBA needs to understand the Transaction Log usage, Recovery Models, and critical configuration flags that impact performance and disaster recovery.

The following query provides a powerful, single-pane-of-glass view into every database on your instance, gathering crucial insights from across multiple system views and performance counters.

SQL Database Audit Script


-- Comprehensive Database Property and Log Usage Audit
SELECT 
    db.[name] AS [Database Name],
    SUSER_SNAME(db.owner_sid) AS [Database Owner],
    db.recovery_model_desc AS [Recovery Model],
    db.state_desc AS [State],
    db.log_reuse_wait_desc AS [Log Reuse Wait],
    CONVERT(DECIMAL(18, 2), ls.cntr_value / 1024.0) AS [Log Size (MB)],
    CONVERT(DECIMAL(18, 2), lu.cntr_value / 1024.0) AS [Log Used (MB)],
    CAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT) AS DECIMAL(18, 2)) * 100 AS [Log Used %],
    db.[compatibility_level] AS [Compatibility],
    db.page_verify_option_desc AS [Page Verify],
    db.is_auto_create_stats_on AS [Auto-Create Stats],
    db.is_auto_update_stats_on AS [Auto-Update Stats],
    db.is_read_committed_snapshot_on AS [RCSI Enabled],
    db.is_auto_close_on AS [Auto-Close],
    db.is_auto_shrink_on AS [Auto-Shrink],
    db.is_query_store_on AS [Query Store],
    db.is_encrypted AS [Is Encrypted],
    de.encryption_state AS [TDE State],
    db.is_accelerated_database_recovery_on AS [ADR Enabled]
FROM sys.databases AS db WITH (NOLOCK)
INNER JOIN sys.dm_os_performance_counters AS lu WITH (NOLOCK) 
    ON db.name = lu.instance_name
INNER JOIN sys.dm_os_performance_counters AS ls WITH (NOLOCK) 
    ON db.name = ls.instance_name
LEFT OUTER JOIN sys.dm_database_encryption_keys AS de WITH (NOLOCK) 
    ON db.database_id = de.database_id
WHERE lu.counter_name LIKE N'Log File(s) Used Size (KB)%'
    AND ls.counter_name LIKE N'Log File(s) Size (KB)%'
    AND ls.cntr_value > 0
ORDER BY db.[name]
OPTION (RECOMPILE);
        

Why This Matters for Performance

  • Log Reuse Wait: If your log is full, this column tells you why. Common reasons include LOG_BACKUP (needs a transaction log backup) or ACTIVE_TRANSACTION (an uncommitted transaction is pinning the log).
  • Auto-Close/Auto-Shrink: Red Flag! In production, these should almost always be 0. Auto-close causes performance overhead on every connection, and Auto-shrink causes massive fragmentation.
  • Compatibility Level: Ensure your databases are taking advantage of the latest Query Optimizer features by aligning this with your current SQL Server version.
  • RCSI Enabled: Read Committed Snapshot Isolation can significantly reduce locking and blocking in highly concurrent environments.

This query leverages two key Dynamic Management Views (DMVs) for its data:

Is your Transaction Log out of control? Identifying the Log Reuse Wait Description is the first step toward fixing log growth issues and avoiding "Disk Full" errors!

Sunday, April 25, 2021

SQL Server Extended Properties: How to Query Metadata for All Database Object

Summary: A comprehensive guide and T-SQL script library for retrieving extended properties across SQL Server objects, including tables, columns, indexes, schemas, and Service Broker components.

Retrieving Extended Properties in SQL Server

Extended properties are a powerful way to store metadata (like descriptions, versions, or owner info) directly within your database. This post provides a complete library of scripts to query sys.extended_properties for every major database object.


1. Objects and Columns (Class 1)

This query pulls properties for tables, views, stored procedures, and specific columns.


SELECT 
  CASE 
    WHEN ob.parent_object_id > 0
    THEN OBJECT_SCHEMA_NAME(ob.parent_object_id) + '.' + OBJECT_NAME(ob.parent_object_id) + '.' + ob.name
    ELSE OBJECT_SCHEMA_NAME(ob.object_id) + '.' + ob.name
  END + CASE 
    WHEN ep.minor_id > 0
    THEN '.' + col.name
    ELSE ''
  END AS [Path]
  ,ep.name AS [Property Name]
  ,ep.value AS [Property Value]
FROM sys.extended_properties ep
INNER JOIN sys.objects ob ON ep.major_id = ob.OBJECT_ID AND class = 1
LEFT OUTER JOIN sys.columns col ON ep.major_id = col.Object_id 
  AND class = 1 AND ep.minor_id = col.column_id;
        

2. Indexes (Class 7)


SELECT 
  OBJECT_SCHEMA_NAME(ob.object_id) + '.' + OBJECT_NAME(ob.object_id) + '.' + ix.name AS [Index Path],
  ep.name, value
FROM sys.extended_properties ep
INNER JOIN sys.objects ob ON ep.major_id = ob.OBJECT_ID AND class = 7
INNER JOIN sys.indexes ix ON ep.major_id = ix.Object_id 
  AND class = 7 AND ep.minor_id = ix.index_id;
        

3. Schemas (Class 3) and Database (Class 0)


-- Schemas
SELECT sch.name AS [Schema], ep.name, ep.value
FROM sys.extended_properties ep
INNER JOIN sys.schemas sch ON class = 3 AND ep.major_id = SCHEMA_ID;

-- Database Level
SELECT DB_NAME() AS [Database], ep.name, ep.value
FROM sys.extended_properties ep
WHERE class = 0;
        

4. Service Broker & Specialized Objects

Retrieving properties for Routes, Services, and Message Types.


-- Routes (Class 19)
SELECT rt.name, ep.name, ep.value
FROM sys.extended_properties ep
INNER JOIN sys.routes rt ON class = 19 AND ep.major_id = rt.route_id;

-- Services (Class 17)
SELECT sv.name COLLATE DATABASE_DEFAULT, ep.name, ep.value
FROM sys.extended_properties ep
INNER JOIN sys.services sv ON class = 17 AND ep.major_id = sv.service_id;
        

Quick Reference: Class ID Table

When writing custom queries against sys.extended_properties, use these class IDs:

Class ID Object Type
0Database
1Object or Column
2Parameter
3Schema
7Index
10XML Schema Collection

Further Reading

Pro Tip: Use Extended Properties to store 'Data Sensitivity' or 'Owner' tags to automate your compliance auditing and data cataloging!