Describe the bug
The TipID 1510 is being flagged and reaching a limit but that is not true.
There are two problems
1st one - the comparison:
https://github.com/microsoft/azure-sql-tips/blob/main/sqldb-tips/get-sqldb-tips.sql#L2011
To Reproduce
Steps to reproduce the behavior:
- Create a sequence (seen in real life)
CREATE SEQUENCE dbo.testSequence
AS BIGINT
START WITH 10000
INCREMENT BY 1
MINVALUE -9223372036854775808
MAXVALUE 9999999999;
- use some values
SELECT NEXT VALUE FOR dbo.testSequence
GO 100
- Run the 1520 tip with default configured ration 0.2 (meaning we want to be warned if there is less than 20% available, correct?)
The sequence is flagged with following message:
schema: [dbo], sequence: [testSequence], data type: bigint, start value: 10,000, current value: 10,099, increment: 1, range: -9,223,372,036,854,780,000 to 9,999,999,999, exhausted: No
This happens because using the current calculation the output is 1.08420107626582E-09
(for better readability is 0.000000001084201
) which is lower than the 0.2
configured for @IdentitySequenceRangeExhaustionThresholdRatio
and, therefore, it appears on the radar.
Expected behavior
It should not flag this sequence.
The calculation may need a 1-"calculation" < 0.2
where 1-"calculation"
is the remaining.
In this example, this would translate into 0.999999998915799
which isn't < 0.2
and therefore wouldn't be flagged.
Current:
WHERE -- less than x% of the maximum sequence range remains
CASE WHEN increment > 0 THEN (maximum_value - current_value) / (maximum_value - minimum_value)
WHEN increment < 0 THEN (minimum_value - current_value) / (minimum_value - maximum_value)
END < @IdentitySequenceRangeExhaustionThresholdRatio
Suggestion:
WHERE -- less than x% of the maximum sequence range remains
(1- CASE WHEN increment > 0 THEN (maximum_value - current_value) / (maximum_value - minimum_value)
WHEN increment < 0 THEN (minimum_value - current_value) / (minimum_value - maximum_value)
END) < @IdentitySequenceRangeExhaustionThresholdRatio
2nd one - The calculation
The current calculation isn't looking to the start_value
neither to the increment
value the sequence.
Continuing with the previous example, the division is done by subtracting max/min value (maximum_value - minimum_value)
If the sequence starts on the minimum value I would agree, but in our example, it starts on 10000 wouldn't be this one the one to consider as minimum_value? Even if it cycles this is the value that will be used.
That said we should have:
StillAvailable: (maximum_value - start_value - current_value)
divided by
TotalAvailable: (maximum_value - start_value)
And that will be a value of: 0.99999899009899
where the current calculation is 0.999999998915799
. This gives a difference of 0.000001008816809
more values that actually won't be available.
However, we are still missing the increment
variable.
If it increments by 10000 the number of StillAvailable and TotalAvailable will be 10000 times less.
So putting it all together I would suggest (please anyone that confirm my calculations ๐ )
old:
CASE WHEN increment > 0 THEN (maximum_value - current_value) / (maximum_value - minimum_value)
new:
CASE WHEN increment > 0 THEN ((maximum_value - start_value - current_value) / increment) / ((maximum_value - start_value) / increment)
Final question:
What if is_cycling
is true? Should this ever be flagged?
Database info
Single database
Additional context
Maybe it is worth double check the TipID 1510 too.