Capturing All SQL and Stored Procedure Calls Using Extended Events in SQL Server

Monitoring SQL Server can be a complex task, especially when trying to capture all SQL queries and stored procedure calls for detailed analysis. Extended Events (XEvents) provide a robust way to capture this data with minimal performance impact. In this post, we'll set up an Extended Events session to capture all SQL and stored procedure calls, including important system events.

Setting Up an Extended Events Session

To monitor and capture SQL Server activity, you can create an Extended Events session using the script below. This session, named "CaptureAllSQLAndStoredProcCalls," will track various events including errors, connections, logins, logouts, RPC completions, and SQL batch completions.

Script Breakdown

Here’s a detailed script for creating the Extended Events session:

Here are key points about the buffer cache in SQL Server:

    The buffer cache in SQL Server is a part of the SQL Server memory architecture that is responsible for caching database pages in memory. When SQL Server reads data from a disk, it stores a copy of that data in the buffer cache. Subsequent queries that need the same data can then be served from the in-memory buffer rather than reading from disk, which is significantly faster.

Here are key points about the buffer cache in SQL Server:

Buffer Pool:

The buffer cache is often referred to as the "buffer pool" or "data cache." It is a region in the SQL Server memory space dedicated to storing data pages.

Pages and Extents:

SQL Server divides its storage into fixed-size pages (usually 8 KB). These pages are grouped into larger structures called extents. The buffer cache holds these pages in memory.

Data Access:

When a query needs data, SQL Server first checks if the required pages are already in the buffer cache. If the data is present, it's called a "cache hit," and the data can be retrieved quickly from memory. If not, it's a "cache miss," and the data must be read from disk.

Read-Ahead Mechanism:

SQL Server uses a read-ahead mechanism to anticipate and pre-fetch pages into the buffer cache before they are needed. This helps to minimize the impact of physical I/O on query performance.

LRU (Least Recently Used) Algorithm:

The buffer cache uses an LRU algorithm to manage the contents of the cache. When the cache becomes full, pages that haven't been used recently are candidates for removal to make room for new pages.

Dirty Pages and Checkpoints:

When modifications are made to data in the buffer cache, the modified pages become "dirty." SQL Server periodically writes these dirty pages back to the data files during a process called a checkpoint. This ensures that changes are persisted to disk.

Monitoring Buffer Cache:

Performance monitoring tools and DMVs (Dynamic Management Views) can be used to monitor the state of the buffer cache. For example, the sys.dm_os_buffer_descriptors view provides information about the pages currently in the buffer cache.

SELECT * FROM sys.dm_os_buffer_descriptors;

Configuring Buffer Cache:

SQL Server provides configuration options for the size and behavior of the buffer cache. The "max server memory" configuration option limits the amount of memory that SQL Server can use for the buffer cache.

sp_configure 'max server memory', <value>;

The buffer cache plays a crucial role in optimizing SQL Server performance by reducing the need to perform expensive disk I/O operations. Properly configuring and monitoring the buffer cache is important for maintaining optimal database performance.


Here are common SQL Server performance issues and potential solutions:

 SQL Server performance issues can arise for various reasons, and resolving them often involves identifying bottlenecks, optimizing queries, and configuring the server appropriately. Here are common SQL Server performance issues and potential solutions:

High CPU Usage:

Issue: Excessive CPU utilization.

Solutions:

Identify and optimize poorly performing queries.

Consider adding indexes to improve query performance.

Scale up resources (CPU, memory).

Review and adjust the SQL Server configuration for parallelism.

Memory Pressure:

Issue: Insufficient available memory for SQL Server.

Solutions:

Configure SQL Server memory settings appropriately.

Identify and optimize memory-consuming queries.

Monitor and adjust memory-related configuration settings.

I/O Bottlenecks:

Issue: Slow disk I/O affecting query performance.

Solutions:

Optimize queries to reduce I/O load.

Consider adding more/faster disks.

