Wednesday, December 29, 2021

Get a count of SQL connections by IP address

Here's a handy SQL query to get an overview of your active SQL Server connections and sessions. It helps you quickly see who is connected, from where, and how many connections they have open. This can be super useful for monitoring activity or troubleshooting connection issues.

SELECT ec.client_net_address
 ,es.[program_name]
 ,es.[host_name]
 ,es.login_name
 ,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);

This query joins two dynamic management views (DMVs):

By grouping and counting, we can easily see the number of connections per unique combination of client IP address, program name, host name, and login name. The OPTION (RECOMPILE) ensures the query plan is recompiled each time it runs, which can be beneficial for DMVs that frequently change data.

Get tempdb version store space usage by database

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 is your go-to. It provides a table showing the total tempdb space consumed by version store records for each database.

This view is super efficient and inexpensive to run because it doesn't dig into individual version store records. Instead, it gives you an aggregated view of the version store space used in tempdb on a per-database basis. That makes it perfect for quick checks and monitoring!

Retrieve Version Store Space Usage

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

This query will give you a clear breakdown of the version store space by database, ordered from largest to smallest.

For more SQL Server insights, check out this article on getting your TempDB files count.

You can also find more detailed documentation on sys.dm_tran_version_store_space_usage on the Microsoft Docs website.

Sunday, December 26, 2021

CPU utilization trends

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.

The 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 Process CPU Utilization]
 ,SystemIdle AS [System Idle Process]
 ,100 - SystemIdle - SQLProcessUtilization AS [Other Process CPU Utilization]
 ,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 looking at the `RING_BUFFER_SCHEDULER_MONITOR` type. This ring buffer captures system health events, including CPU utilization. By parsing the XML output from the `record` column, we can extract details like `SystemIdle` (how much CPU is idle), `SQLProcessUtilization` (how much CPU SQL Server is using), and then calculate the CPU usage by other processes.

For more in-depth information about `sys.dm_os_ring_buffers` and how it's used, check out this great resource: Inside sys.dm_os_ring_buffers.

Give this script a try and let us know in the comments if you found it useful for your SQL Server monitoring!

Sunday, December 19, 2021

Hardware information from SQL Server

This query provides valuable basic hardware information about your database server.

It's important to note that 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 your host machine.

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 [SQL Server Up Time (hrs)],
       virtual_machine_type_desc AS [Virtual Machine Type], 
       softnuma_configuration_desc AS [Soft NUMA Configuration], --SQL Server 2016
       sql_memory_model_desc, --Added in SQL Server 2016 SP1
       container_type_desc -- New in SQL Server 2019
FROM sys.dm_os_sys_info WITH (NOLOCK) OPTION (RECOMPILE);

For more in-depth information, you can explore the following resources:

Sunday, December 12, 2021

Check all drive space on the server

Ever need to quickly check the available space on your SQL Server drives? Here are a couple of handy SQL queries that can help you out. We'll explore using a dynamic management view and a system stored procedure.

Method 1: Using `sys.dm_os_enumerate_fixed_drives`

This dynamic management view provides detailed information about fixed drives, including their path, type, and free space. It's a robust method for obtaining precise data.

SELECT fixed_drive_path
    ,drive_type_desc
    ,CONVERT(DECIMAL(18, 2), free_space_in_bytes / 1073741824.0) AS [Available Space (GB)]
FROM sys.dm_os_enumerate_fixed_drives WITH (NOLOCK)
OPTION (RECOMPILE);

Method 2: Using `xp_fixeddrives`

For a simpler and quicker overview, the `xp_fixeddrives` extended stored procedure is a great option. It returns a summary of free space on fixed drives.

xp_fixeddrives

You can find more in-depth information about sys.dm_os_enumerate_fixed_drives on the Microsoft documentation.

---

Further Reading on SQL Server Space Management

If you're interested in learning more about managing space in SQL Server, check out these related posts:

Saturday, December 11, 2021

Resource Governor Resource Pool information

Ever wondered about the current status of your SQL Server resource pools? This quick query provides valuable insights into their performance and memory utilization.

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);

This query leverages the sys.dm_resource_governor_resource_pools dynamic management view to give you a clear picture of how your resource governor is managing your SQL Server resources.

Sunday, December 5, 2021

Get any memory dumps from SQL Server

Understanding the status of memory dumps in your SQL Server instance is crucial for troubleshooting and performance analysis. This post provides a simple method to quickly get details about any memory dumps, including their location, when they occurred, and their size.

Retrieve SQL Server Memory Dump Information

You can use the following SQL query to access data from the sys.dm_server_memory_dumps dynamic management view. This view provides valuable insights into recent memory dump events.

SELECT
    [filename],
    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 will return the **filename** of the dump, its **creation time**, and its **size in megabytes**. The results are ordered by creation time, showing the most recent dumps first.

For more in-depth information about the sys.dm_server_memory_dumps view, you can refer to the official Microsoft documentation: sys.dm_server_memory_dumps on Microsoft Docs

Related SQL Server Memory Management Resources

Monday, November 29, 2021

Manufacturer information inside SQL server

How to Identify Your System's 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? It's a handy trick, especially when you need to gather system details without digging deep into system properties.

Using a Simple SQL Query

Here's the straightforward SQL query you can use:

EXEC sys.xp_readerrorlog 0, 1, N'Manufacturer';

This command searches the current SQL Server error log for entries containing the word "Manufacturer." The output will typically include a line detailing your system's make and model.

Important Considerations

Keep in mind that this query will only yield results if the error log hasn't been recycled since your SQL Server instance last started. If the log has cycled, the relevant information might no longer be present in the current log.

Verifying Virtual Machine Environments

Beyond just identifying the manufacturer, this method can also be used to confirm if your SQL Server is running within a virtual machine (VM). Many virtualized environments will clearly state "Virtual Machine" or similar in their manufacturer details.

Further Reading and Resources

For more advanced techniques on working with SQL Server error logs and system information, check out these related posts:

Saturday, November 20, 2021

Determine which scalar UDFs are in-lineable

When you're working with SQL Server, understanding the properties of your functions can be really helpful for performance optimization. The following SQL query helps you identify your scalar user-defined functions (UDFs) and check if they are "inlineable."

Check if Your SQL Scalar Functions are Inlineable

This query provides insight into whether a scalar UDF can be inlined, which can significantly improve query performance by essentially expanding the function's logic directly into the calling query, avoiding the overhead of a function call.

SELECT OBJECT_NAME(m.object_id) AS [Function Name]
 ,is_inlineable
 ,inline_type
FROM sys.sql_modules AS m WITH (NOLOCK)
LEFT OUTER JOIN sys.dm_exec_function_stats AS efs WITH (NOLOCK) ON m.object_id = efs.object_id
WHERE efs.type_desc = N'SQL_SCALAR_FUNCTION'
OPTION (RECOMPILE);

For more detailed information on scalar UDF inlining and related system views, you can refer to the official Microsoft documentation:

Saturday, November 13, 2021

How to check what databases are accessible?


Ever wonder which databases you can actually get into? There's a simple SQL query that'll show you exactly which ones are accessible on your system. It's a quick way to check your database permissions at a glance.


