Skip to content

Advanced

tashda edited this page Mar 9, 2026 · 1 revision

Advanced Topics

Activity Monitor (Performance Diagnostics)

SQLServerNIO features a built-in diagnostic tool modeled after the SSMS Activity Monitor. It allows you to programmatically monitor server pressure, running processes, and resource waits by querying Dynamic Management Views (DMVs).

Requires VIEW SERVER STATE permissions. Available on SQL Server 2008 and newer.

let monitor = SQLServerActivityMonitor(client: client)

// 1. Take a one-shot snapshot of current server health
let snap = try await monitor.snapshot()
print("Total Processes: \(snap.processes.count)")
print("Active Waits: \(snap.waits.count)")

// 2. Kill a problematic session
try await monitor.killSession(sessionId: 55)

Streaming Snapshots

Because many DMVs log cumulative statistics (e.g., total wait time since server restart), analyzing them requires taking two snapshots and comparing the delta. The streamSnapshots method handles this automatically.

// Stream snapshots every 5 seconds
let stream = monitor.streamSnapshots(every: 5.0, options: .init(includeSqlText: false))

for try await s in stream {
    // waitsDelta exposes the resources waited on during the last 5 seconds
    if let highestWait = s.waitsDelta?.first {
         print("Highest recent wait: \(highestWait.waitType) (\(highestWait.waitTimeMs)ms)")
    }
}

(Querying includeSqlText: true or includeQueryPlan: true can be extremely heavy on the server; use cautiously).


Execution Options

You can pass SqlServerExecutionOptions to instruct the server on how to handle the execution context of your query.

import SQLServerKit

let options = SqlServerExecutionOptions(
    mode: .auto,                 // Can be forced to .simple or .cursor
    rowsetFetchSize: nil,        // Reserved for future cursor support
    progressThrottleMs: 120      // Throttle cadence
)

let result = try await client.query("SELECT * FROM GiganticTable", options: options)

EventLoopFuture APIs

If you are developing inside an older architecture or directly inside SwiftNIO handlers, every async API in SQLServerNIO is mirrored with an EventLoopFuture version.

client.query("SELECT COUNT(*) AS count FROM sys.tables").whenComplete { result in
    switch result {
    case .success(let rows):
        let count = rows.first?.column("count")?.int ?? 0
        print("Total tables: \(count)")
    case .failure(let error):
        print("Query failed: \(error)")
    }
}

Clone this wiki locally