Use storage with higher IOPS capabilities.

Review and optimize file placement, such as database and log files.

Blocking and Deadlocks:

Issue: Transactions waiting on locks, leading to performance degradation.

Solutions:

Optimize queries and transactions.

Use appropriate isolation levels.

Monitor and identify blocking using tools like SQL Server Profiler.

Implement proper indexing.

Inefficient Query Plans:

Issue: SQL Server generates suboptimal query execution plans.

Solutions:

Update statistics to ensure accurate query plans.

Use index hints to force specific indexes.

Rewrite queries to improve performance.

Indexing Issues:

Issue: Missing or poorly designed indexes.

Solutions:

Regularly analyze and create missing indexes.

Remove unnecessary indexes to improve write performance.

Use the Database Engine Tuning Advisor (DTA) to recommend index changes.

TempDB Contention:

Issue: High contention in the TempDB database.

Solutions:

Split TempDB data files equally across multiple disks.

Adjust the number of TempDB files based on CPU cores.

Monitor and optimize queries that heavily use TempDB.

Out-of-date Statistics:

Issue: Query optimizer relies on outdated statistics.

Solutions:

Regularly update statistics on tables and indexes.

Consider enabling the AUTO_UPDATE_STATISTICS database option.

Network Latency:

Issue: Slow communication between the application and the database.

Solutions:

Optimize network infrastructure.

Use the appropriate network protocols.

Consider deploying closer Azure regions for Azure SQL Database.

Fragmented Indexes:

Issue: Fragmentation affecting index scan/seek performance.

Solutions:

Regularly rebuild or reorganize fragmented indexes.

Monitor index fragmentation using DMVs.

Long-running Queries:

Issue: Queries taking too long to execute.

Solutions:

Optimize queries using proper indexing.

Use execution plans to identify and address performance bottlenecks.

Insufficient Server Resources:

Issue: Not enough CPU, memory, or disk resources.

Solutions:

Consider upgrading hardware or moving to a larger VM size.

Optimize queries to use resources more efficiently.

Regular monitoring, proper configuration, and ongoing performance tuning are essential for maintaining optimal SQL Server performance. It's often helpful to use tools like SQL Server Profiler, SQL Server Management Studio (SSMS), and dynamic management views (DMVs) to diagnose and address performance issues. Additionally, regularly reviewing and implementing best practices for SQL Server performance can help prevent and mitigate potential problems.

Version control in SQL Server

 Version control in SQL Server refers to the practice of managing and tracking changes to database objects, such as tables, views, stored procedures, and functions, over time. Using version control helps in maintaining a history of changes, collaborating with multiple developers, and rolling back to previous states if needed. Here are common approaches and tools for version control in SQL Server:

  1. Scripting and Source Control Systems:
    • Manual Scripting: Developers manually create and maintain SQL scripts for database objects. These scripts are then stored in a version control system such as Git.
    • Source Control Integration: Many version control systems offer integrations with SQL Server Management Studio (SSMS) or other database development tools. Developers can directly commit changes to version control from within the tool.
  1. Database Projects in Visual Studio:
    • SQL Server Data Tools (SSDT): Visual Studio includes a project type known as SQL Server Data Tools, which allows developers to create and manage database projects. These projects can be version-controlled using Git, TFS (Team Foundation Server), or other source control systems.
  1. Migrations and Change Tracking:
    • Database Migrations: Tools like Fluent Migrator, DbUp, or Entity Framework Migrations can be used to create scripts that represent changes to the database schema. These scripts can be version-controlled and applied in a structured manner.
    • Change Tracking: SQL Server has built-in features like Change Data Capture (CDC) and Change Tracking that can help track changes to data. While not a complete version control solution, these features complement version control practices.
  1. Third-Party Tools:
    • Redgate SQL Source Control: This tool integrates with SSMS and supports popular version control systems. It allows developers to link databases to version control repositories and track changes.
    • Liquibase and Flyway: These are database migration tools that support version control for databases. They use scripts or configurations to manage changes and can be integrated with source control systems.
  1. Git Hooks and Database CI/CD:
    • Git Hooks: Pre-commit and post-commit hooks in Git can be used to automate checks and tasks related to version control, such as running tests, enforcing coding standards, or triggering continuous integration (CI) builds.
    • Database CI/CD: Implementing a continuous integration and continuous delivery (CI/CD) pipeline for databases helps automate the process of deploying database changes from version control to different environments.