SELECT name, HAS_DBACCESS(name) FROM sys.databases;

This statement lists each database by name and tells you whether you have access to it. Pretty handy for a quick security check!



Friday, October 29, 2021

Read Windows Registry from SQL server

Ever wonder about the nitty-gritty details of your SQL Server's underlying hardware? Sometimes, peeking into the Windows Registry can give you some valuable insights. Here are a few handy SQL commands to pull essential hardware information, along with some important considerations for optimizing performance.

Unveiling Storage Driver Parameters

For those running SQL Server on VMware, understanding your storage driver settings is crucial for optimal I/O. You can query the registry to see the current driver parameters for your PVSCSI adapter:

EXEC sys.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'SYSTEM\CurrentControlSet\services\pvscsi\Parameters\Device', N'DriverParameter';

VMware suggests specific values for intensive I/O workloads: RequestRingPages=32 and MaxQueueDepth=254. These settings can significantly impact your disk performance.

For more in-depth information, refer to the official VMware knowledge base article: https://kb.vmware.com/s/article/2053145

---

Discovering Your BIOS Release Date

Knowing your system's BIOS release date can be useful for troubleshooting or determining if you're running on an up-to-date firmware version. Here's how to retrieve it directly from the Windows Registry:

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

Identifying Your Processor Details

Understanding your server's processor is fundamental to SQL Server performance tuning. You can grab the full processor description from the registry with this command:

EXEC sys.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'HARDWARE\DESCRIPTION\System\CentralProcessor\0', N'ProcessorNameString';

For insights into processor selection for SQL Server and how it impacts performance, check out this valuable resource:

https://www.sqlskills.com/blogs/glenn/processor-selection-for-sql-server/

And if you're looking for a comprehensive utility to analyze your CPU and other system components, CPU-Z is a fantastic tool:

https://www.cpuid.com/softwares/cpu-z.html

Monday, October 25, 2021

How to Identify Tables Without a Primary Key in SQL Server

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 Tables Without a Primary Key

The query below retrieves a list of all tables in your database that do not have a primary key defined:


SELECT s.[name] + N'.' + t.[name] AS [Table]
FROM sys.tables t
INNER JOIN sys.schemas s ON t.[schema_id] = s.[schema_id]
WHERE NOT EXISTS (
    SELECT 1
    FROM sys.key_constraints kc
    WHERE kc.[type] = N'PK'
      AND kc.parent_object_id = t.[object_id]
);

🧩 Why This Matters

Tables without primary keys can lead to:

  • Duplicate or inconsistent data
  • Poor query performance
  • Issues with joins and indexing strategies
  • Complications in replication, ETL, and other operations

Make it a habit to review your schema regularly and ensure every table has a well-defined primary key—unless there's a valid reason not to.

Tuesday, September 28, 2021

SQL Server Services information

Ever wondered about the nitty-gritty details of your SQL Server services? This handy query gives you a quick overview of essential information for each service running on your server.

SELECT servicename
 ,process_id
 ,startup_type_desc
 ,status_desc
 ,last_startup_time
 ,service_account
 ,is_clustered
 ,cluster_nodename
 ,[filename]
 ,instant_file_initialization_enabled
FROM sys.dm_server_services WITH (NOLOCK)
OPTION (RECOMPILE);

This query pulls details like the **service name**, its **process ID**, how it's set to **start up** (manual, automatic, etc.), its **current status**, when it last **started**, the **account** it's running under, and whether it's part of a **cluster**. It even tells you if **Instant File Initialization** is enabled!

For more in-depth information about `sys.dm_server_services`, you can always refer to the official Microsoft documentation.



Sunday, August 29, 2021

Get Memory Clerk Usage

Here's a useful SQL query to help you understand how memory is being utilized by different components within your SQL Server instance. This query provides a clear breakdown of memory usage by various memory clerk types, ordered by the highest consumption.

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);

This query leverages the sys.dm_os_memory_clerks Dynamic Management View (DMV), which is an excellent resource for monitoring SQL Server memory. For more in-depth exploration of SQL Server memory and performance, check out these related articles:

Feel free to leave a comment if you have any questions or further insights on SQL Server memory management!

SQL Server NUMA Node information

This query provides valuable insights into your NUMA (Non-Uniform Memory Access) nodes, showing their composition and how much load they're handling. It helps you understand the distribution of resources and activity across your system's memory architecture.

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);

After running this, you'll want to verify that an equal number of 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, as balanced scheduler distribution can significantly impact performance.

For more detailed information, check out these resources:

Saturday, August 28, 2021

Get Server properties

Discovering SQL Server Instance Details with SERVERPROPERTY

Ever needed to quickly grab essential information about your SQL Server instance? The `SERVERPROPERTY` function is your best friend! It allows you to retrieve a wide range of details, from server names and versions to specific configurations like collation and default paths. Below is a comprehensive SQL query that leverages `SERVERPROPERTY` to pull numerous valuable insights about your SQL Server environment.

SELECT SERVERPROPERTY('MachineName') AS val, 'Machine Name' AS Descr
UNION ALL SELECT SERVERPROPERTY('ServerName'), 'Server Name'
UNION ALL SELECT SERVERPROPERTY('InstanceName'), 'Instance'
UNION ALL SELECT SERVERPROPERTY('IsClustered'), 'IsClustered'
UNION ALL SELECT SERVERPROPERTY('ComputerNamePhysicalNetBIOS'), 'Computer Name Physical NetBIOS'
UNION ALL SELECT SERVERPROPERTY('Edition'), 'Edition'
UNION ALL SELECT SERVERPROPERTY('ProductLevel'), 'Product Level (What servicing branch (RTM/SP/CU))'
UNION ALL SELECT SERVERPROPERTY('ProductUpdateLevel'), 'Product Update Level (Within a servicing branch, what CU# is applied)'
UNION ALL SELECT SERVERPROPERTY('ProductVersion'), 'Product Version'
UNION ALL SELECT SERVERPROPERTY('ProductMajorVersion'), 'Product Major Version'
UNION ALL SELECT SERVERPROPERTY('ProductMinorVersion'), 'Product Minor Version'
UNION ALL SELECT SERVERPROPERTY('ProductBuild'), 'Product Build'
UNION ALL SELECT SERVERPROPERTY('ProductBuildType'), 'Product Build Type ( Is this a GDR or OD hotfix (NULL if on a CU build))'
UNION ALL SELECT SERVERPROPERTY('ProductUpdateReference'), 'Product Update Reference (KB article number that is applicable for this build)'
UNION ALL SELECT SERVERPROPERTY('ProcessID'), 'ProcessID'
UNION ALL SELECT SERVERPROPERTY('Collation'), 'Collation'
UNION ALL SELECT SERVERPROPERTY('IsFullTextInstalled'), 'IsFullTextInstalled'
UNION ALL SELECT SERVERPROPERTY('IsIntegratedSecurityOnly'), 'IsIntegratedSecurityOnly'
UNION ALL SELECT SERVERPROPERTY('FilestreamConfiguredLevel'), 'FilestreamConfiguredLevel'
UNION ALL SELECT SERVERPROPERTY('IsHadrEnabled'), 'IsHadrEnabled'
UNION ALL SELECT SERVERPROPERTY('HadrManagerStatus'), 'HadrManagerStatus'
UNION ALL SELECT SERVERPROPERTY('InstanceDefaultDataPath'), 'InstanceDefaultDataPath'
UNION ALL SELECT SERVERPROPERTY('InstanceDefaultLogPath'), 'InstanceDefaultLogPath'
UNION ALL SELECT SERVERPROPERTY('BuildClrVersion'), 'Build CLR Version'
UNION ALL SELECT SERVERPROPERTY('IsXTPSupported'), 'IsXTPSupported'
UNION ALL SELECT SERVERPROPERTY('IsPolybaseInstalled'), 'IsPolybaseInstalled'
UNION ALL SELECT SERVERPROPERTY('IsAdvancedAnalyticsInstalled'), 'IsRServicesInstalled'
  

