sys.dm_db_index_usage_stats also starts over when a database is taken offline, closed by AUTO_CLOSE or (2012/2014) an index is rebuilt. The delta was then clamped to 0, so the usage since the reset was lost from the daily history and the tracked totals. A lower counter now counts as new usage. IndexInfo.Key also used the literal text "001f" as its separator instead of the unit separator character. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
45 lines
2.4 KiB
C#
45 lines
2.4 KiB
C#
using SQLInsight.Core.Data;
|
|
|
|
namespace SQLInsight.Core.Tests;
|
|
|
|
public class IndexUsageTests
|
|
{
|
|
private static readonly DateTime Start = new(2026, 9, 1, 6, 0, 0, DateTimeKind.Utc);
|
|
|
|
private static IndexSnapshot Snapshot(DateTime start, DateTimeOffset at, long reads, long writes) => new()
|
|
{
|
|
CapturedAt = at,
|
|
SqlServerStartTime = start,
|
|
Databases = [new IndexDatabase { Name = "AX", Indexes = [new IndexInfo { Schema = "dbo", Table = "INVENTTRANS", IndexId = 5, Name = "I_177ITEMIDX", Type = "NONCLUSTERED", UserSeeks = reads, UserUpdates = writes }] }],
|
|
};
|
|
|
|
[Fact]
|
|
public void Usage_is_summed_across_restarts_and_tracked_from_the_first_restart_seen()
|
|
{
|
|
var first = IndexUsageTracking.Advance(null, Snapshot(Start, new DateTimeOffset(Start.AddDays(1)), 10, 100));
|
|
var second = IndexUsageTracking.Advance(first, Snapshot(Start, new DateTimeOffset(Start.AddDays(2)), 15, 300));
|
|
var restart = Start.AddDays(3);
|
|
var afterRestart = IndexUsageTracking.Advance(second, Snapshot(restart, new DateTimeOffset(restart.AddHours(6)), 2, 50));
|
|
|
|
var index = afterRestart.Databases[0].Indexes[0];
|
|
Assert.Equal((17L, 350L), (index.TrackedReads, index.TrackedWrites));
|
|
Assert.Equal(new DateTimeOffset(Start), index.TrackedSince);
|
|
Assert.Equal(TimeSpan.FromDays(3.25), afterRestart.TrackedFor(index));
|
|
Assert.Equal(TimeSpan.FromHours(6), afterRestart.Uptime);
|
|
var delta = Assert.Single(second.UsageDeltas);
|
|
Assert.Equal((5L, 200L), (delta.Reads, delta.Writes));
|
|
Assert.Equal((2L, 50L), (afterRestart.UsageDeltas[0].Reads, afterRestart.UsageDeltas[0].Writes)); // counters started over
|
|
}
|
|
|
|
[Fact]
|
|
public void A_counter_reset_without_a_restart_counts_what_the_counter_holds_now()
|
|
{
|
|
// The database was taken offline (or closed by AUTO_CLOSE) between the collections: same start time, lower counters.
|
|
var first = IndexUsageTracking.Advance(null, Snapshot(Start, new DateTimeOffset(Start.AddDays(1)), 100, 1000));
|
|
var second = IndexUsageTracking.Advance(first, Snapshot(Start, new DateTimeOffset(Start.AddDays(2)), 7, 40));
|
|
|
|
var delta = Assert.Single(second.UsageDeltas);
|
|
Assert.Equal((7L, 40L), (delta.Reads, delta.Writes));
|
|
Assert.Equal((107L, 1040L), (second.Databases[0].Indexes[0].TrackedReads, second.Databases[0].Indexes[0].TrackedWrites));
|
|
}
|
|
}
|