Isolation levels in SQL Server

 Isolation levels in SQL Server define the degree to which one transaction must be isolated from resource or data modifications made by other transactions. SQL Server supports several isolation levels, each providing a different level of consistency, concurrency, and isolation. The isolation levels in SQL Server are defined by the SQL standard and include the following:

  1. READ UNCOMMITTED:
    • Description: Allows a transaction to read data that is being modified by another transaction without waiting for the other transaction to complete.
    • Issues: Non-repeatable reads, dirty reads, and phantom reads are possible.
  1. READ COMMITTED:
    • Description: Ensures that a transaction reads only committed data. It prevents dirty reads but still allows non-repeatable reads and phantom reads.
    • Issues: Non-repeatable reads and phantom reads are possible.
  1. REPEATABLE READ:
    • Description: Ensures that if a transaction reads a value, it will get the same value if it reads it again within the same transaction. It prevents dirty reads and non-repeatable reads but allows phantom reads.
    • Issues: Phantom reads are possible.
  1. SNAPSHOT:
    • Description: Allows a transaction to read a version of data as it existed at the start of the transaction. This provides a consistent snapshot of the data for the duration of the transaction.
    • Issues: Avoids dirty reads, non-repeatable reads, and phantom reads.
  1. SERIALIZABLE:
    • Description: Provides the highest level of isolation. It ensures that transactions are completely isolated from one another. It prevents dirty reads, non-repeatable reads, and phantom reads.
    • Issues: Increased contention and potential for slower performance due to locks.

The isolation level can be set for a session using the SET TRANSACTION ISOLATION LEVEL statement. 

For example:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

it's important to note that selecting a higher isolation level typically comes with an increased risk of performance issues, such as blocking and decreased concurrency. Developers and database administrators need to carefully choose the appropriate isolation level based on the requirements of the application and the specific trade-offs they are willing to make in terms of consistency and performance.

 

Common SQL Server wait types

In SQL Server, wait types are events or conditions that cause a task (such as a query or a process) to wait for a specific resource or event to be available before it can continue processing. Monitoring and analyzing wait types can help identify performance bottlenecks and optimize the database system.

Here are some common SQL Server wait types:

  1. PAGEIOLATCH_XX:
    • Description: Indicates that a process is waiting for a data page to be read from disk into memory.
    • Possible Causes: Slow I/O subsystem, high disk latency.
  1. CXPACKET:
    • Description: Related to parallel query execution. Indicates that a parallel query is waiting for another thread to complete its work.
    • Possible Causes: Overloaded parallelism, uneven workload distribution.
  1. LCK_XX:
    • Description: Indicates a process is waiting to acquire a lock on a resource.
    • Possible Causes: Contentious locks due to high concurrency.
  1. ASYNC_NETWORK_IO:
    • Description: Indicates a task is waiting for network packets to be sent or received.
    • Possible Causes: Slow or congested network.
  1. WRITELOG:
    • Description: Indicates a process is waiting for a log flush to complete.
    • Possible Causes: High transaction log activity, slow disk write performance.
  1. SOS_SCHEDULER_YIELD:
    • Description: Indicates that a task voluntarily yielded the scheduler to let other tasks run.
    • Possible Causes: High CPU usage, resource contention.
  1. PAGE_VERIFY:
    • Description: Indicates a task is waiting for a page verification operation to complete.
    • Possible Causes: Configuring database option CHECKSUM and experiencing high I/O.
  1. OLEDB:
    • Description: Indicates a task is waiting for an OLE DB operation to complete.
    • Possible Causes: Issues with external data source or linked server.
  1. WAITFOR:
    • Description: Indicates a task is waiting for a specified amount of time to elapse.
    • Possible Causes: Delays introduced in queries using the WAITFOR statement.

