Azure Database Watcher Series: Generating Sample Workload on SQL Targets in Azure Database Watcher

Welcome to the Azure Database Watcher Series! πŸ‘‹

In our latest YouTube video titled “Azure Database Watcher Series: Generating Sample Workload on SQL Targets in Azure Database Watcher”, we demonstrate how to generate a realistic workload on an Azure SQL Managed Instance β€” a critical step before exploring metrics on the Azure Database Watcher dashboard.

To help you follow along and practice everything shown in the video, we’ve prepared a ZIP file containing all the necessary scripts. These scripts simulate a variety of workloads β€” including read, write, and even blocking scenarios β€” perfect for testing your monitoring setup in Azure.

πŸ“¦ Download the Scripts

Click below to download the sample workload bundle:

πŸ”— Download JB_Database_Watcher_Sample_Workload.zip

The ZIP file includes the following SQL files:

  • Loadtest1.txt – Master script to create required objects for the workload.
  • Loadtest1_q1.txt – Script 1 that simulates workload on the Azure SQL managed instance.
  • Loadtest1_q2.txt – Script 2 that simulates workload on the Azure SQL managed instance.
  • Blocking.txt – Script to check object details.

πŸ’‘ How to Use

  1. Deploy the scripts against an Azure SQL Managed Instance that is being monitored by Azure Database Watcher.
  2. Follow the exact steps as shown in the video.
  3. Generate workloads and wait for metrics to populate.
  4. Get ready for our next video, where we’ll explore the Database Watcher dashboard and deep-dive into the insights gathered.

Thank You,
Vivek Janakiraman

Disclaimer:
The views expressed on this blog are mine alone and do not reflect the views of my company or anyone else. All postings on this blog are provided β€œAS IS” with no warranties, and confers no rights.

SQL Server 2022: Exploring the DATE_BUCKET Function

πŸ•’SQL Server 2022 introduces several new and exciting features, and one of the standout additions is the DATE_BUCKET function. This function allows you to group dates into fixed intervals, making it easier to analyze time-based data. In this blog, we’ll dive into how DATE_BUCKET works, using the JBDB database for our demonstrations. We’ll also explore a business use case to showcase the function’s practical applications.πŸ•’

Business Use Case: Analyzing Customer Orders πŸ“Š

Imagine a retail company, “Retail Insights,” that wants to analyze customer order data to understand purchasing patterns over time. Specifically, the company wants to group orders into weekly intervals to identify trends and peak periods. Using the DATE_BUCKET function, we can efficiently bucketize order dates into weekly intervals and perform various analyses.

Setting Up the JBDB Database

First, let’s set up our sample database and table. We’ll create a database named JBDB and a table Orders to store our order data.

-- Create JBDB Database
CREATE DATABASE JBDB;
GO

-- Use JBDB Database
USE JBDB;
GO

-- Create Orders Table
CREATE TABLE Orders (
    OrderID INT PRIMARY KEY IDENTITY(1,1),
    CustomerID INT,
    OrderDate DATETIME,
    TotalAmount DECIMAL(10, 2)
);
GO

Inserting Sample Data πŸ“¦

Next, we’ll insert some sample data into the Orders table to simulate a few months of order history.

-- Insert Sample Data into Orders Table
INSERT INTO Orders (CustomerID, OrderDate, TotalAmount)
VALUES
(1, '2022-01-05', 250.00),
(2, '2022-01-12', 300.50),
(1, '2022-01-19', 450.00),
(3, '2022-01-25', 500.75),
(4, '2022-02-01', 320.00),
(5, '2022-02-08', 275.00),
(2, '2022-02-15', 150.25),
(3, '2022-02-22', 600.00),
(4, '2022-03-01', 350.00),
(5, '2022-03-08', 425.75);
GO

Using the DATE_BUCKET Function πŸ—“οΈ

The DATE_BUCKET function simplifies the process of grouping dates into fixed intervals. Let’s see how it works by bucketing our orders into weekly intervals.

-- Group Orders into Weekly Intervals Using DATE_BUCKET
SELECT 
    CustomerID,
    OrderDate,
    TotalAmount,
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek
FROM Orders
ORDER BY OrderWeek;
GO

In the above query:

  • WEEK specifies the interval size.
  • 1 is the number of weeks per bucket.
  • OrderDate is the column containing the dates to be bucketed.
  • CAST('2022-01-01' AS datetime) is the reference date from which the intervals are calculated, cast to the datetime type to match OrderDate.

Analyzing Sales Trends πŸ“ˆ

