sqlinsight-pro/tests/SQLInsight.Core.Tests/IndexUsageTests.cs
Søren Eggert Lundsteen Olsen 6cc65e3c75 Index usage over time and never-updated statistics (8g, F)
The index collector now sums index reads and writes between collections
across restarts of SQL Server (and of the agent, by seeding from the
stored snapshot) and keeps them per day in insight.IndexUsageDaily
(migration 0015, HourlyDays). SQLI-IDX-002 judges an index once it has
been followed for 7 days instead of needing 7 days of uptime.
GET /api/v1/instances/{name}/index-usage lists usage per index.

SQLI-STAT-001 also reports statistics that were never updated on tables
with rows; statistic rows now come from the table's heap or clustered
index, as a never-updated statistic has no row count of its own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:55:22 +02:00

33 lines
1.7 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
}
}