This query provides a detailed overview of your SQL Server setup, making it incredibly useful for inventory, troubleshooting, or just getting a quick snapshot of your environment.

Further Reading

For a complete and in-depth understanding of all the properties available with `SERVERPROPERTY`, check out the official Microsoft documentation.

Wednesday, August 18, 2021

Get Volume statistics (Storage Partition)

Ever wonder about the nitty-gritty details of where your SQL Server databases and files live? There's a handy dynamic management function in SQL Server that spills the beans on the operating system volume (directory) where your data resides. It's incredibly useful for checking out the attributes of your physical disk drives or getting a quick peek at the available free space in a specific directory.

SELECT DISTINCT vs.volume_mount_point
 ,vs.file_system_type
 ,vs.logical_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 vs.volume_mount_point
OPTION (RECOMPILE);

This SQL query leverages the sys.dm_os_volume_stats function to give you a comprehensive overview, including the mount point, file system type, logical volume name, total size, available space, and even the percentage of free space. It also provides information on whether the volume supports compression, is compressed, or supports sparse files and alternate streams.

For more in-depth documentation on this powerful function, you can refer to the official Microsoft documentation: sys.dm_os_volume_stats (Transact-SQL)

Saturday, August 7, 2021

SQL Socket & Core information

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.

EXEC sys.xp_readerrorlog 0, 1, N'detected', N'socket';

Running the command above helps you quickly confirm your SQL Server's configuration and ensure it aligns with your licensing.

Wednesday, July 28, 2021

List of all global trace flags that are enabled

Ever wondered which global trace flags are active in your SQL Server environment? You can easily discover them using the following command:

DBCC TRACESTATUS (-1);
  

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

  • TF 3226: This flag is a neat trick to keep your SQL Server Error Log cleaner by suppressing messages for successful database backups.
  • TF 6534: If you're working with spatial data, this flag is your friend! It enables the use of native code, which can significantly boost performance.
  • TF 7745: Important for maintaining data integrity, this flag prevents Query Store data from being written to disk during a failover or shutdown.

To enable a specific trace flag, simply use the DBCC TRACEON command, replacing <Ftrace flag> with the desired flag number:

DBCC TRACEON <Ftrace flag>
  

For a comprehensive understanding of SQL Server trace flags and their functionalities, refer to the official Microsoft documentation.

Monday, June 28, 2021

SQL Configuration Values

When working with SQL Server, understanding its configuration settings is crucial for optimal performance and troubleshooting. The sys.configurations system catalog view provides a wealth of information about all the server-wide configuration options. Here's a quick way to view all of them:

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 name of each configuration, its current value, the value actually in use, its minimum and maximum possible settings, a description, and whether it's dynamic (can be changed without restarting the server) or advanced (should only be changed by experienced administrators).

While reviewing all configurations is helpful, you'll often want to check specific settings that are critical for performance or common troubleshooting scenarios. Here are some examples of important configurations and their typical recommended values:

select * from  sys.configurations WITH (NOLOCK) where name like 'automatic soft-NUMA%'  --should be 0 in most cases
select * from  sys.configurations WITH (NOLOCK) where name like 'backup checksum%'  --should be 1
select * from  sys.configurations WITH (NOLOCK) where name like 'backup compression default%'  --should be 1 in most cases
select * from  sys.configurations WITH (NOLOCK) where name like 'clr enabled%'  --only enable if it is needed
select * from  sys.configurations WITH (NOLOCK) where name like 'cost threshold for parallelism%'  --(depends on your workload)
select * from  sys.configurations WITH (NOLOCK) where name like 'lightweight%'  --should be zero
select * from  sys.configurations WITH (NOLOCK) where name like 'max degree of parallelism%'  --depends on your workload and hardware
select * from  sys.configurations WITH (NOLOCK) where name like 'max server memory%'  --set to an appropriate value, not the default
select * from  sys.configurations WITH (NOLOCK) where name like 'optimize for ad hoc workloads'  --should be 1
select * from  sys.configurations WITH (NOLOCK) where name like 'priority boost%'  --should be zero
select * from  sys.configurations WITH (NOLOCK) where name like 'remote admin connections%'  --should be 1
select * from  sys.configurations WITH (NOLOCK) where name like 'tempdb metadata memory-optimized%'  --0 by default, some workloads may benefit by enabling

Remember that the "best" setting for some of these options, like cost threshold for parallelism and max degree of parallelism, can vary significantly depending on your specific workload and server hardware. Always test changes in a development environment before applying them to production.

For more in-depth details on each configuration option, you can always refer to the official Microsoft documentation for sys.configurations.

SQL Information

Ever wonder about the specific build and version of your SQL Server instance? You can easily find out using this simple SQL query:

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

Speaking of versions, here's a detailed look at the various builds of **SQL Server 2019**, including their release dates and links to relevant Microsoft Knowledge Base (KB) articles:

Build Description 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/RC1 Refresh 8/29/2019
15.0.2000.5 RTM 11/4/2019
15.0.2070.41 GDR1 11/4/2019

For more comprehensive information, you can refer to these official Microsoft resources:

Saturday, June 19, 2021

Get in-memory OLTP index usage

Understanding how your SQL Server indexes are performing is crucial for database optimization. The following SQL query leverages sys.dm_db_xtp_index_stats to provide valuable insights into your in-memory OLTP (Hekaton) index usage. This dynamic management view gives you statistics like the number of scans, retries, rows touched, and rows returned for each index.

SELECT OBJECT_NAME(i.[object_id]) AS [Object Name],
       i.index_id,
       i.[name] AS [Index Name],
       i.[type_desc],
       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.[object_id])
OPTION (RECOMPILE);

This query helps you identify which indexes are being heavily utilized and which might be underperforming or not being used efficiently. For more detailed information on sys.dm_db_xtp_index_stats, you can refer to the official Microsoft documentation:

sys.dm_db_xtp_index_stats (Transact-SQL) - SQL Server | Microsoft Docs

You might also find these related articles helpful for further exploration of SQL Server memory management and performance:

Saturday, June 5, 2021

Find Your Database's Query Store Settings

SQL query that pulls data from the sys.database_query_store_options view.

This query is likely related to monitoring or troubleshooting the SQL Server Query Store settings.