Now that we have our orders grouped into weekly intervals, we can analyze sales trends, such as total sales per week.

-- Calculate Total Sales Per Week
SELECT 
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek,
    SUM(TotalAmount) AS TotalSales
FROM Orders
GROUP BY DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderWeek;
GO

This query helps “Retail Insights” identify peak sales periods and trends over time. For example, they might find that certain weeks have consistently higher sales, prompting them to investigate further.

Grouping by Month

SELECT 
    CustomerID,
    OrderDate,
    TotalAmount,
    DATE_BUCKET(MONTH, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderMonth
FROM Orders
ORDER BY OrderMonth;
GO

Analyzing Orders Per Customer

SELECT 
    CustomerID,
    COUNT(OrderID) AS NumberOfOrders,
    SUM(TotalAmount) AS TotalSpent,
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek
FROM Orders
GROUP BY CustomerID, DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderWeek;
GO

Counting Orders in Each Weekly Interval

This query counts the number of orders placed in each weekly interval.

-- Count Orders in Each Weekly Interval Using DATE_BUCKET
SELECT 
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek,
    COUNT(OrderID) AS NumberOfOrders
FROM Orders
GROUP BY DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderWeek;
GO

Average Order Value per Week

Calculate the average value of orders in each weekly interval.

-- Calculate Average Order Value Per Week
SELECT 
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek,
    AVG(TotalAmount) AS AverageOrderValue
FROM Orders
GROUP BY DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderWeek;
GO

Monthly Sales Analysis

Analyze total sales on a monthly basis.

-- Analyze Monthly Sales Using DATE_BUCKET
SELECT 
    DATE_BUCKET(MONTH, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderMonth,
    SUM(TotalAmount) AS MonthlySales
FROM Orders
GROUP BY DATE_BUCKET(MONTH, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderMonth;
GO

Identifying Peak Ordering Days

Identify the days with the highest total sales using daily buckets.

-- Identify Peak Ordering Days
SELECT 
    DATE_BUCKET(DAY, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderDay,
    SUM(TotalAmount) AS TotalSales
FROM Orders
GROUP BY DATE_BUCKET(DAY, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY TotalSales DESC;
GO

Customer Order Frequency Analysis

Determine the frequency of orders for each customer on a weekly basis.

-- Customer Order Frequency Analysis Using DATE_BUCKET
SELECT 
    CustomerID,
    DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek,
    COUNT(OrderID) AS OrdersPerWeek
FROM Orders
GROUP BY CustomerID, DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY CustomerID, OrderWeek;
GO

Weekly Revenue Growth Rate

Calculate the weekly growth rate in sales revenue.

-- Calculate Weekly Revenue Growth Rate
WITH WeeklySales AS (
    SELECT 
        DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderWeek,
        SUM(TotalAmount) AS WeeklySales
    FROM Orders
    GROUP BY DATE_BUCKET(WEEK, 1, OrderDate, CAST('2022-01-01' AS datetime))
)
SELECT 
    OrderWeek,
    WeeklySales,
    LAG(WeeklySales) OVER (ORDER BY OrderWeek) AS PreviousWeekSales,
    (WeeklySales - LAG(WeeklySales) OVER (ORDER BY OrderWeek)) / LAG(WeeklySales) OVER (ORDER BY OrderWeek) * 100 AS GrowthRate
FROM WeeklySales
ORDER BY OrderWeek;
GO

Orders Distribution Across Quarters

Analyze the distribution of orders across different quarters.

-- Distribution of Orders Across Quarters
SELECT 
    DATE_BUCKET(QUARTER, 1, OrderDate, CAST('2022-01-01' AS datetime)) AS OrderQuarter,
    COUNT(OrderID) AS NumberOfOrders
FROM Orders
GROUP BY DATE_BUCKET(QUARTER, 1, OrderDate, CAST('2022-01-01' AS datetime))
ORDER BY OrderQuarter;
GO

Business Insights πŸ’‘

Using the DATE_BUCKET function, “Retail Insights” can gain valuable insights into customer purchasing patterns:

  1. Identify Peak Periods: By analyzing weekly sales data, the company can pinpoint peak periods and prepare for increased demand.
  2. Marketing Strategies: Understanding customer behavior patterns helps in tailoring marketing strategies, such as promotions during slower periods.
  3. Inventory Management: Forecasting demand based on historical data enables better inventory planning and reduces stockouts or overstock situations.

Conclusion πŸŽ‰

The DATE_BUCKET function in SQL Server 2022 is a powerful tool for time-based data analysis. It simplifies the process of grouping dates into intervals, making it easier to extract meaningful insights from your data. Whether you’re analyzing sales trends, customer behavior, or other time-sensitive information, DATE_BUCKET can help streamline your workflow and improve decision-making.

Feel free to try these examples in your own environment and explore the potential of DATE_BUCKET in your data analysis tasks! Happy querying! πŸš€

For more tutorials and tips on SQL Server, including performance tuning and database management, be sure to check out our JBSWiki YouTube channel.

Thank You,
Vivek Janakiraman

Disclaimer:
The views expressed on this blog are mine alone and do not reflect the views of my company or anyone else. All postings on this blog are provided β€œAS IS” with no warranties, and confers no rights.

Unleashing SQL Server 2022: Enhancements to sys.dm_exec_query_statistics_xml

In the world of data management and analysis, SQL Server 2022 has brought numerous improvements and enhancements, one of the most notable being the advancements to the dynamic management view (DMV) sys.dm_exec_query_statistics_xml. This DMV provides detailed runtime statistics about query execution, which is invaluable for performance tuning and query optimization.

In this blog, we will explore the enhancements to sys.dm_exec_query_statistics_xml in SQL Server 2022 using the JBDB database. We’ll walk through a comprehensive business use case, demonstrate these enhancements with T-SQL queries, and show how these can be leveraged for better performance insights.

Business Use Case: Optimizing an E-commerce Database πŸ›’

Imagine you are a database administrator for JBDB, an e-commerce platform with millions of users and transactions. Ensuring optimal query performance is crucial for providing a seamless user experience. You need to monitor query performance, identify slow-running queries, and understand execution patterns to make informed optimization decisions.

The JBDB Database Schema

For this demo, we’ll use a simplified version of the JBDB database with the following schema:

  • Customers: Stores customer information.
  • Orders: Stores order details.
  • OrderItems: Stores items within an order.
  • Products: Stores product details.

CREATE TABLE Customers (
    CustomerID INT PRIMARY KEY,
    Name NVARCHAR(100),
    Email NVARCHAR(100),
    CreatedAt DATETIME
);

CREATE TABLE Products (
    ProductID INT PRIMARY KEY,
    ProductName NVARCHAR(100),
    Price DECIMAL(10, 2),
    Stock INT
);

CREATE TABLE Orders (
    OrderID INT PRIMARY KEY,
    CustomerID INT FOREIGN KEY REFERENCES Customers(CustomerID),
    OrderDate DATETIME
);

CREATE TABLE OrderItems (
    OrderItemID INT PRIMARY KEY,
    OrderID INT FOREIGN KEY REFERENCES Orders(OrderID),
    ProductID INT FOREIGN KEY REFERENCES Products(ProductID),
    Quantity INT,
    Price DECIMAL(10, 2)
);
INSERT INTO Customers (CustomerID, Name, Email, CreatedAt)
VALUES 
(1, 'John Doe', 'john.doe@example.com', '2023-01-10'),
(2, 'Jane Smith', 'jane.smith@example.com', '2023-02-15'),
(3, 'Emily Johnson', 'emily.johnson@example.com', '2023-03-22'),
(4, 'Michael Brown', 'michael.brown@example.com', '2023-04-05'),
(5, 'Sarah Davis', 'sarah.davis@example.com', '2023-05-30');


INSERT INTO Products (ProductID, ProductName, Price, Stock)
VALUES 
(1, 'Laptop', 999.99, 50),
(2, 'Smartphone', 499.99, 150),
(3, 'Tablet', 299.99, 75),
(4, 'Headphones', 149.99, 200),
(5, 'Smartwatch', 199.99, 100);

INSERT INTO Orders (OrderID, CustomerID, OrderDate)
VALUES 
(1, 1, '2023-06-15'),
(2, 2, '2023-07-20'),
(3, 3, '2023-08-25'),
(4, 4, '2023-09-10'),
(5, 5, '2023-10-05');

INSERT INTO OrderItems (OrderItemID, OrderID, ProductID, Quantity, Price)
VALUES 
(1, 1, 1, 1, 999.99),
(2, 1, 4, 2, 149.99),
(3, 2, 2, 1, 499.99),
(4, 2, 5, 1, 199.99),
(5, 3, 3, 2, 299.99),
(6, 4, 1, 1, 999.99),
(7, 4, 2, 1, 499.99),
(8, 5, 5, 2, 199.99),
(9, 5, 3, 1, 299.99);

Enhancements to sys.dm_exec_query_statistics_xml πŸ†•

SQL Server 2022 introduces several key enhancements to sys.dm_exec_query_statistics_xml, including:

  1. Enhanced Plan Information: More detailed execution plan information is now available.
  2. Wait Statistics: Comprehensive wait statistics are included to identify bottlenecks.
  3. Query Store Integration: Better integration with the Query Store for historical analysis.

Demonstrating Enhancements with T-SQL Queries πŸ“Š

Let’s dive into some T-SQL queries to see these enhancements in action.

Step 1: Capture a Sample Query Execution

First, we’ll execute a sample query to fetch order details along with customer and product information.

SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price
FROM
Orders o
JOIN
Customers c ON o.CustomerID = c.CustomerID
JOIN
OrderItems oi ON o.OrderID = oi.OrderID
JOIN
Products p ON oi.ProductID = p.ProductID
WHERE
o.OrderDate BETWEEN '2023-01-01' AND '2023-12-31';

Step 2: Retrieve Query Statistics XML

Next, we’ll use sys.dm_exec_query_statistics_xml to retrieve detailed execution statistics for the above query.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT
qst.sql_handle,
qst.plan_handle,
qst.execution_count,
qst.total_worker_time,
qst.total_elapsed_time,
qst.total_logical_reads,
qst.total_physical_reads,
qst.creation_time,
qst.last_execution_time,
q.text AS query_text,
qpx.query_plan
FROM
sys.dm_exec_query_stats AS qst
CROSS APPLY
sys.dm_exec_sql_text(qst.sql_handle) AS q
CROSS APPLY
sys.dm_exec_query_plan(qst.plan_handle) AS qpx
WHERE
q.text LIKE '%SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price%';

Step 3: Analyzing Enhanced Plan Information πŸ”

With SQL Server 2022, the execution plan XML now includes more detailed information about the query execution. You can parse the XML to extract specific details.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT 
    query_plan.value('(//RelOp/LogicalOp)[1]', 'NVARCHAR(100)') AS LogicalOperation,
    query_plan.value('(//RelOp/PhysicalOp)[1]', 'NVARCHAR(100)') AS PhysicalOperation,
    query_plan.value('(//RelOp/RunTimeInformation/RunTimeCountersPerThread/ActualRows)[1]', 'INT') AS ActualRows,
    query_plan.value('(//RelOp/RunTimeInformation/RunTimeCountersPerThread/ActualEndOfScans)[1]', 'INT') AS ActualEndOfScans
FROM 
    (SELECT CAST(qpx.query_plan AS XML) AS query_plan
     FROM sys.dm_exec_query_stats qs
     CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qpx
     WHERE qs.sql_handle = (SELECT sql_handle FROM sys.dm_exec_requests WHERE session_id = @@SPID)) AS x;

Step 4: Monitoring Wait Statistics ⏱️

Wait statistics help identify performance bottlenecks such as CPU, IO, or memory waits. SQL Server 2022 provides enhanced wait statistics in the query execution plans.

WITH XMLNAMESPACES (DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT 
    wait_type,
    wait_time_ms AS total_wait_time_ms,
    wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms,
    signal_wait_time_ms
FROM 
    sys.dm_exec_session_wait_stats
WHERE 
    session_id = @@SPID;

Leveraging Query Store Integration πŸ“ˆ

SQL Server 2022’s improved integration with the Query Store allows for historical query performance analysis, helping you understand performance trends and regressions.

SELECT 
    qsp.plan_id,
    qsp.query_id,
    qsqt.query_sql_text AS query_text,
    qsrs.count_executions AS execution_count,
    qsrs.avg_duration,
    qsrs.avg_cpu_time,
    qsrs.avg_logical_io_reads
FROM 
    sys.query_store_runtime_stats qsrs
JOIN 
    sys.query_store_plan qsp ON qsrs.plan_id = qsp.plan_id
JOIN 
    sys.query_store_query qsq ON qsp.query_id = qsq.query_id
JOIN 
    sys.query_store_query_text qsqt ON qsq.query_text_id = qsqt.query_text_id
WHERE 
    qsqt.query_sql_text LIKE '%SELECT o.OrderID, o.OrderDate, c.Name AS CustomerName, p.ProductName, oi.Quantity, oi.Price%';

Conclusion πŸŽ‰

The enhancements to sys.dm_exec_query_statistics_xml in SQL Server 2022 provide deeper insights into query performance, making it easier to identify and resolve performance issues. By leveraging these new capabilities, database administrators can ensure their SQL Server instances run more efficiently and effectively.

Feel free to experiment with the queries provided and explore the powerful new features SQL Server 2022 has to offer. Happy querying! πŸ§‘β€πŸ’»