Monitoring and analyzing wait types can be done using dynamic management views (DMVs) such as sys.dm_os_wait_stats. By querying these views, you can identify which wait types are causing the most contention and focus on optimizing those areas for better performance. Additionally, tools like SQL Server Profiler and Extended Events can be used for more in-depth analysis of wait statistics.

What is the Lazy Writer in SQL Server?

The Lazy Writer is a vital background process in SQL Server, designed to optimize the efficiency of the buffer pool. The buffer pool is a crucial memory area where SQL Server caches data pages, reducing the need to repeatedly read data from disk.

Here’s how the Lazy Writer operates:

  • Purpose: Its primary role is to manage the buffer pool by handling clean pages (data pages that have been modified but not yet written to disk).

  • Function: The Lazy Writer periodically moves aged and less frequently accessed data pages from the buffer pool to disk. This helps free up space in the buffer pool for new, more actively used data pages.

  • Benefits: By performing this cleanup, the Lazy Writer helps maintain the performance and efficiency of SQL Server, ensuring that the buffer pool is optimized for handling incoming data requests.

In essence, the Lazy Writer keeps your SQL Server running smoothly by ensuring that memory resources are used effectively and that new data can be cached efficiently.

The Role of a SQL Server Database Administrator (DBA)

A SQL Server Database Administrator (DBA) is essential for managing and maintaining SQL Server databases within an organization. The specific responsibilities can vary based on the organization's size and structure, but generally, a SQL Server DBA handles the following tasks:-

Database Installation and Configuration

  • Install and Configure SQL Server: Set up SQL Server instances following best practices.
  • Optimize Settings: Configure server and database settings to enhance performance and security.

Database Design

  • Collaborate with Developers: Work with developers and system architects to design efficient, normalized database structures.
  • Manage Database Objects: Create and modify tables, views, indexes, and stored procedures.

Security Management

  • Implement Security Policies: Manage roles, permissions, and security policies at both server and database levels.
  • Review Access: Regularly audit and review database access to ensure compliance and security.

Backup and Recovery

  • Develop Strategies: Create and execute backup and recovery plans to ensure data integrity and availability.
  • Test Disaster Recovery: Document and test procedures to handle potential disasters.

Performance Monitoring and Optimization

  • Monitor Performance: Use tools and logs to monitor server and database performance.
  • Resolve Bottlenecks: Identify and address performance issues through indexing, query optimization, and tuning.

High Availability and Disaster Recovery

  • Implement Solutions: Set up high availability solutions like clustering, mirroring, or AlwaysOn Availability Groups.
  • Plan for Recovery: Develop and test disaster recovery plans to minimize data loss and downtime.

Patch Management and Upgrades

  • Apply Updates: Install patches and updates to maintain SQL Server security and stability.
  • Execute Upgrades: Plan and manage version upgrades as needed.

Automation and Scripting

  • Develop Scripts: Create and maintain scripts for routine tasks, monitoring, and automation.
  • Streamline Tasks: Use PowerShell or other scripting languages to automate administrative functions.

Documentation

  • Maintain Records: Keep comprehensive documentation of databases, configurations, and procedures.
  • Ensure Accessibility: Ensure documentation is current and accessible to relevant stakeholders.

Capacity Planning

  • Monitor Growth: Track database growth and plan for necessary capacity upgrades.
  • Forecast Needs: Predict future capacity requirements based on usage trends.

Troubleshooting and Incident Response

  • Resolve Issues: Investigate and resolve database-related problems and incidents.
  • Respond to Outages: Provide timely responses to system outages or performance issues.