Here's a quick breakdown of the query:


SELECT
  actual_state_desc,               -- Description of the current state of the Query Store
  desired_state_desc,              -- Description of the desired state of the Query Store
  interval_length_minutes,         -- The length of the interval in minutes for Query Store data collection
  current_storage_size_mb,         -- The current size of the Query Store in MB
  max_storage_size_mb,             -- The maximum storage size for the Query Store in MB
  query_capture_mode_desc,         -- The capture mode for query plans and runtime statistics
  size_based_cleanup_mode_desc     -- The cleanup mode used when managing Query Store size
FROM sys.database_query_store_options WITH (NOLOCK)
OPTION (RECOMPILE);

Key Points:

  • WITH (NOLOCK): This hint tells SQL Server to perform a dirty read, meaning it doesn't acquire shared locks and can read uncommitted data. This can speed up queries but might return inconsistent results if data is being modified.
  • OPTION (RECOMPILE): Forces SQL Server to recompile the query plan each time it's run, which could be useful for queries with varying parameters but may add overhead.

Saturday, May 29, 2021

Check Memory pressure on the server

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.

Checking for 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 zero.

SELECT m.process_physical_memory_low
 ,m.process_virtual_memory_low
FROM sys.dm_os_process_memory m --both should be zero

Current Memory Usage by SQL Server Process

This query displays the amount of physical memory currently being used by your SQL Server instance in megabytes (MB).

SELECT m.physical_memory_in_use_kb / 1024 [Mem Used in MB]
FROM sys.dm_os_process_memory m

Overall System Memory Status

Gain a comprehensive overview of your system's memory, including total physical memory, available physical memory, and the current system memory state. The `system_memory_state_desc` provides a quick indicator of memory health.

SELECT m.total_physical_memory_kb / 1024 [Mem in MB]
 ,m.available_physical_memory_kb / 1024 [Available Mem MB]
 ,m.system_memory_state_desc
FROM sys.dm_os_sys_memory m

Committed Memory Information

Understand how much memory has been committed by the operating system to SQL Server and the target memory for the instance.

SELECT m.committed_kb / 1024 [Committed in MB]
 ,m.committed_target_kb / 1024 [Target Mem MB]
FROM sys.dm_os_sys_info m

Possible System Memory State Descriptions:

  • Available physical memory is high: Your system has ample free physical memory.
  • Physical memory usage is steady: Memory usage is stable, with no significant fluctuations.
  • Available physical memory is low: Your system is running low on available physical memory.
  • Available physical memory is running low: A critical state indicating very little free physical memory.
  • Physical memory state is transitioning: The system's memory state is currently changing.

Detailed OS Memory Information

This query provides more detailed insights into your operating system's memory, including page file usage and system cache. Ideally, `System Memory State` should be "Available physical memory is high" for optimal performance.

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] --should be "Available physical memory is high"
FROM sys.dm_os_sys_memory WITH (NOLOCK) OPTION (RECOMPILE);

Further Reading and Resources:

Saturday, May 8, 2021

Get lock waits for the current database

Hey there, fellow database enthusiasts! Ever wondered about those pesky database locks that can slow things down? Today, we're sharing a super useful SQL query to help you identify and analyze lock waits in your SQL Server databases. This script is a fantastic tool for pinpointing tables and indexes experiencing contention, allowing you to optimize your database performance.

Here’s the SQL query:

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(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
GROUP BY o.name
 ,i.name
 ,ios.index_id
 ,ios.partition_number
HAVING SUM(ios.page_lock_wait_in_ms) + SUM(row_lock_wait_in_ms) > 0
ORDER BY total_lock_wait_in_ms DESC
OPTION (RECOMPILE);

This query leverages sys.dm_db_index_operational_stats, a dynamic management function that provides detailed information about index activity, including lock waits. By joining it with sys.objects and sys.indexes, we can get a clear picture of which tables and their associated indexes are experiencing the most lock contention.

The results will show you the total wait counts and wait times for both row and page locks, helping you quickly identify bottlenecks. Remember, analyzing these lock waits is a crucial step in maintaining a healthy and performant SQL Server environment!

Saturday, May 1, 2021

Columnstore index physical statistics

Ever wondered how to peek behind the curtains of your SQL Server's columnstore indexes? This handy query will give you a detailed look at their physical stats, helping you understand their health and performance.

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
 ,100 * (ISNULL(ps.deleted_rows, 0)) / ps.total_rows 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 ps.object_id
 ,ps.partition_number
 ,ps.row_group_id
OPTION (RECOMPILE);

This SQL script dives into sys.dm_db_column_store_row_group_physical_stats to provide insights like table and index names, row counts, size in bytes, and even a fragmentation percentage. It's a great tool for monitoring your columnstore indexes and ensuring they're performing optimally.

Thursday, April 29, 2021

Database performance information

Understanding Your SQL Server Databases: A Comprehensive Query

This post provides a powerful SQL query to gather crucial information about all databases on your SQL Server instance. You'll get insights into their **recovery model**, **log reuse wait description**, **log file size**, **log usage size**, and **compatibility level**, along with many other important database settings. This script is invaluable for monitoring database health and performance.


SELECT db.[name] AS [Database Name]
 ,SUSER_SNAME(db.owner_sid) AS [Database Owner]
 ,db.recovery_model_desc AS [Recovery Model]
 ,db.state_desc
 ,db.containment_desc
 ,db.log_reuse_wait_desc AS [Log Reuse Wait Description]
 ,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 [DB Compatibility Level]
 ,db.is_mixed_page_allocation_on
 ,db.page_verify_option_desc AS [Page Verify Option]
 ,db.is_auto_create_stats_on
 ,db.is_auto_update_stats_on
 ,db.is_auto_update_stats_async_on
 ,db.is_parameterization_forced
 ,db.snapshot_isolation_state_desc
 ,db.is_read_committed_snapshot_on
 ,db.is_auto_close_on
 ,db.is_auto_shrink_on
 ,db.target_recovery_time_in_seconds
 ,db.is_cdc_enabled
 ,db.is_published
 ,db.is_distributor
 ,db.group_database_id
 ,db.replica_id
 ,db.is_memory_optimized_elevate_to_snapshot_on
 ,db.delayed_durability_desc
 ,db.is_auto_create_stats_incremental_on
 ,db.is_query_store_on
 ,db.is_sync_with_backup
 ,db.is_temporal_history_retention_enabled
 ,db.is_supplemental_logging_enabled
 ,db.is_remote_data_archive_enabled
 ,db.is_encrypted
 ,de.encryption_state
 ,de.percent_complete
 ,de.key_algorithm
 ,de.key_length
 ,db.resource_pool_id
 ,db.is_tempdb_spill_to_remote_store
 ,db.is_result_set_caching_on
 ,db.is_accelerated_database_recovery_on
 ,is_stale_page_detection_on
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);

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


Sunday, April 25, 2021

Find all comments in SQL server for all kind of objects

This post details how to retrieve records using extended properties within your SQL Server database. The following SQL scripts demonstrate how to query various database objects for their associated extended properties.

