Review 1.2: scan the version store for its generators at most hourly
sys.dm_tran_top_version_generators reads the whole version store. It ran every 5 minutes while the version store was over half the threshold, i.e. exactly when it is large and expensive to scan, and a timeout failed the whole tempdb collection. It now runs at most once per hour (the previous answer is kept in between, with its time) and a failed scan keeps the previous answer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4ceb64f2d5
commit
d070cd872b
2 changed files with 31 additions and 3 deletions
|
|
@ -42,6 +42,9 @@ public sealed class TempdbCollector(int versionStoreMegabytes = 1024, int sessio
|
|||
ORDER BY t.elapsed_time_seconds DESC
|
||||
""";
|
||||
|
||||
/// <summary>How often the version store is scanned for the databases generating it, while it is large.</summary>
|
||||
public static readonly TimeSpan GeneratorsInterval = TimeSpan.FromHours(1);
|
||||
|
||||
// Scans the version store: only run when it is large enough to need explaining.
|
||||
internal const string GeneratorsSql = """
|
||||
SELECT TOP 10 DB_NAME(database_id), SUM(CAST(aggregated_record_length_in_bytes AS bigint))
|
||||
|
|
@ -68,9 +71,30 @@ public sealed class TempdbCollector(int versionStoreMegabytes = 1024, int sessio
|
|||
var oldest = (await Db.QueryAsync(connection, OldestSnapshotSql, r => new SnapshotTransaction(r.Int(0), r.NullableLong(1) ?? 0, r.NullableString(2), r.NullableString(3)), ct)
|
||||
.ConfigureAwait(false)).FirstOrDefault();
|
||||
var versionMb = space.VersionKb is { } kb ? kb / 1024.0 : space.Version * PageMb;
|
||||
var generators = versionMb >= versionStoreMegabytes / 2.0
|
||||
? await Db.QueryAsync(connection, GeneratorsSql, r => new VersionGenerator(r.NullableString(0) ?? "?", (r.NullableLong(1) ?? 0) / 1024.0 / 1024.0), ct).ConfigureAwait(false)
|
||||
: [];
|
||||
IReadOnlyList<VersionGenerator> generators = [];
|
||||
DateTimeOffset? generatorsAt = null;
|
||||
if (versionMb >= versionStoreMegabytes / 2.0)
|
||||
{
|
||||
// Scanning a large version store every 5 minutes is not cheap: at most once per GeneratorsInterval, and a
|
||||
// scan that fails (times out) keeps the previous answer instead of failing the whole collection.
|
||||
if (previous is { VersionGeneratorsAt: { } at } && context.Now - at < GeneratorsInterval)
|
||||
{
|
||||
(generators, generatorsAt) = (previous.VersionGenerators, at);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
generators = await Db.QueryAsync(connection, GeneratorsSql, r => new VersionGenerator(r.NullableString(0) ?? "?", (r.NullableLong(1) ?? 0) / 1024.0 / 1024.0), ct)
|
||||
.ConfigureAwait(false);
|
||||
generatorsAt = context.Now;
|
||||
}
|
||||
catch (System.Data.Common.DbException)
|
||||
{
|
||||
(generators, generatorsAt) = (previous?.VersionGenerators ?? [], previous?.VersionGeneratorsAt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TempdbAnalysis.Advance(previous, new TempdbSnapshot
|
||||
{
|
||||
|
|
@ -84,6 +108,7 @@ public sealed class TempdbCollector(int versionStoreMegabytes = 1024, int sessio
|
|||
TopSessions = sessions,
|
||||
OldestSnapshotTransaction = oldest,
|
||||
VersionGenerators = generators,
|
||||
VersionGeneratorsAt = generatorsAt,
|
||||
VersionStoreThresholdMegabytes = versionStoreMegabytes,
|
||||
SessionThresholdMegabytes = sessionMegabytes,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ public sealed record TempdbSnapshot
|
|||
public SnapshotTransaction? OldestSnapshotTransaction { get; init; }
|
||||
public IReadOnlyList<VersionGenerator> VersionGenerators { get; init; } = [];
|
||||
|
||||
/// <summary>When <see cref="VersionGenerators"/> was read (the scan is expensive and is repeated at most hourly).</summary>
|
||||
public DateTimeOffset? VersionGeneratorsAt { get; init; }
|
||||
|
||||
/// <summary>Version store sizes of the latest samples (MB), oldest first: the trend.</summary>
|
||||
public IReadOnlyList<double> VersionStoreHistory { get; init; } = [];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue