Fix various places in PerfStatsAnalysis.sql - minor issues#489
Fix various places in PerfStatsAnalysis.sql - minor issues#489
Conversation
There was a problem hiding this comment.
Pull request overview
This PR applies a set of small correctness and robustness fixes to PerfStatsAnalysis.sql, primarily around wait stats calculations and a few stored-procedure logic issues.
Changes:
- Harden wait stats outputs (e.g., clamp negative wait deltas; exclude zero/negative waits from “top” category selection; use
BIGINTfor available CPU seconds). - Fix query logic issues (e.g., correct boolean grouping in blocking-chain time filtering; fix cursor loop condition).
- Prevent runtime errors / logic inversions (e.g.,
NULLIFto avoid divide-by-zero; correctCOL_LENGTHnull check; remove stray debugSELECT).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/microsoft/SqlNexus/sessions/4bf32a8d-734c-42b4-98c1-d14f2f6ad6e8 Co-authored-by: PiJoCoder <23519517+PiJoCoder@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/SqlNexus/sessions/20c9b77f-b44d-41f2-8830-d9fcd5ddc2e5 Co-authored-by: PiJoCoder <23519517+PiJoCoder@users.noreply.github.com>
Applied in commit 9e57bde — updated the |
|
@copilot: can you summarize and update the description in the PR of all the changes/commits in this PR |
Updated the PR description with a full summary of all changes across the three commits. Here's the breakdown: Wait stats hardening
Query logic fixes
Runtime error / logic-inversion fixes
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
hacitandogan
left a comment
There was a problem hiding this comment.
PerfStatsAnalysis.sql hash needs to be updated;
{ Application.StartupPath + "\" + "PerfStatsAnalysis.sql", "37111E6F2052A2A7B15E26329475738B4E543FE66AFB7BA426639C062D9E81A1" }, vs { "PerfStatsAnalysis.sql", "841466E4E5F7AB980BB6492D3AEB636C4E55749107DCF391A585601B6263A5E5" },
I am not sending a modification so we don’t end up with the same approver / modifier loop as before, we can check this together in the call.
DataSet_WaitStats_WaitStatsTopCategories does not exists , is it DataSet_WaitStats_WaitStatsTopCategoriesOther or DataSet_WaitStats_WaitStatsTop5Categories
DataSet_WaitStats_WaitStatsTop5Categories has <= 0 check but DataSet_WaitStats_WaitStatsTopCategoriesOther does not, I believe we may need the same check there as well.
Other modifications looks good.
This PR applies a set of small correctness and robustness fixes to
PerfStatsAnalysis.sql, primarily around wait stats calculations and a few stored-procedure logic issues.Changes:
BIGINTfor available CPU seconds).NULLIFto avoid divide-by-zero; correctCOL_LENGTHnull check; remove stray debugSELECT).Test Case Plan — PR: Fix Various Issues in PerfStatsAnalysis.sql
Prerequisites
PerfStatsAnalysis.sqlagainst the target database before executing any test case.Test Case 1 —
wait_time_ms_per_secclamped to 0 on counter rolloverFix: Negative
wait_time_ms_per_secvalues (e.g. after a SQL Server restart mid-collection) are now returned as0.Steps:
w_end.wait_time_ms < w_start.wait_time_msfor at least one wait category.DataSet_WaitStats_WaitStatsTopCategoriesOtherfor that time range.Expected result:
wait_time_ms_per_sec=0for the affected category — not a negative value.Test Case 2 — No divide-by-zero when
@StartTimeequals@EndTimeFix:
NULLIF(DATEDIFF(s, @StartTime, @EndTime) + 1, 0)prevents a divide-by-zero when the interval is zero seconds.Steps:
Execute either stored proc below with identical start and end timestamps:
Expected result: Both queries complete without error;
wait_time_ms_per_secreturnsNULLor0.Test Case 3 — No integer overflow for
@avail_cpu_time_secon high-CPU systemsFix:
@avail_cpu_time_secwidened fromINTtoBIGINT.Steps:
Set a high CPU count in the server properties table:
Execute either wait stats proc with a long collection window (e.g. 50,000+ seconds).
Expected result: CPU seconds are calculated correctly with no arithmetic overflow error.
Test Case 4 — Top-5 wait categories excludes zero-wait entries and
SOS_SCHEDULER_YIELDFix: The subquery alias collision (
cat→cat2) is resolved, zero-wait rows are filtered out, andSOS_SCHEDULER_YIELDis explicitly excluded from the Top 5 exclusion list.Steps:
SOS_SCHEDULER_YIELDhas the highestwait_time_ms_per_secin the dataset.wait_time_ms_per_sec = 0andtotal_wait_time_ms = 0.DataSet_WaitStats_WaitStatsTopCategoriesOther.Expected result:
SOS_SCHEDULER_YIELDis not in the Top 5 exclusion list and appears in the "Other" results.Test Case 5 — Blocking chains correctly filtered by time window boundary
Fix: Missing parentheses around the
ORcondition caused incorrectAND/ORprecedence in theWHEREclause.Steps:
vw_BLOCKING_CHAINS(or its source) where:blocking_startis before@StartTime, andblocking_endfalls within@StartTimeand@EndTime.DataSet_WaitStats_BlockingChainsExpected result: The blocking event is returned. Confirm that events entirely outside the window are not returned.
Test Case 6 — Cursor loop processes all blocking rows
Fix:
WHILE (@@FETCH_STATUS <> -1)corrected toWHILE (@@FETCH_STATUS = 0)so the loop stops on any non-success status.Steps:
vw_BLOCKING_CHAINShas 3 or more rows within the selected time range.@txtoutblocking summary string.Expected result: All rows are represented in the output string — no rows are skipped or duplicated.
Test Case 7 — No divide-by-zero for zero-rowtables in stats properties
Fix:
NULLIF([rows], 0)prevents divide-by-zero inusp_SmallSampledStats.Steps:
Insert a test row:
Execute
usp_SmallSampledStats.Expected result: Proc completes without a divide-by-zero error. The zero-row entry is handled gracefully.
Test Case 8 — Query plan file lookup executes when
xml_plancolumn existsFix: Condition was inverted (
IS NULL→IS NOT NULL), causing the lookup to be skipped when the column was present.Steps:
PerfStatsAnalysis.sql.Expected result: The
@FileNamevariable is populated and the query plan lookupblock executes. Previously it was silently skipped.Test Case 9 — Script is idempotent (safe to re-run)
Fix: Added
DROP PROC IF EXISTSguard beforeCREATE PROC DataSet_WaitStats_WaitStatsTopCategoriesOther.Steps:
PerfStatsAnalysis.sqlagainst the target database.PerfStatsAnalysis.sqla second time without dropping any objects.Expected result: The script completes successfully on both runs with no "object already exists" error.
Pass Criteria
All 9 test cases must produce their expected results with no SQL errors, no incorrect data silently returned, and no arithmetic overflow or divide-by-zero exceptions.