Objects and 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
  ,'schema' + CASE 
    WHEN ob.parent_object_id > 0
    THEN '/table'
    ELSE ''
  END + '/' + CASE 
    WHEN ob.type IN (
      'TF'
      ,'FN'
      ,'IF'
      ,'FS'
      ,'FT'
      )
    THEN 'function'
    WHEN ob.type IN (
      'P'
      ,'PC'
      ,'RF'
      ,'X'
      )
    THEN 'procedure'
    WHEN ob.type IN (
      'U'
      ,'IT'
      )
    THEN 'table'
    WHEN ob.type = 'SQ'
    THEN 'queue'
    ELSE LOWER(ob.type_desc)
  END + CASE 
    WHEN col.column_id IS NULL
    THEN ''
    ELSE '/column'
  END AS thing
  ,ep.name
  ,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

Indexes

SELECT --indexes
  OBJECT_SCHEMA_NAME(ob.object_id) + '.' + OBJECT_NAME(ob.object_id) + '.' + ix.name
  ,'schema/' + LOWER(ob.type_desc) + '/index'
  ,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

Parameters

SELECT --Parameters
  OBJECT_SCHEMA_NAME(ob.object_id) + '.' + OBJECT_NAME(ob.object_id) + '.' + par.name
  ,'schema/' + LOWER(ob.type_desc) + '/parameter'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.objects ob ON ep.major_id = ob.OBJECT_ID
  AND class = 2
INNER JOIN sys.parameters par ON ep.major_id = par.Object_id
  AND class = 2
  AND ep.minor_id = par.parameter_id

Schemas

SELECT --schemas
  sch.name
  ,'schema'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.schemas sch ON class = 3
  AND ep.major_id = SCHEMA_ID

Database

SELECT DB_NAME()
  ,''
  ,ep.name
  ,value
FROM sys.extended_properties ep
WHERE class = 0

XML Schema Collections

SELECT SCHEMA_NAME(SCHEMA_ID) + '.' + XC.name
  ,'schema/xml_Schema_collection'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.xml_schema_collections xc ON class = 10
  AND ep.major_id = xml_collection_id

Database Files

SELECT --Database Files
  df.name
  ,'database_file'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.database_files df ON class = 22
  AND ep.major_id = file_id

Data Spaces

SELECT --Data Spaces
  ds.name
  ,'dataspace'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.data_spaces ds ON class = 20
  AND ep.major_id = data_space_id

Users

SELECT --USER
  dp.name
  ,'database_principal'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.database_principals dp ON class = 4
  AND ep.major_id = dp.principal_id

Partition Function

SELECT --PARTITION FUNCTION
  pf.name
  ,'partition_function'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.partition_functions pf ON class = 21
  AND ep.major_id = pf.function_id

Remote Service Binding

SELECT --REMOTE SERVICE BINDING
  rsb.name
  ,'remote service binding'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.remote_service_bindings rsb ON class = 18
  AND ep.major_id = rsb.remote_service_binding_id

Route

SELECT --Route
  rt.name
  ,'route'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.routes rt ON class = 19
  AND ep.major_id = rt.route_id

Service

SELECT --Service
  sv.name COLLATE DATABASE_DEFAULT
  ,'service'
  ,ep.name
  ,value
FROM sys.extended_properties ep
INNER JOIN sys.services sv ON class = 17
  AND ep.major_id = sv.service_id

Contract

SELECT -- 'CONTRACT'
  svc.name
  ,'service_contract'
  ,ep.name
  ,value
FROM sys.service_contracts svc
INNER JOIN sys.extended_properties ep ON class = 16
  AND ep.major_id = svc.service_contract_id

Message Type

SELECT -- 'MESSAGE TYPE'
  smt.name
  ,'message_type'
  ,ep.name
  ,value
FROM sys.service_message_types smt
INNER JOIN sys.extended_properties ep ON class = 15
  AND ep.major_id = smt.message_type_id

Plan Guide

SELECT -- 'PLAN GUIDE' 
  pg.name
  ,'plan_guide'
  ,ep.name
  ,value
FROM sys.plan_guides pg
INNER JOIN sys.extended_properties ep ON class = 27
  AND ep.major_id = pg.plan_guide_id

Assembly

SELECT -- 'assembly'
  asy.name
  ,'assembly'
  ,ep.name
  ,value
FROM sys.assemblies asy
INNER JOIN sys.extended_properties ep ON class = 5
  AND ep.major_id = asy.assembly_id

Certificates, Asymmetric Keys, and Symmetric Keys

Note: The following SQL queries for Certificates, Asymmetric Keys, and Symmetric Keys require the `class` values to be filled in for accurate results. You can find these values in the reference table below.

--UNION ALL 
SELECT --'CERTIFICATE'
  cer.name,'certificate', ep.name,value 
FROM sys.certificates cer
INNER JOIN sys.extended_properties ep ON class=? AND ep.major_id=cer.certificate_id

UNION ALL --'ASYMMETRIC KEY'
 
SELECT amk.name,'asymmetric_key', ep.name,value  
FROM sys.asymmetric_keys amk
INNER JOIN sys.extended_properties ep ON class=? AND ep.major_id=amk.asymmetric_key_id

SELECT --'SYMMETRIC KEY'
  smk.name,'symmetric_key', ep.name,value 
FROM sys.symmetric_keys smk
INNER JOIN sys.services sv ON class=? AND ep.major_id=smk.symmetric_key_id 

Here's a table outlining the `class` values for different database items:

class tinyint Identifies the class of item on which the property exists. Can be one of the following:
0 = Database
1 = Object or column
2 = Parameter
3 = Schema
4 = Database principal
5 = Assembly
6 = Type
7 = Index
8 = User defined table type column
10 = XML schema collection
15 = Message type
16 = Service contract
17 = Service
18 = Remote service binding
19 = Route
20 = Dataspace (filegroup or partition scheme)
21 = Partition function
22 = Database file
27 = Plan guide

Additional Resources

For more detailed information, please refer to the following resources:

Sunday, April 18, 2021

Database documentation within a database

This post demonstrates how to add descriptive comments to SQL Server database objects using SQL scripts. These comments help document your database structure and provide context to developers and analysts.

How to Comment on a Table in SQL Server

-- Add a description to a table
EXEC sys.sp_addextendedproperty   
 @name = N'MS_Description', 
 @value = N'Contains customer-related data.',   
 @level0type = N'SCHEMA',    
 @level0name = 'dbo',  
 @level1type = N'TABLE',     
 @level1name = 'tblCustomer';  
GO

Now let's see how to add a comment to a specific column within a table.

-- Add a description to a column
EXEC sp_addextendedproperty   
 @name  = N'MS_Description',
 @value = 'Primary key identifier for the customer.',  
 @level0type = N'Schema',  
 @level0name = 'dbo',  
 @level1type = N'Table',   
 @level1name = 'tblCustomer',   
 @level2type = N'Column',  
 @level2name = 'CustomerID';  
GO

For more in-depth guidance on querying all existing comments across SQL Server objects, visit the reference below:

Find All Comments in SQL Server – Himanshu Patel

Saturday, April 17, 2021

Foreign Key scripts

