sqlmemory-review — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sqlmemory-review (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Analyze SQL Server memory state and identify the root cause of memory pressure. Applies 20 checks (O1–O20) across four categories:
Accept any of:
sys.dm_os_memory_clerks capture query below (paste the result grid)sys.dm_os_ring_buffers WHERE ring_buffer_type = N'RING_BUFFER_RESOURCE_MONITOR' — memory pressure notifications (also accept RING_BUFFER_OOM records for out-of-memory events)sys.dm_exec_query_memory_grants for current grant queue statesys.dm_os_performance_counters or SSMS Activity Monitorsys.dm_os_sys_memory for OS-level memory state-- 1. Memory clerks — top consumers (paste top 20+ rows)
SELECT TOP 20
type,
name,
memory_node_id,
pages_kb,
virtual_memory_reserved_kb,
virtual_memory_committed_kb,
awe_allocated_kb,
shared_memory_reserved_kb,
shared_memory_committed_kb
FROM sys.dm_os_memory_clerks
ORDER BY pages_kb DESC;
-- 2. Page Life Expectancy (PLE)
SELECT object_name, counter_name, instance_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE object_name LIKE '%Buffer Manager%'
AND counter_name = 'Page life expectancy';
-- 3. Plan cache single-use waste
SELECT
SUM(CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) / 1048576 AS single_use_mb,
SUM(size_in_bytes) / 1048576 AS total_plan_cache_mb,
COUNT(*) AS total_plans,
SUM(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS single_use_plans
FROM sys.dm_exec_cached_plans
WHERE objtype IN ('Adhoc', 'Prepared');
-- 4. Memory grant queue (current requests waiting)
SELECT
session_id,
request_id,
scheduler_id,
grant_time,
requested_memory_kb,
granted_memory_kb,
required_memory_kb,
used_memory_kb,
max_used_memory_kb,
query_cost,
timeout_sec,
resource_semaphore_id,
wait_order,
is_next_candidate
FROM sys.dm_exec_query_memory_grants
ORDER BY wait_order;
-- 5. OS memory state
SELECT
total_physical_memory_kb,
available_physical_memory_kb,
total_page_file_kb,
available_page_file_kb,
system_memory_state_desc
FROM sys.dm_os_sys_memory;| Metric | Info | Warning | Critical |
|---|---|---|---|
| PLE (single NUMA node) | ≥ scaled floor (GB/4)×300 | < scaled floor | < 25% of floor (or < 60 s) |
| PLE (multi-NUMA, per node) | ≥ scaled floor (GB/4)×300 | < scaled floor | < 25% of floor (or < 60 s) |
| PLE decline rate (trend) | < 10 s/min | ≥ 10 s/min | ≥ 60 s/min |
| Single-use plan cache as % of total plan cache | < 30% | ≥ 30% | ≥ 60% |
| RESOURCE_SEMAPHORE wait (from sqlwait-review) | 0 sessions | 1–5 queued | > 5 queued |
| Memory grant timeout | 0 | Any | — |
| Stolen memory (non-buffer) as % of target | < 15% | ≥ 15% | ≥ 30% |
| Buffer pool: one DB as % of pool | < 60% | ≥ 60% | ≥ 80% |
| ColumnStore pool (COLUMNSTORE_OBJECT_POOL) | — | > 25% | > 50% |
| In-Memory OLTP (XTP) memory | — | > 25% | > 50% |
Threshold provenance: O1 (PLE, scaled by buffer pool) and O10 (hit-ratio direction) are grounded in Microsoft Learn. The remaining cutoffs — O2–O9, O11, and O13 (single-use plan %, RESOURCE_SEMAPHORE queue depth, stolen-memory %, buffer-pool concentration, ColumnStore/XTP pool %, grant timeout/decline rates) — are reasonable operational heuristics, not Microsoft-documented values. Treat them as starting points and calibrate to your workload's baseline; a value crossing a line is a prompt to investigate, not proof of a problem.
Run these first to determine if SQL Server is under immediate memory pressure.
Page life expectancy cntr_value in sys.dm_os_performance_counters (object Buffer Manager, or per-node Buffer Node) below a buffer-pool-scaled floor — roughly (buffer pool GB / 4) × 300 seconds (so ~9,600 s on a 128 GB pool), or a sudden/sustained dip (see O2). Microsoft does not endorse a fixed value: per MS Learn, "a higher, growing value is best; a sudden dip indicates a significant churn." Use 300 s only as an absolute floor on small (≤4 GB) pools./sqltrace-review to identify full-scan workloads; (3) check if total committed memory is near Max Server Memory — run O20 to verify the setting./sqltrace-review or Query Store. Common causes: a newly deployed query causing a large table scan, a growing database whose working set no longer fits in memory, or a maintenance job (REBUILD, DBCC CHECKDB) running without WITH TABLOCK / WITH PHYSICAL_ONLY limits.Buffer Node PLE counters are present (multi-NUMA system), any node's PLE is < 50% of the maximum node PLEsys.dm_os_nodes for memory allocation per node. Consider soft-NUMA if physical NUMA is unavailable.sys.dm_os_buffer_descriptors grouped by database_id)pages_kb ≥ 15% of committed_target_kb from sys.dm_os_sys_infooptimize for ad hoc workloads (sp_configure 'optimize for ad hoc workloads', 1) to store only a stub on first execution, saving the full plan allocation until the query runs a second time. Longer term, parameterize application queries or use sp_executesql with parameters.SQL Compilations/sec or SQL Re-Compilations/sec from sys.dm_os_performance_counters > 500/secWITH RECOMPILE hints on hot paths, DDL/statistics changes triggering recompiles, or SET option changes per connection. Run /tsql-review on the top offending query text to check for recompile hints.sys.dm_exec_cached_plans has size_in_bytes > 10 MBOBJECTSTORE_LOCK_MANAGER clerk in sys.dm_os_memory_clerks has pages_kb > 100,000 KB (100 MB)sys.dm_tran_locks for escalation events; (3) long-running transactions holding many locks — pair with /sqlwait-review for LCK_ wait analysis.Plan Cache : Cache Hit Ratio counter can corroborate, but treat a threshold on it as a heuristic only — MS Learn documents "90 or higher is desirable" for the Buffer Cache Hit Ratio (Buffer Manager object), not for Plan Cache Hit Ratio, which is just "the ratio between cache hits and lookups for plans" with no documented healthy floor and is often misleadingly near 100% even under ad-hoc bloat.SQL Statistics : SQL Compilations/sec vs Re-Compilations/sec — rather than the Plan Cache Hit Ratio counter alone. Enabling optimize for ad hoc workloads is the first mitigation; review parameterization next. (If you want a documented hit-ratio health check, use Buffer Cache Hit Ratio ≥ 90% from the Buffer Manager object.)sys.dm_exec_query_memory_grants has any row where grant_time IS NULL (query waiting for a grant) — i.e., wait_order > 0granted_memory_kb) and consider OPTION (MAXDOP 1) or OPTION (MAX_GRANT_PERCENT = 10) as emergency mitigations. Long-term: add indexes to eliminate hash operations; increase Max Server Memory if available physical memory allows (O20).timeout_sec in sys.dm_exec_query_memory_grants is the configured time-out before the query gives up its grant request, not an indicator that a timeout occurredOPTION (MIN_GRANT_PERCENT = 1) to the offending query. Root cause: the query's estimated row count is drastically wrong, causing an oversized grant estimate — run /sqlplan-review to check N21 (cardinality estimate accuracy) and /sqlstats-review for stale statistics.granted_memory_kb > 25% of max_memory_grant for the resource pool, OR max_used_memory_kb / granted_memory_kb < 0.25 (granted 4× more than actually used)/sqlplan-review on this query and look for N21 (row count estimate mismatch). Fix statistics with UPDATE STATISTICS ... WITH FULLSCAN.sys.dm_resource_governor_resource_pools shows a user pool with max_memory_percent = 100 or min_memory_percent = 0 when multiple pools are in usemin_memory_percent and max_memory_percent on high-priority pools (OLTP) to protect them from being crowded out by reporting workloads. Use ALTER RESOURCE POOL + ALTER RESOURCE GOVERNOR RECONFIGURE.sys.dm_os_buffer_pool_extension_configuration shows state = 5 (BUFFER POOL EXTENSION ENABLED)CACHESTORE_COLUMNSTOREOBJECTPOOL clerk in sys.dm_os_memory_clerks has pages_kb > 25% of committed_target_kb/tsql-review to check for unnecessary column store usage (T-series checks for ColumnStore on low-cardinality tables).MEMORYCLERK_XTP clerk has pages_kb > 25% of committed_target_kbMIN_MEMORY_PERCENT/MAX_MEMORY_PERCENT set, using sp_xtp_bind_db_resource_pool (database must go offline/online for the binding to take effect). If XTP memory is growing, check: sys.dm_db_xtp_memory_consumers for the largest consumers; whether durable in-memory tables have an appropriate checkpoint file footprint; whether non-durable (SCHEMA_ONLY) in-memory tables are accumulating rows that are never cleaned up.sys.dm_os_ring_buffers WHERE ring_buffer_type = N'RING_BUFFER_RESOURCE_MONITOR' contains records with RESOURCE_MEMPHYSICAL_LOW or RESOURCE_MEMVIRTUAL_LOW notifications in the last 24 hourssys.dm_os_memory_clerks for unexpected non-buffer growth. Set Max Server Memory to leave at least 4–10% or 4 GB (whichever is larger) for the OS.sys.dm_os_sys_info.sql_memory_model_desc = 'CONVENTIONAL' (LPIM not enabled on a large-memory server)sys.dm_os_sys_memory shows available memory. On servers with > 32 GB RAM running under memory pressure, enable LPIM via Group Policy (Lock Pages in Memory user right for the SQL Server service account). LPIM prevents OS paging but does not protect against OOM — Max Server Memory must still be set correctly (O20).sys.configurations WHERE name = 'max server memory (MB)' has value_in_use = 2147483647 (the default unlimited value)Total RAM − OS overhead (4–10%) − SSAS/SSRS/SSIS if co-located − 1 GB per 4 GB RAM for non-buffer memory. Use sp_configure 'max server memory (MB)', <calculated value>; RECONFIGURE. Then verify LPIM is enabled (O19) on large-memory servers.Present findings in this order:
| Check | Severity | Metric | Finding | Fix |
|---|---|---|---|---|
| O1 | Critical | PLE = 45 s | Well below 300 s threshold; dropping 3 s/min | Increase Max Server Memory or identify scan-heavy queries |
Analyzed by: sqlmemory-review (O1–O20)/sqlwait-review — RESOURCE_SEMAPHORE (V11), CMEMTHREAD (V12), and PAGEIOLATCH (V1–V3) waits are the live signal of memory pressure that this skill explains at the configuration level/sqltrace-review — identify which workload queries are flooding the buffer pool or acquiring large memory grants/sqlplan-review — N21 (row count estimate mismatch) and N15/N16 (sort/hash spills) explain why grants are oversized/sqlquerystore-review — Q23 (memory grant regression) and Q24 (spill regression) link plan changes to memory pressure events/sqldiskio-review — if PLE is low and sys.dm_io_virtual_file_stats shows high latency, the working set is spilling to disk; disk I/O is the symptom of memory pressureSee skills/VERSION_COMPATIBILITY.md for the full compatibility matrix.
| Check | 2008 R2 | 2012 | 2014 | 2016 | 2017 | 2019 | 2022 | Azure SQL |
|---|---|---|---|---|---|---|---|---|
| O1 PLE | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O2 PLE Trend | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O3 NUMA PLE | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| O4 DB concentration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O5 Stolen memory | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Partial |
| O6 Single-use plan | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O7 Compile rate | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O8 Large plan | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O9 Lock clerk | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O10 Plan hit rate | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O11 Grant queue | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O12 Grant timeout | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O13 Oversized grant | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O14 RG pool | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O15 BPE | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| O16 ColumnStore | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O17 XTP/In-Memory | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| O18 OS pressure | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — |
| O19 LPIM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | N/A |
| O20 Max Server Mem | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | N/A |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.