-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Benchmarking our current integration tests it became clear that our test setup time took longer than the actual test case execution.
And looking further into this, the option WithReseed = true is the culprit.
The Reseed SQL uses on average 870ms (per test execution!) on my machine.
Tweaking the SQL has brought this time down to average 160ms, a 700ms reduction (again per test case).
With a few thousand tests this makes a huge difference in total runtime :)
The tweaked SQL:
DECLARE @SchemaAndTableName sysname = N''
DECLARE @NewSeedValue int = 0
-- find all non-system tables and load into a cursor
DECLARE IdentityTables CURSOR FAST_FORWARD
FOR
SELECT QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id, db_id())) + '.' + QUOTENAME(t.name) as schemaAndTableName,
IDENT_SEED(QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id, db_id())) + '.' + QUOTENAME(t.name)) - 1 as newSeedValue
FROM sys.tables t
JOIN sys.columns c ON t.object_id=c.object_id
JOIN sys.identity_columns ic on ic.object_id = c.object_id
WHERE c.is_identity = 1
AND ic.last_value IS NOT null -- Skip null values
AND ic.last_value <> IDENT_SEED(QUOTENAME(OBJECT_SCHEMA_NAME(t.object_id, db_id())) + '.' + QUOTENAME(t.name)) - 1 -- Skip if we don't need to reseed the value
AND OBJECT_SCHEMA_NAME(t.object_id, db_id()) + '.' + t.name in ('{string.Join("', '", tablesToDelete)}')
OPEN IdentityTables
FETCH NEXT FROM IdentityTables INTO @SchemaAndTableName, @NewSeedValue
WHILE @@FETCH_STATUS = 0
BEGIN
-- reseed the identity only on tables that actually have had a value, otherwise next value will be off-by-one
-- https://stackoverflow.com/questions/472578/dbcc-checkident-sets-identity-to-0
DBCC CHECKIDENT(@SchemaAndTableName, RESEED, @NewSeedValue)
FETCH NEXT FROM IdentityTables INTO @SchemaAndTableName, @NewSeedValue
END
DEALLOCATE IdentityTables
Tweaks:
Instead of selecting the schema and table separately, this can be done in a single select.
We can select identityInitialSeedValue - 1 directly as this is the value passed to DBCC CHECKIDENT anyways.
We can filter out cases where ic.last_value is null in the where clause.
We can check the current seed value and make sure it's different from identityInitialSeedValue - 1, since otherwise we just set it to it's current value anyways.
Lastly instead of creating the DBCC CHECKIDENT command as a string and executing it, we can just call the function directly using the 2 new variables which contain what we need directly.
Let me know if I missed something :)
I would be happy to create a PR for this as well, just let me know.