Skip to content

Commit

Permalink
Update instructions for psp demo and show new query store DMVs
Browse files Browse the repository at this point in the history
  • Loading branch information
rgward committed Jun 24, 2022
1 parent 4b00070 commit 41eaa71
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 29 deletions.
45 changes: 34 additions & 11 deletions demos/sqlserver2022/IQP/psp/populatedata.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ USE WideWorldImporters;
GO
-- Add StockItems to cause a data skew in Suppliers
--
DECLARE @StockItemID int;
DECLARE @StockItemName varchar(100);
DECLARE @SupplierID int;
SELECT @StockItemID = 228;
SET @StockItemName = 'Dallas Cowboys Shirt'+convert(varchar(10), @StockItemID);
SET @SupplierID = 4;
DELETE FROM Warehouse.StockItems WHERE StockItemID >= @StockItemID;
SET NOCOUNT ON;
BEGIN TRANSACTION;
DECLARE @StockItemID int
DECLARE @StockItemName varchar(100)
DECLARE @SupplierID int
SELECT @StockItemID = 228
SET @StockItemName = 'Dallas Cowboys Shirt'+convert(varchar(10), @StockItemID)
SET @SupplierID = 4
DELETE FROM Warehouse.StockItems WHERE StockItemID >= @StockItemID
SET NOCOUNT ON
BEGIN TRANSACTION
WHILE @StockItemID <= 4000000
BEGIN
INSERT INTO Warehouse.StockItems
Expand All @@ -19,7 +19,30 @@ QuantityPerOuter, IsChillerStock, TaxRate, UnitPrice, TypicalWeightPerUnit, Last
)
VALUES (@StockItemID, @StockItemName, @SupplierID, 10, 9, 12, 100, 0, 15.00, 100.00, 0.300, 1)
SET @StockItemID = @StockItemID + 1
SET @StockItemName = 'Dallas Cowboys Shirt'+convert(varchar(10), @StockItemID);
SET @StockItemName = 'Dallas Cowboys Shirt'+convert(varchar(10), @StockItemID)
END
COMMIT TRANSACTION;
COMMIT TRANSACTION
SET NOCOUNT OFF
GO
DECLARE @StockItemID int
DECLARE @StockItemName varchar(100)
DECLARE @SupplierID int
SELECT @StockItemID = 4000001
SET @StockItemName = 'Dallas Cowboys Mug'+convert(varchar(10), @StockItemID)
SET @SupplierID = 5
DELETE FROM Warehouse.StockItems WHERE StockItemID >= @StockItemID
SET NOCOUNT ON
BEGIN TRANSACTION
WHILE @StockItemID <= 8000000
BEGIN
INSERT INTO Warehouse.StockItems
(StockItemID, StockItemName, SupplierID, UnitPackageID, OuterPackageID, LeadTimeDays,
QuantityPerOuter, IsChillerStock, TaxRate, UnitPrice, TypicalWeightPerUnit, LastEditedBy
)
VALUES (@StockItemID, @StockItemName, @SupplierID, 10, 9, 12, 100, 0, 15.00, 100.00, 0.300, 1)
SET @StockItemID = @StockItemID + 1
SET @StockItemName = 'Dallas Cowboys Mug'+convert(varchar(10), @StockItemID)
END
COMMIT TRANSACTION
SET NOCOUNT OFF
GO
34 changes: 29 additions & 5 deletions demos/sqlserver2022/IQP/psp/query_store_dmvs.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
USE WideWorldImporters;
GO
SELECT * FROM sys.query_store_query_text;
-- Look at the queries and plans for variants
-- Notice each query is from the same parent_query_id and the query_hash is the same
SELECT qt.query_sql_text, qq.query_id, qv.query_variant_query_id, qv.parent_query_id,
qq.query_hash,qr.count_executions, qp.plan_id, qv.dispatcher_plan_id, qp.query_plan_hash,
cast(qp.query_plan as XML) as xml_plan
FROM sys.query_store_query_text qt
JOIN sys.query_store_query qq
ON qt.query_text_id = qq.query_text_id
JOIN sys.query_store_plan qp
ON qq.query_id = qp.query_id
JOIN sys.query_store_query_variant qv
ON qq.query_id = qv.query_variant_query_id
JOIN sys.query_store_runtime_stats qr
ON qp.plan_id = qr.plan_id
ORDER BY qv.parent_query_id
GO
SELECT * FROM sys.query_store_query;
-- Look at the "parent" query
-- Notice this is the SELECT statement from the procedure with no OPTION for variants.
SELECT qt.query_sql_text
FROM sys.query_store_query_text qt
JOIN sys.query_store_query qq
ON qt.query_text_id = qq.query_text_id
JOIN sys.query_store_query_variant qv
ON qq.query_id = qv.parent_query_id
GO
SELECT * FROM sys.query_store_plan;
-- Look at the dispatcher plan
-- If you "click" on the SHOWPLAN XML output you will see a "multiple plans" operator
SELECT qp.plan_id, qp.query_plan_hash, cast (qp.query_plan as XML)
FROM sys.query_store_plan qp
JOIN sys.query_store_query_variant qv
ON qp.plan_id = qv.dispatcher_plan_id
GO
SELECT * FROM sys.query_store_query_variant;
GO
30 changes: 17 additions & 13 deletions demos/sqlserver2022/IQP/psp/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,48 @@ Here are the steps to demonstrate the new PSP optimization feature for SQL Serve