It's helpful to maintain ready-to-use scripts for resetting database contents, including reseeding identities. Feel free to adjust these scripts to fit your specific needs.

Drop Temporary Table

IF OBJECT_ID('tempdb..#Fkey') IS NOT NULL
    DROP TABLE #Fkey;
  

Create Temporary Table with Foreign Key Information

;WITH cte AS (
    SELECT 
        fkc.constraint_column_id AS consColumn,
        fk.NAME AS foreignKeyName,
        parentSchema.name AS parentSchema,
        parentTable.NAME AS parentTableName,
        parent_col.NAME AS parentColName,
        refSchema.name AS refSchema,
        refTable.NAME AS refTableName,
        ref_col.NAME AS refColName
    FROM sys.foreign_keys fk
    INNER JOIN sys.foreign_key_columns fkc ON fk.object_id = fkc.constraint_object_id
    INNER JOIN sys.tables parentTable ON parentTable.object_id = fkc.parent_object_id
    INNER JOIN sys.schemas parentSchema ON parentSchema.schema_id = parentTable.schema_id
    INNER JOIN sys.columns parent_col ON fkc.parent_column_id = parent_col.column_id AND parent_col.object_id = parentTable.object_id
    INNER JOIN sys.tables refTable ON refTable.object_id = fkc.referenced_object_id
    INNER JOIN sys.schemas refSchema ON refSchema.schema_id = refTable.schema_id
    INNER JOIN sys.columns ref_col ON fkc.referenced_column_id = ref_col.column_id AND ref_col.object_id = refTable.object_id
    WHERE parentTable.type = 'U' AND refTable.type = 'U'
)
SELECT DISTINCT 
    foreignKeyName,
    parentSchema,
    parentTableName,
    SUBSTRING((
        SELECT ',' + a.parentColName
        FROM cte a
        WHERE a.foreignKeyName = c.foreignKeyName
        ORDER BY a.consColumn
        FOR XML PATH('')
    ), 2, 300000) AS parentColName,
    refSchema,
    refTableName,
    SUBSTRING((
        SELECT ',' + b.refColName
        FROM cte b
        WHERE b.foreignKeyName = c.foreignKeyName
        ORDER BY b.consColumn
        FOR XML PATH('')
    ), 2, 300000) AS refColName
INTO #Fkey
FROM cte c;
  

Generate Scripts to Drop Foreign Keys

-- Generate scripts to drop existing foreign key constraints
SELECT DISTINCT 
    'IF EXISTS (SELECT * FROM sys.foreign_keys 
        WHERE object_id = OBJECT_ID(N''[' + parentSchema + '].[' + foreignKeyName + ']'') 
        AND parent_object_id = OBJECT_ID(N''[' + parentSchema + '].[' + ParentTableName + ']''))
    ALTER TABLE [' + parentSchema + '].[' + ParentTableName + '] DROP CONSTRAINT [' + foreignKeyName + ']' 
AS foreignKey_drop_script
FROM #Fkey;
  

Generate Scripts to Recreate Foreign Keys

-- Generate scripts to recreate the foreign key constraints
SELECT DISTINCT 
    'ALTER TABLE [' + parentSchema + '].[' + ParentTableName + '] WITH CHECK 
    ADD CONSTRAINT [' + foreignKeyName + '] FOREIGN KEY(' + parentColName + ') 
    REFERENCES [' + refSchema + '].[' + refTableName + '](' + refColName + ')' 
AS Add_constraints_script
FROM #Fkey;
GO
  

Additional Resources:

Sunday, April 11, 2021

Database Snapshots (SQL Server)

Starting with SQL Server 2016 SP1, all editions now support the database snapshot feature.

A database snapshot provides a static, read-only image of a SQL Server database at a specific point in time. This snapshot remains transactionally consistent with the source database as it existed at the moment the snapshot was taken. Note that the snapshot must reside on the same server instance as its original database.


CREATE DATABASE <database_snapshot_name>
ON (
  NAME = <logical_file_name>, FILENAME = '<os_file_name>'
) [ ,...n ]
AS SNAPSHOT OF <source_database_name>
  

Note: The .ss file extension shown in the examples is user-defined and not mandatory.


CREATE DATABASE AdventureWorks_dbss1800 ON  
( NAME = AdventureWorks, FILENAME =  
'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Data\AdventureWorks_data_1800.ss' )  
AS SNAPSHOT OF AdventureWorks;  
GO
  

Restoring the Original Database Using a Snapshot


RESTORE DATABASE <database_name> 
FROM DATABASE_SNAPSHOT = <database_snapshot_name>
  

Further Reading:

Saturday, April 10, 2021

SSIS CSV Import error when a special character in the text column

If you encounter issues importing a CSV file using an SSIS package—particularly when strings are enclosed in double quotes—here’s a method you can try to fix the problem.

Sample CSV Data

"090","Grey",""
"091","Grey, Red",""
"092","White/Teal",""
"042","Blue ","(\"is not blue\" )"    --- TextQualified '"' with single quote inside value
"093","Light Grey",""

Error Message:
[SSIS.Pipeline] Error: SSIS Error Code DTS_E_PRIMEOUTPUTFAILED. The PrimeOutput method on Flat File Source returned error code 0xC0202092. This error is fatal and stops pipeline execution. Additional error details might be available earlier in the log.

To fix this, review the column settings in the Flat File Connection Manager:

Steps:
Navigate to Flat File Connection Manager → Advanced Tab and review the column properties.

Flat File Connection Manager settings

Set TextQualified to false.

TextQualified property setting

Now, attempt to import the CSV file again. The issue should be resolved.

Sunday, April 4, 2021

Pivot table

Below is the general syntax used when working with the PIVOT operator in SQL. This technique transforms rows into columns to better analyze aggregated data.

SELECT <non-pivoted column>,  
    [first pivoted column] AS <column name>,  
    [second pivoted column] AS <column name>,  
    ...  
    [last pivoted column] AS <column name>  
FROM  
    (<SELECT query that retrieves the data>) AS <source alias>  
PIVOT  
(  
    <aggregate function>(<column to aggregate>)  
    FOR [<column with values to become headers>]  
    IN ([first pivoted column], [second pivoted column], ..., [last pivoted column])  
) AS <pivot table alias>  
<optional ORDER BY clause>;

Example: Basic PIVOT Query

-- This example creates a pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,  
[0], [1], [2], [3], [4]  
FROM  
(SELECT DaysToManufacture, StandardCost FROM Production.Product) AS SourceTable  
PIVOT  
(  
AVG(StandardCost)  
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])  
) AS PivotTable;

Advanced PIVOT Example

USE AdventureWorks2014;  
GO  
SELECT VendorID, [250] AS Emp1, [251] AS Emp2, [256] AS Emp3, [257] AS Emp4, [260] AS Emp5  
FROM  
(SELECT PurchaseOrderID, EmployeeID, VendorID FROM Purchasing.PurchaseOrderHeader) AS p  
PIVOT  
(  
COUNT(PurchaseOrderID)  
FOR EmployeeID IN ([250], [251], [256], [257], [260])  
) AS pvt  
ORDER BY pvt.VendorID;

Example: UNPIVOT Operation