Training and Knowledge Sharing

  • Stay Informed: Keep up with new features and best practices in SQL Server.
  • Train Others: Conduct training sessions and share knowledge with team members and developers.

Navigating the Linux File System Hierarchy: A Beginner's Guide 🌐

 For IT professionals and Linux enthusiasts, mastering the Linux file system hierarchy is key to efficient system management. Unlike the physical layout on disk, the Linux file system is organized logically, starting from the root directory /.

Here’s a snapshot of the core directories and their functions:

  1. /bin 🛠️: Contains essential system binaries like bash, ls, and grep.
  2. /boot 🚀: Houses boot essentials such as the kernel image and bootloader.
  3. /dev 🔌: A hub for device files representing connected hardware.
  4. /etc 📜: The directory for system configuration files.
  5. /home 🏠: Stores user home directories.
  6. /lib 📚: Contains shared libraries used by various programs.
  7. /media 💿: Mount points for removable media like CDs and USB drives.
  8. /mnt 🧲: Used for temporary filesystem mounts.
  9. /opt 📦: Houses optional software packages.
  10. /proc 📊: Information central for system processes and memory usage.
  11. /root 👑: The home directory for the root user.
  12. /sbin 🔧: Contains system administration binaries like init and fdisk.
  13. /srv 🌐: Data storage for services like web servers.
  14. /tmp 🌡️: A space for temporary files.
  15. /usr 🖥️: Most user-installed software is found here.
  16. /var 🔄: Holds variable data such as logs and temporary files.

Useful Commands

  • ls — List directory contents.
  • cd — Change directory.
  • pwd — Print working directory.
  • mkdir — Make a new directory.
  • rm — Remove files or directories.
  • cp — Copy files or directories.
  • mv — Move or rename files or directories.
  • cat — Concatenate and display files.
  • chmod — Change file or directory permissions.
  • chown — Change file or directory ownership.
  • grep — Search for patterns in files.
  • top — Display system processes.
  • ps — Display running processes.
  • kill — Terminate processes.
  • sudo — Execute a command as a superuser.
  • du — Estimate file space usage.
  • tar — Create or extract archive files.
  • ping — Test network connectivity.
  • vi — Edit files using a text editor.
  • ssh — Connect to remote servers securely.

Tips for Navigating the Linux File System

  • cd 🚶: Navigate directories.
  • ls 📋: List directory contents.
  • mkdir 📁: Create a directory.
  • rmdir 🗑️: Remove a directory.
  • cp 📤: Copy files/directories.
  • mv 🚚: Move files/directories.
  • rm: Delete files/directories.

⚠️ Caution: Some directories, like /bin, are read-only. Avoid altering their contents to prevent system issues!

Understanding this hierarchy is crucial for efficient Linux system management. Dive into the Linux file system to enhance your skills and streamline your workflows! 🌟




How To Send SQL Server CPU Utilization Alerts Using SQL Server Agent

 This article explains how to send an email alert using SQL Server alerts when the SQL Server CPU utilization reaches a specific threshold.

In Microsoft SQL Server, you can use T-SQL and SQL Server Agent to generate an alert when CPU usage exceeds a threshold, such as 80%. Here's an example of how you can achieve this:

Create a SQL Server Agent alert: Open SQL Server Management Studio (SSMS) and connect to your SQL Server instance. Navigate to the SQL Server Agent node in the Object Explorer, right-click on the "Alerts" folder, and select "New Alert."

Configure the alert properties: In the "New Alert" dialog, configure the following properties:

Name: Provide a name for the alert.

Type: Select the type of alert as "SQL Server performance condition alert."

Object: Choose the "Resource Pool Stats."

Counter: Choose the "CPU Usage target %" counter.

 Instance: Select "default" to monitor the overall CPU usage of the entire system.

Alert if counter: Choose "Rises above" to trigger the alert when CPU usage exceeds the threshold.

Value: Enter "0.8" to set the threshold for CPU usage to 80%.

 Enable this alert: Check this option to enable the alert.