## Prerequisites

- VM with at least 4 CPUs and 4 Gb RAM
- VM or computer with at min 2 CPUs and 8Gb RAM.

**Note**: Some of the timings from this exercise may differ if you use a VM or computer with more resources than the minimum.

- SQL Server 2022 CTP 2.0
- SQL Server Management Studio (SSMS) Version 19 Preview
- Download ostress.exe from https://www.microsoft.com/en-us/download/details.aspx?id=103126

**Note**: All command scripts assume windows authentication for currently logged in user and a local server.

Follow these steps to demonstrate Parameter Sensitive Plan (PSP) optimization

## Setup the demo

1. Create a directory called **c:\sql_sample_databases** to store backups and files.
1. Copy WideWorldImporters from https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak (the restore script assumes c:\sql_sample_databases)
1. Copy a backup of WideWorldImporters from https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak (the restore script assumes c:\sql_sample_databases)
1. Restore the WideWorldImporters backup. You can edit and use the **restorewwi.sql** script.
1. Load and execute the **populatedata.sql** script to load more data into the Warehouse.StockItems table. This script will take 5 mins to run
1. Rebuild an index associated with the table with **rebuild_index.sql**
1. Execute the **populatedata.sql** script to load more data into the Warehouse.StockItems table. This script will take ~5-6 mins to run.
1. Rebuild an index associated with the table using the script **rebuild_index.sql**
1. Create a new procedure to be used for the workload test using **proc.sql**.
1. Edit your servername in **sqlsetup.cmd** and execute the script from a command prompt. This will ensure the WideWorldImporters database is at dbcompat 150 and clear the query store.
1. Execute the script **sqlsetup.cmd** from a command prompt. This will ensure the WideWorldImporters database is at dbcompat 150 and clear the query store.

## See a PSP problem for a single query execution.

7. Set the actual execution plan option in SSMS. Run **query_plan_seek.sql** in a query window in SSMS. Note the query time is fast and the values from SET STATISTICS TIME is around 20ms. Note the query plan uses an Index Seek.
7. Set the actual execution plan option in SSMS. Run **query_plan_seek.sql** **twice** in a query window in SSMS. Note the query execution time is fast (< 1 second). Check the timings from SET STATISTICS TIME ON from the second execution. The query is run twice so the 2nd execution will not require a compile. This is the time we want to compare. Note the query plan uses an Index Seek.
8. In a different query window set the actual execution option in SSMS. Run **query_plan_scan.sql** in a query windows in SSMS. Note the query plan uses an Clustered Index Scan and parallelism.
9. Now go back and run **query_plan_seek.sql** again. Note the timing from SET STATISTICS IO is now ~250ms. Ten times slower but a single execution seems fast.
9. Now go back and run **query_plan_seek.sql** again. Note that even though the query executes quickly (< 1 sec), the timing from SET STATISTICS TIME is significantly longer than the previous execution. Also note the query plan also uses a clustered index scan and parallelism.

## See a workload problem for PSP

10. Setup perfmon to capture % processor time and batch requests/second.
11. Edit the scripts **workload_index_scan.cmd** and **workload_index_seek.cmd** for your servername.
13. Run **workload_index_seek.cmd** from the command prompt. This should complete in a few seconds. Observe perfmon counters.
14. Run **workload_index_scan.cmd**. This should take longer but now locks into cache a plan for a scan.
15. Run **workload_index_seek.cmd** again. Observe perfmon counters. Notice much higher CPU and much lower batch requests/sec.
15. Run **workload_index_seek.cmd** again. Observe perfmon counters. Notice much higher CPU and much lower batch requests/sec. Also note the workload doesn't finish in a few seconds as before.
16. Hit <Ctrl>+<C> in the command window for **workload_index_seek.cmd** as it can take minutes to complete.
17. Use the query **suppliercount.sql** to see the skew in supplierID values in the table. This explains why "one size does not fit all" for the stored procedure based on parameter values.
17. Use the script **suppliercount.sql** to see the skew in supplierID values in the table. This explains why "one size does not fit all" for the stored procedure based on parameter values.

## Solve the problem in SQL Server 2022

17. Let's get this workload much faster using PSP optimization. Execute the T-SQL script **dbcompat160.sql** with SSMS.
17. Let's get this workload to run much faster and consistently using PSP optimization. Execute the T-SQL script **dbcompat160.sql** with SSMS.
18. Run **workload_index_seek.cmd** again. Should finish in a few seconds.
19. Run **workload_index_scan.cmd** again.
20. Run **workload_index_seek.cmd** again and see that it now finish again in a few seconds. Observe perfmon counters and see consistent performance.
21. Run Top Resource Consuming Queries report and see that there are two plans for the same stored procedure
20. Run **workload_index_seek.cmd** again and see that it now finishes again in a few seconds. Observe perfmon counters and see consistent performance.
21. Run Top Resource Consuming Queries report from SSMS and see that there are two plans for the same stored procedure. The one difference is that there is new OPTION applied to the query for each procedure which is why there are two different "queries" in the Query Store.
22. It looks like are "two" queries but these are two query "variants". Use the script **query_store_dmvs.sql** to see the details.

0 comments on commit 41eaa71

Please sign in to comment.