Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
4.5 KiB
AuditLogEntries index usage: first measurement (2026-11-13)
Tracks: Gitea ScadaBridge#70 (deferred-work register row 135).
Question: are the single-column IX_AuditLogEntries_Timestamp, _User and _EntityType indexes
dead weight now that ReviewRemediationIndexes added (EntityType, Timestamp DESC),
(User, Timestamp DESC) and (Timestamp DESC, Id DESC)?
Decision: no migration yet. The measurement window is too short on both tiers, and no index on the table was read at all, the new composites included. Re-measure on or after 2026-11-27.
Method
Read-only SELECTs over a direct SQL login (sqlcmd -C), no remote exec, run 2026-11-13 ~02:10 server time:
sys.dm_db_index_usage_stats LEFT JOIN sys.indexes for dbo.AuditLogEntries, plus
sys.dm_db_index_operational_stats, sys.partitions/sys.allocation_units for rows and size, and
sys.dm_os_sys_info.sqlserver_start_time (the DMVs reset when SQL Server restarts).
Measurement window
| Tier | SQL host / DB | sqlserver_start_time |
Window | Latest migration |
|---|---|---|---|---|
| DEV | wonder-app-vd03 / ScadaBridge |
2026-11-10 06:42 | ~3 days | 20261110120000_AuditMaintenanceGrants (64) |
| QA | wonder-sql-vq03 / ScadaBridge |
2026-11-03 07:09 | ~10 days | 20261022133907_ReviewRemediationIndexes (58) |
Both are under the two weeks needed. The migration went in on 2026-10-22, but SQL restarts since then have reset the counters.
Results
Table size: DEV 471 rows (Timestamp 2026-05-29 to 2026-10-28), QA 567 rows (to 2026-11-06).
| Index | Keys | DEV seeks/scans/lookups | DEV updates | QA seeks/scans/lookups | QA updates | Size |
|---|---|---|---|---|---|---|
| PK_AuditLogEntries (clustered) | Id | 0/0/0 | 0 | 0/0/0 | 10 | 1.4 MB / 4.3 MB |
| IX_AuditLogEntries_Action | Action | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_EntityId | EntityId | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_EntityType | EntityType | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_Timestamp | Timestamp | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_User | User | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_BundleImportId | BundleImportId | 0/0/0 | 0 | 0/0/0 | 10 | 72 KB |
| IX_AuditLogEntries_EntityType_Timestamp | EntityType, Timestamp DESC | 0/0/0 | 0 | 0/0/0 | 10 | 200 KB |
| IX_AuditLogEntries_Timestamp_Id | Timestamp DESC, Id DESC | 0/0/0 | 0 | 0/0/0 | 10 | 200 KB |
| IX_AuditLogEntries_User_Timestamp | User, Timestamp DESC | 0/0/0 | 0 | 0/0/0 | 10 | 200 KB |
| IX_AuditLogEntries_EntityName (DEV only, migration 59+) | EntityName | 0/0/0 | 0 | — | — | 200 KB |
sys.dm_db_index_operational_stats agrees: zero range scans and singleton lookups on every index on both
tiers, with 10 leaf inserts per index on QA and none on DEV.
Reading
- The data does not settle the question. Every index reads zero, including the composites that are supposed to replace the single-column ones. Nobody used the config-audit page or the CLI query on either tier during the window, and the purge job did not touch the table. A zero on an old index only means something if the composite that replaces it shows reads.
- On write cost: the table is tiny (about 500 rows) and takes about 1 write a day on QA. The three single-column indexes cost about 216 KB and 3 extra index writes per insert. Nothing is urgent.
- Static coverage (from code, not from the measurement): each single-column index is a left prefix of
a composite. The filters in
CentralUiRepository(User ==,EntityType ==,Timestamprange, ordered byTimestamp DESC, Id DESC) and the purge inConfigAuditPurgeService(Timestamp < cutoff ORDER BY Timestamp, which can use a backward scan ofIX_AuditLogEntries_Timestamp_Id) are all served by the composites. So the case for dropping the three indexes is sound in principle. The register's rule is "measured, not assumed", and this run measured nothing useful.
Next step
Re-run the same query on or after 2026-11-27, which is two weeks after both current
sqlserver_start_times. Check sqlserver_start_time again first. If the composites show reads and
the single-column indexes still show zero, drop IX_AuditLogEntries_Timestamp, _User and
_EntityType in one migration whose Down() recreates them. Leave Action, EntityId,
BundleImportId and EntityName alone, because no composite covers them. If every index still reads
zero, the owner has to decide whether to drop on static grounds or to exercise the config-audit page
on QA first and then measure.