Response: Choose the appropriate response action, such as "Notify operators" or "Execute job" to determine what action should be taken when the alert is triggered.

Additional actions: As needed, you can configure additional actions, such as sending an email or running a script.

Click on "OK" to create the alert.

Once the alert is created, SQL Server Agent will automatically monitor the CPU usage based on the specified threshold. When the CPU usage exceeds 80%, the alert will be triggered, and the configured response action will be executed, such as sending notifications or running a script.

T-SQL Stored Procedure To Send CPU-Intensive Queries

Let us understand this with a simple demonstration. Suppose I want to create an alert when the CPU utilization reaches 80%; the SQL Server automatically sends the alert along with the list of the top 10 CPU-intensive queries. We will email the queries in an HTML table.

We can use the following query to populate the top 10 CPU-intensive queries list.


SELECT TOP 10 session.session_id, 

           req.cpu_time, 

           req.logical_reads, 

           req.reads, 

           req.writes, 

           SUBSTRING(sqltext.TEXT, (req.statement_start_offset / 2) + 1, 

           ((CASE req.statement_end_offset 

                WHEN -1 THEN DATALENGTH(sqltext.TEXT) 

                ELSE req.statement_end_offset 

            END - req.statement_start_offset) / 2) + 1) AS statement_text, 

           COALESCE(QUOTENAME(DB_NAME(sqltext.dbid)) + N'.' + QUOTENAME(OBJECT_SCHEMA_NAME(sqltext.objectid, sqltext.dbid))  

           + N'.' + QUOTENAME(OBJECT_NAME(sqltext.objectid, sqltext.dbid)), '') AS command_text, 

       req.command, 

           session.login_name, 

           session.host_name, 

           session.program_name, 

           session.last_request_end_time,

           session.login_time   

FROM sys.dm_exec_sessions AS session 

JOIN sys.dm_exec_requests AS req ON req.session_id = session.session_id CROSS APPLY sys.Dm_exec_sql_text(req.sql_handle) AS sqltext 

WHERE req.session_id != @@SPID 

ORDER BY req.cpu_time DESC 

Query Output:



The entire stored procedure is following:

