Lead
PSP to lekarstwo na „jeden parametr rządzi wszystkimi”. Pokażę Ci demo: trzy przedziały selektywności, trzy plany, zero dramatu.
Setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| USE tempdb;
DROP TABLE IF EXISTS dbo.Sales;
CREATE TABLE dbo.Sales (
Id int IDENTITY primary key,
CustomerId int not null,
Amount money not null,
CreatedAt datetime2 not null,
filler char(200) null
);
CREATE INDEX IX_Sales_CustomerId ON dbo.Sales(CustomerId);
-- Dane z rozkładem Zipfa – część klientów bardzo „ciężka”
WITH n AS (SELECT TOP (1000000) ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS n FROM sys.all_objects a, sys.all_objects b)
INSERT dbo.Sales(CustomerId, Amount, CreatedAt, filler)
SELECT ABS(CHECKSUM(NEWID()))%1000, RAND(CHECKSUM(NEWID()))*100, DATEADD(day, -ABS(CHECKSUM(NEWID()))%365, SYSDATETIME()), NULL FROM n;
|
Włącz PSP (domyślnie ON w nowszych CU):
1
| ALTER DATABASE SCOPED CONFIGURATION SET PARAMETER_SENSITIVE_PLAN_OPTIMIZATION = ON;
|
Test
1
2
3
4
5
6
| CREATE OR ALTER PROC dbo.GetSalesByCustomer @CustomerId int AS
SELECT * FROM dbo.Sales WHERE CustomerId=@CustomerId OPTION (RECOMPILE OFF);
GO
EXEC dbo.GetSalesByCustomer @CustomerId=1; -- rzadki
EXEC dbo.GetSalesByCustomer @CustomerId=500; -- średni
EXEC dbo.GetSalesByCustomer @CustomerId=999; -- „gorący”
|
W Query Store sprawdź: sys.query_store_plan – pojawią się warianty planów na różne „bucket’y” selektywności.
Stabilizacja gdy trzeba
- Hint
OPTIMIZE FOR (@CustomerId UNKNOWN) gdy wolisz plan „robust”. - Plan forcing w Query Store, jeśli regresja po CU.
Co monitorować
- Liczba variant plans na zapytanie.
- Regresje czasu/CPU po deployu.
- Czy PSP nie generuje nadmiaru planów dla zapytań ad‑hoc.
PSP to nie srebrna kula — czasem lepszy jest nowy indeks lub refaktoryzacja filtra.