-- Creating the base table and inserting sample values
CREATE TABLE pvt (
    VendorID INT, 
    Emp1 INT, 
    Emp2 INT, 
    Emp3 INT, 
    Emp4 INT, 
    Emp5 INT
);  
GO  

INSERT INTO pvt VALUES (1,4,3,5,4,4);  
INSERT INTO pvt VALUES (2,4,1,5,5,5);  
INSERT INTO pvt VALUES (3,4,3,5,4,4);  
INSERT INTO pvt VALUES (4,4,2,5,5,4);  
INSERT INTO pvt VALUES (5,5,1,5,5,5);  
GO  

-- Applying the UNPIVOT operator
SELECT VendorID, Employee, Orders  
FROM  
(SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5 FROM pvt) AS p  
UNPIVOT  
(Orders FOR Employee IN (Emp1, Emp2, Emp3, Emp4, Emp5)) AS unpvt;  
GO

Monday, March 29, 2021

Get IO Statistics by database

Understanding and monitoring database I/O is crucial for maintaining a healthy and performant SQL Server. High I/O can often indicate bottlenecks and impact overall system responsiveness. The following SQL query provides a quick and effective way to analyze I/O statistics across your databases, helping you identify which databases are generating the most read and write activity.

WITH IOStat
AS (
 SELECT DB_NAME(database_id) AS [Database Name]
  ,CAST(SUM(num_of_bytes_read + num_of_bytes_written) / 1048576 AS DECIMAL(12, 2)) AS [TotalMB]
  ,CAST(SUM(num_of_bytes_read) / 1048576 AS DECIMAL(12, 2)) AS [ReadMB]
  ,CAST(SUM(num_of_bytes_written) / 1048576 AS DECIMAL(12, 2)) AS [WriteMB]
 FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
 GROUP BY database_id
 )
SELECT ROW_NUMBER() OVER (
  ORDER BY TotalMB DESC
  ) AS [I/O Rank]
 ,[Database Name]
 ,TotalMB AS [I/O Total (MB)]
 ,CAST(TotalMB / SUM(TotalMB) OVER () * 100.0 AS DECIMAL(5, 2)) AS [I/O Total %]
 ,ReadMB AS [I/O Read (MB)]
 ,CAST(ReadMB / SUM(ReadMB) OVER () * 100.0 AS DECIMAL(5, 2)) AS [I/O Read %]
 ,WriteMB AS [I/O Write (MB)]
 ,CAST(WriteMB / SUM(WriteMB) OVER () * 100.0 AS DECIMAL(5, 2)) AS [I/O Write %]
FROM IOStat
ORDER BY [I/O Rank]
OPTION (RECOMPILE);

This query leverages the **sys.dm_io_virtual_file_stats** Dynamic Management View (DMV), which provides detailed I/O statistics for data and log files. By grouping the results by database, we can easily see which databases are contributing most to the overall I/O workload on your SQL Server instance.

For more in-depth information on the **sys.dm_io_virtual_file_stats** DMV, you can refer to the official Microsoft documentation: sys.dm_io_virtual_file_stats.

Get VLF count for all databases

This post explores how to retrieve information about Virtual Log Files (VLFs) within your SQL Server transaction logs. Understanding VLF distribution is crucial because a large number of VLFs can negatively impact database startup, restore, and recovery times.


What are Virtual Log Files (VLFs)?

VLFs are segments within your SQL Server transaction log. While the physical transaction log file appears as one continuous unit, SQL Server internally divides it into these smaller, manageable VLFs. You can learn more about their architecture here.


Why VLF Count Matters

An excessive number of VLFs can lead to performance degradation. When SQL Server needs to read or process the transaction log (e.g., during database startup, recovery after a crash, or restoring a backup), it has to process each VLF. More VLFs mean more overhead, extending these critical operations.


Querying VLF Information

You can use the sys.dm_db_log_info dynamic management function to inspect VLF details for your databases.

Here's a handy query to identify databases with a high VLF count, ordered from highest to lowest:

SELECT [name] AS [Database Name]
 ,[VLF Count]
FROM sys.databases AS db WITH (NOLOCK)
CROSS APPLY (
 SELECT file_id
 ,COUNT(*) AS [VLF Count]
 FROM sys.dm_db_log_info(db.database_id)
 GROUP BY file_id
 ) AS li
ORDER BY [VLF Count] DESC
OPTION (RECOMPILE);

To see the detailed VLF information for your current database, you can run:

select * from sys.dm_db_log_info(db_id())

Further Reading

For more in-depth information about sys.dm_db_log_info, refer to the official Microsoft documentation: dm_db_log_info (Transact-SQL).

SQL Query to Retrieve Alert Information from SQL Server

This SQL query retrieves alert information from the msdb.dbo.sysalerts table, such as alert name, event source, severity, and occurrence details. This can be useful for monitoring SQL Server alerts and troubleshooting purposes.


SELECT name
     ,event_source
     ,message_id
     ,severity
     ,[enabled]
     ,has_notification
     ,delay_between_responses
     ,occurrence_count
     ,last_occurrence_date
     ,last_occurrence_time
FROM msdb.dbo.sysalerts WITH (NOLOCK)
ORDER BY name
OPTION (RECOMPILE);

The query uses the WITH (NOLOCK) hint to avoid blocking and reads uncommitted data. The results are ordered by the name of the alert. The OPTION (RECOMPILE) ensures that SQL Server doesn't cache the query plan, improving performance for dynamic conditions.

Explanation:

  • name: The name of the alert.
  • event_source: The source that triggered the alert.
  • message_id: The ID of the message associated with the alert.
  • severity: The severity level of the alert.
  • [enabled]: Whether the alert is enabled or not.
  • has_notification: Whether the alert has a notification configured.
  • delay_between_responses: The delay between consecutive responses.
  • occurrence_count: How many times the alert has occurred.
  • last_occurrence_date: The date when the alert last occurred.
  • last_occurrence_time: The time when the alert last occurred.

This query is useful for monitoring the status and history of SQL Server alerts. You can customize it further by filtering specific conditions or adding additional columns from the sysalerts table.

Sunday, March 28, 2021

SQL Server database design: Best practice

Table Design Best Practices

  • Avoid special characters and spaces in table names, column names, and other database object names (e.g., views, stored procedures). Stick to alphanumeric characters and underscores (_) for consistency and compatibility.
  • Avoid storing binary data, such as files or images, directly in tables. Instead, use file paths or dedicated storage solutions like blob storage for better performance and manageability.
  • Always define a primary key on each table. This ensures data integrity and helps with indexing and performance optimization.
  • Do not use deprecated data types like NTEXT, TEXT, and IMAGE. Use NVARCHAR(MAX), VARCHAR(MAX), and VARBINARY(MAX) instead.
  • Avoid using UNIQUEIDENTIFIER as a primary key unless absolutely necessary. It can lead to performance issues due to its large size and randomness, which affects index efficiency.

Friday, March 19, 2021

Get IO warning from log

If you're managing a SQL Server instance, you know how crucial fast disk I/O is for overall database performance. When I/O operations start to slow down, it can lead to noticeable performance degradation and user frustration. Thankfully, SQL Server logs warnings when I/O operations take longer than 15 seconds, and you can easily access this information to pinpoint potential bottlenecks.