USE ajay --- change Database

 go

 Create PROCEDURE Sp_send_highcpu_alert

 AS

   BEGIN

       CREATE TABLE #tbl_highcpu_query_output

         (

            sessionid             INT,

            cpu_time              BIGINT,

            logicalreads          BIGINT,

            reads                 BIGINT,

            writes                BIGINT,

            querystatement        VARCHAR(max),

            command_text          VARCHAR(max),

            command               VARCHAR(1500),

            login_name            VARCHAR(1000),

            hostname              VARCHAR(50),

            program_name          VARCHAR(500),

            last_request_end_time DATETIME,

            login_time            DATETIME

         )

       INSERT INTO #tbl_highcpu_query_output

       SELECT TOP 10 session.session_id,

                     req.cpu_time,

                     req.logical_reads,

                     req.reads,

                     req.writes,

                     Substring(sqltext.text, ( req.statement_start_offset / 2 ) +

                                             1

                     , (

                     (

                     CASE req.statement_end_offset

                       WHEN -1 THEN Datalength(sqltext.text)

                       ELSE req.statement_end_offset

                     END - req.statement_start_offset ) / 2 ) + 1)

                     AS statement_text,

                     COALESCE(Quotename(Db_name(sqltext.dbid)) + N'.'

                              + Quotename(Object_schema_name(sqltext.objectid,

                              sqltext.dbid))

                              + N'.'

                              + Quotename(Object_name(sqltext.objectid,

                              sqltext.dbid)),

                     '') AS

                     command_text,

                     req.command,

                     session.login_name,

                     session.host_name,

                     session.program_name,

                     session.last_request_end_time,

                     session.login_time

       FROM   sys.dm_exec_sessions AS session

              JOIN sys.dm_exec_requests AS req

                ON req.session_id = session.session_id

              CROSS apply sys.Dm_exec_sql_text(req.sql_handle) AS sqltext

       WHERE  req.session_id != @@SPID

       ORDER  BY req.cpu_time DESC


       DECLARE @HTMLString NVARCHAR(max)

       DECLARE @SUBJECT VARCHAR(max) = 'High CPU Alert on: ' + @@servername + '.'


       SET @HTMLString= '   <H2>Top 10 CPU Intesnive Queries</H2>   <table id="AutoNumber1" borderColor="#111111" border="1">      <tr>     <td bgcolor="#99CC33">session ID</td>     <td bgColor="#99CC33">CPU Time</td>     <td bgcolor="#99CC33">Logical Reads<</b></td>     <td bgcolor="#99CC33">Reads</td>     <td bgcolor="#99CC33">Writes</td>     <td bgcolor="#99CC33">Query Statement</td>     <td bgcolor="#99CC33">Stored Procedure</td>     <td bgcolor="#99CC33">Command</td>     <td bgcolor="#99CC33">Login name</td>     <td bgcolor="#99CC33">hostname</td>     <td bgColor="#99CC33">program_name</td>     <td bgcolor="#99CC33">last_request_end_time</b></td>     <td bgcolor="#99CC33">login_time</td>      </tr>'

                        + Cast((SELECT DISTINCT td = sessionid, ' ', td= cpu_time

                        ,

                        ' ',

                        td = logicalreads, ' ', td = reads, ' ', td = writes, ' '

                        ,

                        td =

                        querystatement, ' ', td = command_text, ' ', td = command

                        ,

                        ' ',

                        td = login_name, ' ', td = hostname, ' ', td=

                        program_name,

                        ' '

                        , td = last_request_end_time, ' ', td = login_time, ' '

                        FROM

                        #tbl_highcpu_query_output WHERE program_name NOT LIKE

                        '%Mail%'

                        FOR xml path('tr'), type) AS NVARCHAR(max))

                        + '</table>'


       SELECT @HTMLString


       -- Send email using sp_send_dbmail  

       EXEC msdb.dbo.Sp_send_dbmail

         @profile_name = 'SQLmail',

         -- Replace with the name of your DbMail profile  

         @recipients = 'sqldbanow@gmail.com',

         @subject = @subject,

         @body = @HTMLString,

         @body_format = 'HTML';

   END 


Configure Alert

Create a database alert, as I explained at the article's beginning. The alert parameters should be as shown in the screenshot below.



When the alert is raised, we want to send the list of CPU-intensive queries. To do that, we must create an SQL Job. I have created a SQL Server Agent job named Populate_High_CPU_Queries. The SQL Job executes the sp_send_HIGHCPU_Alert stored procedure.

In our case, the job step should look like the following image:



Once the SQL job named Populate_High_CPU_Queries is created, you can specify the job name in the response option of the alert. Below is the image of the Response tab for reference.


Sample Email report


Monitoring SQL Server Worker Threads

    Effective performance monitoring in SQL Server includes keeping an eye on worker threads and their utilization. Below is a detailed SQL query that helps you understand the current state of worker threads on your SQL Server instance. 

This query leverages the sys.dm_os_schedulers dynamic management view to provide valuable insights.

Query to Monitor Worker Threads

-- Declare a variable to hold the maximum worker threads count

DECLARE @max INT;

-- Get the maximum number of worker threads

SELECT @max = max_workers_count

FROM sys.dm_os_sys_info;

-- Retrieve current thread utilization statistics

SELECT

    GETDATE() AS 'CurrentDate',

    @max AS 'TotalThreads',

    SUM(active_workers_count) AS 'CurrentThreads',

    @max - SUM(active_workers_count) AS 'AvailableThreads',

    SUM(runnable_tasks_count) AS 'WorkersWaitingForCpu',

    SUM(work_queue_count) AS 'RequestsWaitingForThreads',

    SUM(current_workers_count) AS 'AssociatedWorkers'