By querying the SQL Server error log, you can identify these long-running I/O warnings. This can be an invaluable first step in diagnosing disk-related performance issues, allowing you to investigate further and optimize your storage subsystem.

Here's a handy SQL script you can use to retrieve these I/O warning messages from your SQL Server error logs:

CREATE TABLE #IOWarning (LogDate datetime
 , ProcessInfo sysname
 , LogText nvarchar(1000));

INSERT INTO #IOWarning EXEC xp_readerrorlog 0, 1, N'taking longer than 15 seconds';
INSERT INTO #IOWarning EXEC xp_readerrorlog 1, 1, N'taking longer than 15 seconds';
INSERT INTO #IOWarning EXEC xp_readerrorlog 2, 1, N'taking longer than 15 seconds';
INSERT INTO #IOWarning EXEC xp_readerrorlog 3, 1, N'taking longer than 15 seconds';
INSERT INTO #IOWarning EXEC xp_readerrorlog 4, 1, N'taking longer than 15 seconds';
INSERT INTO #IOWarning EXEC xp_readerrorlog 5, 1, N'taking longer than 15 seconds';

SELECT LogDate, ProcessInfo, LogText
FROM #IOWarning
ORDER BY LogDate DESC;
  

How the Script Works:

  • The script first creates a temporary table named #IOWarning to store the retrieved log entries.
  • It then uses xp_readerrorlog to query the SQL Server error logs. The parameters `0, 1, N'taking longer than 15 seconds'` specifically look for the current log (0) and archived logs (1 through 5) for entries containing the phrase "taking longer than 15 seconds," which is the standard warning message for slow I/O.
  • Finally, it selects and orders the results by LogDate in descending order, showing you the most recent warnings first.

This script provides a quick way to gain insight into potential I/O performance issues. If you consistently see these warnings, it's a strong indicator that you need to investigate your disk configuration, storage array, or underlying hardware. Happy troubleshooting!

Sunday, February 28, 2021

Get CPU utilization by database

Ever wonder which database on your SQL Server instance is consuming the most CPU power? This handy SQL query helps you pinpoint those resource-intensive databases.

WITH DB_CPU
AS (
 SELECT pa.DatabaseID
  ,DB_Name(pa.DatabaseID) AS [Database Name]
  ,SUM(qs.total_worker_time / 1000) AS [CPU_Time_Ms]
 FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
 CROSS APPLY (
  SELECT CONVERT(INT, value) AS [DatabaseID]
  FROM sys.dm_exec_plan_attributes(qs.plan_handle)
  WHERE attribute = N'dbid'
  ) AS pa
 GROUP BY DatabaseID
 )
SELECT ROW_NUMBER() OVER (
  ORDER BY [CPU_Time_Ms] DESC
  ) AS [CPU Rank]
 ,[Database Name]
 ,[CPU_Time_Ms] AS [CPU Time (ms)]
 ,CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER () * 100.0 AS DECIMAL(5, 2)) AS [CPU Percent]
FROM DB_CPU
WHERE DatabaseID <> 32767 -- ResourceDB
ORDER BY [CPU Rank]
OPTION (RECOMPILE);

Keep in mind that the results of this query depend on the currently cached query plans.

For more in-depth information on the Dynamic Management Views (DMVs) used in this query, check out the official Microsoft documentation:

Sunday, February 7, 2021

Get input buffer information for the current database

Exploring Input Buffer Information for Non-System Sessions in SQL Server

Ever needed to peek into what all your active, non-system SQL Server sessions are actually doing? This handy SQL query allows you to retrieve input buffer information for all user sessions within the current database, giving you insight into the commands or queries they are executing.

SQL Query to Get Session Input Buffer Details


SELECT
    es.session_id,
    DB_NAME(es.database_id) AS [Database Name],
    es.login_time,
    es.cpu_time,
    es.logical_reads,
    es.memory_usage,
    es.[status],
    ib.event_info AS [Input Buffer]
FROM
    sys.dm_exec_sessions AS es WITH (NOLOCK)
CROSS APPLY
    sys.dm_exec_input_buffer(es.session_id, NULL) AS ib
WHERE
    es.database_id = DB_ID()
    AND es.session_id > 50 -- Excludes system sessions
    AND es.session_id <> @@SPID -- Excludes the current session
OPTION (RECOMPILE);

Related Commands and Resources

For quick checks, you can also use the DBCC INPUTBUFFER command:


DBCC INPUTBUFFER

For more in-depth information, check out these Microsoft documentation pages:

Thursday, February 4, 2021

Last VLF status of the current database

When you're working with SQL Server, understanding your transaction log files (VLFs) is crucial for database performance and management. This quick T-SQL snippet helps you get a snapshot of the most recent Virtual Log File (VLF) for your current database.

Understanding Your Latest VLF

This SQL query leverages the sys.dm_db_log_info dynamic management function, which provides detailed information about the virtual log files of the transaction log. By ordering the results by vlf_sequence_number in descending order and selecting only the top 1, we can quickly pinpoint the most recently created VLF.

SELECT TOP (1) DB_NAME(li.database_id) AS [Database Name]
 ,li.[file_id]
 ,li.vlf_size_mb
 ,li.vlf_sequence_number
 ,li.vlf_active
 ,li.vlf_status
FROM sys.dm_db_log_info(DB_ID()) AS li
ORDER BY vlf_sequence_number DESC
OPTION (RECOMPILE);

What the Columns Mean:

  • Database Name: The name of the database.
  • file_id: The ID of the log file.
  • vlf_size_mb: The size of the VLF in megabytes.
  • vlf_sequence_number: The sequence number of the VLF, indicating its order of creation.
  • vlf_active: Indicates if the VLF is currently active (1 = active, 0 = inactive).
  • vlf_status: The status of the VLF (e.g., 2 for active, 0 for reusable).

This query is a handy tool for database administrators looking to quickly assess the state of their transaction log and identify potential issues related to VLF fragmentation.

Friday, January 29, 2021

Find single-use, ad-hoc, and prepared queries

Ever wondered what's lurking in your SQL Server's plan cache? This handy query helps you find single-use ad-hoc and prepared statements that might be cluttering up your memory. Identifying these can be a great first step in optimizing your database performance!

SELECT TOP (50) DB_NAME(t.[dbid]) AS [Database Name]
 ,t.[text] AS [Query Text]
 ,cp.objtype AS [Object Type]
 ,cp.cacheobjtype AS [Cache Object Type]
 ,cp.size_in_bytes / 1024 AS [Plan Size in KB]
FROM sys.dm_exec_cached_plans AS cp WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t
WHERE cp.cacheobjtype = N'Compiled Plan'
 AND cp.objtype IN (N'Adhoc', N'Prepared')
 AND cp.usecounts = 1
ORDER BY cp.size_in_bytes DESC
 ,DB_NAME(t.[dbid])
OPTION (RECOMPILE);

This query leverages two powerful Dynamic Management Views (DMVs) in SQL Server to gather its insights:

Popular Posts