FROM sys.dm_os_schedulers

WHERE STATUS = 'VISIBLE ONLINE';

SQL Server Database Capacity Planning

 SQL Server database capacity planning involves estimating the resources and storage requirements necessary to support the expected growth of your database over time. Here are some key considerations and steps to help you with SQL Server database capacity planning:

Data Analysis and Profiling:

Analyze the existing data and understand its characteristics, including the size, growth rate, and usage patterns.

Identify the tables, indexes, and other database objects that contribute to the overall database size.

Profile the workload by capturing and analyzing relevant queries and transactions to determine resource usage patterns.
 
Storage Requirements:

Estimate the size of the database files (data files, transaction log files) based on the current data size and expected growth rate.

Consider factors such as data compression, partitioning, and archiving strategies to optimize storage utilization.

Choose appropriate storage technology (e.g., direct-attached storage, SAN, or cloud storage) based on performance, scalability, and cost considerations.
 
Memory Considerations:

Determine the memory requirements for SQL Server based on the database size, workload, and query complexity.

Allocate sufficient memory for SQL Server's buffer cache, query execution plans, and other caching mechanisms to optimize performance.

Configure the appropriate maximum memory setting to ensure SQL Server does not consume excessive resources on the server.
 
CPU and Processing Power:
Analyze the workload and identify the CPU-intensive queries or processes.
Determine the CPU requirements based on the workload's complexity, concurrency, and expected growth.
Consider factors such as parallelism settings, query optimization, and server hardware capabilities to ensure adequate CPU resources.
 
Network Considerations:

Assess the network bandwidth requirements based on data transfer rates between clients and the SQL Server.

Consider factors such as client connections, data replication, and backup/restore operations that may utilize network resources.
 
Optimize the network configuration and infrastructure to minimize latency and maximize performance.

Scalability and Growth:

Consider the expected growth rate of the database and plan for future scalability.
Implement strategies such as database partitioning, table partitioning, or sharding to distribute data across multiple servers if required.

Regularly monitor database growth and performance to ensure that the capacity planning remains aligned with the actual usage.
 
Monitoring and Maintenance:

Implement a robust monitoring and alerting system to track resource utilization, performance metrics, and storage growth.

Regularly review and analyze monitoring data to identify trends, bottlenecks, and areas for optimization.
Perform routine database maintenance tasks such as index maintenance, statistics updates, and backup integrity checks to optimize performance and storage utilization.

Interview Questions on AOAG in SQL server

1.What are the prerequisites for setting up AlwaysOn?

2.How do you set up replication in AlwaysOn environment?

3.How do you manage replication during Windows patching or failover if replication has been set up in AlwaysOn?

4.How do you sync logins in AlwaysOn?

5.How do you sync users in AlwaysOn secondary?

6.How do you add database files in AlwaysOn?

7.How do you perform an in-place upgrade of SQL Server in a AlwaysOn environment?

8.What is the procedure for SQL Server patching in AlwaysOn?

9.How do you failover a mirror server if replication has been set up?

10.What is the SPN concept in AlwaysOn?

11.What is file share in AlwaysOn?

12.How do you create multiple AlwaysOn listeners?

13.How do you check latency in AlwaysOn?

14.What is the command used to check latency in replication without using GUI?

15.What are DNS issues in AlwaysOn?

16.If a user is connecting to the primary and not able to connect to the secondary, and the secondary is in read-only mode, how do you fix the issue in AlwaysOn?

17.How do you fix if secondary is not in sync?

18.How do you apply TDE in AlwaysOn?

19.How do you add the databases to availability group when encryption is enabled?

20.How to check the health of AlwaysOn?

21.How to resolve if blockings occur in secondary replica due to reporting server?

22.What are the DMVs used to troubleshoot AlwaysOn?

23.How do you set backup priority in AlwaysOn?

24.How do you restore the database which is part of AG ?